Form.cpp 13 KB

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