Form.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  1. #include "Base.h"
  2. #include "Form.h"
  3. #include "AbsoluteLayout.h"
  4. #include "FlowLayout.h"
  5. #include "ScrollLayout.h"
  6. #include "VerticalLayout.h"
  7. #include "Game.h"
  8. #include "Theme.h"
  9. #include "Label.h"
  10. #include "Button.h"
  11. #include "CheckBox.h"
  12. #include "Scene.h"
  13. namespace gameplay
  14. {
  15. static std::vector<Form*> __forms;
  16. Form::Form() : _theme(NULL), _quad(NULL), _node(NULL), _frameBuffer(NULL), _spriteBatch(NULL)
  17. {
  18. }
  19. Form::Form(const Form& copy)
  20. {
  21. }
  22. Form::~Form()
  23. {
  24. SAFE_RELEASE(_quad);
  25. SAFE_RELEASE(_node);
  26. SAFE_RELEASE(_frameBuffer);
  27. SAFE_RELEASE(_theme);
  28. SAFE_DELETE(_spriteBatch);
  29. // Remove this Form from the global list.
  30. std::vector<Form*>::iterator it = std::find(__forms.begin(), __forms.end(), this);
  31. if (it != __forms.end())
  32. {
  33. __forms.erase(it);
  34. }
  35. }
  36. Form* Form::create(const char* url)
  37. {
  38. // Load Form from .form file.
  39. Properties* properties = Properties::create(url);
  40. if (properties == NULL)
  41. {
  42. GP_ASSERT(properties);
  43. return NULL;
  44. }
  45. // Check if the Properties is valid and has a valid namespace.
  46. Properties* formProperties = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
  47. assert(formProperties);
  48. if (!formProperties || !(strcmp(formProperties->getNamespace(), "form") == 0))
  49. {
  50. GP_ASSERT(formProperties);
  51. SAFE_DELETE(properties);
  52. return NULL;
  53. }
  54. // Create new form with given ID, theme and layout.
  55. const char* themeFile = formProperties->getString("theme");
  56. const char* layoutString = formProperties->getString("layout");
  57. Layout* layout;
  58. switch (getLayoutType(layoutString))
  59. {
  60. case Layout::LAYOUT_ABSOLUTE:
  61. layout = AbsoluteLayout::create();
  62. break;
  63. case Layout::LAYOUT_FLOW:
  64. layout = FlowLayout::create();
  65. break;
  66. case Layout::LAYOUT_VERTICAL:
  67. layout = VerticalLayout::create();
  68. break;
  69. case Layout::LAYOUT_SCROLL:
  70. layout = ScrollLayout::create();
  71. break;
  72. default:
  73. GP_ERROR("Unsupported layout type \'%d\'.", getLayoutType(layoutString));
  74. }
  75. Theme* theme = Theme::create(themeFile);
  76. GP_ASSERT(theme);
  77. Form* form = new Form();
  78. form->_layout = layout;
  79. form->_theme = theme;
  80. const char* styleName = formProperties->getString("style");
  81. form->initialize(theme->getStyle(styleName), formProperties);
  82. // Add all the controls to the form.
  83. form->addControls(theme, formProperties);
  84. Game* game = Game::getInstance();
  85. Matrix::createOrthographicOffCenter(0, game->getWidth(), game->getHeight(), 0, 0, 1, &form->_defaultProjectionMatrix);
  86. SAFE_DELETE(properties);
  87. __forms.push_back(form);
  88. return form;
  89. }
  90. Form* Form::getForm(const char* id)
  91. {
  92. std::vector<Form*>::const_iterator it;
  93. for (it = __forms.begin(); it < __forms.end(); it++)
  94. {
  95. Form* f = *it;
  96. GP_ASSERT(f);
  97. if (strcmp(id, f->getID()) == 0)
  98. {
  99. return f;
  100. }
  101. }
  102. return NULL;
  103. }
  104. void Form::setSize(float width, float height)
  105. {
  106. if (_autoWidth)
  107. {
  108. width = Game::getInstance()->getWidth();
  109. }
  110. if (_autoHeight)
  111. {
  112. height = Game::getInstance()->getHeight();
  113. }
  114. if (width != _bounds.width || height != _bounds.height)
  115. {
  116. // Width and height must be powers of two to create a texture.
  117. int w = width;
  118. int h = height;
  119. if (!((w & (w - 1)) == 0))
  120. {
  121. w = nextHighestPowerOfTwo(w);
  122. }
  123. if (!((h & (h - 1)) == 0))
  124. {
  125. h = nextHighestPowerOfTwo(h);
  126. }
  127. _u2 = width / (float)w;
  128. _v1 = height / (float)h;
  129. // Create framebuffer if necessary.
  130. if (!_frameBuffer)
  131. {
  132. _frameBuffer = FrameBuffer::create(_id.c_str());
  133. GP_ASSERT(_frameBuffer);
  134. }
  135. // Re-create render target.
  136. RenderTarget* rt = RenderTarget::create(_id.c_str(), w, h);
  137. GP_ASSERT(rt);
  138. _frameBuffer->setRenderTarget(rt);
  139. SAFE_RELEASE(rt);
  140. // Re-create projection matrix.
  141. Matrix::createOrthographicOffCenter(0, width, height, 0, 0, 1, &_projectionMatrix);
  142. // Re-create sprite batch.
  143. SAFE_DELETE(_spriteBatch);
  144. _spriteBatch = SpriteBatch::create(_frameBuffer->getRenderTarget()->getTexture());
  145. GP_ASSERT(_spriteBatch);
  146. _bounds.width = width;
  147. _bounds.height = height;
  148. _dirty = true;
  149. }
  150. }
  151. void Form::setBounds(const Rectangle& bounds)
  152. {
  153. setPosition(bounds.x, bounds.y);
  154. setSize(bounds.width, bounds.height);
  155. }
  156. void Form::setAutoWidth(bool autoWidth)
  157. {
  158. if (_autoWidth != autoWidth)
  159. {
  160. _autoWidth = autoWidth;
  161. _dirty = true;
  162. if (_autoWidth)
  163. {
  164. setSize(_bounds.width, Game::getInstance()->getWidth());
  165. }
  166. }
  167. }
  168. void Form::setAutoHeight(bool autoHeight)
  169. {
  170. if (_autoHeight != autoHeight)
  171. {
  172. _autoHeight = autoHeight;
  173. _dirty = true;
  174. if (_autoHeight)
  175. {
  176. setSize(_bounds.width, Game::getInstance()->getHeight());
  177. }
  178. }
  179. }
  180. void Form::setQuad(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4)
  181. {
  182. Mesh* mesh = Mesh::createQuad(p1, p2, p3, p4);
  183. initializeQuad(mesh);
  184. SAFE_RELEASE(mesh);
  185. }
  186. void Form::setQuad(float x, float y, float width, float height)
  187. {
  188. float x2 = x + width;
  189. float y2 = y + height;
  190. float vertices[] =
  191. {
  192. x, y2, 0, 0, _v1,
  193. x, y, 0, 0, 0,
  194. x2, y2, 0, _u2, _v1,
  195. x2, y, 0, _u2, 0
  196. };
  197. VertexFormat::Element elements[] =
  198. {
  199. VertexFormat::Element(VertexFormat::POSITION, 3),
  200. VertexFormat::Element(VertexFormat::TEXCOORD0, 2)
  201. };
  202. Mesh* mesh = Mesh::createMesh(VertexFormat(elements, 2), 4, false);
  203. assert(mesh);
  204. mesh->setPrimitiveType(Mesh::TRIANGLE_STRIP);
  205. mesh->setVertexData(vertices, 0, 4);
  206. initializeQuad(mesh);
  207. SAFE_RELEASE(mesh);
  208. }
  209. void Form::setNode(Node* node)
  210. {
  211. _node = node;
  212. if (_node)
  213. {
  214. // Set this Form up to be 3D by initializing a quad.
  215. setQuad(0.0f, 0.0f, _bounds.width, _bounds.height);
  216. _node->setModel(_quad);
  217. }
  218. }
  219. void Form::update()
  220. {
  221. if (isDirty())
  222. {
  223. Container::update(Rectangle(0, 0, _bounds.width, _bounds.height), Vector2::zero());
  224. }
  225. }
  226. void Form::draw()
  227. {
  228. /*
  229. The first time a form is drawn, its contents are rendered into a framebuffer.
  230. The framebuffer will only be drawn into again when the contents of the form change.
  231. If this form has a node then it's a 3D form and the framebuffer will be used
  232. to texture a quad. The quad will be given the same dimensions as the form and
  233. must be transformed appropriately by the user, unless they call setQuad() themselves.
  234. On the other hand, if this form has not been set on a node, SpriteBatch will be used
  235. to render the contents of the frambuffer directly to the display.
  236. */
  237. // Check whether this form has changed since the last call to draw()
  238. // and if so, render into the framebuffer.
  239. if (isDirty())
  240. {
  241. GP_ASSERT(_frameBuffer);
  242. _frameBuffer->bind();
  243. Game* game = Game::getInstance();
  244. Rectangle prevViewport = game->getViewport();
  245. game->setViewport(Rectangle(_bounds.x, _bounds.y, _bounds.width, _bounds.height));
  246. GP_ASSERT(_theme);
  247. _theme->setProjectionMatrix(_projectionMatrix);
  248. draw(_theme->getSpriteBatch(), _viewportClipBounds);
  249. _theme->setProjectionMatrix(_defaultProjectionMatrix);
  250. // Rebind the default framebuffer and game viewport.
  251. FrameBuffer::bindDefault();
  252. // restore the previous game viewport
  253. game->setViewport(prevViewport);
  254. }
  255. if (_node)
  256. {
  257. GP_ASSERT(_quad);
  258. _quad->draw();
  259. }
  260. else
  261. {
  262. if (!_spriteBatch)
  263. {
  264. _spriteBatch = SpriteBatch::create(_frameBuffer->getRenderTarget()->getTexture());
  265. GP_ASSERT(_spriteBatch);
  266. }
  267. _spriteBatch->begin();
  268. _spriteBatch->draw(_bounds.x, _bounds.y, 0, _bounds.width, _bounds.height, 0, _v1, _u2, 0, Vector4::one());
  269. _spriteBatch->end();
  270. }
  271. }
  272. void Form::draw(SpriteBatch* spriteBatch, const Rectangle& clip)
  273. {
  274. GP_ASSERT(spriteBatch);
  275. std::vector<Control*>::const_iterator it;
  276. // Batch each font individually.
  277. std::set<Font*>::const_iterator fontIter;
  278. for (fontIter = _theme->_fonts.begin(); fontIter != _theme->_fonts.end(); fontIter++)
  279. {
  280. Font* font = *fontIter;
  281. if (font)
  282. {
  283. font->begin();
  284. }
  285. }
  286. // Batch for all themed border and background sprites.
  287. spriteBatch->begin();
  288. // Draw the form's border and background.
  289. // We don't pass the form's position to itself or it will be applied twice!
  290. Control::drawBorder(spriteBatch, Rectangle(0, 0, _bounds.width, _bounds.height));
  291. Rectangle boundsUnion = Rectangle::empty();
  292. for (it = _controls.begin(); it < _controls.end(); it++)
  293. {
  294. Control* control = *it;
  295. GP_ASSERT(control);
  296. if (_skin || control->isDirty() || control->_clearBounds.intersects(boundsUnion))
  297. {
  298. control->draw(spriteBatch, clip, _skin == NULL, _bounds.height);
  299. Rectangle::combine(control->_clearBounds, boundsUnion, &boundsUnion);
  300. }
  301. }
  302. // Done all batching.
  303. spriteBatch->end();
  304. for (fontIter = _theme->_fonts.begin(); fontIter != _theme->_fonts.end(); fontIter++)
  305. {
  306. Font* font = *fontIter;
  307. if (font)
  308. {
  309. font->end();
  310. }
  311. }
  312. _dirty = false;
  313. }
  314. void Form::initializeQuad(Mesh* mesh)
  315. {
  316. // Release current model.
  317. SAFE_RELEASE(_quad);
  318. // Create the model.
  319. _quad = Model::create(mesh);
  320. // Create the material.
  321. Material* material = _quad->setMaterial("res/shaders/textured.vsh", "res/shaders/textured.fsh");
  322. GP_ASSERT(material);
  323. // Set the common render state block for the material.
  324. GP_ASSERT(_theme);
  325. GP_ASSERT(_theme->getSpriteBatch());
  326. RenderState::StateBlock* stateBlock = _theme->getSpriteBatch()->getStateBlock();
  327. GP_ASSERT(stateBlock);
  328. stateBlock->setDepthWrite(true);
  329. material->setStateBlock(stateBlock);
  330. // Bind the WorldViewProjection matrix.
  331. material->setParameterAutoBinding("u_worldViewProjectionMatrix", RenderState::WORLD_VIEW_PROJECTION_MATRIX);
  332. // Bind the texture.
  333. Texture::Sampler* sampler = Texture::Sampler::create(_frameBuffer->getRenderTarget()->getTexture());
  334. GP_ASSERT(sampler);
  335. sampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
  336. material->getParameter("u_diffuseTexture")->setValue(sampler);
  337. material->getParameter("u_diffuseColor")->setValue(Vector4::one());
  338. SAFE_RELEASE(sampler);
  339. }
  340. bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  341. {
  342. // Check for a collision with each Form in __forms.
  343. // Pass the event on.
  344. std::vector<Form*>::const_iterator it;
  345. for (it = __forms.begin(); it < __forms.end(); it++)
  346. {
  347. Form* form = *it;
  348. GP_ASSERT(form);
  349. if (form->isEnabled())
  350. {
  351. Node* node = form->_node;
  352. if (node)
  353. {
  354. Scene* scene = node->getScene();
  355. GP_ASSERT(scene);
  356. Camera* camera = scene->getActiveCamera();
  357. if (camera)
  358. {
  359. // Get info about the form's position.
  360. Matrix m = node->getMatrix();
  361. Vector3 min(0, 0, 0);
  362. m.transformPoint(&min);
  363. // Unproject point into world space.
  364. Ray ray;
  365. camera->pickRay(Game::getInstance()->getViewport(), x, y, &ray);
  366. // Find the quad's plane.
  367. // We know its normal is the quad's forward vector.
  368. Vector3 normal = node->getForwardVectorWorld();
  369. // To get the plane's distance from the origin,
  370. // we'll find the distance from the plane defined
  371. // by the quad's forward vector and one of its points
  372. // to the plane defined by the same vector and the origin.
  373. const float& a = normal.x; const float& b = normal.y; const float& c = normal.z;
  374. const float d = -(a*min.x) - (b*min.y) - (c*min.z);
  375. const float distance = abs(d) / sqrt(a*a + b*b + c*c);
  376. Plane plane(normal, -distance);
  377. // Check for collision with plane.
  378. float collisionDistance = ray.intersects(plane);
  379. if (collisionDistance != Ray::INTERSECTS_NONE)
  380. {
  381. // Multiply the ray's direction vector by collision distance
  382. // and add that to the ray's origin.
  383. Vector3 point = ray.getOrigin() + collisionDistance*ray.getDirection();
  384. // Project this point into the plane.
  385. m.invert();
  386. m.transformPoint(&point);
  387. // Pass the touch event on.
  388. const Rectangle& bounds = form->getBounds();
  389. if (form->getState() == Control::FOCUS ||
  390. (evt == Touch::TOUCH_PRESS &&
  391. point.x >= bounds.x &&
  392. point.x <= bounds.x + bounds.width &&
  393. point.y >= bounds.y &&
  394. point.y <= bounds.y + bounds.height))
  395. {
  396. if (form->touchEvent(evt, point.x - bounds.x, bounds.height - point.y - bounds.y, contactIndex))
  397. {
  398. return true;
  399. }
  400. }
  401. }
  402. }
  403. }
  404. else
  405. {
  406. // Simply compare with the form's bounds.
  407. const Rectangle& bounds = form->getBounds();
  408. if (form->getState() == Control::FOCUS ||
  409. (evt == Touch::TOUCH_PRESS &&
  410. x >= bounds.x &&
  411. x <= bounds.x + bounds.width &&
  412. y >= bounds.y &&
  413. y <= bounds.y + bounds.height))
  414. {
  415. // Pass on the event's position relative to the form.
  416. if (form->touchEvent(evt, x - bounds.x, y - bounds.y, contactIndex))
  417. {
  418. return true;
  419. }
  420. }
  421. }
  422. }
  423. }
  424. return false;
  425. }
  426. void Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
  427. {
  428. std::vector<Form*>::const_iterator it;
  429. for (it = __forms.begin(); it < __forms.end(); it++)
  430. {
  431. Form* form = *it;
  432. GP_ASSERT(form);
  433. if (form->isEnabled())
  434. {
  435. form->keyEvent(evt, key);
  436. }
  437. }
  438. }
  439. int Form::nextHighestPowerOfTwo(int x)
  440. {
  441. x--;
  442. x |= x >> 1;
  443. x |= x >> 2;
  444. x |= x >> 4;
  445. x |= x >> 8;
  446. x |= x >> 16;
  447. return x + 1;
  448. }
  449. }