Form.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. #include "Base.h"
  2. #include "Form.h"
  3. #include "AbsoluteLayout.h"
  4. #include "VerticalLayout.h"
  5. #include "Game.h"
  6. #include "Theme.h"
  7. #include "Label.h"
  8. #include "Button.h"
  9. #include "CheckBox.h"
  10. #include "Scene.h"
  11. namespace gameplay
  12. {
  13. static std::vector<Form*> __forms;
  14. Form::Form() : _theme(NULL), _quad(NULL), _node(NULL), _frameBuffer(NULL)
  15. {
  16. }
  17. Form::Form(const Form& copy)
  18. {
  19. }
  20. Form::~Form()
  21. {
  22. SAFE_RELEASE(_quad);
  23. SAFE_RELEASE(_node);
  24. SAFE_RELEASE(_frameBuffer);
  25. SAFE_RELEASE(_theme);
  26. // Remove this Form from the global list.
  27. std::vector<Form*>::iterator it = std::find(__forms.begin(), __forms.end(), this);
  28. if (it != __forms.end())
  29. {
  30. __forms.erase(it);
  31. }
  32. }
  33. Form* Form::create(const char* url)
  34. {
  35. // Load Form from .form file.
  36. assert(url);
  37. Properties* properties = Properties::create(url);
  38. assert(properties);
  39. if (properties == NULL)
  40. return NULL;
  41. // Check if the Properties is valid and has a valid namespace.
  42. Properties* formProperties = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
  43. assert(formProperties);
  44. if (!formProperties || !(strcmp(formProperties->getNamespace(), "form") == 0))
  45. {
  46. SAFE_DELETE(properties);
  47. return NULL;
  48. }
  49. // Create new form with given ID, theme and layout.
  50. const char* themeFile = formProperties->getString("theme");
  51. const char* layoutString = formProperties->getString("layout");
  52. Layout* layout;
  53. switch (getLayoutType(layoutString))
  54. {
  55. case Layout::LAYOUT_ABSOLUTE:
  56. layout = AbsoluteLayout::create();
  57. break;
  58. case Layout::LAYOUT_FLOW:
  59. break;
  60. case Layout::LAYOUT_VERTICAL:
  61. layout = VerticalLayout::create();
  62. break;
  63. }
  64. assert(themeFile);
  65. Theme* theme = Theme::create(themeFile);
  66. assert(theme);
  67. Form* form = new Form();
  68. form->_layout = layout;
  69. form->_theme = theme;
  70. //Theme* theme = form->_theme;
  71. const char* styleName = formProperties->getString("style");
  72. form->initialize(theme->getStyle(styleName), formProperties);
  73. if (form->_autoWidth)
  74. {
  75. form->_bounds.width = Game::getInstance()->getWidth();
  76. }
  77. if (form->_autoHeight)
  78. {
  79. form->_bounds.height = Game::getInstance()->getHeight();
  80. }
  81. // Add all the controls to the form.
  82. form->addControls(theme, formProperties);
  83. SAFE_DELETE(properties);
  84. __forms.push_back(form);
  85. return form;
  86. }
  87. Form* Form::getForm(const char* id)
  88. {
  89. std::vector<Form*>::const_iterator it;
  90. for (it = __forms.begin(); it < __forms.end(); it++)
  91. {
  92. Form* f = *it;
  93. if (strcmp(id, f->getID()) == 0)
  94. {
  95. return f;
  96. }
  97. }
  98. return NULL;
  99. }
  100. void Form::setQuad(const Vector3& p1, const Vector3& p2, const Vector3& p3, const Vector3& p4)
  101. {
  102. Mesh* mesh = Mesh::createQuad(p1, p2, p3, p4);
  103. initializeQuad(mesh);
  104. SAFE_RELEASE(mesh);
  105. }
  106. void Form::setQuad(float x, float y, float width, float height)
  107. {
  108. Mesh* mesh = Mesh::createQuad(x, y, width, height);
  109. initializeQuad(mesh);
  110. SAFE_RELEASE(mesh);
  111. }
  112. void Form::setNode(Node* node)
  113. {
  114. _node = node;
  115. if (_node && !_quad)
  116. {
  117. // Set this Form up to be 3D by initializing a quad, projection matrix and viewport.
  118. setQuad(0.0f, 0.0f, _bounds.width, _bounds.height);
  119. Matrix::createOrthographicOffCenter(0, _bounds.width, _bounds.height, 0, 0, 1, &_projectionMatrix);
  120. _theme->setProjectionMatrix(_projectionMatrix);
  121. _node->setModel(_quad);
  122. }
  123. }
  124. void Form::update()
  125. {
  126. if (isDirty())
  127. {
  128. Container::update(Rectangle(0, 0, _bounds.width, _bounds.height));
  129. }
  130. }
  131. void Form::draw()
  132. {
  133. // If this form has a node then it's a 3D form. The contents will be rendered
  134. // into a framebuffer which will be used to texture a quad. The quad will be
  135. // given the same dimensions as the form and must be transformed appropriately
  136. // by the user, unless they call setQuad() themselves.
  137. // On the other hand, if this form has not been set on a node it will render
  138. // directly to the display.
  139. if (_node)
  140. {
  141. // Check whether this form has changed since the last call to draw()
  142. // and if so, render into the framebuffer.
  143. if (isDirty())
  144. {
  145. _frameBuffer->bind();
  146. Game* game = Game::getInstance();
  147. Rectangle prevViewport = game->getViewport();
  148. game->setViewport(Rectangle(_bounds.x, _bounds.y, _bounds.width, _bounds.height));
  149. draw(_theme->getSpriteBatch(), _clip);
  150. // Rebind the default framebuffer and game viewport.
  151. FrameBuffer::bindDefault();
  152. // restore the previous game viewport
  153. game->setViewport(prevViewport);
  154. }
  155. _quad->draw();
  156. }
  157. else
  158. {
  159. draw(_theme->getSpriteBatch(), _clip);
  160. }
  161. }
  162. void Form::draw(SpriteBatch* spriteBatch, const Rectangle& clip)
  163. {
  164. std::vector<Control*>::const_iterator it;
  165. // Batch for all themed border and background sprites.
  166. spriteBatch->begin();
  167. // Batch each font individually.
  168. std::set<Font*>::const_iterator fontIter;
  169. for (fontIter = _theme->_fonts.begin(); fontIter != _theme->_fonts.end(); fontIter++)
  170. {
  171. Font* font = *fontIter;
  172. if (font)
  173. {
  174. font->begin();
  175. }
  176. }
  177. // Draw the form's border and background.
  178. // We don't pass the form's position to itself or it will be applied twice!
  179. Control::drawBorder(spriteBatch, Rectangle(0, 0, _bounds.width, _bounds.height));
  180. for (it = _controls.begin(); it < _controls.end(); it++)
  181. {
  182. Control* control = *it;
  183. // Draw this control's border and background.
  184. control->drawBorder(spriteBatch, clip);
  185. // Add all themed foreground sprites (checkboxes etc.) to the same batch.
  186. control->drawImages(spriteBatch, clip);
  187. control->drawText(clip);
  188. }
  189. // Done all batching.
  190. spriteBatch->end();
  191. for (fontIter = _theme->_fonts.begin(); fontIter != _theme->_fonts.end(); fontIter++)
  192. {
  193. Font* font = *fontIter;
  194. if (font)
  195. {
  196. font->end();
  197. }
  198. }
  199. _dirty = false;
  200. }
  201. void Form::initializeQuad(Mesh* mesh)
  202. {
  203. // Release current model.
  204. SAFE_RELEASE(_quad);
  205. // Create the model
  206. _quad = Model::create(mesh);
  207. // Create the material
  208. Material* material = _quad->setMaterial("res/shaders/textured.vsh", "res/shaders/textured.fsh");
  209. // Set the common render state block for the material
  210. RenderState::StateBlock* stateBlock = _theme->getSpriteBatch()->getStateBlock();
  211. stateBlock->setDepthWrite(true);
  212. material->setStateBlock(stateBlock);
  213. // Bind the WorldViewProjection matrix
  214. material->setParameterAutoBinding("u_worldViewProjectionMatrix", RenderState::WORLD_VIEW_PROJECTION_MATRIX);
  215. // Create a FrameBuffer if necessary.
  216. if (!_frameBuffer)
  217. {
  218. _frameBuffer = FrameBuffer::create(_id.c_str());
  219. }
  220. // Use the FrameBuffer to texture the quad.
  221. if (!_frameBuffer->getRenderTarget())
  222. {
  223. RenderTarget* rt = RenderTarget::create(_id.c_str(), _bounds.width, _bounds.height);
  224. _frameBuffer->setRenderTarget(rt);
  225. SAFE_RELEASE(rt);
  226. }
  227. Texture::Sampler* sampler = Texture::Sampler::create(_frameBuffer->getRenderTarget()->getTexture());
  228. sampler->setWrapMode(Texture::CLAMP, Texture::CLAMP);
  229. material->getParameter("u_texture")->setValue(sampler);
  230. material->getParameter("u_textureRepeat")->setValue(Vector2::one());
  231. material->getParameter("u_textureTransform")->setValue(Vector2::zero());
  232. SAFE_RELEASE(sampler);
  233. }
  234. bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  235. {
  236. // Check for a collision with each Form in __forms.
  237. // Pass the event on.
  238. std::vector<Form*>::const_iterator it;
  239. for (it = __forms.begin(); it < __forms.end(); it++)
  240. {
  241. Form* form = *it;
  242. if (form->isEnabled())
  243. {
  244. Node* node = form->_node;
  245. if (node)
  246. {
  247. Scene* scene = node->getScene();
  248. Camera* camera = scene->getActiveCamera();
  249. if (camera)
  250. {
  251. // Get info about the form's position.
  252. Matrix m = node->getMatrix();
  253. Vector3 min(0, 0, 0);
  254. m.transformPoint(&min);
  255. // Unproject point into world space.
  256. Ray ray;
  257. camera->pickRay(Game::getInstance()->getViewport(), x, y, &ray);
  258. // Find the quad's plane.
  259. // We know its normal is the quad's forward vector.
  260. Vector3 normal = node->getForwardVectorWorld();
  261. // To get the plane's distance from the origin,
  262. // we'll find the distance from the plane defined
  263. // by the quad's forward vector and one of its points
  264. // to the plane defined by the same vector and the origin.
  265. const float& a = normal.x; const float& b = normal.y; const float& c = normal.z;
  266. const float d = -(a*min.x) - (b*min.y) - (c*min.z);
  267. const float distance = abs(d) / sqrt(a*a + b*b + c*c);
  268. Plane plane(normal, -distance);
  269. // Check for collision with plane.
  270. float collisionDistance = ray.intersects(plane);
  271. if (collisionDistance != Ray::INTERSECTS_NONE)
  272. {
  273. // Multiply the ray's direction vector by collision distance
  274. // and add that to the ray's origin.
  275. Vector3 point = ray.getOrigin() + collisionDistance*ray.getDirection();
  276. // Project this point into the plane.
  277. m.invert();
  278. m.transformPoint(&point);
  279. // Pass the touch event on.
  280. const Rectangle& bounds = form->getClipBounds();
  281. if (form->getState() == Control::FOCUS ||
  282. (evt == Touch::TOUCH_PRESS &&
  283. point.x >= bounds.x &&
  284. point.x <= bounds.x + bounds.width &&
  285. point.y >= bounds.y &&
  286. point.y <= bounds.y + bounds.height))
  287. {
  288. if (form->touchEvent(evt, point.x - bounds.x, bounds.height - point.y - bounds.y, contactIndex))
  289. {
  290. return true;
  291. }
  292. }
  293. }
  294. }
  295. }
  296. else
  297. {
  298. // Simply compare with the form's bounds.
  299. const Rectangle& bounds = form->getClipBounds();
  300. if (form->getState() == Control::FOCUS ||
  301. (evt == Touch::TOUCH_PRESS &&
  302. x >= bounds.x &&
  303. x <= bounds.x + bounds.width &&
  304. y >= bounds.y &&
  305. y <= bounds.y + bounds.height))
  306. {
  307. // Pass on the event's position relative to the form.
  308. if (form->touchEvent(evt, x - bounds.x, y - bounds.y, contactIndex))
  309. {
  310. return true;
  311. }
  312. }
  313. }
  314. }
  315. }
  316. return false;
  317. }
  318. void Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
  319. {
  320. std::vector<Form*>::const_iterator it;
  321. for (it = __forms.begin(); it < __forms.end(); it++)
  322. {
  323. Form* form = *it;
  324. if (form->isEnabled())
  325. {
  326. form->keyEvent(evt, key);
  327. }
  328. }
  329. }
  330. }