guiCanvas.cc 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "torqueConfig.h"
  23. #include "console/consoleInternal.h"
  24. #include "debug/profiler.h"
  25. #include "graphics/dgl.h"
  26. #include "platform/event.h"
  27. #include "platform/platform.h"
  28. #include "platform/platformInput.h"
  29. #include "platform/platformVideo.h"
  30. #include "gui/guiTypes.h"
  31. #include "gui/guiControl.h"
  32. #include "gui/guiCanvas.h"
  33. #include "game/gameInterface.h"
  34. #include "guiCanvas_ScriptBinding.h"
  35. extern int _AndroidGetScreenWidth();
  36. extern int _AndroidGetScreenHeight();
  37. IMPLEMENT_CONOBJECT(GuiCanvas);
  38. GuiCanvas *Canvas = NULL;
  39. GuiCanvas::GuiCanvas()
  40. {
  41. #ifdef TORQUE_OS_IOS
  42. mBounds.set(0, 0, IOS_DEFAULT_RESOLUTION_X, IOS_DEFAULT_RESOLUTION_Y);
  43. #elif TORQUE_OS_ANDROID
  44. mBounds.set(0, 0, _AndroidGetScreenWidth(), _AndroidGetScreenHeight());
  45. #else
  46. mBounds.set(0, 0, MIN_RESOLUTION_X, MIN_RESOLUTION_Y);
  47. #endif
  48. mAwake = true;
  49. mPixelsPerMickey = 1.0f;
  50. cursorON = true;
  51. mShowCursor = false;
  52. mUseNativeCursor = true;
  53. lastCursorON = false;
  54. rLastFrameTime = 0.0f;
  55. mMouseCapturedControl = NULL;
  56. mMouseControl = NULL;
  57. mMouseControlClicked = false;
  58. mMouseButtonDown = false;
  59. mMouseRightButtonDown = false;
  60. mMouseMiddleButtonDown = false;
  61. lastCursor = NULL;
  62. lastCursorPt.set(0,0);
  63. cursorPt.set(0,0);
  64. mLastMouseClickCount = 0;
  65. mLastMouseDownTime = 0;
  66. mPrevMouseTime = 0;
  67. defaultCursor = NULL;
  68. mRenderFront = false;
  69. hoverControlStart = Platform::getRealMilliseconds();
  70. hoverControl = NULL;
  71. hoverPosition = getCursorPos();
  72. hoverPositionSet = false;
  73. hoverLeftControlTime = 0;
  74. mLeftMouseLast = false;
  75. mMiddleMouseLast = false;
  76. mRightMouseLast = false;
  77. mDoubleClickWidth = Input::getDoubleClickWidth();
  78. mDoubleClickHeight = Input::getDoubleClickHeight();
  79. mDoubleClickTime = Input::getDoubleClickTime();
  80. /// Background color.
  81. mBackgroundColor.set( 0.0f, 0.0f, 0.0f, 0.0f );
  82. mUseBackgroundColor = true;
  83. }
  84. GuiCanvas::~GuiCanvas()
  85. {
  86. if(Canvas == this)
  87. Canvas = 0;
  88. }
  89. //-----------------------------------------------------------------------------
  90. void GuiCanvas::initPersistFields()
  91. {
  92. // Call Parent.
  93. Parent::initPersistFields();
  94. // Physics.
  95. addField("UseBackgroundColor", TypeBool, Offset(mUseBackgroundColor, GuiCanvas), "" );
  96. addField("BackgroundColor", TypeColorF, Offset(mBackgroundColor, GuiCanvas), "" );
  97. }
  98. //------------------------------------------------------------------------------
  99. void GuiCanvas::setCursor(GuiCursor *curs)
  100. {
  101. defaultCursor = curs;
  102. if(mShowCursor)
  103. {
  104. Input::setCursorState(false);
  105. }
  106. }
  107. void GuiCanvas::setCursorON(bool onOff)
  108. {
  109. cursorON = onOff;
  110. if(!cursorON)
  111. mMouseControl = NULL;
  112. }
  113. bool GuiCanvas::getUseNativeCursor(void)
  114. {
  115. return mUseNativeCursor;
  116. }
  117. void GuiCanvas::useNativeCursor(bool useNative)
  118. {
  119. mUseNativeCursor = useNative;
  120. }
  121. void GuiCanvas::setCursorPos(const Point2I &pt)
  122. {
  123. cursorPt.x = F32(pt.x);
  124. cursorPt.y = F32(pt.y);
  125. Input::setCursorPos( pt.x, pt.y );
  126. }
  127. void GuiCanvas::addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier)
  128. {
  129. if (keyCode > 0 && ctrl)
  130. {
  131. AccKeyMap newMap;
  132. newMap.ctrl = ctrl;
  133. newMap.index = index;
  134. newMap.keyCode = keyCode;
  135. newMap.modifier = modifier;
  136. mAcceleratorMap.push_back(newMap);
  137. }
  138. }
  139. bool GuiCanvas::tabNext(void)
  140. {
  141. GuiControl *ctrl = static_cast<GuiControl *>(last());
  142. if (ctrl)
  143. {
  144. //save the old
  145. GuiControl *oldResponder = mFirstResponder;
  146. GuiControl* newResponder = ctrl->findNextTabable(mFirstResponder);
  147. if ( !newResponder )
  148. newResponder = ctrl->findFirstTabable();
  149. if ( newResponder && newResponder != oldResponder )
  150. {
  151. newResponder->setFirstResponder();
  152. if ( oldResponder )
  153. oldResponder->onLoseFirstResponder();
  154. return true;
  155. }
  156. }
  157. return false;
  158. }
  159. bool GuiCanvas::tabPrev(void)
  160. {
  161. GuiControl *ctrl = static_cast<GuiControl *>(last());
  162. if (ctrl)
  163. {
  164. //save the old
  165. GuiControl *oldResponder = mFirstResponder;
  166. GuiControl* newResponder = ctrl->findPrevTabable(mFirstResponder);
  167. if ( !newResponder )
  168. newResponder = ctrl->findLastTabable();
  169. if ( newResponder && newResponder != oldResponder )
  170. {
  171. newResponder->setFirstResponder();
  172. if ( oldResponder )
  173. oldResponder->onLoseFirstResponder();
  174. return true;
  175. }
  176. }
  177. return false;
  178. }
  179. void GuiCanvas::processScreenTouchEvent(const ScreenTouchEvent *event)
  180. {
  181. //copy the cursor point into the event
  182. mLastEvent.mousePoint.x = S32(event->xPos);
  183. mLastEvent.mousePoint.y = S32(event->yPos);
  184. mLastEvent.eventID = event->touchID;
  185. mLastEvent.mouseClickCount = event->numTouches;
  186. //see if button was pressed
  187. if (event->action == SI_MAKE)
  188. {
  189. U32 curTime = Platform::getVirtualMilliseconds();
  190. mNextMouseTime = curTime + mInitialMouseDelay;
  191. mLastMouseDownTime = curTime;
  192. // mLastEvent.mouseClickCount = mLastMouseClickCount;
  193. rootScreenTouchDown(mLastEvent);
  194. }
  195. else if(event->action == SI_MOVE)
  196. {
  197. rootScreenTouchMove(mLastEvent);
  198. }
  199. //else button was released
  200. else if(event->action == SI_BREAK)
  201. {
  202. mNextMouseTime = 0xFFFFFFFF;
  203. rootScreenTouchUp(mLastEvent);
  204. }
  205. }
  206. void GuiCanvas::processMouseMoveEvent(const MouseMoveEvent *event)
  207. {
  208. if( cursorON )
  209. {
  210. //copy the modifier into the new event
  211. mLastEvent.modifier = event->modifier;
  212. cursorPt.x += ( F32(event->xPos - cursorPt.x) * mPixelsPerMickey);
  213. cursorPt.y += ( F32(event->yPos - cursorPt.y) * mPixelsPerMickey);
  214. // clamp the cursor to the window, or not
  215. if( ! Con::getBoolVariable( "$pref::Gui::noClampTorqueCursorToWindow", true ))
  216. {
  217. cursorPt.x =(F32) getMax(0, getMin((S32)cursorPt.x, mBounds.extent.x - 1));
  218. cursorPt.y = (F32)getMax(0, getMin((S32)cursorPt.y, mBounds.extent.y - 1));
  219. }
  220. mLastEvent.mousePoint.x = S32(cursorPt.x);
  221. mLastEvent.mousePoint.y = S32(cursorPt.y);
  222. mLastEvent.eventID = 0;
  223. Point2F movement = mMouseDownPoint - cursorPt;
  224. if ((mAbs((S32)movement.x) > mDoubleClickWidth) || (mAbs((S32)movement.y) > mDoubleClickHeight))
  225. {
  226. mLeftMouseLast = false;
  227. mMiddleMouseLast = false;
  228. mRightMouseLast = false;
  229. }
  230. if (mMouseButtonDown)
  231. rootMouseDragged(mLastEvent);
  232. else if (mMouseRightButtonDown)
  233. rootRightMouseDragged(mLastEvent);
  234. else if(mMouseMiddleButtonDown)
  235. rootMiddleMouseDragged(mLastEvent);
  236. else
  237. rootMouseMove(mLastEvent);
  238. }
  239. }
  240. bool GuiCanvas::processInputEvent(const InputEvent *event)
  241. {
  242. // First call the general input handler (on the extremely off-chance that it will be handled):
  243. if ( mFirstResponder )
  244. {
  245. if ( mFirstResponder->onInputEvent( *event ) )
  246. return( true );
  247. }
  248. if(event->deviceType == KeyboardDeviceType)
  249. {
  250. mLastEvent.ascii = event->ascii;
  251. mLastEvent.modifier = event->modifier;
  252. mLastEvent.keyCode = (U8)event->objInst;
  253. U32 eventModifier = event->modifier;
  254. if(eventModifier & SI_SHIFT)
  255. eventModifier |= SI_SHIFT;
  256. if(eventModifier & SI_CTRL)
  257. eventModifier |= SI_CTRL;
  258. if(eventModifier & SI_ALT)
  259. eventModifier |= SI_ALT;
  260. if (event->action == SI_MAKE)
  261. {
  262. //see if we should tab next/prev
  263. //see if we should now pass the event to the first responder
  264. if (mFirstResponder)
  265. {
  266. if(mFirstResponder->onKeyDown(mLastEvent))
  267. return true;
  268. }
  269. if ( isCursorON() && ( event->objInst == KEY_TAB ) )
  270. {
  271. if (size() > 0)
  272. {
  273. if (event->modifier & SI_SHIFT)
  274. {
  275. if(tabPrev())
  276. return true;
  277. }
  278. else if (event->modifier == 0)
  279. {
  280. if(tabNext())
  281. return true;
  282. }
  283. }
  284. }
  285. //if not handled, search for an accelerator
  286. for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
  287. {
  288. if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
  289. {
  290. mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
  291. return true;
  292. }
  293. }
  294. }
  295. else if(event->action == SI_BREAK)
  296. {
  297. if(mFirstResponder)
  298. if(mFirstResponder->onKeyUp(mLastEvent))
  299. return true;
  300. //see if there's an accelerator
  301. for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
  302. {
  303. if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
  304. {
  305. mAcceleratorMap[i].ctrl->acceleratorKeyRelease(mAcceleratorMap[i].index);
  306. return true;
  307. }
  308. }
  309. }
  310. else if(event->action == SI_REPEAT)
  311. {
  312. //if not handled, search for an accelerator
  313. for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
  314. {
  315. if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
  316. {
  317. mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
  318. return true;
  319. }
  320. }
  321. if(mFirstResponder)
  322. mFirstResponder->onKeyRepeat(mLastEvent);
  323. return true;
  324. }
  325. }
  326. else if(event->deviceType == MouseDeviceType && cursorON)
  327. {
  328. //copy the modifier into the new event
  329. mLastEvent.modifier = event->modifier;
  330. if(event->objType == SI_XAXIS || event->objType == SI_YAXIS)
  331. {
  332. bool moved = false;
  333. Point2I oldpt((S32)cursorPt.x, (S32)cursorPt.y);
  334. Point2F pt(cursorPt.x, cursorPt.y);
  335. if (event->objType == SI_XAXIS)
  336. {
  337. pt.x += (event->fValues[0] * mPixelsPerMickey);
  338. cursorPt.x = (F32)getMax(0, getMin((S32)pt.x, mBounds.extent.x - 1));
  339. if (oldpt.x != S32(cursorPt.x))
  340. moved = true;
  341. }
  342. else
  343. {
  344. pt.y += (event->fValues[0] * mPixelsPerMickey);
  345. cursorPt.y = (F32)getMax(0, getMin((S32)pt.y, mBounds.extent.y - 1));
  346. if (oldpt.y != S32(cursorPt.y))
  347. moved = true;
  348. }
  349. if (moved)
  350. {
  351. mLastEvent.mousePoint.x = S32(cursorPt.x);
  352. mLastEvent.mousePoint.y = S32(cursorPt.y);
  353. mLastEvent.eventID = 0;
  354. #ifdef TORQUE_ALLOW_JOURNALING
  355. // [tom, 9/8/2006] If we're journaling, we need to update the plat cursor
  356. if(Game->isJournalReading())
  357. Input::setCursorPos((S32)cursorPt.x, (S32)cursorPt.y);
  358. #endif //TORQUE_ALLOW_JOURNALING
  359. if (mMouseButtonDown)
  360. rootMouseDragged(mLastEvent);
  361. else if (mMouseRightButtonDown)
  362. rootRightMouseDragged(mLastEvent);
  363. else if(mMouseMiddleButtonDown)
  364. rootMiddleMouseDragged(mLastEvent);
  365. else
  366. rootMouseMove(mLastEvent);
  367. }
  368. return true;
  369. }
  370. else if ( event->objType == SI_ZAXIS )
  371. {
  372. mLastEvent.mousePoint.x = S32( cursorPt.x );
  373. mLastEvent.mousePoint.y = S32( cursorPt.y );
  374. mLastEvent.eventID = 0;
  375. if ( event->fValues[0] < 0.0f )
  376. rootMouseWheelDown( mLastEvent );
  377. else
  378. rootMouseWheelUp( mLastEvent );
  379. }
  380. else if(event->objType == SI_BUTTON)
  381. {
  382. //copy the cursor point into the event
  383. mLastEvent.mousePoint.x = S32(cursorPt.x);
  384. mLastEvent.mousePoint.y = S32(cursorPt.y);
  385. mLastEvent.eventID = 0;
  386. mMouseDownPoint = cursorPt;
  387. if(event->objInst == KEY_BUTTON0) // left button
  388. {
  389. //see if button was pressed
  390. if (event->action == SI_MAKE)
  391. {
  392. U32 curTime = Platform::getVirtualMilliseconds();
  393. mNextMouseTime = curTime + mInitialMouseDelay;
  394. //if the last button pressed was the left...
  395. if (mLeftMouseLast)
  396. {
  397. //if it was within the double click time count the clicks
  398. if ((S32)curTime - mLastMouseDownTime <= mDoubleClickTime)
  399. mLastMouseClickCount++;
  400. else
  401. mLastMouseClickCount = 1;
  402. }
  403. else
  404. {
  405. mLeftMouseLast = true;
  406. mLastMouseClickCount = 1;
  407. }
  408. mLastMouseDownTime = curTime;
  409. mLastEvent.mouseClickCount = mLastMouseClickCount;
  410. rootMouseDown(mLastEvent);
  411. }
  412. //else button was released
  413. else
  414. {
  415. mNextMouseTime = 0xFFFFFFFF;
  416. rootMouseUp(mLastEvent);
  417. }
  418. return true;
  419. }
  420. else if(event->objInst == KEY_BUTTON1) // right button
  421. {
  422. if(event->action == SI_MAKE)
  423. {
  424. U32 curTime = Platform::getVirtualMilliseconds();
  425. //if the last button pressed was the right...
  426. if (mRightMouseLast)
  427. {
  428. //if it was within the double click time count the clicks
  429. if ((S32)curTime - mLastMouseDownTime <= mDoubleClickTime)
  430. mLastMouseClickCount++;
  431. else
  432. mLastMouseClickCount = 1;
  433. }
  434. else
  435. {
  436. mRightMouseLast = true;
  437. mLastMouseClickCount = 1;
  438. }
  439. mLastMouseDownTime = curTime;
  440. mLastEvent.mouseClickCount = mLastMouseClickCount;
  441. rootRightMouseDown(mLastEvent);
  442. }
  443. else // it was a mouse up
  444. rootRightMouseUp(mLastEvent);
  445. return true;
  446. }
  447. else if(event->objInst == KEY_BUTTON2) // middle button
  448. {
  449. if(event->action == SI_MAKE)
  450. {
  451. U32 curTime = Platform::getVirtualMilliseconds();
  452. //if the last button pressed was the right...
  453. if (mMiddleMouseLast)
  454. {
  455. //if it was within the double click time count the clicks
  456. if ((S32)curTime - mLastMouseDownTime <= mDoubleClickTime)
  457. mLastMouseClickCount++;
  458. else
  459. mLastMouseClickCount = 1;
  460. }
  461. else
  462. {
  463. mMiddleMouseLast = true;
  464. mLastMouseClickCount = 1;
  465. }
  466. mLastMouseDownTime = curTime;
  467. mLastEvent.mouseClickCount = mLastMouseClickCount;
  468. rootMiddleMouseDown(mLastEvent);
  469. }
  470. else // it was a mouse up
  471. rootMiddleMouseUp(mLastEvent);
  472. return true;
  473. }
  474. }
  475. }
  476. return false;
  477. }
  478. void GuiCanvas::rootMouseDown(const GuiEvent &event)
  479. {
  480. mPrevMouseTime = Platform::getVirtualMilliseconds();
  481. mMouseButtonDown = true;
  482. //pass the event to the mouse locked control
  483. if (bool(mMouseCapturedControl))
  484. mMouseCapturedControl->onMouseDown(event);
  485. //else pass it to whoever is underneath the cursor
  486. else
  487. {
  488. iterator i;
  489. i = end();
  490. while (i != begin())
  491. {
  492. i--;
  493. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  494. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  495. //see if the controlHit is a modeless dialog...
  496. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  497. continue;
  498. else
  499. {
  500. controlHit->onMouseDown(event);
  501. break;
  502. }
  503. }
  504. }
  505. if (bool(mMouseControl))
  506. mMouseControlClicked = true;
  507. }
  508. void GuiCanvas::findMouseControl(const GuiEvent &event)
  509. {
  510. if(size() == 0)
  511. {
  512. mMouseControl = NULL;
  513. return;
  514. }
  515. GuiControl *controlHit = findHitControl(event.mousePoint);
  516. if(controlHit != static_cast<GuiControl*>(mMouseControl))
  517. {
  518. if(bool(mMouseControl))
  519. mMouseControl->onMouseLeave(event);
  520. mMouseControl = controlHit;
  521. mMouseControl->onMouseEnter(event);
  522. }
  523. }
  524. //Luma: Some fixes from the forums, Dave Calabrese
  525. //http://www.garagegames.com/community/forums/viewthread/93467/1#comment-669559
  526. void GuiCanvas::rootScreenTouchDown(const GuiEvent &event)
  527. {
  528. mPrevMouseTime = Platform::getVirtualMilliseconds();
  529. mMouseButtonDown = true;
  530. iterator i;
  531. i = end();
  532. while (i != begin())
  533. {
  534. i--;
  535. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  536. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  537. //If the control we hit is not the same one that is locked,
  538. // then unlock the existing control.
  539. if (bool(mMouseCapturedControl))
  540. {
  541. if(mMouseCapturedControl->isMouseLocked())
  542. {
  543. if(mMouseCapturedControl != controlHit)
  544. {
  545. mMouseCapturedControl->onMouseLeave(event);
  546. }
  547. }
  548. }
  549. //see if the controlHit is a modeless dialog...
  550. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  551. continue;
  552. else
  553. {
  554. controlHit->onMouseDown(event);
  555. break;
  556. }
  557. }
  558. if (bool(mMouseControl))
  559. mMouseControlClicked = true;
  560. }
  561. void GuiCanvas::rootScreenTouchUp(const GuiEvent &event)
  562. {
  563. mPrevMouseTime = Platform::getVirtualMilliseconds();
  564. mMouseButtonDown = false;
  565. iterator i;
  566. i = end();
  567. while (i != begin())
  568. {
  569. i--;
  570. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  571. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  572. //see if the controlHit is a modeless dialog...
  573. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  574. continue;
  575. else
  576. {
  577. controlHit->onMouseUp(event);
  578. break;
  579. }
  580. }
  581. }
  582. void GuiCanvas::rootScreenTouchMove(const GuiEvent &event)
  583. {
  584. //pass the event to the mouse locked control
  585. if (bool(mMouseCapturedControl))
  586. {
  587. checkLockMouseMove(event);
  588. if(!mMouseCapturedControl.isNull())
  589. mMouseCapturedControl->onMouseDragged(event);
  590. }
  591. else
  592. {
  593. findMouseControl(event);
  594. if(bool(mMouseControl))
  595. {
  596. mMouseControl->onMouseDragged(event);
  597. }
  598. }
  599. }
  600. void GuiCanvas::refreshMouseControl()
  601. {
  602. GuiEvent evt;
  603. evt.mousePoint.x = S32(cursorPt.x);
  604. evt.mousePoint.y = S32(cursorPt.y);
  605. findMouseControl(evt);
  606. }
  607. void GuiCanvas::rootMouseUp(const GuiEvent &event)
  608. {
  609. mPrevMouseTime = Platform::getVirtualMilliseconds();
  610. mMouseButtonDown = false;
  611. //pass the event to the mouse locked control
  612. if (bool(mMouseCapturedControl))
  613. mMouseCapturedControl->onMouseUp(event);
  614. else
  615. {
  616. findMouseControl(event);
  617. if(bool(mMouseControl))
  618. mMouseControl->onMouseUp(event);
  619. }
  620. }
  621. void GuiCanvas::checkLockMouseMove(const GuiEvent &event)
  622. {
  623. GuiControl *controlHit = findHitControl(event.mousePoint);
  624. if(controlHit != mMouseControl)
  625. {
  626. if(mMouseControl == mMouseCapturedControl)
  627. mMouseCapturedControl->onMouseLeave(event);
  628. else if(controlHit == mMouseCapturedControl)
  629. mMouseCapturedControl->onMouseEnter(event);
  630. mMouseControl = controlHit;
  631. }
  632. }
  633. void GuiCanvas::rootMouseDragged(const GuiEvent &event)
  634. {
  635. //pass the event to the mouse locked control
  636. if (bool(mMouseCapturedControl))
  637. {
  638. checkLockMouseMove(event);
  639. if(!mMouseCapturedControl.isNull())
  640. mMouseCapturedControl->onMouseDragged(event);
  641. //Luma: Mouse dragged calls mouse Moved on iPhone
  642. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID)
  643. mMouseCapturedControl->onMouseMove(event);
  644. #endif //TORQUE_OS_IOS
  645. }
  646. else
  647. {
  648. findMouseControl(event);
  649. if(bool(mMouseControl))
  650. {
  651. mMouseControl->onMouseDragged(event);
  652. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID)
  653. mMouseControl->onMouseMove(event);
  654. #endif //TORQUE_OS_IOS
  655. }
  656. }
  657. }
  658. void GuiCanvas::rootMouseMove(const GuiEvent &event)
  659. {
  660. if(mMouseCapturedControl != NULL)
  661. {
  662. checkLockMouseMove(event);
  663. if(mMouseCapturedControl != NULL)
  664. mMouseCapturedControl->onMouseMove(event);
  665. }
  666. else
  667. {
  668. findMouseControl(event);
  669. if(bool(mMouseControl))
  670. mMouseControl->onMouseMove(event);
  671. }
  672. }
  673. void GuiCanvas::rootRightMouseDown(const GuiEvent &event)
  674. {
  675. mPrevMouseTime = Platform::getVirtualMilliseconds();
  676. mMouseRightButtonDown = true;
  677. if (bool(mMouseCapturedControl))
  678. mMouseCapturedControl->onRightMouseDown(event);
  679. else
  680. {
  681. findMouseControl(event);
  682. if(bool(mMouseControl))
  683. {
  684. mMouseControl->onRightMouseDown(event);
  685. }
  686. }
  687. }
  688. void GuiCanvas::rootRightMouseUp(const GuiEvent &event)
  689. {
  690. mPrevMouseTime = Platform::getVirtualMilliseconds();
  691. mMouseRightButtonDown = false;
  692. if (bool(mMouseCapturedControl))
  693. mMouseCapturedControl->onRightMouseUp(event);
  694. else
  695. {
  696. findMouseControl(event);
  697. if(bool(mMouseControl))
  698. mMouseControl->onRightMouseUp(event);
  699. }
  700. }
  701. void GuiCanvas::rootRightMouseDragged(const GuiEvent &event)
  702. {
  703. mPrevMouseTime = Platform::getVirtualMilliseconds();
  704. if (bool(mMouseCapturedControl))
  705. {
  706. checkLockMouseMove(event);
  707. mMouseCapturedControl->onRightMouseDragged(event);
  708. }
  709. else
  710. {
  711. findMouseControl(event);
  712. if(bool(mMouseControl))
  713. mMouseControl->onRightMouseDragged(event);
  714. }
  715. }
  716. void GuiCanvas::rootMiddleMouseDown(const GuiEvent &event)
  717. {
  718. mPrevMouseTime = Platform::getVirtualMilliseconds();
  719. mMouseMiddleButtonDown = true;
  720. if (bool(mMouseCapturedControl))
  721. mMouseCapturedControl->onMiddleMouseDown(event);
  722. else
  723. {
  724. findMouseControl(event);
  725. if(bool(mMouseControl))
  726. {
  727. mMouseControl->onMiddleMouseDown(event);
  728. }
  729. }
  730. }
  731. void GuiCanvas::rootMiddleMouseUp(const GuiEvent &event)
  732. {
  733. mPrevMouseTime = Platform::getVirtualMilliseconds();
  734. mMouseMiddleButtonDown = false;
  735. if (bool(mMouseCapturedControl))
  736. mMouseCapturedControl->onMiddleMouseUp(event);
  737. else
  738. {
  739. findMouseControl(event);
  740. if(bool(mMouseControl))
  741. mMouseControl->onMiddleMouseUp(event);
  742. }
  743. }
  744. void GuiCanvas::rootMiddleMouseDragged(const GuiEvent &event)
  745. {
  746. mPrevMouseTime = Platform::getVirtualMilliseconds();
  747. if (bool(mMouseCapturedControl))
  748. {
  749. checkLockMouseMove(event);
  750. mMouseCapturedControl->onMiddleMouseDragged(event);
  751. }
  752. else
  753. {
  754. findMouseControl(event);
  755. if(bool(mMouseControl))
  756. mMouseControl->onMiddleMouseDragged(event);
  757. }
  758. }
  759. void GuiCanvas::rootMouseWheelUp(const GuiEvent &event)
  760. {
  761. if (bool(mMouseCapturedControl))
  762. mMouseCapturedControl->onMouseWheelUp(event);
  763. else
  764. {
  765. findMouseControl(event);
  766. if (bool(mMouseControl))
  767. mMouseControl->onMouseWheelUp(event);
  768. }
  769. }
  770. void GuiCanvas::rootMouseWheelDown(const GuiEvent &event)
  771. {
  772. if (bool(mMouseCapturedControl))
  773. mMouseCapturedControl->onMouseWheelDown(event);
  774. else
  775. {
  776. findMouseControl(event);
  777. if (bool(mMouseControl))
  778. mMouseControl->onMouseWheelDown(event);
  779. }
  780. }
  781. void GuiCanvas::setContentControl(GuiControl *gui)
  782. {
  783. if(!gui)
  784. return;
  785. // If we're setting the same content, don't do anything
  786. if( gui == at(0) )
  787. return;
  788. //remove all dialogs on layer 0
  789. U32 index = 0;
  790. while ((U32)size() > index)
  791. {
  792. GuiControl *ctrl = static_cast<GuiControl*>((*this)[index]);
  793. if (ctrl == gui || ctrl->mLayer != 0)
  794. index++;
  795. removeObject(ctrl);
  796. Sim::getGuiGroup()->addObject(ctrl);
  797. }
  798. // lose the first responder from the old GUI
  799. GuiControl* responder = gui->findFirstTabable();
  800. if(responder)
  801. responder->setFirstResponder();
  802. //add the gui to the front
  803. if(!size() || gui != (*this)[0])
  804. {
  805. // automatically wakes objects in GuiControl::onWake
  806. addObject(gui);
  807. if (size() >= 2)
  808. reOrder(gui, *begin());
  809. }
  810. //refresh the entire gui
  811. resetUpdateRegions();
  812. //rebuild the accelerator map
  813. mAcceleratorMap.clear();
  814. for(iterator i = end(); i != begin() ; )
  815. {
  816. i--;
  817. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  818. ctrl->buildAcceleratorMap();
  819. if (ctrl->mProfile->mModal)
  820. break;
  821. }
  822. refreshMouseControl();
  823. // Force the canvas to update the sizing of the new content control
  824. maintainSizing();
  825. }
  826. GuiControl *GuiCanvas::getContentControl()
  827. {
  828. if(size() > 0)
  829. return (GuiControl *) first();
  830. return NULL;
  831. }
  832. void GuiCanvas::pushDialogControl(GuiControl *gui, S32 layer)
  833. {
  834. //add the gui
  835. gui->mLayer = layer;
  836. // GuiControl::addObject wakes the object
  837. addObject(gui);
  838. //reorder it to the correct layer
  839. iterator i;
  840. for (i = begin(); i != end(); i++)
  841. {
  842. GuiControl *ctrl = static_cast<GuiControl*>(*i);
  843. if (ctrl->mLayer > gui->mLayer)
  844. {
  845. reOrder(gui, ctrl);
  846. break;
  847. }
  848. }
  849. //call the dialog push method
  850. gui->onDialogPush();
  851. //find the top most dialog
  852. //find the first responder
  853. GuiControl* responder = gui->findFirstTabable();
  854. if(responder)
  855. responder->setFirstResponder();
  856. // call the 'onWake' method?
  857. //if(wakedGui)
  858. // Con::executef(gui, 1, "onWake");
  859. //refresh the entire gui
  860. resetUpdateRegions();
  861. //rebuild the accelerator map
  862. mAcceleratorMap.clear();
  863. if (size() > 0)
  864. {
  865. GuiControl *ctrl = static_cast<GuiControl*>(last());
  866. ctrl->buildAcceleratorMap();
  867. }
  868. refreshMouseControl();
  869. if(gui->mProfile && gui->mProfile->mModal)
  870. {
  871. Input::pushCursor(CursorManager::curArrow);
  872. }
  873. }
  874. void GuiCanvas::popDialogControl(GuiControl *gui)
  875. {
  876. if (size() < 1)
  877. return;
  878. //first, find the dialog, and call the "onDialogPop()" method
  879. GuiControl *ctrl = NULL;
  880. if (gui)
  881. {
  882. //*** DAW: For modal dialogs, reset the mouse cursor and enable the appropriate platform menus
  883. if(gui->mProfile && gui->mProfile->mModal)
  884. {
  885. Input::popCursor();
  886. }
  887. //make sure the gui really exists on the stack
  888. iterator i;
  889. bool found = false;
  890. for(i = begin(); i != end(); i++)
  891. {
  892. GuiControl *check = static_cast<GuiControl *>(*i);
  893. if (check == gui)
  894. {
  895. ctrl = check;
  896. found = true;
  897. }
  898. }
  899. if (! found)
  900. return;
  901. }
  902. else
  903. ctrl = static_cast<GuiControl*>(last());
  904. //call the "on pop" function
  905. ctrl->onDialogPop();
  906. // sleep the object
  907. //now pop the last child (will sleep if awake)
  908. removeObject(ctrl);
  909. // Save the old responder:
  910. Sim::getGuiGroup()->addObject(ctrl);
  911. if (size() > 0)
  912. {
  913. GuiControl *ctrl = static_cast<GuiControl *>(last());
  914. if(ctrl->mFirstResponder)
  915. ctrl->mFirstResponder->setFirstResponder();
  916. }
  917. else
  918. {
  919. setFirstResponder(NULL);
  920. }
  921. //refresh the entire gui
  922. resetUpdateRegions();
  923. //rebuild the accelerator map
  924. mAcceleratorMap.clear();
  925. if (size() > 0)
  926. {
  927. GuiControl *ctrl = static_cast<GuiControl*>(last());
  928. ctrl->buildAcceleratorMap();
  929. }
  930. refreshMouseControl();
  931. }
  932. void GuiCanvas::popDialogControl(S32 layer)
  933. {
  934. if (size() < 1)
  935. return;
  936. GuiControl *ctrl = NULL;
  937. iterator i = end(); // find in z order (last to first)
  938. while (i != begin())
  939. {
  940. i--;
  941. ctrl = static_cast<GuiControl*>(*i);
  942. if (ctrl->mLayer == layer)
  943. break;
  944. }
  945. if (ctrl)
  946. popDialogControl(ctrl);
  947. }
  948. void GuiCanvas::mouseLock(GuiControl *lockingControl)
  949. {
  950. if (bool(mMouseCapturedControl))
  951. return;
  952. mMouseCapturedControl = lockingControl;
  953. if(mMouseControl && mMouseControl != mMouseCapturedControl)
  954. {
  955. GuiEvent evt;
  956. evt.mousePoint.x = S32(cursorPt.x);
  957. evt.mousePoint.y = S32(cursorPt.y);
  958. mMouseControl->onMouseLeave(evt);
  959. }
  960. }
  961. void GuiCanvas::mouseUnlock(GuiControl *lockingControl)
  962. {
  963. if (static_cast<GuiControl*>(mMouseCapturedControl) != lockingControl)
  964. return;
  965. GuiEvent evt;
  966. evt.mousePoint.x = S32(cursorPt.x);
  967. evt.mousePoint.y = S32(cursorPt.y);
  968. GuiControl * controlHit = findHitControl(evt.mousePoint);
  969. if(controlHit != mMouseCapturedControl)
  970. {
  971. mMouseControl = controlHit;
  972. mMouseControlClicked = false;
  973. if(bool(mMouseControl))
  974. mMouseControl->onMouseEnter(evt);
  975. }
  976. mMouseCapturedControl = NULL;
  977. }
  978. void GuiCanvas::paint()
  979. {
  980. resetUpdateRegions();
  981. // inhibit explicit refreshes in the case we're swapped out
  982. if (TextureManager::mDGLRender)
  983. renderFrame(false);
  984. }
  985. void GuiCanvas::maintainSizing()
  986. {
  987. Point2I size = Platform::getWindowSize();
  988. if(size.x == 0 || size.y == 0)
  989. return;
  990. RectI screenRect(0, 0, size.x, size.y);
  991. mBounds = screenRect;
  992. //all bottom level controls should be the same dimensions as the canvas
  993. //this is necessary for passing mouse events accurately
  994. iterator i;
  995. for (i = begin(); i != end(); i++)
  996. {
  997. AssertFatal(static_cast<GuiControl*>((*i))->isAwake(), "GuiCanvas::renderFrame: ctrl is not awake");
  998. GuiControl *ctrl = static_cast<GuiControl*>(*i);
  999. Point2I ext = ctrl->getExtent();
  1000. Point2I pos = ctrl->getPosition();
  1001. if(pos != screenRect.point || ext != screenRect.extent)
  1002. {
  1003. ctrl->resize(screenRect.point, screenRect.extent);
  1004. resetUpdateRegions();
  1005. }
  1006. }
  1007. }
  1008. void GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */)
  1009. {
  1010. PROFILE_START(CanvasPreRender);
  1011. #if !defined TORQUE_OS_IOS && !defined TORQUE_OS_ANDROID && !defined TORQUE_OS_EMSCRIPTEN
  1012. if(mRenderFront)
  1013. glDrawBuffer(GL_FRONT);
  1014. else
  1015. glDrawBuffer(GL_BACK);
  1016. #endif
  1017. // Make sure the root control is the size of the canvas.
  1018. Point2I size = Platform::getWindowSize();
  1019. if(size.x == 0 || size.y == 0)
  1020. {
  1021. //Luma: Fixed missing PROFILE_END()
  1022. PROFILE_END();
  1023. return;
  1024. }
  1025. RectI screenRect(0, 0, size.x, size.y);
  1026. maintainSizing();
  1027. //preRender (recursive) all controls
  1028. preRender();
  1029. PROFILE_END();
  1030. if(preRenderOnly)
  1031. return;
  1032. // for now, just always reset the update regions - this is a
  1033. // fix for FSAA on ATI cards
  1034. resetUpdateRegions();
  1035. // Moved this below object integration for performance reasons. -JDD
  1036. // // finish the gl render so we don't get too far ahead of ourselves
  1037. //#if defined(TORQUE_OS_WIN32)
  1038. // PROFILE_START(glFinish);
  1039. // glFinish();
  1040. // PROFILE_END();
  1041. //#endif
  1042. //draw the mouse, but not using tags...
  1043. PROFILE_START(CanvasRenderControls);
  1044. GuiCursor *mouseCursor = NULL;
  1045. bool cursorVisible = true;
  1046. if(bool(mMouseCapturedControl))
  1047. mMouseCapturedControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
  1048. else if(bool(mMouseControl))
  1049. mMouseControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
  1050. Point2I cursorPos((S32)cursorPt.x, (S32)cursorPt.y);
  1051. if(!mouseCursor)
  1052. mouseCursor = defaultCursor;
  1053. if(lastCursorON && lastCursor)
  1054. {
  1055. Point2I spot = lastCursor->getHotSpot();
  1056. Point2I cext = lastCursor->getExtent();
  1057. Point2I pos = lastCursorPt - spot;
  1058. addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
  1059. }
  1060. if(cursorVisible && mouseCursor)
  1061. {
  1062. Point2I spot = mouseCursor->getHotSpot();
  1063. Point2I cext = mouseCursor->getExtent();
  1064. Point2I pos = cursorPos - spot;
  1065. addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
  1066. }
  1067. lastCursorON = cursorVisible;
  1068. lastCursor = mouseCursor;
  1069. lastCursorPt = cursorPos;
  1070. RectI updateUnion;
  1071. buildUpdateUnion(&updateUnion);
  1072. if (updateUnion.intersect(screenRect))
  1073. {
  1074. // Clear the background color if requested.
  1075. if ( mUseBackgroundColor )
  1076. {
  1077. glClearColor( mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha );
  1078. glClear(GL_COLOR_BUFFER_BIT);
  1079. }
  1080. //render the dialogs
  1081. iterator i;
  1082. for(i = begin(); i != end(); i++)
  1083. {
  1084. GuiControl *contentCtrl = static_cast<GuiControl*>(*i);
  1085. dglSetClipRect(updateUnion);
  1086. glDisable( GL_CULL_FACE );
  1087. contentCtrl->onRender(contentCtrl->getPosition(), updateUnion);
  1088. }
  1089. // Tooltip resource
  1090. if(bool(mMouseControl))
  1091. {
  1092. U32 curTime = Platform::getRealMilliseconds();
  1093. if(hoverControl == mMouseControl)
  1094. {
  1095. if(hoverPositionSet || (curTime - hoverControlStart) >= (U32)hoverControl->mTipHoverTime || (curTime - hoverLeftControlTime) <= (U32)hoverControl->mTipHoverTime)
  1096. {
  1097. // MM: Controls whether the tooltip tracks the mouse cursor or not.
  1098. #if 0
  1099. if(!hoverPositionSet)
  1100. {
  1101. hoverPosition = cursorPos;
  1102. }
  1103. #else
  1104. hoverPosition = cursorPos;
  1105. #endif
  1106. hoverPositionSet = mMouseControl->renderTooltip(hoverPosition);
  1107. }
  1108. } else
  1109. {
  1110. if(hoverPositionSet)
  1111. {
  1112. hoverLeftControlTime = curTime;
  1113. hoverPositionSet = false;
  1114. }
  1115. hoverControl = mMouseControl;
  1116. hoverControlStart = curTime;
  1117. }
  1118. }
  1119. //end tooltip
  1120. dglSetClipRect(updateUnion);
  1121. //temp draw the mouse
  1122. if (cursorON && mShowCursor && !mouseCursor && Canvas->getUseNativeCursor())
  1123. {
  1124. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID) || defined(TORQUE_OS_EMSCRIPTEN)
  1125. glColor4ub(255, 0, 0, 255);
  1126. GLfloat vertices[] = {
  1127. (GLfloat)(cursorPt.x),(GLfloat)(cursorPt.y),
  1128. (GLfloat)(cursorPt.x + 2),(GLfloat)(cursorPt.y),
  1129. (GLfloat)(cursorPt.x + 2),(GLfloat)(cursorPt.y + 2),
  1130. (GLfloat)(cursorPt.x),(GLfloat)(cursorPt.y + 2),
  1131. };
  1132. glEnableClientState(GL_VERTEX_ARRAY);
  1133. glVertexPointer(2, GL_FLOAT, 0, vertices);
  1134. glDrawArrays(GL_LINE_LOOP, 0, 4);
  1135. #else
  1136. glColor4ub(255, 0, 0, 255);
  1137. glRecti((S32)cursorPt.x, (S32)cursorPt.y, (S32)(cursorPt.x + 2), (S32)(cursorPt.y + 2));
  1138. #endif
  1139. }
  1140. //DEBUG
  1141. //draw the help ctrl
  1142. //if (helpCtrl)
  1143. //{
  1144. // helpCtrl->render(srf);
  1145. //}
  1146. if (cursorON && mouseCursor && mShowCursor)
  1147. {
  1148. Point2I pos((S32)cursorPt.x, (S32)cursorPt.y);
  1149. Point2I spot = mouseCursor->getHotSpot();
  1150. pos -= spot;
  1151. mouseCursor->render(pos);
  1152. }
  1153. }
  1154. PROFILE_END();
  1155. if( bufferSwap )
  1156. swapBuffers();
  1157. //#if defined(TORQUE_OS_WIN32)
  1158. // PROFILE_START(glFinish);
  1159. // glFinish(); // This was changed to work with the D3D layer -pw
  1160. // PROFILE_END();
  1161. //#endif
  1162. }
  1163. void GuiCanvas::swapBuffers()
  1164. {
  1165. PROFILE_START(SwapBuffers);
  1166. //flip the surface
  1167. if(!mRenderFront)
  1168. Video::swapBuffers();
  1169. PROFILE_END();
  1170. }
  1171. void GuiCanvas::buildUpdateUnion(RectI *updateUnion)
  1172. {
  1173. *updateUnion = mOldUpdateRects[0];
  1174. //the update region should encompass the oldUpdateRects, and the curUpdateRect
  1175. Point2I upperL;
  1176. Point2I lowerR;
  1177. upperL.x = getMin(mOldUpdateRects[0].point.x, mOldUpdateRects[1].point.x);
  1178. upperL.x = getMin(upperL.x, mCurUpdateRect.point.x);
  1179. upperL.y = getMin(mOldUpdateRects[0].point.y, mOldUpdateRects[1].point.y);
  1180. upperL.y = getMin(upperL.y, mCurUpdateRect.point.y);
  1181. lowerR.x = getMax(mOldUpdateRects[0].point.x + mOldUpdateRects[0].extent.x, mOldUpdateRects[1].point.x + mOldUpdateRects[1].extent.x);
  1182. lowerR.x = getMax(lowerR.x, mCurUpdateRect.point.x + mCurUpdateRect.extent.x);
  1183. lowerR.y = getMax(mOldUpdateRects[0].point.y + mOldUpdateRects[0].extent.y, mOldUpdateRects[1].point.y + mOldUpdateRects[1].extent.y);
  1184. lowerR.y = getMax(lowerR.y, mCurUpdateRect.point.y + mCurUpdateRect.extent.y);
  1185. updateUnion->point = upperL;
  1186. updateUnion->extent = lowerR - upperL;
  1187. //shift the oldUpdateRects
  1188. mOldUpdateRects[0] = mOldUpdateRects[1];
  1189. mOldUpdateRects[1] = mCurUpdateRect;
  1190. mCurUpdateRect.point.set(0,0);
  1191. mCurUpdateRect.extent.set(0,0);
  1192. }
  1193. void GuiCanvas::addUpdateRegion(Point2I pos, Point2I ext)
  1194. {
  1195. if(mCurUpdateRect.extent.x == 0)
  1196. {
  1197. mCurUpdateRect.point = pos;
  1198. mCurUpdateRect.extent = ext;
  1199. }
  1200. else
  1201. {
  1202. Point2I upperL;
  1203. upperL.x = getMin(mCurUpdateRect.point.x, pos.x);
  1204. upperL.y = getMin(mCurUpdateRect.point.y, pos.y);
  1205. Point2I lowerR;
  1206. lowerR.x = getMax(mCurUpdateRect.point.x + mCurUpdateRect.extent.x, pos.x + ext.x);
  1207. lowerR.y = getMax(mCurUpdateRect.point.y + mCurUpdateRect.extent.y, pos.y + ext.y);
  1208. mCurUpdateRect.point = upperL;
  1209. mCurUpdateRect.extent = lowerR - upperL;
  1210. }
  1211. }
  1212. void GuiCanvas::resetUpdateRegions()
  1213. {
  1214. //DEBUG - get surface width and height
  1215. mOldUpdateRects[0].set(mBounds.point, mBounds.extent);
  1216. mOldUpdateRects[1] = mOldUpdateRects[0];
  1217. mCurUpdateRect = mOldUpdateRects[0];
  1218. }
  1219. void GuiCanvas::setFirstResponder( GuiControl* newResponder )
  1220. {
  1221. GuiControl* oldResponder = mFirstResponder;
  1222. Parent::setFirstResponder( newResponder );
  1223. if ( oldResponder && ( oldResponder != mFirstResponder ) )
  1224. oldResponder->onLoseFirstResponder();
  1225. }