guiCanvas.cc 40 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438
  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. {
  520. mMouseControl->onMouseLeave(event);
  521. hoverControlStart = Platform::getRealMilliseconds();
  522. hoverPositionSet = false;
  523. }
  524. mMouseControl = controlHit;
  525. mMouseControl->onMouseEnter(event);
  526. }
  527. }
  528. //Luma: Some fixes from the forums, Dave Calabrese
  529. //http://www.garagegames.com/community/forums/viewthread/93467/1#comment-669559
  530. void GuiCanvas::rootScreenTouchDown(const GuiEvent &event)
  531. {
  532. mPrevMouseTime = Platform::getVirtualMilliseconds();
  533. mMouseButtonDown = true;
  534. iterator i;
  535. i = end();
  536. while (i != begin())
  537. {
  538. i--;
  539. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  540. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  541. //If the control we hit is not the same one that is locked,
  542. // then unlock the existing control.
  543. if (bool(mMouseCapturedControl))
  544. {
  545. if(mMouseCapturedControl->isMouseLocked())
  546. {
  547. if(mMouseCapturedControl != controlHit)
  548. {
  549. mMouseCapturedControl->onMouseLeave(event);
  550. }
  551. }
  552. }
  553. //see if the controlHit is a modeless dialog...
  554. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  555. continue;
  556. else
  557. {
  558. controlHit->onMouseDown(event);
  559. break;
  560. }
  561. }
  562. if (bool(mMouseControl))
  563. mMouseControlClicked = true;
  564. }
  565. void GuiCanvas::rootScreenTouchUp(const GuiEvent &event)
  566. {
  567. mPrevMouseTime = Platform::getVirtualMilliseconds();
  568. mMouseButtonDown = false;
  569. iterator i;
  570. i = end();
  571. while (i != begin())
  572. {
  573. i--;
  574. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  575. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  576. //see if the controlHit is a modeless dialog...
  577. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  578. continue;
  579. else
  580. {
  581. controlHit->onMouseUp(event);
  582. break;
  583. }
  584. }
  585. }
  586. void GuiCanvas::rootScreenTouchMove(const GuiEvent &event)
  587. {
  588. //pass the event to the mouse locked control
  589. if (bool(mMouseCapturedControl))
  590. {
  591. checkLockMouseMove(event);
  592. if(!mMouseCapturedControl.isNull())
  593. mMouseCapturedControl->onMouseDragged(event);
  594. }
  595. else
  596. {
  597. findMouseControl(event);
  598. if(bool(mMouseControl))
  599. {
  600. mMouseControl->onMouseDragged(event);
  601. }
  602. }
  603. }
  604. void GuiCanvas::refreshMouseControl()
  605. {
  606. GuiEvent evt;
  607. evt.mousePoint.x = S32(cursorPt.x);
  608. evt.mousePoint.y = S32(cursorPt.y);
  609. findMouseControl(evt);
  610. }
  611. void GuiCanvas::rootMouseUp(const GuiEvent &event)
  612. {
  613. mPrevMouseTime = Platform::getVirtualMilliseconds();
  614. mMouseButtonDown = false;
  615. //pass the event to the mouse locked control
  616. if (bool(mMouseCapturedControl))
  617. mMouseCapturedControl->onMouseUp(event);
  618. else
  619. {
  620. findMouseControl(event);
  621. if(bool(mMouseControl))
  622. mMouseControl->onMouseUp(event);
  623. }
  624. }
  625. void GuiCanvas::checkLockMouseMove(const GuiEvent &event)
  626. {
  627. GuiControl *controlHit = findHitControl(event.mousePoint);
  628. if(controlHit != mMouseControl)
  629. {
  630. if(mMouseControl == mMouseCapturedControl)
  631. mMouseCapturedControl->onMouseLeave(event);
  632. else if(controlHit == mMouseCapturedControl)
  633. mMouseCapturedControl->onMouseEnter(event);
  634. mMouseControl = controlHit;
  635. }
  636. }
  637. void GuiCanvas::rootMouseDragged(const GuiEvent &event)
  638. {
  639. //pass the event to the mouse locked control
  640. if (bool(mMouseCapturedControl))
  641. {
  642. checkLockMouseMove(event);
  643. if(!mMouseCapturedControl.isNull())
  644. mMouseCapturedControl->onMouseDragged(event);
  645. //Luma: Mouse dragged calls mouse Moved on iPhone
  646. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID)
  647. mMouseCapturedControl->onMouseMove(event);
  648. #endif //TORQUE_OS_IOS
  649. }
  650. else
  651. {
  652. findMouseControl(event);
  653. if(bool(mMouseControl))
  654. {
  655. mMouseControl->onMouseDragged(event);
  656. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID)
  657. mMouseControl->onMouseMove(event);
  658. #endif //TORQUE_OS_IOS
  659. }
  660. }
  661. }
  662. void GuiCanvas::rootMouseMove(const GuiEvent &event)
  663. {
  664. if(mMouseCapturedControl != NULL)
  665. {
  666. checkLockMouseMove(event);
  667. if(mMouseCapturedControl != NULL)
  668. mMouseCapturedControl->onMouseMove(event);
  669. }
  670. else
  671. {
  672. findMouseControl(event);
  673. if(bool(mMouseControl))
  674. mMouseControl->onMouseMove(event);
  675. }
  676. }
  677. void GuiCanvas::rootRightMouseDown(const GuiEvent &event)
  678. {
  679. mPrevMouseTime = Platform::getVirtualMilliseconds();
  680. mMouseRightButtonDown = true;
  681. if (bool(mMouseCapturedControl))
  682. mMouseCapturedControl->onRightMouseDown(event);
  683. else
  684. {
  685. findMouseControl(event);
  686. if(bool(mMouseControl))
  687. {
  688. mMouseControl->onRightMouseDown(event);
  689. }
  690. }
  691. }
  692. void GuiCanvas::rootRightMouseUp(const GuiEvent &event)
  693. {
  694. mPrevMouseTime = Platform::getVirtualMilliseconds();
  695. mMouseRightButtonDown = false;
  696. if (bool(mMouseCapturedControl))
  697. mMouseCapturedControl->onRightMouseUp(event);
  698. else
  699. {
  700. findMouseControl(event);
  701. if(bool(mMouseControl))
  702. mMouseControl->onRightMouseUp(event);
  703. }
  704. }
  705. void GuiCanvas::rootRightMouseDragged(const GuiEvent &event)
  706. {
  707. mPrevMouseTime = Platform::getVirtualMilliseconds();
  708. if (bool(mMouseCapturedControl))
  709. {
  710. checkLockMouseMove(event);
  711. mMouseCapturedControl->onRightMouseDragged(event);
  712. }
  713. else
  714. {
  715. findMouseControl(event);
  716. if(bool(mMouseControl))
  717. mMouseControl->onRightMouseDragged(event);
  718. }
  719. }
  720. void GuiCanvas::rootMiddleMouseDown(const GuiEvent &event)
  721. {
  722. mPrevMouseTime = Platform::getVirtualMilliseconds();
  723. mMouseMiddleButtonDown = true;
  724. if (bool(mMouseCapturedControl))
  725. mMouseCapturedControl->onMiddleMouseDown(event);
  726. else
  727. {
  728. findMouseControl(event);
  729. if(bool(mMouseControl))
  730. {
  731. mMouseControl->onMiddleMouseDown(event);
  732. }
  733. }
  734. }
  735. void GuiCanvas::rootMiddleMouseUp(const GuiEvent &event)
  736. {
  737. mPrevMouseTime = Platform::getVirtualMilliseconds();
  738. mMouseMiddleButtonDown = false;
  739. if (bool(mMouseCapturedControl))
  740. mMouseCapturedControl->onMiddleMouseUp(event);
  741. else
  742. {
  743. findMouseControl(event);
  744. if(bool(mMouseControl))
  745. mMouseControl->onMiddleMouseUp(event);
  746. }
  747. }
  748. void GuiCanvas::rootMiddleMouseDragged(const GuiEvent &event)
  749. {
  750. mPrevMouseTime = Platform::getVirtualMilliseconds();
  751. if (bool(mMouseCapturedControl))
  752. {
  753. checkLockMouseMove(event);
  754. mMouseCapturedControl->onMiddleMouseDragged(event);
  755. }
  756. else
  757. {
  758. findMouseControl(event);
  759. if(bool(mMouseControl))
  760. mMouseControl->onMiddleMouseDragged(event);
  761. }
  762. }
  763. void GuiCanvas::rootMouseWheelUp(const GuiEvent &event)
  764. {
  765. if (bool(mMouseCapturedControl))
  766. mMouseCapturedControl->onMouseWheelUp(event);
  767. else
  768. {
  769. findMouseControl(event);
  770. if (bool(mMouseControl))
  771. mMouseControl->onMouseWheelUp(event);
  772. }
  773. }
  774. void GuiCanvas::rootMouseWheelDown(const GuiEvent &event)
  775. {
  776. if (bool(mMouseCapturedControl))
  777. mMouseCapturedControl->onMouseWheelDown(event);
  778. else
  779. {
  780. findMouseControl(event);
  781. if (bool(mMouseControl))
  782. mMouseControl->onMouseWheelDown(event);
  783. }
  784. }
  785. void GuiCanvas::setContentControl(GuiControl *gui)
  786. {
  787. if(!gui)
  788. return;
  789. // If we're setting the same content, don't do anything
  790. if( gui == at(0) )
  791. return;
  792. //remove all dialogs on layer 0
  793. U32 index = 0;
  794. while ((U32)size() > index)
  795. {
  796. GuiControl *ctrl = static_cast<GuiControl*>((*this)[index]);
  797. if (ctrl == gui || ctrl->mLayer != 0)
  798. index++;
  799. removeObject(ctrl);
  800. Sim::getGuiGroup()->addObject(ctrl);
  801. }
  802. // lose the first responder from the old GUI
  803. GuiControl* responder = gui->findFirstTabable();
  804. if(responder)
  805. responder->setFirstResponder();
  806. //add the gui to the front
  807. if(!size() || gui != (*this)[0])
  808. {
  809. // automatically wakes objects in GuiControl::onWake
  810. addObject(gui);
  811. if (size() >= 2)
  812. reOrder(gui, *begin());
  813. }
  814. //refresh the entire gui
  815. resetUpdateRegions();
  816. //rebuild the accelerator map
  817. mAcceleratorMap.clear();
  818. for(iterator i = end(); i != begin() ; )
  819. {
  820. i--;
  821. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  822. ctrl->buildAcceleratorMap();
  823. if (ctrl->mProfile->mModal)
  824. break;
  825. }
  826. refreshMouseControl();
  827. // Force the canvas to update the sizing of the new content control
  828. maintainSizing();
  829. }
  830. GuiControl *GuiCanvas::getContentControl()
  831. {
  832. if(size() > 0)
  833. return (GuiControl *) first();
  834. return NULL;
  835. }
  836. void GuiCanvas::pushDialogControl(GuiControl *gui, S32 layer)
  837. {
  838. //add the gui
  839. gui->mLayer = layer;
  840. // GuiControl::addObject wakes the object
  841. addObject(gui);
  842. //reorder it to the correct layer
  843. iterator i;
  844. for (i = begin(); i != end(); i++)
  845. {
  846. GuiControl *ctrl = static_cast<GuiControl*>(*i);
  847. if (ctrl->mLayer > gui->mLayer)
  848. {
  849. reOrder(gui, ctrl);
  850. break;
  851. }
  852. }
  853. //call the dialog push method
  854. gui->onDialogPush();
  855. //find the top most dialog
  856. //find the first responder
  857. GuiControl* responder = gui->findFirstTabable();
  858. if(responder)
  859. responder->setFirstResponder();
  860. // call the 'onWake' method?
  861. //if(wakedGui)
  862. // Con::executef(gui, 1, "onWake");
  863. //refresh the entire gui
  864. resetUpdateRegions();
  865. //rebuild the accelerator map
  866. mAcceleratorMap.clear();
  867. if (size() > 0)
  868. {
  869. GuiControl *ctrl = static_cast<GuiControl*>(last());
  870. ctrl->buildAcceleratorMap();
  871. }
  872. refreshMouseControl();
  873. if(gui->mProfile && gui->mProfile->mModal)
  874. {
  875. Input::pushCursor(CursorManager::curArrow);
  876. }
  877. }
  878. void GuiCanvas::popDialogControl(GuiControl *gui)
  879. {
  880. if (size() < 1)
  881. return;
  882. //first, find the dialog, and call the "onDialogPop()" method
  883. GuiControl *ctrl = NULL;
  884. if (gui)
  885. {
  886. //*** DAW: For modal dialogs, reset the mouse cursor and enable the appropriate platform menus
  887. if(gui->mProfile && gui->mProfile->mModal)
  888. {
  889. Input::popCursor();
  890. }
  891. //make sure the gui really exists on the stack
  892. iterator i;
  893. bool found = false;
  894. for(i = begin(); i != end(); i++)
  895. {
  896. GuiControl *check = static_cast<GuiControl *>(*i);
  897. if (check == gui)
  898. {
  899. ctrl = check;
  900. found = true;
  901. }
  902. }
  903. if (! found)
  904. return;
  905. }
  906. else
  907. ctrl = static_cast<GuiControl*>(last());
  908. //call the "on pop" function
  909. ctrl->onDialogPop();
  910. // sleep the object
  911. //now pop the last child (will sleep if awake)
  912. removeObject(ctrl);
  913. // Save the old responder:
  914. Sim::getGuiGroup()->addObject(ctrl);
  915. if (size() > 0)
  916. {
  917. GuiControl *ctrl = static_cast<GuiControl *>(last());
  918. if(ctrl->mFirstResponder)
  919. ctrl->mFirstResponder->setFirstResponder();
  920. }
  921. else
  922. {
  923. setFirstResponder(NULL);
  924. }
  925. //refresh the entire gui
  926. resetUpdateRegions();
  927. //rebuild the accelerator map
  928. mAcceleratorMap.clear();
  929. if (size() > 0)
  930. {
  931. GuiControl *ctrl = static_cast<GuiControl*>(last());
  932. ctrl->buildAcceleratorMap();
  933. }
  934. refreshMouseControl();
  935. }
  936. void GuiCanvas::popDialogControl(S32 layer)
  937. {
  938. if (size() < 1)
  939. return;
  940. GuiControl *ctrl = NULL;
  941. iterator i = end(); // find in z order (last to first)
  942. while (i != begin())
  943. {
  944. i--;
  945. ctrl = static_cast<GuiControl*>(*i);
  946. if (ctrl->mLayer == layer)
  947. break;
  948. }
  949. if (ctrl)
  950. popDialogControl(ctrl);
  951. }
  952. void GuiCanvas::mouseLock(GuiControl *lockingControl)
  953. {
  954. if (bool(mMouseCapturedControl))
  955. return;
  956. mMouseCapturedControl = lockingControl;
  957. if(mMouseControl && mMouseControl != mMouseCapturedControl)
  958. {
  959. GuiEvent evt;
  960. evt.mousePoint.x = S32(cursorPt.x);
  961. evt.mousePoint.y = S32(cursorPt.y);
  962. mMouseControl->onMouseLeave(evt);
  963. }
  964. }
  965. void GuiCanvas::mouseUnlock(GuiControl *lockingControl)
  966. {
  967. if (static_cast<GuiControl*>(mMouseCapturedControl) != lockingControl)
  968. return;
  969. GuiEvent evt;
  970. evt.mousePoint.x = S32(cursorPt.x);
  971. evt.mousePoint.y = S32(cursorPt.y);
  972. GuiControl * controlHit = findHitControl(evt.mousePoint);
  973. if(controlHit != mMouseCapturedControl)
  974. {
  975. mMouseControl = controlHit;
  976. mMouseControlClicked = false;
  977. if(bool(mMouseControl))
  978. mMouseControl->onMouseEnter(evt);
  979. }
  980. mMouseCapturedControl = NULL;
  981. }
  982. void GuiCanvas::paint()
  983. {
  984. resetUpdateRegions();
  985. // inhibit explicit refreshes in the case we're swapped out
  986. if (TextureManager::mDGLRender)
  987. renderFrame(false);
  988. }
  989. void GuiCanvas::maintainSizing()
  990. {
  991. Point2I size = Platform::getWindowSize();
  992. if(size.x == 0 || size.y == 0)
  993. return;
  994. RectI screenRect(0, 0, size.x, size.y);
  995. mBounds = screenRect;
  996. //all bottom level controls should be the same dimensions as the canvas
  997. //this is necessary for passing mouse events accurately
  998. iterator i;
  999. for (i = begin(); i != end(); i++)
  1000. {
  1001. AssertFatal(static_cast<GuiControl*>((*i))->isAwake(), "GuiCanvas::renderFrame: ctrl is not awake");
  1002. GuiControl *ctrl = static_cast<GuiControl*>(*i);
  1003. Point2I ext = ctrl->getExtent();
  1004. Point2I pos = ctrl->getPosition();
  1005. if(pos != screenRect.point || ext != screenRect.extent)
  1006. {
  1007. ctrl->resize(screenRect.point, screenRect.extent);
  1008. resetUpdateRegions();
  1009. }
  1010. }
  1011. }
  1012. void GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */)
  1013. {
  1014. PROFILE_START(CanvasPreRender);
  1015. #if !defined TORQUE_OS_IOS && !defined TORQUE_OS_ANDROID && !defined TORQUE_OS_EMSCRIPTEN
  1016. if(mRenderFront)
  1017. glDrawBuffer(GL_FRONT);
  1018. else
  1019. glDrawBuffer(GL_BACK);
  1020. #endif
  1021. // Make sure the root control is the size of the canvas.
  1022. Point2I size = Platform::getWindowSize();
  1023. if(size.x == 0 || size.y == 0)
  1024. {
  1025. //Luma: Fixed missing PROFILE_END()
  1026. PROFILE_END();
  1027. return;
  1028. }
  1029. RectI screenRect(0, 0, size.x, size.y);
  1030. maintainSizing();
  1031. //preRender (recursive) all controls
  1032. preRender();
  1033. PROFILE_END();
  1034. if(preRenderOnly)
  1035. return;
  1036. // for now, just always reset the update regions - this is a
  1037. // fix for FSAA on ATI cards
  1038. resetUpdateRegions();
  1039. // Moved this below object integration for performance reasons. -JDD
  1040. // // finish the gl render so we don't get too far ahead of ourselves
  1041. //#if defined(TORQUE_OS_WIN32)
  1042. // PROFILE_START(glFinish);
  1043. // glFinish();
  1044. // PROFILE_END();
  1045. //#endif
  1046. //draw the mouse, but not using tags...
  1047. PROFILE_START(CanvasRenderControls);
  1048. GuiCursor *mouseCursor = NULL;
  1049. bool cursorVisible = true;
  1050. if(bool(mMouseCapturedControl))
  1051. mMouseCapturedControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
  1052. else if(bool(mMouseControl))
  1053. mMouseControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
  1054. Point2I cursorPos((S32)cursorPt.x, (S32)cursorPt.y);
  1055. if(!mouseCursor)
  1056. mouseCursor = defaultCursor;
  1057. if(lastCursorON && lastCursor)
  1058. {
  1059. Point2I spot = lastCursor->getHotSpot();
  1060. Point2I cext = lastCursor->getExtent();
  1061. Point2I pos = lastCursorPt - spot;
  1062. addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
  1063. }
  1064. if(cursorVisible && mouseCursor)
  1065. {
  1066. Point2I spot = mouseCursor->getHotSpot();
  1067. Point2I cext = mouseCursor->getExtent();
  1068. Point2I pos = cursorPos - spot;
  1069. addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
  1070. }
  1071. lastCursorON = cursorVisible;
  1072. lastCursor = mouseCursor;
  1073. lastCursorPt = cursorPos;
  1074. RectI updateUnion;
  1075. buildUpdateUnion(&updateUnion);
  1076. if (updateUnion.intersect(screenRect))
  1077. {
  1078. // Clear the background color if requested.
  1079. if ( mUseBackgroundColor )
  1080. {
  1081. glClearColor( mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha );
  1082. glClear(GL_COLOR_BUFFER_BIT);
  1083. }
  1084. //render the dialogs
  1085. iterator i;
  1086. for(i = begin(); i != end(); i++)
  1087. {
  1088. GuiControl *contentCtrl = static_cast<GuiControl*>(*i);
  1089. dglSetClipRect(updateUnion);
  1090. glDisable( GL_CULL_FACE );
  1091. contentCtrl->onRender(contentCtrl->getPosition(), updateUnion);
  1092. }
  1093. // Tooltip resource
  1094. if(bool(mMouseControl))
  1095. {
  1096. U32 curTime = Platform::getRealMilliseconds();
  1097. if(hoverControl == mMouseControl)
  1098. {
  1099. if(hoverPositionSet || (curTime - hoverControlStart) >= (U32)hoverControl->mTipHoverTime || (curTime - hoverLeftControlTime) <= (U32)hoverControl->mTipHoverTime)
  1100. {
  1101. // MM: Controls whether the tooltip tracks the mouse cursor or not.
  1102. #if 0
  1103. if(!hoverPositionSet)
  1104. {
  1105. hoverPosition = cursorPos;
  1106. }
  1107. #else
  1108. hoverPosition = cursorPos;
  1109. #endif
  1110. hoverPositionSet = mMouseControl->renderTooltip(hoverPosition);
  1111. }
  1112. } else
  1113. {
  1114. if(hoverPositionSet)
  1115. {
  1116. hoverLeftControlTime = curTime;
  1117. hoverPositionSet = false;
  1118. }
  1119. hoverControl = mMouseControl;
  1120. hoverControlStart = curTime;
  1121. }
  1122. }
  1123. //end tooltip
  1124. dglSetClipRect(updateUnion);
  1125. //temp draw the mouse
  1126. if (cursorON && mShowCursor && !mouseCursor && Canvas->getUseNativeCursor())
  1127. {
  1128. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID) || defined(TORQUE_OS_EMSCRIPTEN)
  1129. glColor4ub(255, 0, 0, 255);
  1130. GLfloat vertices[] = {
  1131. (GLfloat)(cursorPt.x),(GLfloat)(cursorPt.y),
  1132. (GLfloat)(cursorPt.x + 2),(GLfloat)(cursorPt.y),
  1133. (GLfloat)(cursorPt.x + 2),(GLfloat)(cursorPt.y + 2),
  1134. (GLfloat)(cursorPt.x),(GLfloat)(cursorPt.y + 2),
  1135. };
  1136. glEnableClientState(GL_VERTEX_ARRAY);
  1137. glVertexPointer(2, GL_FLOAT, 0, vertices);
  1138. glDrawArrays(GL_LINE_LOOP, 0, 4);
  1139. #else
  1140. glColor4ub(255, 0, 0, 255);
  1141. glRecti((S32)cursorPt.x, (S32)cursorPt.y, (S32)(cursorPt.x + 2), (S32)(cursorPt.y + 2));
  1142. #endif
  1143. }
  1144. //DEBUG
  1145. //draw the help ctrl
  1146. //if (helpCtrl)
  1147. //{
  1148. // helpCtrl->render(srf);
  1149. //}
  1150. if (cursorON && mouseCursor && mShowCursor)
  1151. {
  1152. Point2I pos((S32)cursorPt.x, (S32)cursorPt.y);
  1153. Point2I spot = mouseCursor->getHotSpot();
  1154. pos -= spot;
  1155. mouseCursor->render(pos);
  1156. }
  1157. }
  1158. PROFILE_END();
  1159. if( bufferSwap )
  1160. swapBuffers();
  1161. //#if defined(TORQUE_OS_WIN32)
  1162. // PROFILE_START(glFinish);
  1163. // glFinish(); // This was changed to work with the D3D layer -pw
  1164. // PROFILE_END();
  1165. //#endif
  1166. }
  1167. void GuiCanvas::swapBuffers()
  1168. {
  1169. PROFILE_START(SwapBuffers);
  1170. //flip the surface
  1171. if(!mRenderFront)
  1172. Video::swapBuffers();
  1173. PROFILE_END();
  1174. }
  1175. void GuiCanvas::buildUpdateUnion(RectI *updateUnion)
  1176. {
  1177. *updateUnion = mOldUpdateRects[0];
  1178. //the update region should encompass the oldUpdateRects, and the curUpdateRect
  1179. Point2I upperL;
  1180. Point2I lowerR;
  1181. upperL.x = getMin(mOldUpdateRects[0].point.x, mOldUpdateRects[1].point.x);
  1182. upperL.x = getMin(upperL.x, mCurUpdateRect.point.x);
  1183. upperL.y = getMin(mOldUpdateRects[0].point.y, mOldUpdateRects[1].point.y);
  1184. upperL.y = getMin(upperL.y, mCurUpdateRect.point.y);
  1185. lowerR.x = getMax(mOldUpdateRects[0].point.x + mOldUpdateRects[0].extent.x, mOldUpdateRects[1].point.x + mOldUpdateRects[1].extent.x);
  1186. lowerR.x = getMax(lowerR.x, mCurUpdateRect.point.x + mCurUpdateRect.extent.x);
  1187. lowerR.y = getMax(mOldUpdateRects[0].point.y + mOldUpdateRects[0].extent.y, mOldUpdateRects[1].point.y + mOldUpdateRects[1].extent.y);
  1188. lowerR.y = getMax(lowerR.y, mCurUpdateRect.point.y + mCurUpdateRect.extent.y);
  1189. updateUnion->point = upperL;
  1190. updateUnion->extent = lowerR - upperL;
  1191. //shift the oldUpdateRects
  1192. mOldUpdateRects[0] = mOldUpdateRects[1];
  1193. mOldUpdateRects[1] = mCurUpdateRect;
  1194. mCurUpdateRect.point.set(0,0);
  1195. mCurUpdateRect.extent.set(0,0);
  1196. }
  1197. void GuiCanvas::addUpdateRegion(Point2I pos, Point2I ext)
  1198. {
  1199. if(mCurUpdateRect.extent.x == 0)
  1200. {
  1201. mCurUpdateRect.point = pos;
  1202. mCurUpdateRect.extent = ext;
  1203. }
  1204. else
  1205. {
  1206. Point2I upperL;
  1207. upperL.x = getMin(mCurUpdateRect.point.x, pos.x);
  1208. upperL.y = getMin(mCurUpdateRect.point.y, pos.y);
  1209. Point2I lowerR;
  1210. lowerR.x = getMax(mCurUpdateRect.point.x + mCurUpdateRect.extent.x, pos.x + ext.x);
  1211. lowerR.y = getMax(mCurUpdateRect.point.y + mCurUpdateRect.extent.y, pos.y + ext.y);
  1212. mCurUpdateRect.point = upperL;
  1213. mCurUpdateRect.extent = lowerR - upperL;
  1214. }
  1215. }
  1216. void GuiCanvas::resetUpdateRegions()
  1217. {
  1218. //DEBUG - get surface width and height
  1219. mOldUpdateRects[0].set(mBounds.point, mBounds.extent);
  1220. mOldUpdateRects[1] = mOldUpdateRects[0];
  1221. mCurUpdateRect = mOldUpdateRects[0];
  1222. }
  1223. void GuiCanvas::setFirstResponder( GuiControl* newResponder )
  1224. {
  1225. GuiControl* oldResponder = mFirstResponder;
  1226. Parent::setFirstResponder( newResponder );
  1227. if ( oldResponder && ( oldResponder != mFirstResponder ) )
  1228. oldResponder->onLoseFirstResponder();
  1229. }