guiCanvas.cc 41 KB

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