Form.cpp 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124
  1. #include "Base.h"
  2. #include "Form.h"
  3. #include "AbsoluteLayout.h"
  4. #include "FlowLayout.h"
  5. #include "VerticalLayout.h"
  6. #include "Game.h"
  7. #include "Theme.h"
  8. #include "Label.h"
  9. #include "Button.h"
  10. #include "CheckBox.h"
  11. #include "Scene.h"
  12. // Scroll speed when using a DPad -- max scroll speed when using a joystick.
  13. static const float GAMEPAD_SCROLL_SPEED = 500.0f;
  14. // Distance a joystick must be pushed in order to trigger focus-change and/or scrolling.
  15. static const float JOYSTICK_THRESHOLD = 0.75f;
  16. // If the DPad or joystick is held down, this is the initial delay in milliseconds between focus changes.
  17. static const float GAMEPAD_FOCUS_REPEAT_DELAY = 300.0f;
  18. // Shaders used for drawing offscreen quad when form is attached to a node
  19. #define FORM_VSH "res/shaders/sprite.vert"
  20. #define FORM_FSH "res/shaders/sprite.frag"
  21. namespace gameplay
  22. {
  23. static std::vector<Form*> __forms;
  24. static Control* __focusControl = NULL;
  25. static Control* __activeControl[Touch::MAX_TOUCH_POINTS];
  26. static bool __shiftKeyDown = false;
  27. /**
  28. * Static initializer for forms.
  29. * @script{ignore}
  30. */
  31. struct FormInit
  32. {
  33. FormInit()
  34. {
  35. memset(__activeControl, 0, sizeof(__activeControl));
  36. }
  37. };
  38. static FormInit __init;
  39. Form::Form() : _node(NULL), _batched(true)
  40. {
  41. }
  42. Form::~Form()
  43. {
  44. // Remove this Form from the global list.
  45. std::vector<Form*>::iterator it = std::find(__forms.begin(), __forms.end(), this);
  46. if (it != __forms.end())
  47. {
  48. __forms.erase(it);
  49. }
  50. }
  51. Form* Form::create(const char* url)
  52. {
  53. Form* form = new Form();
  54. // Load Form from .form file.
  55. Properties* properties = Properties::create(url);
  56. if (!properties)
  57. {
  58. GP_WARN("Failed to load properties file for Form.");
  59. return NULL;
  60. }
  61. // Check if the Properties is valid and has a valid namespace.
  62. Properties* formProperties = (strlen(properties->getNamespace()) > 0) ? properties : properties->getNextNamespace();
  63. if (!formProperties || !(strcmpnocase(formProperties->getNamespace(), "form") == 0))
  64. {
  65. GP_WARN("Invalid properties file for form: %s", url);
  66. SAFE_DELETE(properties);
  67. return NULL;
  68. }
  69. // Load the form's theme style.
  70. Theme* theme = NULL;
  71. Theme::Style* style = NULL;
  72. if (formProperties->exists("theme"))
  73. {
  74. std::string themeFile;
  75. if (formProperties->getPath("theme", &themeFile))
  76. {
  77. theme = Theme::create(themeFile.c_str());
  78. }
  79. }
  80. if (!theme)
  81. {
  82. theme = Theme::getDefault();
  83. }
  84. if (theme)
  85. {
  86. // Load the form's style
  87. const char* styleName = formProperties->getString("style", "Form");
  88. style = theme->getStyle(styleName);
  89. if (!style)
  90. style = theme->getEmptyStyle();
  91. }
  92. form->_batched = formProperties->getBool("batchingEnabled", true);
  93. // Initialize the form and all of its child controls
  94. form->initialize("Form", style, formProperties);
  95. // Release the theme: its lifetime is controlled by addRef() and release() calls in initialize (above) and ~Control.
  96. if (theme != Theme::getDefault())
  97. {
  98. SAFE_RELEASE(theme);
  99. }
  100. SAFE_DELETE(properties);
  101. return form;
  102. }
  103. Form* Form::create(const char* id, Theme::Style* style, Layout::Type layoutType)
  104. {
  105. Form* form = new Form();
  106. form->_id = id ? id : "";
  107. form->_layout = createLayout(layoutType);
  108. form->initialize("Form", style, NULL);
  109. return form;
  110. }
  111. void Form::initialize(const char* typeName, Theme::Style* style, Properties* properties)
  112. {
  113. Container::initialize(typeName, style, properties);
  114. __forms.push_back(this);
  115. // After creation, update our bounds once so code that runs immediately after form
  116. // creation has access to up-to-date bounds.
  117. if (updateBoundsInternal(Vector2::zero()))
  118. updateBoundsInternal(Vector2::zero());
  119. }
  120. Form* Form::getForm(const char* id)
  121. {
  122. for (size_t i = 0, size = __forms.size(); i < size; ++i)
  123. {
  124. Form* f = __forms[i];
  125. GP_ASSERT(f);
  126. if (strcmp(id, f->getId()) == 0)
  127. {
  128. return f;
  129. }
  130. }
  131. return NULL;
  132. }
  133. Control* Form::getActiveControl(unsigned int touchPoint)
  134. {
  135. if (touchPoint >= Touch::MAX_TOUCH_POINTS)
  136. return NULL;
  137. return __activeControl[touchPoint];
  138. }
  139. Control* Form::getFocusControl()
  140. {
  141. return __focusControl;
  142. }
  143. void Form::clearFocus()
  144. {
  145. setFocusControl(NULL);
  146. }
  147. bool Form::isForm() const
  148. {
  149. return true;
  150. }
  151. void Form::setNode(Node* node)
  152. {
  153. if (_node != node)
  154. {
  155. _node = node;
  156. }
  157. }
  158. static unsigned int nextPowerOfTwo(unsigned int v)
  159. {
  160. if (!((v & (v - 1)) == 0))
  161. {
  162. v--;
  163. v |= v >> 1;
  164. v |= v >> 2;
  165. v |= v >> 4;
  166. v |= v >> 8;
  167. v |= v >> 16;
  168. return v + 1;
  169. }
  170. return v;
  171. }
  172. void Form::update(float elapsedTime)
  173. {
  174. Container::update(elapsedTime);
  175. // Do a two-pass bounds update:
  176. // 1. First pass updates leaf controls
  177. // 2. Second pass updates parent controls that depend on child sizes
  178. if (updateBoundsInternal(Vector2::zero()))
  179. updateBoundsInternal(Vector2::zero());
  180. }
  181. void Form::startBatch(SpriteBatch* batch)
  182. {
  183. // TODO (note: might want to pass a level number/depth here so that batch draw calls can be sorted correctly, such as all text on top)
  184. if (!batch->isStarted())
  185. {
  186. batch->setProjectionMatrix(_projectionMatrix);
  187. batch->start();
  188. if (_batched)
  189. _batches.push_back(batch);
  190. }
  191. }
  192. void Form::finishBatch(SpriteBatch* batch)
  193. {
  194. if (!_batched)
  195. {
  196. batch->finish();
  197. }
  198. }
  199. const Matrix& Form::getProjectionMatrix() const
  200. {
  201. return _projectionMatrix;
  202. }
  203. unsigned int Form::draw()
  204. {
  205. if (!_visible || _absoluteClipBounds.width == 0 || _absoluteClipBounds.height == 0)
  206. return 0;
  207. Game* game = Game::getInstance();
  208. Rectangle viewport = game->getViewport();
  209. // If we're drawing in 2D (i.e. not attached to a node), we need to clear the depth buffer
  210. if (_node)
  211. {
  212. // Drawing in 3D.
  213. // Setup a projection matrix for drawing the form via the node's world transform.
  214. Matrix world(_node->getWorldMatrix());
  215. world.scale(1, -1, 1);
  216. world.translate(0, -_absoluteClipBounds.height, 0);
  217. Matrix::multiply(_node->getViewProjectionMatrix(), world, &_projectionMatrix);
  218. }
  219. else
  220. {
  221. // Drawing in 2D, so we need to clear the depth buffer
  222. Game::getInstance()->clear(Game::CLEAR_DEPTH, Vector4::zero(), 1, 0);
  223. // Setup an ortho matrix that maps to the current viewport
  224. const Rectangle& viewport = Game::getInstance()->getViewport();
  225. Matrix::createOrthographicOffCenter(0, viewport.width, viewport.height, 0, 0, 1, &_projectionMatrix);
  226. }
  227. // Draw the form
  228. unsigned int drawCalls = Container::draw(this, _absoluteClipBounds);
  229. // Flush all batches that were queued during drawing and then empty the batch list
  230. if (_batched)
  231. {
  232. unsigned int batchCount = _batches.size();
  233. for (unsigned int i = 0; i < batchCount; ++i)
  234. _batches[i]->finish();
  235. _batches.clear();
  236. drawCalls = batchCount;
  237. }
  238. return drawCalls;
  239. }
  240. const char* Form::getType() const
  241. {
  242. return "form";
  243. }
  244. bool Form::isBatchingEnabled() const
  245. {
  246. return _batched;
  247. }
  248. void Form::setBatchingEnabled(bool enabled)
  249. {
  250. _batched = enabled;
  251. }
  252. void Form::updateInternal(float elapsedTime)
  253. {
  254. pollGamepads();
  255. for (size_t i = 0, size = __forms.size(); i < size; ++i)
  256. {
  257. Form* form = __forms[i];
  258. if (form && form->isEnabled() && form->isVisible())
  259. {
  260. form->update(elapsedTime);
  261. }
  262. }
  263. }
  264. bool Form::screenToForm(Control* ctrl, int* x, int* y)
  265. {
  266. Form* form = ctrl->getTopLevelForm();
  267. if (form)
  268. {
  269. if (form->_node)
  270. {
  271. // Form is attached to a scene node, so project the screen space point into the
  272. // form's coordinate space (which may be transformed by the node).
  273. Vector3 point;
  274. if (form->projectPoint(*x, *y, &point))
  275. {
  276. *x = (int)point.x;
  277. *y = form->_absoluteBounds.height - (int)point.y;
  278. }
  279. else
  280. {
  281. return false;
  282. }
  283. }
  284. return true;
  285. }
  286. return false;
  287. }
  288. Control* Form::findInputControl(int* x, int* y, bool focus, unsigned int contactIndex)
  289. {
  290. for (int i = (int)__forms.size() - 1; i >= 0; --i)
  291. {
  292. Form* form = __forms[i];
  293. if (!form || !form->isEnabled() || !form->isVisible())
  294. continue;
  295. // Convert to local form coordinates
  296. int formX = *x;
  297. int formY = *y;
  298. if (!screenToForm(form, &formX, &formY))
  299. continue;
  300. // Search for an input control within this form
  301. Control* ctrl = findInputControl(form, formX, formY, focus, contactIndex);
  302. if (ctrl)
  303. {
  304. *x = formX;
  305. *y = formY;
  306. return ctrl;
  307. }
  308. // If the form consumes input events and the point intersects the form,
  309. // don't traverse other forms below it.
  310. if (form->_consumeInputEvents && form->_absoluteClipBounds.contains(formX, formY))
  311. return NULL;
  312. }
  313. return NULL;
  314. }
  315. Control* Form::findInputControl(Control* control, int x, int y, bool focus, unsigned int contactIndex)
  316. {
  317. if (!(control->_visible && control->isEnabled()))
  318. return NULL;
  319. Control* result = NULL;
  320. // Does the passed in control's bounds intersect the specified coordinates - and
  321. // does the control support the specified input state?
  322. if (control->_consumeInputEvents && (!focus || control->canFocus()))
  323. {
  324. if (control->_absoluteClipBounds.contains(x, y))
  325. result = control;
  326. }
  327. // If the control has children, search for an input control inside it that also
  328. // supports the above conditions.
  329. if (control->isContainer())
  330. {
  331. Container* container = static_cast<Container*>(control);
  332. for (unsigned int i = 0, childCount = container->getControlCount(); i < childCount; ++i)
  333. {
  334. Control* ctrl = findInputControl(container->getControl(i), x, y, focus, contactIndex);
  335. if (ctrl)
  336. result = ctrl;
  337. }
  338. }
  339. return result;
  340. }
  341. Control* Form::handlePointerPressRelease(int* x, int* y, bool pressed, unsigned int contactIndex)
  342. {
  343. if (contactIndex >= Touch::MAX_TOUCH_POINTS)
  344. return NULL;
  345. Control* ctrl = NULL;
  346. int newX = *x;
  347. int newY = *y;
  348. if (pressed)
  349. {
  350. // Update active state changes
  351. if ((ctrl = findInputControl(&newX, &newY, false, contactIndex)) != NULL)
  352. {
  353. if (__activeControl[contactIndex] != ctrl || ctrl->_state != ACTIVE)
  354. {
  355. if (__activeControl[contactIndex])
  356. {
  357. __activeControl[contactIndex]->_state = NORMAL;
  358. __activeControl[contactIndex]->setDirty(DIRTY_STATE);
  359. }
  360. __activeControl[contactIndex] = ctrl;
  361. ctrl->_state = ACTIVE;
  362. ctrl->setDirty(DIRTY_STATE);
  363. }
  364. ctrl->notifyListeners(Control::Listener::PRESS);
  365. }
  366. }
  367. else // !pressed
  368. {
  369. Control* active = (__activeControl[contactIndex] && __activeControl[contactIndex]->_state == ACTIVE) ? __activeControl[contactIndex] : NULL;
  370. if (active)
  371. {
  372. active->addRef(); // protect against event-hanlder evil
  373. // Release happened for an active control (that was pressed)
  374. ctrl = active;
  375. // Transform point to form-space
  376. screenToForm(ctrl, &newX, &newY);
  377. // No longer any active control
  378. active->setDirty(DIRTY_STATE);
  379. active->_state = NORMAL;
  380. __activeControl[contactIndex] = NULL;
  381. }
  382. else
  383. {
  384. // Update active and hover control state on release
  385. Control* inputControl = findInputControl(&newX, &newY, false, contactIndex);
  386. if (inputControl)
  387. {
  388. ctrl = inputControl;
  389. if (__activeControl[contactIndex] != ctrl || ctrl->_state != HOVER)
  390. {
  391. if (__activeControl[contactIndex])
  392. {
  393. __activeControl[contactIndex]->_state = NORMAL;
  394. __activeControl[contactIndex]->setDirty(Control::DIRTY_STATE);
  395. }
  396. __activeControl[contactIndex] = ctrl;
  397. ctrl->_state = HOVER;
  398. ctrl->setDirty(DIRTY_STATE);
  399. }
  400. }
  401. else
  402. {
  403. // Control no longer active
  404. if (__activeControl[contactIndex])
  405. {
  406. __activeControl[contactIndex]->setDirty(Control::DIRTY_STATE);
  407. __activeControl[contactIndex]->_state = NORMAL;
  408. __activeControl[contactIndex] = NULL;
  409. }
  410. }
  411. }
  412. if (active)
  413. {
  414. // Fire release event for the previously active control
  415. active->notifyListeners(Control::Listener::RELEASE);
  416. // If the release event was received on the same control that was
  417. // originally pressed, fire a click event
  418. if (active->_absoluteClipBounds.contains(newX, newY))
  419. {
  420. if (!active->_parent || !active->_parent->isScrolling())
  421. {
  422. active->notifyListeners(Control::Listener::CLICK);
  423. }
  424. }
  425. active->release();
  426. }
  427. }
  428. *x = newX;
  429. *y = newY;
  430. return ctrl;
  431. }
  432. Control* Form::handlePointerMove(int* x, int* y, unsigned int contactIndex)
  433. {
  434. if (contactIndex >= Touch::MAX_TOUCH_POINTS)
  435. return NULL;
  436. Control* ctrl = NULL;
  437. // Handle hover control changes on move, only if there is no currently active control
  438. // (i.e. when the mouse or a finger is not down).
  439. if (__activeControl[contactIndex] && __activeControl[contactIndex]->_state == ACTIVE)
  440. {
  441. // Active controls always continue receiving pointer events, even when the pointer
  442. // is not on top of the control.
  443. ctrl = __activeControl[contactIndex];
  444. screenToForm(ctrl, x, y);
  445. }
  446. else
  447. {
  448. ctrl = findInputControl(x, y, false, contactIndex);
  449. if (ctrl)
  450. {
  451. // Update hover control
  452. if (__activeControl[contactIndex] != ctrl || ctrl->_state != HOVER)
  453. {
  454. if (__activeControl[contactIndex])
  455. {
  456. __activeControl[contactIndex]->_state = NORMAL;
  457. __activeControl[contactIndex]->setDirty(DIRTY_STATE);
  458. }
  459. __activeControl[contactIndex] = ctrl;
  460. ctrl->_state = HOVER;
  461. ctrl->setDirty(DIRTY_STATE);
  462. }
  463. }
  464. else
  465. {
  466. // No active/hover control
  467. if (__activeControl[contactIndex])
  468. {
  469. __activeControl[contactIndex]->setDirty(DIRTY_STATE);
  470. __activeControl[contactIndex]->_state = NORMAL;
  471. __activeControl[contactIndex] = NULL;
  472. }
  473. }
  474. }
  475. return ctrl;
  476. }
  477. void Form::verifyRemovedControlState(Control* control)
  478. {
  479. if (__focusControl == control)
  480. {
  481. __focusControl = NULL;
  482. }
  483. if (control->_state == ACTIVE || control->_state == HOVER)
  484. {
  485. for (unsigned int i = 0; i < Touch::MAX_TOUCH_POINTS; ++i)
  486. {
  487. if (__activeControl[i] == control)
  488. {
  489. __activeControl[i] = NULL;
  490. }
  491. }
  492. control->_state = NORMAL;
  493. }
  494. }
  495. // Generic pointer event handler that both touch and mouse events map to.
  496. // Mappings:
  497. // mouse - true for mouse events, false for touch events
  498. // evt - Mouse::MouseEvent or Touch::TouchEvent
  499. // x, y - Point of event
  500. // param - wheelData for mouse events, contactIndex for touch events
  501. bool Form::pointerEventInternal(bool mouse, int evt, int x, int y, int param)
  502. {
  503. // Do not process mouse input when mouse is captured
  504. if (mouse && Game::getInstance()->isMouseCaptured())
  505. return false;
  506. // Is this a press event (TOUCH_PRESS has the same value as MOUSE_PRESS_LEFT_BUTTON)
  507. bool pressEvent = evt == Touch::TOUCH_PRESS || (mouse && (evt == Mouse::MOUSE_PRESS_MIDDLE_BUTTON || evt == Mouse::MOUSE_PRESS_RIGHT_BUTTON));
  508. Control* ctrl = NULL;
  509. int formX = x;
  510. int formY = y;
  511. unsigned int contactIndex = mouse ? 0 : param;
  512. // Note: TOUCH_PRESS and TOUCH_RELEASE have same values as MOUSE_PRESS_LEFT_BUTTON and MOUSE_RELEASE_LEFT_BUTTON
  513. if (evt == Touch::TOUCH_PRESS)
  514. {
  515. ctrl = handlePointerPressRelease(&formX, &formY, true, contactIndex);
  516. }
  517. else if (evt == Touch::TOUCH_RELEASE)
  518. {
  519. ctrl = handlePointerPressRelease(&formX, &formY, false, contactIndex);
  520. }
  521. else if ((mouse && evt == Mouse::MOUSE_MOVE) || (!mouse && evt == Touch::TOUCH_MOVE))
  522. {
  523. ctrl = handlePointerMove(&formX, &formY, contactIndex);
  524. }
  525. // Dispatch input events to all controls that intersect this point
  526. if (ctrl == NULL)
  527. {
  528. formX = x;
  529. formY = y;
  530. ctrl = findInputControl(&formX, &formY, false, contactIndex);
  531. }
  532. if (ctrl)
  533. {
  534. // Handle setting focus for all press events
  535. if (pressEvent)
  536. {
  537. Control* focusControl = ctrl;
  538. while (focusControl && !focusControl->setFocus())
  539. focusControl = focusControl->_parent;
  540. if (focusControl == NULL)
  541. {
  542. // Nothing got focus on this press, so remove current focused control
  543. setFocusControl(NULL);
  544. }
  545. }
  546. // Dispatch the event from the bottom upwards, until a control intersecting the point consumes the event
  547. while (ctrl)
  548. {
  549. int localX = formX - ctrl->_absoluteBounds.x;
  550. int localY = formY - ctrl->_absoluteBounds.y;
  551. if (mouse)
  552. {
  553. if (ctrl->mouseEvent((Mouse::MouseEvent)evt, localX, localY, param))
  554. return true;
  555. // Forward to touch event hanlder if unhandled by mouse handler
  556. switch (evt)
  557. {
  558. case Mouse::MOUSE_PRESS_LEFT_BUTTON:
  559. if (ctrl->touchEvent(Touch::TOUCH_PRESS, localX, localY, 0))
  560. return true;
  561. break;
  562. case Mouse::MOUSE_RELEASE_LEFT_BUTTON:
  563. if (ctrl->touchEvent(Touch::TOUCH_RELEASE, localX, localY, 0))
  564. return true;
  565. break;
  566. case Mouse::MOUSE_MOVE:
  567. if (ctrl->touchEvent(Touch::TOUCH_MOVE, localX, localY, 0))
  568. return true;
  569. break;
  570. }
  571. }
  572. else
  573. {
  574. if (ctrl->touchEvent((Touch::TouchEvent)evt, localX, localY, contactIndex))
  575. return true;
  576. }
  577. // Handle container scrolling
  578. Control* tmp = ctrl;
  579. while (tmp)
  580. {
  581. if (tmp->isContainer())
  582. {
  583. Container* container = static_cast<Container*>(tmp);
  584. if (container->_scroll != SCROLL_NONE)
  585. {
  586. if (mouse)
  587. {
  588. if (container->mouseEventScroll((Mouse::MouseEvent)evt, formX - tmp->_absoluteBounds.x, formY - tmp->_absoluteBounds.y, param))
  589. return true;
  590. }
  591. else
  592. {
  593. if (container->touchEventScroll((Touch::TouchEvent)evt, formX - tmp->_absoluteBounds.x, formY - tmp->_absoluteBounds.y, param))
  594. return true;
  595. }
  596. break; // scrollable parent container found
  597. }
  598. }
  599. tmp = tmp->_parent;
  600. }
  601. // Consume all input events anyways?
  602. if (ctrl->getConsumeInputEvents())
  603. return true;
  604. ctrl = ctrl->getParent();
  605. }
  606. }
  607. else
  608. {
  609. // If this was a press event, remove all focus
  610. if (pressEvent)
  611. {
  612. setFocusControl(NULL);
  613. }
  614. }
  615. return false;
  616. }
  617. bool Form::touchEventInternal(Touch::TouchEvent evt, int x, int y, unsigned int contactIndex)
  618. {
  619. return pointerEventInternal(false, evt, x, y, (int)contactIndex);
  620. }
  621. bool Form::mouseEventInternal(Mouse::MouseEvent evt, int x, int y, int wheelDelta)
  622. {
  623. return pointerEventInternal(true, evt, x, y, wheelDelta);
  624. }
  625. bool Form::keyEventInternal(Keyboard::KeyEvent evt, int key)
  626. {
  627. switch (key)
  628. {
  629. case Keyboard::KEY_ESCAPE:
  630. return false; // ignore escape key presses
  631. case Keyboard::KEY_SHIFT:
  632. if (evt == Keyboard::KEY_PRESS)
  633. __shiftKeyDown = true;
  634. else if (evt == Keyboard::KEY_RELEASE)
  635. __shiftKeyDown = false;
  636. break;
  637. }
  638. // Handle focus changing
  639. if (__focusControl)
  640. {
  641. switch (evt)
  642. {
  643. case Keyboard::KEY_CHAR:
  644. switch (key)
  645. {
  646. case Keyboard::KEY_TAB:
  647. if (__focusControl->_parent)
  648. {
  649. if (__focusControl->_parent->moveFocus(__shiftKeyDown ? Container::PREVIOUS : Container::NEXT))
  650. return true;
  651. }
  652. break;
  653. }
  654. break;
  655. }
  656. }
  657. // Dispatch key events
  658. Control* ctrl = __focusControl;
  659. while (ctrl)
  660. {
  661. if (ctrl->isEnabled() && ctrl->isVisible())
  662. {
  663. if (ctrl->keyEvent(evt, key))
  664. return true;
  665. }
  666. ctrl = ctrl->getParent();
  667. }
  668. return false;
  669. }
  670. void Form::pollGamepads()
  671. {
  672. Game* game = Game::getInstance();
  673. // If no gamepads are connected, return immediately
  674. unsigned int gamepadCount = game->getGamepadCount();
  675. if (gamepadCount == 0)
  676. return;
  677. // For now, always use gamepad zero for controlling the UI.
  678. // Possibly allow the developer to set the active gamepad for UI later.
  679. Gamepad* gamepad = game->getGamepad(0, true);
  680. if (!gamepad)
  681. return;
  682. pollGamepad(gamepad);
  683. }
  684. bool Form::pollGamepad(Gamepad* gamepad)
  685. {
  686. // Get the currently focused control's container for focus management and scrolling
  687. if (!__focusControl)
  688. return false;
  689. // Get parent container
  690. Container* parentContainer = NULL;
  691. if (__focusControl->_parent)
  692. parentContainer = __focusControl->_parent;
  693. // Get scroll container
  694. Container* scrollContainer = NULL;
  695. if (__focusControl->isContainer())
  696. {
  697. scrollContainer = static_cast<Container*>(__focusControl);
  698. if (scrollContainer->_scroll == SCROLL_NONE)
  699. scrollContainer = NULL;
  700. }
  701. if (!scrollContainer && parentContainer && parentContainer->_scroll != SCROLL_NONE)
  702. scrollContainer = parentContainer;
  703. // Static static maintained across function calls
  704. static bool scrolling = false;
  705. static double lastFocusChangeTime = 0;
  706. bool focusPressed = false;
  707. bool stillScrolling = false;
  708. double currentTime = Game::getAbsoluteTime();
  709. double focusChangeElapsedTime = currentTime - lastFocusChangeTime;
  710. // Is a selection button down (i.e. buttons used for UI clicking/interactions)?
  711. bool selectButtonDown = gamepad->isButtonDown(Gamepad::BUTTON_A) || gamepad->isButtonDown(Gamepad::BUTTON_X);
  712. if (!selectButtonDown)
  713. {
  714. // Get values of analog joysticks 1 and 2 (assume left and right analog sticks)
  715. Vector2 joystick;
  716. unsigned int joystickCount = gamepad->getJoystickCount();
  717. gamepad->getJoystickValues(0, &joystick);
  718. if (parentContainer)
  719. {
  720. // The Dpad and left analog stick (i.e. first analog stick when there are two joysticks) controls focus
  721. if (gamepad->isButtonDown(Gamepad::BUTTON_UP) || (joystickCount > 1 && joystick.y > JOYSTICK_THRESHOLD))
  722. {
  723. focusPressed = true;
  724. if (focusChangeElapsedTime > GAMEPAD_FOCUS_REPEAT_DELAY && parentContainer->moveFocus(UP))
  725. {
  726. lastFocusChangeTime = currentTime;
  727. }
  728. }
  729. if (gamepad->isButtonDown(Gamepad::BUTTON_DOWN) || (joystickCount > 1 && joystick.y < -JOYSTICK_THRESHOLD))
  730. {
  731. focusPressed = true;
  732. if (focusChangeElapsedTime > GAMEPAD_FOCUS_REPEAT_DELAY && parentContainer->moveFocus(DOWN))
  733. {
  734. lastFocusChangeTime = currentTime;
  735. }
  736. }
  737. if (gamepad->isButtonDown(Gamepad::BUTTON_LEFT) || (joystickCount > 1 && joystick.x < -JOYSTICK_THRESHOLD))
  738. {
  739. focusPressed = true;
  740. if (focusChangeElapsedTime > GAMEPAD_FOCUS_REPEAT_DELAY && parentContainer->moveFocus(LEFT))
  741. {
  742. lastFocusChangeTime = currentTime;
  743. }
  744. }
  745. if (gamepad->isButtonDown(Gamepad::BUTTON_RIGHT) || (joystickCount > 1 && joystick.x > JOYSTICK_THRESHOLD))
  746. {
  747. focusPressed = true;
  748. if (focusChangeElapsedTime > GAMEPAD_FOCUS_REPEAT_DELAY && parentContainer->moveFocus(RIGHT))
  749. {
  750. lastFocusChangeTime = currentTime;
  751. }
  752. }
  753. }
  754. // The RIGHT analog stick (i.e. second), or ONLY analog stick (when only 1 joystick), is used to scroll.
  755. if (scrollContainer && joystickCount > 0)
  756. {
  757. if (joystickCount > 1)
  758. gamepad->getJoystickValues(1, &joystick);
  759. if (std::fabs(joystick.x) > JOYSTICK_THRESHOLD || std::fabs(joystick.y) > JOYSTICK_THRESHOLD)
  760. {
  761. scrollContainer->startScrolling(GAMEPAD_SCROLL_SPEED * joystick.x, GAMEPAD_SCROLL_SPEED * joystick.y, !scrolling);
  762. scrolling = stillScrolling = true;
  763. }
  764. }
  765. }
  766. if (!focusPressed)
  767. {
  768. // Reset focus repeat
  769. lastFocusChangeTime = 0;
  770. }
  771. if (scrolling && !stillScrolling)
  772. {
  773. scrolling = false;
  774. if (scrollContainer)
  775. scrollContainer->stopScrolling();
  776. }
  777. return focusPressed || scrolling;
  778. }
  779. bool Form::gamepadButtonEventInternal(Gamepad* gamepad)
  780. {
  781. if (!__focusControl)
  782. return false;
  783. bool selectButtonPressed = gamepad->isButtonDown(Gamepad::BUTTON_A) || gamepad->isButtonDown(Gamepad::BUTTON_X);
  784. // Fire press, release and click events to focused controls
  785. if (selectButtonPressed && __focusControl->_state != ACTIVE)
  786. {
  787. if (__activeControl[0])
  788. __activeControl[0]->setDirty(DIRTY_STATE);
  789. __activeControl[0] = __focusControl;
  790. __focusControl->_state = ACTIVE;
  791. __focusControl->notifyListeners(Control::Listener::PRESS);
  792. return true;
  793. }
  794. else if (!selectButtonPressed && __focusControl->_state == ACTIVE)
  795. {
  796. if (__activeControl[0])
  797. __activeControl[0]->setDirty(DIRTY_STATE);
  798. for (unsigned int i = 0; i < Touch::MAX_TOUCH_POINTS; ++i)
  799. {
  800. if (__activeControl[i] == __focusControl)
  801. {
  802. __activeControl[i] = NULL;
  803. }
  804. }
  805. __focusControl->_state = NORMAL;
  806. __focusControl->notifyListeners(Control::Listener::RELEASE);
  807. __focusControl->notifyListeners(Control::Listener::CLICK);
  808. return true;
  809. }
  810. // Dispatch gamepad button events to focused controls (or their parents)
  811. Control* ctrl = __focusControl;
  812. while (ctrl)
  813. {
  814. if (ctrl->isEnabled() && ctrl->isVisible())
  815. {
  816. if (ctrl->gamepadButtonEvent(gamepad))
  817. return true;
  818. }
  819. ctrl = ctrl->getParent();
  820. }
  821. return false;
  822. }
  823. bool Form::gamepadTriggerEventInternal(Gamepad* gamepad, unsigned int index)
  824. {
  825. // Dispatch gamepad trigger events to focused controls (or their parents)
  826. Control* ctrl = __focusControl;
  827. while (ctrl)
  828. {
  829. if (ctrl->isEnabled() && ctrl->isVisible())
  830. {
  831. if (ctrl->gamepadTriggerEvent(gamepad, index))
  832. return true;
  833. }
  834. ctrl = ctrl->getParent();
  835. }
  836. return false;
  837. }
  838. bool Form::gamepadJoystickEventInternal(Gamepad* gamepad, unsigned int index)
  839. {
  840. // Dispatch gamepad joystick events to focused controls (or their parents)
  841. Control* ctrl = __focusControl;
  842. while (ctrl)
  843. {
  844. if (ctrl->isEnabled() && ctrl->isVisible())
  845. {
  846. if (ctrl->gamepadJoystickEvent(gamepad, index))
  847. return true;
  848. }
  849. ctrl = ctrl->getParent();
  850. }
  851. return false;
  852. }
  853. void Form::resizeEventInternal(unsigned int width, unsigned int height)
  854. {
  855. for (size_t i = 0, size = __forms.size(); i < size; ++i)
  856. {
  857. Form* form = __forms[i];
  858. if (form)
  859. {
  860. // Dirty the form
  861. form->setDirty(Control::DIRTY_BOUNDS | Control::DIRTY_STATE);
  862. }
  863. }
  864. }
  865. bool Form::projectPoint(int x, int y, Vector3* point)
  866. {
  867. if (!_node)
  868. return false;
  869. Scene* scene = _node->getScene();
  870. Camera* camera;
  871. if (scene && (camera = scene->getActiveCamera()))
  872. {
  873. // Get info about the form's position.
  874. Matrix m = _node->getWorldMatrix();
  875. Vector3 pointOnPlane(0, 0, 0);
  876. m.transformPoint(&pointOnPlane);
  877. // Unproject point into world space.
  878. Ray ray;
  879. camera->pickRay(Game::getInstance()->getViewport(), x, y, &ray);
  880. // Find the quad's plane. We know its normal is the quad's forward vector.
  881. Vector3 normal = _node->getForwardVectorWorld().normalize();
  882. // To get the plane's distance from the origin, we project a point on the
  883. // plane onto the plane's normal vector.
  884. const float distance = fabs(Vector3::dot(pointOnPlane, normal));
  885. Plane plane(normal, -distance);
  886. // Check for collision with plane.
  887. float collisionDistance = ray.intersects(plane);
  888. if (collisionDistance != Ray::INTERSECTS_NONE)
  889. {
  890. // Multiply the ray's direction vector by collision distance and add that to the ray's origin.
  891. point->set(ray.getOrigin() + collisionDistance*ray.getDirection());
  892. // Project this point into the plane.
  893. m.invert();
  894. m.transformPoint(point);
  895. return true;
  896. }
  897. }
  898. return false;
  899. }
  900. void Form::controlDisabled(Control* control)
  901. {
  902. if (__focusControl && (__focusControl == control || __focusControl->isChild(control)))
  903. {
  904. setFocusControl(NULL);
  905. }
  906. if (control->_state == ACTIVE || control->_state == HOVER)
  907. {
  908. for (unsigned int i = 0; i < Touch::MAX_TOUCH_POINTS; ++i)
  909. {
  910. if (__activeControl[i] == control)
  911. {
  912. __activeControl[i] = NULL;
  913. }
  914. }
  915. }
  916. }
  917. void Form::setFocusControl(Control* control)
  918. {
  919. Control* oldFocus = __focusControl;
  920. __focusControl = control;
  921. // Deactivate the old focus control
  922. if (oldFocus)
  923. {
  924. oldFocus->setDirty(Control::DIRTY_STATE);
  925. oldFocus->notifyListeners(Control::Listener::FOCUS_LOST);
  926. }
  927. // Activate the new focus control
  928. if (__focusControl)
  929. {
  930. __focusControl->setDirty(Control::DIRTY_STATE);
  931. __focusControl->notifyListeners(Control::Listener::FOCUS_GAINED);
  932. // Set the activeControl property of the control's parent container
  933. Container* parent = NULL;
  934. if (__focusControl->_parent)
  935. {
  936. parent = __focusControl->_parent;
  937. parent->_activeControl = __focusControl;
  938. }
  939. // If this control is inside a scrollable container and is not fully visible,
  940. // scroll the container so that it is.
  941. if (parent && parent->_scroll != SCROLL_NONE && !parent->_viewportBounds.isEmpty())
  942. {
  943. const Rectangle& bounds = __focusControl->getBounds();
  944. if (bounds.x < parent->_scrollPosition.x)
  945. {
  946. // Control is to the left of the scrolled viewport.
  947. parent->_scrollPosition.x = -bounds.x;
  948. }
  949. else if (bounds.x + bounds.width > parent->_scrollPosition.x + parent->_viewportBounds.width)
  950. {
  951. // Control is off to the right.
  952. parent->_scrollPosition.x = -(bounds.x + bounds.width - parent->_viewportBounds.width);
  953. }
  954. if (bounds.y < parent->_viewportBounds.y - parent->_scrollPosition.y)
  955. {
  956. // Control is above the viewport.
  957. parent->_scrollPosition.y = -bounds.y;
  958. }
  959. else if (bounds.y + bounds.height > parent->_viewportBounds.height - parent->_scrollPosition.y)
  960. {
  961. // Control is below the viewport.
  962. parent->_scrollPosition.y = -(bounds.y + bounds.height - parent->_viewportBounds.height);
  963. }
  964. }
  965. }
  966. }
  967. }