guiCanvas.cc 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787
  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/platformVideo.h"
  29. #include "gui/guiTypes.h"
  30. #include "gui/guiControl.h"
  31. #include "gui/guiCanvas.h"
  32. #include "game/gameInterface.h"
  33. IMPLEMENT_CONOBJECT(GuiCanvas);
  34. GuiCanvas *Canvas = NULL;
  35. ConsoleMethod( GuiCanvas, getContent, S32, 2, 2, "() Use the getContent method to get the ID of the control which is being used as the current canvas content.\n"
  36. "@return Returns the ID of the current canvas content (a control), or 0 meaning the canvas is empty")
  37. {
  38. GuiControl *ctrl = object->getContentControl();
  39. if(ctrl)
  40. return ctrl->getId();
  41. return -1;
  42. }
  43. ConsoleMethod( GuiCanvas, setContent, void, 3, 3, "( handle ) Use the setContent method to set the control identified by handle as the current canvas content.\n"
  44. "@param handle The numeric ID or name of the control to be made the canvas contents.\n"
  45. "@return No return value")
  46. {
  47. GuiControl *gui = NULL;
  48. if(argv[2][0])
  49. {
  50. if (!Sim::findObject(argv[2], gui))
  51. {
  52. Con::printf("%s(): Invalid control: %s", argv[0], argv[2]);
  53. return;
  54. }
  55. }
  56. //set the new content control
  57. Canvas->setContentControl(gui);
  58. }
  59. ConsoleMethod( GuiCanvas, pushDialog, void, 3, 4, "( handle [ , layer ] ) Use the pushDialog method to open a dialog on a specific canvas layer, or in the same layer the last openned dialog. Newly placed dialogs placed in a layer with another dialog(s) will overlap the prior dialog(s).\n"
  60. "@param handle The numeric ID or name of the dialog to be opened.\n"
  61. "@param layer A integer value in the range [ 0 , inf ) specifying the canvas layer to place the dialog in.\n"
  62. "@return No return value")
  63. {
  64. GuiControl *gui;
  65. if (! Sim::findObject(argv[2], gui))
  66. {
  67. Con::printf("%s(): Invalid control: %s", argv[0], argv[2]);
  68. return;
  69. }
  70. //find the layer
  71. S32 layer = 0;
  72. if (argc == 4)
  73. layer = dAtoi(argv[3]);
  74. //set the new content control
  75. Canvas->pushDialogControl(gui, layer);
  76. }
  77. ConsoleMethod( GuiCanvas, popDialog, void, 2, 3, "( handle ) Use the popDialog method to remove a currently showing dialog. If no handle is provided, the top most dialog is popped.\n"
  78. "@param handle The ID or a previously pushed dialog.\n"
  79. "@return No return value.\n"
  80. "@sa pushDialog, popLayer")
  81. {
  82. // Must initialize this to NULL to avoid crash on the if (gui) statement further down [KNM | 07/28/11 | ITGB-120]
  83. //GuiControl * gui;
  84. GuiControl * gui = NULL;
  85. if (argc == 3)
  86. {
  87. if (!Sim::findObject(argv[2], gui))
  88. {
  89. Con::printf("%s(): Invalid control: %s", argv[0], argv[2]);
  90. return;
  91. }
  92. }
  93. if (gui)
  94. Canvas->popDialogControl(gui);
  95. else
  96. Canvas->popDialogControl();
  97. }
  98. ConsoleMethod( GuiCanvas, popLayer, void, 2, 3, "( layer ) Use the popLayer method to remove (close) all dialogs in the specified canvas �layer�.\n"
  99. "@param layer A integer value in the range [ 0 , inf ) specifying the canvas layer to clear.\n"
  100. "@return No return value.\n"
  101. "@sa pushDialog, popDialog")
  102. {
  103. S32 layer = 0;
  104. if (argc == 3)
  105. layer = dAtoi(argv[2]);
  106. Canvas->popDialogControl(layer);
  107. }
  108. ConsoleMethod(GuiCanvas, cursorOn, void, 2, 2, "() Use the cursorOn method to enable the cursor.\n"
  109. "@return No return value")
  110. {
  111. Canvas->setCursorON(true);
  112. }
  113. ConsoleMethod(GuiCanvas, cursorOff, void, 2, 2, "() Use the cursorOff method to disable the cursor.\n"
  114. "@return No return value")
  115. {
  116. Canvas->setCursorON(false);
  117. }
  118. ConsoleMethod( GuiCanvas, setCursor, void, 3, 3, "( cursorHandle ) Use the setCursor method to select the current cursor.\n"
  119. "@param cursorHandle The ID of a previously defined GuiCursor object.\n"
  120. "@return No return value")
  121. {
  122. GuiCursor *curs = NULL;
  123. if(argv[2][0])
  124. {
  125. if(!Sim::findObject(argv[2], curs))
  126. {
  127. Con::printf("%s is not a valid cursor.", argv[2]);
  128. return;
  129. }
  130. }
  131. Canvas->setCursor(curs);
  132. }
  133. ConsoleMethod( GuiCanvas, renderFront, void, 3, 3, "(bool enable)")
  134. {
  135. Canvas->setRenderFront(dAtob(argv[2]));
  136. }
  137. ConsoleMethod( GuiCanvas, showCursor, void, 2, 2, "")
  138. {
  139. Canvas->showCursor(true);
  140. }
  141. ConsoleMethod( GuiCanvas, hideCursor, void, 2, 2, "")
  142. {
  143. Canvas->showCursor(false);
  144. }
  145. ConsoleMethod( GuiCanvas, isCursorOn, bool, 2, 2, "")
  146. {
  147. return Canvas->isCursorON();
  148. }
  149. ConsoleMethod( GuiCanvas, setDoubleClickDelay, void, 3, 3, "")
  150. {
  151. Canvas->setDoubleClickTime(dAtoi(argv[2]));
  152. }
  153. ConsoleMethod( GuiCanvas, setDoubleClickMoveBuffer, void, 4, 4, "")
  154. {
  155. Canvas->setDoubleClickWidth(dAtoi(argv[2]));
  156. Canvas->setDoubleClickHeight(dAtoi(argv[3]));
  157. }
  158. ConsoleMethod( GuiCanvas, repaint, void, 2, 2, "() Use the repaint method to force the canvas to redraw all elements.\n"
  159. "@return No return value")
  160. {
  161. Canvas->paint();
  162. }
  163. ConsoleMethod( GuiCanvas, reset, void, 2, 2, "() Use the reset method to reset the current canvas update region.\n"
  164. "@return No return value")
  165. {
  166. Canvas->resetUpdateRegions();
  167. }
  168. ConsoleMethod( GuiCanvas, getCursorPos, const char*, 2, 2, "() Use the getCursorPos method to retrieve the current position of the mouse pointer.\n"
  169. "@return Returns a vector containing the �x y� coordinates of the cursor in the canvas")
  170. {
  171. Point2I pos = Canvas->getCursorPos();
  172. char * ret = Con::getReturnBuffer(32);
  173. dSprintf(ret, 32, "%d %d", pos.x, pos.y);
  174. return(ret);
  175. }
  176. ConsoleMethod( GuiCanvas, setCursorPos, void, 3, 4, "( ) Use the setCursorPos method to set the position of the cursor in the cavas.\n"
  177. "@param position An \"x y\" position vector specifying the new location of the cursor.\n"
  178. "@return No return value")
  179. {
  180. Point2I pos(0,0);
  181. if(argc == 4)
  182. pos.set(dAtoi(argv[2]), dAtoi(argv[3]));
  183. else
  184. dSscanf(argv[2], "%d %d", &pos.x, &pos.y);
  185. Canvas->setCursorPos(pos);
  186. }
  187. ConsoleMethod( GuiCanvas, getMouseControl, S32, 2, 2, "Gets the gui control under the mouse.")
  188. {
  189. GuiControl* control = object->getMouseControl();
  190. if (control)
  191. return control->getId();
  192. return NULL;
  193. }
  194. //-----------------------------------------------------------------------------
  195. ConsoleMethod(GuiCanvas, setBackgroundColor, void, 3, 6, "(float red, float green, float blue, [float alpha = 1.0]) - Sets the background color for the canvas."
  196. "@param red The red value.\n"
  197. "@param green The green value.\n"
  198. "@param blue The blue value.\n"
  199. "@param alpha The alpha value.\n"
  200. "@return No return Value.")
  201. {
  202. // The colors.
  203. F32 red;
  204. F32 green;
  205. F32 blue;
  206. F32 alpha = 1.0f;
  207. // Space separated.
  208. if (argc == 3)
  209. {
  210. // Grab the element count.
  211. const U32 elementCount = Utility::mGetStringElementCount(argv[2]);
  212. // Has a single argument been specified?
  213. if ( elementCount == 1 )
  214. {
  215. object->setDataField( StringTable->insert("BackgroundColor"), NULL, argv[2] );
  216. return;
  217. }
  218. // ("R G B [A]")
  219. if ((elementCount == 3) || (elementCount == 4))
  220. {
  221. // Extract the color.
  222. red = dAtof(Utility::mGetStringElement(argv[2], 0));
  223. green = dAtof(Utility::mGetStringElement(argv[2], 1));
  224. blue = dAtof(Utility::mGetStringElement(argv[2], 2));
  225. // Grab the alpha if it's there.
  226. if (elementCount > 3)
  227. alpha = dAtof(Utility::mGetStringElement(argv[2], 3));
  228. }
  229. // Invalid.
  230. else
  231. {
  232. Con::warnf("GuiCanvas::setBackgroundColor() - Invalid Number of parameters!");
  233. return;
  234. }
  235. }
  236. // (R, G, B)
  237. else if (argc >= 5)
  238. {
  239. red = dAtof(argv[2]);
  240. green = dAtof(argv[3]);
  241. blue = dAtof(argv[4]);
  242. // Grab the alpha if it's there.
  243. if (argc > 5)
  244. alpha = dAtof(argv[5]);
  245. }
  246. // Invalid.
  247. else
  248. {
  249. Con::warnf("GuiCanvas::setBackgroundColor() - Invalid Number of parameters!");
  250. return;
  251. }
  252. // Set background color.
  253. object->setBackgroundColor(ColorF(red, green, blue, alpha) );
  254. }
  255. //-----------------------------------------------------------------------------
  256. ConsoleMethod(GuiCanvas, getBackgroundColor, const char*, 2, 2, "Gets the background color for the canvas.\n"
  257. "@return (float red / float green / float blue / float alpha) The background color for the canvas.")
  258. {
  259. // Get the background color.
  260. const ColorF& color = object->getBackgroundColor();
  261. // Fetch color name.
  262. StringTableEntry colorName = StockColor::name( color );
  263. // Return the color name if it's valid.
  264. if ( colorName != StringTable->EmptyString )
  265. return colorName;
  266. // Create Returnable Buffer.
  267. char* pBuffer = Con::getReturnBuffer(64);
  268. // Format Buffer.
  269. dSprintf(pBuffer, 64, "%g %g %g %g", color.red, color.green, color.blue, color.alpha );
  270. // Return buffer.
  271. return pBuffer;
  272. }
  273. //-----------------------------------------------------------------------------
  274. ConsoleMethod(GuiCanvas, setUseBackgroundColor, void, 3, 3, "Sets whether to use the canvas background color or not.\n"
  275. "@param useBackgroundColor Whether to use the canvas background color or not.\n"
  276. "@return No return value." )
  277. {
  278. // Fetch flag.
  279. const bool useBackgroundColor = dAtob(argv[2]);
  280. // Set the flag.
  281. object->setUseBackgroundColor( useBackgroundColor );
  282. }
  283. //-----------------------------------------------------------------------------
  284. ConsoleMethod(GuiCanvas, getUseBackgroundColor, bool, 2, 2, "Gets whether the canvas background color is in use or not.\n"
  285. "@return Whether the canvas background color is in use or not." )
  286. {
  287. // Get the flag.
  288. return object->getUseBackgroundColor();
  289. }
  290. ConsoleFunction( createCanvas, bool, 2, 2, "( WindowTitle ) Use the createCanvas function to initialize the canvas.\n"
  291. "@return Returns true on success, false on failure.\n"
  292. "@sa createEffectCanvas")
  293. {
  294. AssertISV(!Canvas, "CreateCanvas: canvas has already been instantiated");
  295. Platform::initWindow(Point2I(MIN_RESOLUTION_X, MIN_RESOLUTION_Y), argv[1]);
  296. if (!Video::getResolutionList())
  297. return false;
  298. // create the canvas, and add it to the manager
  299. Canvas = new GuiCanvas();
  300. Canvas->registerObject("Canvas"); // automatically adds to GuiGroup
  301. return true;
  302. }
  303. ConsoleFunction( setCanvasTitle, void, 2, 2, "(string windowTitle) Sets the title to the provided string\n"
  304. "@param windowTitle The desired title\n"
  305. "@return No Return Value")
  306. {
  307. Platform::setWindowTitle( argv[1] );
  308. }
  309. ConsoleFunction(screenShot, void, 3, 3, "(string file, string format)"
  310. "Take a screenshot.\n\n"
  311. "@param format One of JPEG or PNG.")
  312. {
  313. #ifndef TORQUE_OS_IOS
  314. // PUAP -Mat no screenshots on iPhone can do it from Xcode
  315. FileStream fStream;
  316. if(!fStream.open(argv[1], FileStream::Write))
  317. {
  318. Con::printf("Failed to open file '%s'.", argv[1]);
  319. return;
  320. }
  321. glReadBuffer(GL_FRONT);
  322. Point2I extent = Canvas->getExtent();
  323. U8 * pixels = new U8[extent.x * extent.y * 4];
  324. glReadPixels(0, 0, extent.x, extent.y, GL_RGB, GL_UNSIGNED_BYTE, pixels);
  325. GBitmap * bitmap = new GBitmap;
  326. bitmap->allocateBitmap(U32(extent.x), U32(extent.y));
  327. // flip the rows
  328. for(U32 y = 0; y < (U32)extent.y; y++)
  329. dMemcpy(bitmap->getAddress(0, extent.y - y - 1), pixels + y * extent.x * 3, U32(extent.x * 3));
  330. if ( dStrcmp( argv[2], "JPEG" ) == 0 )
  331. bitmap->writeJPEG(fStream);
  332. else if( dStrcmp( argv[2], "PNG" ) == 0)
  333. bitmap->writePNG(fStream);
  334. else
  335. bitmap->writePNG(fStream);
  336. fStream.close();
  337. delete [] pixels;
  338. delete bitmap;
  339. #endif
  340. }
  341. GuiCanvas::GuiCanvas()
  342. {
  343. #ifdef TORQUE_OS_IOS
  344. mBounds.set(0, 0, IOS_DEFAULT_RESOLUTION_X, IOS_DEFAULT_RESOLUTION_Y);
  345. #else
  346. mBounds.set(0, 0, MIN_RESOLUTION_X, MIN_RESOLUTION_Y);
  347. #endif
  348. mAwake = true;
  349. mPixelsPerMickey = 1.0f;
  350. cursorON = true;
  351. mShowCursor = false;
  352. lastCursorON = false;
  353. rLastFrameTime = 0.0f;
  354. mMouseCapturedControl = NULL;
  355. mMouseControl = NULL;
  356. mMouseControlClicked = false;
  357. mMouseButtonDown = false;
  358. mMouseRightButtonDown = false;
  359. mMouseMiddleButtonDown = false;
  360. lastCursor = NULL;
  361. lastCursorPt.set(0,0);
  362. cursorPt.set(0,0);
  363. mLastMouseClickCount = 0;
  364. mLastMouseDownTime = 0;
  365. mPrevMouseTime = 0;
  366. defaultCursor = NULL;
  367. mRenderFront = false;
  368. hoverControlStart = Platform::getRealMilliseconds();
  369. hoverControl = NULL;
  370. hoverPosition = getCursorPos();
  371. hoverPositionSet = false;
  372. hoverLeftControlTime = 0;
  373. mLeftMouseLast = false;
  374. mMiddleMouseLast = false;
  375. mRightMouseLast = false;
  376. mDoubleClickWidth = Input::getDoubleClickWidth();
  377. mDoubleClickHeight = Input::getDoubleClickHeight();
  378. mDoubleClickTime = Input::getDoubleClickTime();
  379. /// Background color.
  380. mBackgroundColor.set( 0.0f, 0.0f, 0.0f, 0.0f );
  381. mUseBackgroundColor = true;
  382. }
  383. GuiCanvas::~GuiCanvas()
  384. {
  385. if(Canvas == this)
  386. Canvas = 0;
  387. }
  388. //-----------------------------------------------------------------------------
  389. void GuiCanvas::initPersistFields()
  390. {
  391. // Call Parent.
  392. Parent::initPersistFields();
  393. // Physics.
  394. addField("UseBackgroundColor", TypeBool, Offset(mUseBackgroundColor, GuiCanvas), "" );
  395. addField("BackgroundColor", TypeColorF, Offset(mBackgroundColor, GuiCanvas), "" );
  396. }
  397. //------------------------------------------------------------------------------
  398. void GuiCanvas::setCursor(GuiCursor *curs)
  399. {
  400. defaultCursor = curs;
  401. if(mShowCursor)
  402. {
  403. Input::setCursorState(false);
  404. }
  405. }
  406. void GuiCanvas::setCursorON(bool onOff)
  407. {
  408. cursorON = onOff;
  409. if(!cursorON)
  410. mMouseControl = NULL;
  411. }
  412. void GuiCanvas::setCursorPos(const Point2I &pt)
  413. {
  414. cursorPt.x = F32(pt.x);
  415. cursorPt.y = F32(pt.y);
  416. Input::setCursorPos( pt.x, pt.y );
  417. }
  418. void GuiCanvas::addAcceleratorKey(GuiControl *ctrl, U32 index, U32 keyCode, U32 modifier)
  419. {
  420. if (keyCode > 0 && ctrl)
  421. {
  422. AccKeyMap newMap;
  423. newMap.ctrl = ctrl;
  424. newMap.index = index;
  425. newMap.keyCode = keyCode;
  426. newMap.modifier = modifier;
  427. mAcceleratorMap.push_back(newMap);
  428. }
  429. }
  430. bool GuiCanvas::tabNext(void)
  431. {
  432. GuiControl *ctrl = static_cast<GuiControl *>(last());
  433. if (ctrl)
  434. {
  435. //save the old
  436. GuiControl *oldResponder = mFirstResponder;
  437. GuiControl* newResponder = ctrl->findNextTabable(mFirstResponder);
  438. if ( !newResponder )
  439. newResponder = ctrl->findFirstTabable();
  440. if ( newResponder && newResponder != oldResponder )
  441. {
  442. newResponder->setFirstResponder();
  443. if ( oldResponder )
  444. oldResponder->onLoseFirstResponder();
  445. return true;
  446. }
  447. }
  448. return false;
  449. }
  450. bool GuiCanvas::tabPrev(void)
  451. {
  452. GuiControl *ctrl = static_cast<GuiControl *>(last());
  453. if (ctrl)
  454. {
  455. //save the old
  456. GuiControl *oldResponder = mFirstResponder;
  457. GuiControl* newResponder = ctrl->findPrevTabable(mFirstResponder);
  458. if ( !newResponder )
  459. newResponder = ctrl->findLastTabable();
  460. if ( newResponder && newResponder != oldResponder )
  461. {
  462. newResponder->setFirstResponder();
  463. if ( oldResponder )
  464. oldResponder->onLoseFirstResponder();
  465. return true;
  466. }
  467. }
  468. return false;
  469. }
  470. void GuiCanvas::processScreenTouchEvent(const ScreenTouchEvent *event)
  471. {
  472. //copy the cursor point into the event
  473. mLastEvent.mousePoint.x = S32(event->xPos);
  474. mLastEvent.mousePoint.y = S32(event->yPos);
  475. mLastEvent.eventID = event->touchID;
  476. mLastEvent.mouseClickCount = event->numTouches;
  477. //see if button was pressed
  478. if (event->action == SI_MAKE)
  479. {
  480. U32 curTime = Platform::getVirtualMilliseconds();
  481. mNextMouseTime = curTime + mInitialMouseDelay;
  482. mLastMouseDownTime = curTime;
  483. // mLastEvent.mouseClickCount = mLastMouseClickCount;
  484. rootScreenTouchDown(mLastEvent);
  485. }
  486. else if(event->action == SI_MOVE)
  487. {
  488. rootScreenTouchMove(mLastEvent);
  489. }
  490. //else button was released
  491. else if(event->action == SI_BREAK)
  492. {
  493. mNextMouseTime = 0xFFFFFFFF;
  494. rootScreenTouchUp(mLastEvent);
  495. }
  496. }
  497. void GuiCanvas::processMouseMoveEvent(const MouseMoveEvent *event)
  498. {
  499. if( cursorON )
  500. {
  501. //copy the modifier into the new event
  502. mLastEvent.modifier = event->modifier;
  503. cursorPt.x += ( F32(event->xPos - cursorPt.x) * mPixelsPerMickey);
  504. cursorPt.y += ( F32(event->yPos - cursorPt.y) * mPixelsPerMickey);
  505. // clamp the cursor to the window, or not
  506. if( ! Con::getBoolVariable( "$pref::Gui::noClampTorqueCursorToWindow", true ))
  507. {
  508. cursorPt.x =(F32) getMax(0, getMin((S32)cursorPt.x, mBounds.extent.x - 1));
  509. cursorPt.y = (F32)getMax(0, getMin((S32)cursorPt.y, mBounds.extent.y - 1));
  510. }
  511. mLastEvent.mousePoint.x = S32(cursorPt.x);
  512. mLastEvent.mousePoint.y = S32(cursorPt.y);
  513. mLastEvent.eventID = 0;
  514. Point2F movement = mMouseDownPoint - cursorPt;
  515. if ((mAbs((S32)movement.x) > mDoubleClickWidth) || (mAbs((S32)movement.y) > mDoubleClickHeight))
  516. {
  517. mLeftMouseLast = false;
  518. mMiddleMouseLast = false;
  519. mRightMouseLast = false;
  520. }
  521. if (mMouseButtonDown)
  522. rootMouseDragged(mLastEvent);
  523. else if (mMouseRightButtonDown)
  524. rootRightMouseDragged(mLastEvent);
  525. else if(mMouseMiddleButtonDown)
  526. rootMiddleMouseDragged(mLastEvent);
  527. else
  528. rootMouseMove(mLastEvent);
  529. }
  530. }
  531. bool GuiCanvas::processInputEvent(const InputEvent *event)
  532. {
  533. // First call the general input handler (on the extremely off-chance that it will be handled):
  534. if ( mFirstResponder )
  535. {
  536. if ( mFirstResponder->onInputEvent( *event ) )
  537. return( true );
  538. }
  539. if(event->deviceType == KeyboardDeviceType)
  540. {
  541. mLastEvent.ascii = event->ascii;
  542. mLastEvent.modifier = event->modifier;
  543. mLastEvent.keyCode = (U8)event->objInst;
  544. U32 eventModifier = event->modifier;
  545. if(eventModifier & SI_SHIFT)
  546. eventModifier |= SI_SHIFT;
  547. if(eventModifier & SI_CTRL)
  548. eventModifier |= SI_CTRL;
  549. if(eventModifier & SI_ALT)
  550. eventModifier |= SI_ALT;
  551. if (event->action == SI_MAKE)
  552. {
  553. //see if we should tab next/prev
  554. //see if we should now pass the event to the first responder
  555. if (mFirstResponder)
  556. {
  557. if(mFirstResponder->onKeyDown(mLastEvent))
  558. return true;
  559. }
  560. if ( isCursorON() && ( event->objInst == KEY_TAB ) )
  561. {
  562. if (size() > 0)
  563. {
  564. if (event->modifier & SI_SHIFT)
  565. {
  566. if(tabPrev())
  567. return true;
  568. }
  569. else if (event->modifier == 0)
  570. {
  571. if(tabNext())
  572. return true;
  573. }
  574. }
  575. }
  576. //if not handled, search for an accelerator
  577. for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
  578. {
  579. if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
  580. {
  581. mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
  582. return true;
  583. }
  584. }
  585. }
  586. else if(event->action == SI_BREAK)
  587. {
  588. if(mFirstResponder)
  589. if(mFirstResponder->onKeyUp(mLastEvent))
  590. return true;
  591. //see if there's an accelerator
  592. for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
  593. {
  594. if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
  595. {
  596. mAcceleratorMap[i].ctrl->acceleratorKeyRelease(mAcceleratorMap[i].index);
  597. return true;
  598. }
  599. }
  600. }
  601. else if(event->action == SI_REPEAT)
  602. {
  603. //if not handled, search for an accelerator
  604. for (U32 i = 0; i < (U32)mAcceleratorMap.size(); i++)
  605. {
  606. if ((U32)mAcceleratorMap[i].keyCode == (U32)event->objInst && (U32)mAcceleratorMap[i].modifier == eventModifier)
  607. {
  608. mAcceleratorMap[i].ctrl->acceleratorKeyPress(mAcceleratorMap[i].index);
  609. return true;
  610. }
  611. }
  612. if(mFirstResponder)
  613. mFirstResponder->onKeyRepeat(mLastEvent);
  614. return true;
  615. }
  616. }
  617. else if(event->deviceType == MouseDeviceType && cursorON)
  618. {
  619. //copy the modifier into the new event
  620. mLastEvent.modifier = event->modifier;
  621. if(event->objType == SI_XAXIS || event->objType == SI_YAXIS)
  622. {
  623. bool moved = false;
  624. Point2I oldpt((S32)cursorPt.x, (S32)cursorPt.y);
  625. Point2F pt(cursorPt.x, cursorPt.y);
  626. if (event->objType == SI_XAXIS)
  627. {
  628. pt.x += (event->fValue * mPixelsPerMickey);
  629. cursorPt.x = (F32)getMax(0, getMin((S32)pt.x, mBounds.extent.x - 1));
  630. if (oldpt.x != S32(cursorPt.x))
  631. moved = true;
  632. }
  633. else
  634. {
  635. pt.y += (event->fValue * mPixelsPerMickey);
  636. cursorPt.y = (F32)getMax(0, getMin((S32)pt.y, mBounds.extent.y - 1));
  637. if (oldpt.y != S32(cursorPt.y))
  638. moved = true;
  639. }
  640. if (moved)
  641. {
  642. mLastEvent.mousePoint.x = S32(cursorPt.x);
  643. mLastEvent.mousePoint.y = S32(cursorPt.y);
  644. mLastEvent.eventID = 0;
  645. #ifdef TORQUE_ALLOW_JOURNALING
  646. // [tom, 9/8/2006] If we're journaling, we need to update the plat cursor
  647. if(Game->isJournalReading())
  648. Input::setCursorPos((S32)cursorPt.x, (S32)cursorPt.y);
  649. #endif //TORQUE_ALLOW_JOURNALING
  650. if (mMouseButtonDown)
  651. rootMouseDragged(mLastEvent);
  652. else if (mMouseRightButtonDown)
  653. rootRightMouseDragged(mLastEvent);
  654. else if(mMouseMiddleButtonDown)
  655. rootMiddleMouseDragged(mLastEvent);
  656. else
  657. rootMouseMove(mLastEvent);
  658. }
  659. return true;
  660. }
  661. else if ( event->objType == SI_ZAXIS )
  662. {
  663. mLastEvent.mousePoint.x = S32( cursorPt.x );
  664. mLastEvent.mousePoint.y = S32( cursorPt.y );
  665. mLastEvent.eventID = 0;
  666. if ( event->fValue < 0.0f )
  667. rootMouseWheelDown( mLastEvent );
  668. else
  669. rootMouseWheelUp( mLastEvent );
  670. }
  671. else if(event->objType == SI_BUTTON)
  672. {
  673. //copy the cursor point into the event
  674. mLastEvent.mousePoint.x = S32(cursorPt.x);
  675. mLastEvent.mousePoint.y = S32(cursorPt.y);
  676. mLastEvent.eventID = 0;
  677. mMouseDownPoint = cursorPt;
  678. if(event->objInst == KEY_BUTTON0) // left button
  679. {
  680. //see if button was pressed
  681. if (event->action == SI_MAKE)
  682. {
  683. U32 curTime = Platform::getVirtualMilliseconds();
  684. mNextMouseTime = curTime + mInitialMouseDelay;
  685. //if the last button pressed was the left...
  686. if (mLeftMouseLast)
  687. {
  688. //if it was within the double click time count the clicks
  689. if ((S32)curTime - mLastMouseDownTime <= mDoubleClickTime)
  690. mLastMouseClickCount++;
  691. else
  692. mLastMouseClickCount = 1;
  693. }
  694. else
  695. {
  696. mLeftMouseLast = true;
  697. mLastMouseClickCount = 1;
  698. }
  699. mLastMouseDownTime = curTime;
  700. mLastEvent.mouseClickCount = mLastMouseClickCount;
  701. rootMouseDown(mLastEvent);
  702. }
  703. //else button was released
  704. else
  705. {
  706. mNextMouseTime = 0xFFFFFFFF;
  707. rootMouseUp(mLastEvent);
  708. }
  709. return true;
  710. }
  711. else if(event->objInst == KEY_BUTTON1) // right button
  712. {
  713. if(event->action == SI_MAKE)
  714. {
  715. U32 curTime = Platform::getVirtualMilliseconds();
  716. //if the last button pressed was the right...
  717. if (mRightMouseLast)
  718. {
  719. //if it was within the double click time count the clicks
  720. if ((S32)curTime - mLastMouseDownTime <= mDoubleClickTime)
  721. mLastMouseClickCount++;
  722. else
  723. mLastMouseClickCount = 1;
  724. }
  725. else
  726. {
  727. mRightMouseLast = true;
  728. mLastMouseClickCount = 1;
  729. }
  730. mLastMouseDownTime = curTime;
  731. mLastEvent.mouseClickCount = mLastMouseClickCount;
  732. rootRightMouseDown(mLastEvent);
  733. }
  734. else // it was a mouse up
  735. rootRightMouseUp(mLastEvent);
  736. return true;
  737. }
  738. else if(event->objInst == KEY_BUTTON2) // middle button
  739. {
  740. if(event->action == SI_MAKE)
  741. {
  742. U32 curTime = Platform::getVirtualMilliseconds();
  743. //if the last button pressed was the right...
  744. if (mMiddleMouseLast)
  745. {
  746. //if it was within the double click time count the clicks
  747. if ((S32)curTime - mLastMouseDownTime <= mDoubleClickTime)
  748. mLastMouseClickCount++;
  749. else
  750. mLastMouseClickCount = 1;
  751. }
  752. else
  753. {
  754. mMiddleMouseLast = true;
  755. mLastMouseClickCount = 1;
  756. }
  757. mLastMouseDownTime = curTime;
  758. mLastEvent.mouseClickCount = mLastMouseClickCount;
  759. rootMiddleMouseDown(mLastEvent);
  760. }
  761. else // it was a mouse up
  762. rootMiddleMouseUp(mLastEvent);
  763. return true;
  764. }
  765. }
  766. }
  767. return false;
  768. }
  769. void GuiCanvas::rootMouseDown(const GuiEvent &event)
  770. {
  771. mPrevMouseTime = Platform::getVirtualMilliseconds();
  772. mMouseButtonDown = true;
  773. //pass the event to the mouse locked control
  774. if (bool(mMouseCapturedControl))
  775. mMouseCapturedControl->onMouseDown(event);
  776. //else pass it to whoever is underneath the cursor
  777. else
  778. {
  779. iterator i;
  780. i = end();
  781. while (i != begin())
  782. {
  783. i--;
  784. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  785. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  786. //see if the controlHit is a modeless dialog...
  787. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  788. continue;
  789. else
  790. {
  791. controlHit->onMouseDown(event);
  792. break;
  793. }
  794. }
  795. }
  796. if (bool(mMouseControl))
  797. mMouseControlClicked = true;
  798. }
  799. void GuiCanvas::findMouseControl(const GuiEvent &event)
  800. {
  801. if(size() == 0)
  802. {
  803. mMouseControl = NULL;
  804. return;
  805. }
  806. GuiControl *controlHit = findHitControl(event.mousePoint);
  807. if(controlHit != static_cast<GuiControl*>(mMouseControl))
  808. {
  809. if(bool(mMouseControl))
  810. mMouseControl->onMouseLeave(event);
  811. mMouseControl = controlHit;
  812. mMouseControl->onMouseEnter(event);
  813. }
  814. }
  815. //Luma: Some fixes from the forums, Dave Calabrese
  816. //http://www.garagegames.com/community/forums/viewthread/93467/1#comment-669559
  817. void GuiCanvas::rootScreenTouchDown(const GuiEvent &event)
  818. {
  819. mPrevMouseTime = Platform::getVirtualMilliseconds();
  820. mMouseButtonDown = true;
  821. iterator i;
  822. i = end();
  823. while (i != begin())
  824. {
  825. i--;
  826. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  827. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  828. //If the control we hit is not the same one that is locked,
  829. // then unlock the existing control.
  830. if (bool(mMouseCapturedControl))
  831. {
  832. if(mMouseCapturedControl->isMouseLocked())
  833. {
  834. if(mMouseCapturedControl != controlHit)
  835. {
  836. mMouseCapturedControl->onMouseLeave(event);
  837. }
  838. }
  839. }
  840. //see if the controlHit is a modeless dialog...
  841. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  842. continue;
  843. else
  844. {
  845. controlHit->onMouseDown(event);
  846. break;
  847. }
  848. }
  849. if (bool(mMouseControl))
  850. mMouseControlClicked = true;
  851. }
  852. void GuiCanvas::rootScreenTouchUp(const GuiEvent &event)
  853. {
  854. mPrevMouseTime = Platform::getVirtualMilliseconds();
  855. mMouseButtonDown = false;
  856. iterator i;
  857. i = end();
  858. while (i != begin())
  859. {
  860. i--;
  861. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  862. GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
  863. //see if the controlHit is a modeless dialog...
  864. if ((! controlHit->mActive) && (! controlHit->mProfile->mModal))
  865. continue;
  866. else
  867. {
  868. controlHit->onMouseUp(event);
  869. break;
  870. }
  871. }
  872. }
  873. void GuiCanvas::rootScreenTouchMove(const GuiEvent &event)
  874. {
  875. //pass the event to the mouse locked control
  876. if (bool(mMouseCapturedControl))
  877. {
  878. checkLockMouseMove(event);
  879. if(!mMouseCapturedControl.isNull())
  880. mMouseCapturedControl->onMouseDragged(event);
  881. }
  882. else
  883. {
  884. findMouseControl(event);
  885. if(bool(mMouseControl))
  886. {
  887. mMouseControl->onMouseDragged(event);
  888. }
  889. }
  890. }
  891. void GuiCanvas::refreshMouseControl()
  892. {
  893. GuiEvent evt;
  894. evt.mousePoint.x = S32(cursorPt.x);
  895. evt.mousePoint.y = S32(cursorPt.y);
  896. findMouseControl(evt);
  897. }
  898. void GuiCanvas::rootMouseUp(const GuiEvent &event)
  899. {
  900. mPrevMouseTime = Platform::getVirtualMilliseconds();
  901. mMouseButtonDown = false;
  902. //pass the event to the mouse locked control
  903. if (bool(mMouseCapturedControl))
  904. mMouseCapturedControl->onMouseUp(event);
  905. else
  906. {
  907. findMouseControl(event);
  908. if(bool(mMouseControl))
  909. mMouseControl->onMouseUp(event);
  910. }
  911. }
  912. void GuiCanvas::checkLockMouseMove(const GuiEvent &event)
  913. {
  914. GuiControl *controlHit = findHitControl(event.mousePoint);
  915. if(controlHit != mMouseControl)
  916. {
  917. if(mMouseControl == mMouseCapturedControl)
  918. mMouseCapturedControl->onMouseLeave(event);
  919. else if(controlHit == mMouseCapturedControl)
  920. mMouseCapturedControl->onMouseEnter(event);
  921. mMouseControl = controlHit;
  922. }
  923. }
  924. void GuiCanvas::rootMouseDragged(const GuiEvent &event)
  925. {
  926. //pass the event to the mouse locked control
  927. if (bool(mMouseCapturedControl))
  928. {
  929. checkLockMouseMove(event);
  930. if(!mMouseCapturedControl.isNull())
  931. mMouseCapturedControl->onMouseDragged(event);
  932. //Luma: Mouse dragged calls mouse Moved on iPhone
  933. #ifdef TORQUE_OS_IOS
  934. mMouseCapturedControl->onMouseMove(event);
  935. #endif //TORQUE_OS_IOS
  936. }
  937. else
  938. {
  939. findMouseControl(event);
  940. if(bool(mMouseControl))
  941. {
  942. mMouseControl->onMouseDragged(event);
  943. #ifdef TORQUE_OS_IOS
  944. mMouseControl->onMouseMove(event);
  945. #endif //TORQUE_OS_IOS
  946. }
  947. }
  948. }
  949. void GuiCanvas::rootMouseMove(const GuiEvent &event)
  950. {
  951. if(mMouseCapturedControl != NULL)
  952. {
  953. checkLockMouseMove(event);
  954. if(mMouseCapturedControl != NULL)
  955. mMouseCapturedControl->onMouseMove(event);
  956. }
  957. else
  958. {
  959. findMouseControl(event);
  960. if(bool(mMouseControl))
  961. mMouseControl->onMouseMove(event);
  962. }
  963. }
  964. void GuiCanvas::rootRightMouseDown(const GuiEvent &event)
  965. {
  966. mPrevMouseTime = Platform::getVirtualMilliseconds();
  967. mMouseRightButtonDown = true;
  968. if (bool(mMouseCapturedControl))
  969. mMouseCapturedControl->onRightMouseDown(event);
  970. else
  971. {
  972. findMouseControl(event);
  973. if(bool(mMouseControl))
  974. {
  975. mMouseControl->onRightMouseDown(event);
  976. }
  977. }
  978. }
  979. void GuiCanvas::rootRightMouseUp(const GuiEvent &event)
  980. {
  981. mPrevMouseTime = Platform::getVirtualMilliseconds();
  982. mMouseRightButtonDown = false;
  983. if (bool(mMouseCapturedControl))
  984. mMouseCapturedControl->onRightMouseUp(event);
  985. else
  986. {
  987. findMouseControl(event);
  988. if(bool(mMouseControl))
  989. mMouseControl->onRightMouseUp(event);
  990. }
  991. }
  992. void GuiCanvas::rootRightMouseDragged(const GuiEvent &event)
  993. {
  994. mPrevMouseTime = Platform::getVirtualMilliseconds();
  995. if (bool(mMouseCapturedControl))
  996. {
  997. checkLockMouseMove(event);
  998. mMouseCapturedControl->onRightMouseDragged(event);
  999. }
  1000. else
  1001. {
  1002. findMouseControl(event);
  1003. if(bool(mMouseControl))
  1004. mMouseControl->onRightMouseDragged(event);
  1005. }
  1006. }
  1007. void GuiCanvas::rootMiddleMouseDown(const GuiEvent &event)
  1008. {
  1009. mPrevMouseTime = Platform::getVirtualMilliseconds();
  1010. mMouseMiddleButtonDown = true;
  1011. if (bool(mMouseCapturedControl))
  1012. mMouseCapturedControl->onMiddleMouseDown(event);
  1013. else
  1014. {
  1015. findMouseControl(event);
  1016. if(bool(mMouseControl))
  1017. {
  1018. mMouseControl->onMiddleMouseDown(event);
  1019. }
  1020. }
  1021. }
  1022. void GuiCanvas::rootMiddleMouseUp(const GuiEvent &event)
  1023. {
  1024. mPrevMouseTime = Platform::getVirtualMilliseconds();
  1025. mMouseMiddleButtonDown = false;
  1026. if (bool(mMouseCapturedControl))
  1027. mMouseCapturedControl->onMiddleMouseUp(event);
  1028. else
  1029. {
  1030. findMouseControl(event);
  1031. if(bool(mMouseControl))
  1032. mMouseControl->onMiddleMouseUp(event);
  1033. }
  1034. }
  1035. void GuiCanvas::rootMiddleMouseDragged(const GuiEvent &event)
  1036. {
  1037. mPrevMouseTime = Platform::getVirtualMilliseconds();
  1038. if (bool(mMouseCapturedControl))
  1039. {
  1040. checkLockMouseMove(event);
  1041. mMouseCapturedControl->onMiddleMouseDragged(event);
  1042. }
  1043. else
  1044. {
  1045. findMouseControl(event);
  1046. if(bool(mMouseControl))
  1047. mMouseControl->onMiddleMouseDragged(event);
  1048. }
  1049. }
  1050. void GuiCanvas::rootMouseWheelUp(const GuiEvent &event)
  1051. {
  1052. if (bool(mMouseCapturedControl))
  1053. mMouseCapturedControl->onMouseWheelUp(event);
  1054. else
  1055. {
  1056. findMouseControl(event);
  1057. if (bool(mMouseControl))
  1058. mMouseControl->onMouseWheelUp(event);
  1059. }
  1060. }
  1061. void GuiCanvas::rootMouseWheelDown(const GuiEvent &event)
  1062. {
  1063. if (bool(mMouseCapturedControl))
  1064. mMouseCapturedControl->onMouseWheelDown(event);
  1065. else
  1066. {
  1067. findMouseControl(event);
  1068. if (bool(mMouseControl))
  1069. mMouseControl->onMouseWheelDown(event);
  1070. }
  1071. }
  1072. void GuiCanvas::setContentControl(GuiControl *gui)
  1073. {
  1074. if(!gui)
  1075. return;
  1076. // If we're setting the same content, don't do anything
  1077. if( gui == at(0) )
  1078. return;
  1079. //remove all dialogs on layer 0
  1080. U32 index = 0;
  1081. while ((U32)size() > index)
  1082. {
  1083. GuiControl *ctrl = static_cast<GuiControl*>((*this)[index]);
  1084. if (ctrl == gui || ctrl->mLayer != 0)
  1085. index++;
  1086. removeObject(ctrl);
  1087. Sim::getGuiGroup()->addObject(ctrl);
  1088. }
  1089. // lose the first responder from the old GUI
  1090. GuiControl* responder = gui->findFirstTabable();
  1091. if(responder)
  1092. responder->setFirstResponder();
  1093. //add the gui to the front
  1094. if(!size() || gui != (*this)[0])
  1095. {
  1096. // automatically wakes objects in GuiControl::onWake
  1097. addObject(gui);
  1098. if (size() >= 2)
  1099. reOrder(gui, *begin());
  1100. }
  1101. //refresh the entire gui
  1102. resetUpdateRegions();
  1103. //rebuild the accelerator map
  1104. mAcceleratorMap.clear();
  1105. for(iterator i = end(); i != begin() ; )
  1106. {
  1107. i--;
  1108. GuiControl *ctrl = static_cast<GuiControl *>(*i);
  1109. ctrl->buildAcceleratorMap();
  1110. if (ctrl->mProfile->mModal)
  1111. break;
  1112. }
  1113. refreshMouseControl();
  1114. // Force the canvas to update the sizing of the new content control
  1115. maintainSizing();
  1116. }
  1117. GuiControl *GuiCanvas::getContentControl()
  1118. {
  1119. if(size() > 0)
  1120. return (GuiControl *) first();
  1121. return NULL;
  1122. }
  1123. void GuiCanvas::pushDialogControl(GuiControl *gui, S32 layer)
  1124. {
  1125. //add the gui
  1126. gui->mLayer = layer;
  1127. // GuiControl::addObject wakes the object
  1128. addObject(gui);
  1129. //reorder it to the correct layer
  1130. iterator i;
  1131. for (i = begin(); i != end(); i++)
  1132. {
  1133. GuiControl *ctrl = static_cast<GuiControl*>(*i);
  1134. if (ctrl->mLayer > gui->mLayer)
  1135. {
  1136. reOrder(gui, ctrl);
  1137. break;
  1138. }
  1139. }
  1140. //call the dialog push method
  1141. gui->onDialogPush();
  1142. //find the top most dialog
  1143. //find the first responder
  1144. GuiControl* responder = gui->findFirstTabable();
  1145. if(responder)
  1146. responder->setFirstResponder();
  1147. // call the 'onWake' method?
  1148. //if(wakedGui)
  1149. // Con::executef(gui, 1, "onWake");
  1150. //refresh the entire gui
  1151. resetUpdateRegions();
  1152. //rebuild the accelerator map
  1153. mAcceleratorMap.clear();
  1154. if (size() > 0)
  1155. {
  1156. GuiControl *ctrl = static_cast<GuiControl*>(last());
  1157. ctrl->buildAcceleratorMap();
  1158. }
  1159. refreshMouseControl();
  1160. if(gui->mProfile && gui->mProfile->mModal)
  1161. {
  1162. Input::pushCursor(CursorManager::curArrow);
  1163. }
  1164. }
  1165. void GuiCanvas::popDialogControl(GuiControl *gui)
  1166. {
  1167. if (size() < 1)
  1168. return;
  1169. //first, find the dialog, and call the "onDialogPop()" method
  1170. GuiControl *ctrl = NULL;
  1171. if (gui)
  1172. {
  1173. //*** DAW: For modal dialogs, reset the mouse cursor and enable the appropriate platform menus
  1174. if(gui->mProfile && gui->mProfile->mModal)
  1175. {
  1176. Input::popCursor();
  1177. }
  1178. //make sure the gui really exists on the stack
  1179. iterator i;
  1180. bool found = false;
  1181. for(i = begin(); i != end(); i++)
  1182. {
  1183. GuiControl *check = static_cast<GuiControl *>(*i);
  1184. if (check == gui)
  1185. {
  1186. ctrl = check;
  1187. found = true;
  1188. }
  1189. }
  1190. if (! found)
  1191. return;
  1192. }
  1193. else
  1194. ctrl = static_cast<GuiControl*>(last());
  1195. //call the "on pop" function
  1196. ctrl->onDialogPop();
  1197. // sleep the object
  1198. //now pop the last child (will sleep if awake)
  1199. removeObject(ctrl);
  1200. // Save the old responder:
  1201. Sim::getGuiGroup()->addObject(ctrl);
  1202. if (size() > 0)
  1203. {
  1204. GuiControl *ctrl = static_cast<GuiControl *>(last());
  1205. if(ctrl->mFirstResponder)
  1206. ctrl->mFirstResponder->setFirstResponder();
  1207. }
  1208. else
  1209. {
  1210. setFirstResponder(NULL);
  1211. }
  1212. //refresh the entire gui
  1213. resetUpdateRegions();
  1214. //rebuild the accelerator map
  1215. mAcceleratorMap.clear();
  1216. if (size() > 0)
  1217. {
  1218. GuiControl *ctrl = static_cast<GuiControl*>(last());
  1219. ctrl->buildAcceleratorMap();
  1220. }
  1221. refreshMouseControl();
  1222. }
  1223. void GuiCanvas::popDialogControl(S32 layer)
  1224. {
  1225. if (size() < 1)
  1226. return;
  1227. GuiControl *ctrl = NULL;
  1228. iterator i = end(); // find in z order (last to first)
  1229. while (i != begin())
  1230. {
  1231. i--;
  1232. ctrl = static_cast<GuiControl*>(*i);
  1233. if (ctrl->mLayer == layer)
  1234. break;
  1235. }
  1236. if (ctrl)
  1237. popDialogControl(ctrl);
  1238. }
  1239. void GuiCanvas::mouseLock(GuiControl *lockingControl)
  1240. {
  1241. if (bool(mMouseCapturedControl))
  1242. return;
  1243. mMouseCapturedControl = lockingControl;
  1244. if(mMouseControl && mMouseControl != mMouseCapturedControl)
  1245. {
  1246. GuiEvent evt;
  1247. evt.mousePoint.x = S32(cursorPt.x);
  1248. evt.mousePoint.y = S32(cursorPt.y);
  1249. mMouseControl->onMouseLeave(evt);
  1250. }
  1251. }
  1252. void GuiCanvas::mouseUnlock(GuiControl *lockingControl)
  1253. {
  1254. if (static_cast<GuiControl*>(mMouseCapturedControl) != lockingControl)
  1255. return;
  1256. GuiEvent evt;
  1257. evt.mousePoint.x = S32(cursorPt.x);
  1258. evt.mousePoint.y = S32(cursorPt.y);
  1259. GuiControl * controlHit = findHitControl(evt.mousePoint);
  1260. if(controlHit != mMouseCapturedControl)
  1261. {
  1262. mMouseControl = controlHit;
  1263. mMouseControlClicked = false;
  1264. if(bool(mMouseControl))
  1265. mMouseControl->onMouseEnter(evt);
  1266. }
  1267. mMouseCapturedControl = NULL;
  1268. }
  1269. void GuiCanvas::paint()
  1270. {
  1271. resetUpdateRegions();
  1272. // inhibit explicit refreshes in the case we're swapped out
  1273. if (TextureManager::mDGLRender)
  1274. renderFrame(false);
  1275. }
  1276. void GuiCanvas::maintainSizing()
  1277. {
  1278. Point2I size = Platform::getWindowSize();
  1279. if(size.x == 0 || size.y == 0)
  1280. return;
  1281. RectI screenRect(0, 0, size.x, size.y);
  1282. mBounds = screenRect;
  1283. //all bottom level controls should be the same dimensions as the canvas
  1284. //this is necessary for passing mouse events accurately
  1285. iterator i;
  1286. for (i = begin(); i != end(); i++)
  1287. {
  1288. AssertFatal(static_cast<GuiControl*>((*i))->isAwake(), "GuiCanvas::renderFrame: ctrl is not awake");
  1289. GuiControl *ctrl = static_cast<GuiControl*>(*i);
  1290. Point2I ext = ctrl->getExtent();
  1291. Point2I pos = ctrl->getPosition();
  1292. if(pos != screenRect.point || ext != screenRect.extent)
  1293. {
  1294. ctrl->resize(screenRect.point, screenRect.extent);
  1295. resetUpdateRegions();
  1296. }
  1297. }
  1298. }
  1299. void GuiCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */)
  1300. {
  1301. PROFILE_START(CanvasPreRender);
  1302. #ifndef TORQUE_OS_IOS
  1303. if(mRenderFront)
  1304. glDrawBuffer(GL_FRONT);
  1305. else
  1306. glDrawBuffer(GL_BACK);
  1307. #endif
  1308. // Make sure the root control is the size of the canvas.
  1309. Point2I size = Platform::getWindowSize();
  1310. if(size.x == 0 || size.y == 0)
  1311. {
  1312. //Luma: Fixed missing PROFILE_END()
  1313. PROFILE_END();
  1314. return;
  1315. }
  1316. RectI screenRect(0, 0, size.x, size.y);
  1317. maintainSizing();
  1318. //preRender (recursive) all controls
  1319. preRender();
  1320. PROFILE_END();
  1321. if(preRenderOnly)
  1322. return;
  1323. // for now, just always reset the update regions - this is a
  1324. // fix for FSAA on ATI cards
  1325. resetUpdateRegions();
  1326. // Moved this below object integration for performance reasons. -JDD
  1327. // // finish the gl render so we don't get too far ahead of ourselves
  1328. //#if defined(TORQUE_OS_WIN32)
  1329. // PROFILE_START(glFinish);
  1330. // glFinish();
  1331. // PROFILE_END();
  1332. //#endif
  1333. //draw the mouse, but not using tags...
  1334. PROFILE_START(CanvasRenderControls);
  1335. GuiCursor *mouseCursor = NULL;
  1336. bool cursorVisible = true;
  1337. if(bool(mMouseCapturedControl))
  1338. mMouseCapturedControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
  1339. else if(bool(mMouseControl))
  1340. mMouseControl->getCursor(mouseCursor, cursorVisible, mLastEvent);
  1341. Point2I cursorPos((S32)cursorPt.x, (S32)cursorPt.y);
  1342. if(!mouseCursor)
  1343. mouseCursor = defaultCursor;
  1344. if(lastCursorON && lastCursor)
  1345. {
  1346. Point2I spot = lastCursor->getHotSpot();
  1347. Point2I cext = lastCursor->getExtent();
  1348. Point2I pos = lastCursorPt - spot;
  1349. addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
  1350. }
  1351. if(cursorVisible && mouseCursor)
  1352. {
  1353. Point2I spot = mouseCursor->getHotSpot();
  1354. Point2I cext = mouseCursor->getExtent();
  1355. Point2I pos = cursorPos - spot;
  1356. addUpdateRegion(pos - Point2I(2, 2), Point2I(cext.x + 4, cext.y + 4));
  1357. }
  1358. lastCursorON = cursorVisible;
  1359. lastCursor = mouseCursor;
  1360. lastCursorPt = cursorPos;
  1361. RectI updateUnion;
  1362. buildUpdateUnion(&updateUnion);
  1363. if (updateUnion.intersect(screenRect))
  1364. {
  1365. // Clear the background color if requested.
  1366. if ( mUseBackgroundColor )
  1367. {
  1368. glClearColor( mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha );
  1369. glClear(GL_COLOR_BUFFER_BIT);
  1370. }
  1371. //render the dialogs
  1372. iterator i;
  1373. for(i = begin(); i != end(); i++)
  1374. {
  1375. GuiControl *contentCtrl = static_cast<GuiControl*>(*i);
  1376. dglSetClipRect(updateUnion);
  1377. glDisable( GL_CULL_FACE );
  1378. contentCtrl->onRender(contentCtrl->getPosition(), updateUnion);
  1379. }
  1380. // Tooltip resource
  1381. if(bool(mMouseControl))
  1382. {
  1383. U32 curTime = Platform::getRealMilliseconds();
  1384. if(hoverControl == mMouseControl)
  1385. {
  1386. if(hoverPositionSet || (curTime - hoverControlStart) >= (U32)hoverControl->mTipHoverTime || (curTime - hoverLeftControlTime) <= (U32)hoverControl->mTipHoverTime)
  1387. {
  1388. // MM: Controls whether the tooltip tracks the mouse cursor or not.
  1389. #if 0
  1390. if(!hoverPositionSet)
  1391. {
  1392. hoverPosition = cursorPos;
  1393. }
  1394. #else
  1395. hoverPosition = cursorPos;
  1396. #endif
  1397. hoverPositionSet = mMouseControl->renderTooltip(hoverPosition);
  1398. }
  1399. } else
  1400. {
  1401. if(hoverPositionSet)
  1402. {
  1403. hoverLeftControlTime = curTime;
  1404. hoverPositionSet = false;
  1405. }
  1406. hoverControl = mMouseControl;
  1407. hoverControlStart = curTime;
  1408. }
  1409. }
  1410. //end tooltip
  1411. dglSetClipRect(updateUnion);
  1412. //temp draw the mouse
  1413. if (cursorON && mShowCursor && !mouseCursor)
  1414. {
  1415. #ifdef TORQUE_OS_IOS
  1416. glColor4ub(255, 0, 0, 255);
  1417. GLfloat vertices[] = {
  1418. (GLfloat)(cursorPt.x),(GLfloat)(cursorPt.y),
  1419. (GLfloat)(cursorPt.x + 2),(GLfloat)(cursorPt.y),
  1420. (GLfloat)(cursorPt.x + 2),(GLfloat)(cursorPt.y + 2),
  1421. (GLfloat)(cursorPt.x),(GLfloat)(cursorPt.y + 2),
  1422. };
  1423. glEnableClientState(GL_VERTEX_ARRAY);
  1424. glVertexPointer(2, GL_FLOAT, 0, vertices);
  1425. glDrawArrays(GL_LINE_LOOP, 0, 4);
  1426. #else
  1427. glColor4ub(255, 0, 0, 255);
  1428. glRecti((S32)cursorPt.x, (S32)cursorPt.y, (S32)(cursorPt.x + 2), (S32)(cursorPt.y + 2));
  1429. #endif
  1430. }
  1431. //DEBUG
  1432. //draw the help ctrl
  1433. //if (helpCtrl)
  1434. //{
  1435. // helpCtrl->render(srf);
  1436. //}
  1437. if (cursorON && mouseCursor && mShowCursor)
  1438. {
  1439. Point2I pos((S32)cursorPt.x, (S32)cursorPt.y);
  1440. Point2I spot = mouseCursor->getHotSpot();
  1441. pos -= spot;
  1442. mouseCursor->render(pos);
  1443. }
  1444. }
  1445. PROFILE_END();
  1446. if( bufferSwap )
  1447. swapBuffers();
  1448. //#if defined(TORQUE_OS_WIN32)
  1449. // PROFILE_START(glFinish);
  1450. // glFinish(); // This was changed to work with the D3D layer -pw
  1451. // PROFILE_END();
  1452. //#endif
  1453. }
  1454. void GuiCanvas::swapBuffers()
  1455. {
  1456. PROFILE_START(SwapBuffers);
  1457. //flip the surface
  1458. if(!mRenderFront)
  1459. Video::swapBuffers();
  1460. PROFILE_END();
  1461. }
  1462. void GuiCanvas::buildUpdateUnion(RectI *updateUnion)
  1463. {
  1464. *updateUnion = mOldUpdateRects[0];
  1465. //the update region should encompass the oldUpdateRects, and the curUpdateRect
  1466. Point2I upperL;
  1467. Point2I lowerR;
  1468. upperL.x = getMin(mOldUpdateRects[0].point.x, mOldUpdateRects[1].point.x);
  1469. upperL.x = getMin(upperL.x, mCurUpdateRect.point.x);
  1470. upperL.y = getMin(mOldUpdateRects[0].point.y, mOldUpdateRects[1].point.y);
  1471. upperL.y = getMin(upperL.y, mCurUpdateRect.point.y);
  1472. lowerR.x = getMax(mOldUpdateRects[0].point.x + mOldUpdateRects[0].extent.x, mOldUpdateRects[1].point.x + mOldUpdateRects[1].extent.x);
  1473. lowerR.x = getMax(lowerR.x, mCurUpdateRect.point.x + mCurUpdateRect.extent.x);
  1474. lowerR.y = getMax(mOldUpdateRects[0].point.y + mOldUpdateRects[0].extent.y, mOldUpdateRects[1].point.y + mOldUpdateRects[1].extent.y);
  1475. lowerR.y = getMax(lowerR.y, mCurUpdateRect.point.y + mCurUpdateRect.extent.y);
  1476. updateUnion->point = upperL;
  1477. updateUnion->extent = lowerR - upperL;
  1478. //shift the oldUpdateRects
  1479. mOldUpdateRects[0] = mOldUpdateRects[1];
  1480. mOldUpdateRects[1] = mCurUpdateRect;
  1481. mCurUpdateRect.point.set(0,0);
  1482. mCurUpdateRect.extent.set(0,0);
  1483. }
  1484. void GuiCanvas::addUpdateRegion(Point2I pos, Point2I ext)
  1485. {
  1486. if(mCurUpdateRect.extent.x == 0)
  1487. {
  1488. mCurUpdateRect.point = pos;
  1489. mCurUpdateRect.extent = ext;
  1490. }
  1491. else
  1492. {
  1493. Point2I upperL;
  1494. upperL.x = getMin(mCurUpdateRect.point.x, pos.x);
  1495. upperL.y = getMin(mCurUpdateRect.point.y, pos.y);
  1496. Point2I lowerR;
  1497. lowerR.x = getMax(mCurUpdateRect.point.x + mCurUpdateRect.extent.x, pos.x + ext.x);
  1498. lowerR.y = getMax(mCurUpdateRect.point.y + mCurUpdateRect.extent.y, pos.y + ext.y);
  1499. mCurUpdateRect.point = upperL;
  1500. mCurUpdateRect.extent = lowerR - upperL;
  1501. }
  1502. }
  1503. void GuiCanvas::resetUpdateRegions()
  1504. {
  1505. //DEBUG - get surface width and height
  1506. mOldUpdateRects[0].set(mBounds.point, mBounds.extent);
  1507. mOldUpdateRects[1] = mOldUpdateRects[0];
  1508. mCurUpdateRect = mOldUpdateRects[0];
  1509. }
  1510. void GuiCanvas::setFirstResponder( GuiControl* newResponder )
  1511. {
  1512. GuiControl* oldResponder = mFirstResponder;
  1513. Parent::setFirstResponder( newResponder );
  1514. if ( oldResponder && ( oldResponder != mFirstResponder ) )
  1515. oldResponder->onLoseFirstResponder();
  1516. }