guiSceneObjectCtrl.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  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 "graphics/dgl.h"
  23. #include "console/consoleTypes.h"
  24. #include "gui/guiDefaultControlRender.h"
  25. #include "guiSceneObjectCtrl.h"
  26. #include "debug/profiler.h"
  27. // -----------------------------------------------------------------------------
  28. IMPLEMENT_CONOBJECT(GuiSceneObjectCtrl);
  29. // -----------------------------------------------------------------------------
  30. // -----------------------------------------------------------------------------
  31. // Constructor.
  32. // -----------------------------------------------------------------------------
  33. GuiSceneObjectCtrl::GuiSceneObjectCtrl(void)
  34. {
  35. // Reset Scene Object Name.
  36. mSceneObjectName = StringTable->EmptyString;
  37. // Default to no render margin
  38. mMargin = 0;
  39. mCaption = StringTable->EmptyString;
  40. //mStateOn = false;
  41. //mButtonType = ButtonTypeRadio;
  42. // Set-up private batcher.
  43. mBatchRenderer.setDebugStats( &mDebugStats );
  44. mBatchRenderer.setStrictOrderMode( true, true );
  45. mBatchRenderer.setBatchEnabled( false );
  46. }
  47. // -----------------------------------------------------------------------------
  48. // Persistent Fields.
  49. // -----------------------------------------------------------------------------
  50. void GuiSceneObjectCtrl::initPersistFields()
  51. {
  52. // Call Parent.
  53. Parent::initPersistFields();
  54. // Define Fields.
  55. addGroup("GuiSceneObjectCtrl");
  56. addField("renderMargin", TypeS32, Offset(mMargin, GuiSceneObjectCtrl));
  57. addField("sceneObject", TypeString, Offset(mSceneObjectName, GuiSceneObjectCtrl));
  58. endGroup("GuiSceneObjectCtrl");
  59. }
  60. // -----------------------------------------------------------------------------
  61. // Wake!
  62. // -----------------------------------------------------------------------------
  63. bool GuiSceneObjectCtrl::onWake()
  64. {
  65. // Call Parent.
  66. if (!Parent::onWake())
  67. return false;
  68. if( mProfile->constructBitmapArray() >= 36 )
  69. mHasTexture = true;
  70. else
  71. mHasTexture = false;
  72. // Activate.
  73. setActive(true);
  74. // All Okay.
  75. return true;
  76. }
  77. // -----------------------------------------------------------------------------
  78. // Sleep!
  79. // -----------------------------------------------------------------------------
  80. void GuiSceneObjectCtrl::onSleep()
  81. {
  82. Parent::onSleep();
  83. }
  84. // -----------------------------------------------------------------------------
  85. //
  86. // -----------------------------------------------------------------------------
  87. void GuiSceneObjectCtrl::inspectPostApply()
  88. {
  89. // Call Parent.
  90. Parent::inspectPostApply();
  91. // Set the Scene Object.
  92. setSceneObject( mSceneObjectName );
  93. }
  94. // -----------------------------------------------------------------------------
  95. // Set Scene Object.
  96. // -----------------------------------------------------------------------------
  97. ConsoleMethod( GuiSceneObjectCtrl, setSceneObject, void, 3, 3, "(string obj) Set the scene-object displayed in the control."
  98. "@param obj Either the object's ID or its name."
  99. "@return No return value.")
  100. {
  101. // Set Scene Object.
  102. object->setSceneObject( argv[2] );
  103. }
  104. // Set Scene Object.
  105. void GuiSceneObjectCtrl::setSceneObject( const char* name )
  106. {
  107. // Reset existing object.
  108. mSelectedSceneObject = NULL;
  109. // Get Scene Name.
  110. mSceneObjectName = StringTable->insert( name ? name : "" );
  111. // Valid Scene Object Name?
  112. if ( *mSceneObjectName )
  113. {
  114. // Fetch Scene Object.
  115. SceneObject* pSceneObject = dynamic_cast<SceneObject*>(Sim::findObject( name ));
  116. // Valid?
  117. if ( pSceneObject )
  118. {
  119. // Yes, so set Scene Object.
  120. mSelectedSceneObject = pSceneObject;
  121. // The scene object needs to be integrated otherwise the render OOBB which this GUI control
  122. // relies upon will be undefined. This dependency needs resolving but I suspect it never will.
  123. DebugStats debugStats;
  124. mSelectedSceneObject->preIntegrate(0.0f, 0.0f, &debugStats );
  125. }
  126. }
  127. else
  128. mSelectedSceneObject = NULL;
  129. // Do an update.
  130. setUpdate();
  131. }
  132. ConsoleMethod( GuiSceneObjectCtrl, getSceneObject, const char*, 2,2, "() \n@return Returns displaying sceneobject id")
  133. {
  134. SceneObject *sceneObject = object->getSceneObject();
  135. if( !sceneObject )
  136. return "";
  137. return sceneObject->getIdString();
  138. }
  139. ConsoleMethod( GuiSceneObjectCtrl, setCaption, void, 3, 3, "(string caption) Sets the object caption to specified string.\n"
  140. "@return No return value.")
  141. {
  142. object->setCaption( argv[2] );
  143. }
  144. void GuiSceneObjectCtrl::setCaption( const char* caption )
  145. {
  146. if( caption != NULL )
  147. mCaption = StringTable->insert( caption );
  148. }
  149. //
  150. //
  151. //
  152. void GuiSceneObjectCtrl::onMouseUp(const GuiEvent &event)
  153. {
  154. if( mDepressed && ( event.mouseClickCount % 2 ) == 0 )
  155. Con::executef( this, 2, "onDoubleClick" );
  156. Parent::onTouchUp( event );
  157. }
  158. void GuiSceneObjectCtrl::onMouseLeave( const GuiEvent &event )
  159. {
  160. Con::executef( this, 2, "onMouseLeave" );
  161. Parent::onTouchLeave( event );
  162. }
  163. void GuiSceneObjectCtrl::onMouseEnter( const GuiEvent &event )
  164. {
  165. Con::executef( this, 2, "onMouseEnter" );
  166. Parent::onTouchEnter( event );
  167. }
  168. void GuiSceneObjectCtrl::onMouseDragged( const GuiEvent &event )
  169. {
  170. Con::executef( this, 2, "onMouseDragged" );
  171. Parent::onTouchDragged( event );
  172. }
  173. // -----------------------------------------------------------------------------
  174. // Render any selected Scene Object.
  175. // -----------------------------------------------------------------------------
  176. void GuiSceneObjectCtrl::onRender(Point2I offset, const RectI& updateRect)
  177. {
  178. PROFILE_SCOPE(guiT2DObjectCtrl_onRender);
  179. RectI ctrlRect( offset, mBounds.extent );
  180. // Draw Background
  181. if( mDepressed )
  182. {
  183. if( mHasTexture )
  184. renderUniversalRect( ctrlRect, mProfile, GuiControlState::SelectedState);
  185. else
  186. dglDrawRectFill( ctrlRect, mProfile->mFillColorHL );
  187. }
  188. else if ( mMouseOver )
  189. {
  190. if( mHasTexture )
  191. renderUniversalRect( ctrlRect, mProfile, GuiControlState::HighlightState);
  192. else
  193. dglDrawRectFill( ctrlRect, mProfile->mFillColorHL );
  194. }
  195. else
  196. {
  197. if( mHasTexture )
  198. renderUniversalRect( ctrlRect, mProfile, GuiControlState::NormalState);
  199. else
  200. dglDrawRectFill( ctrlRect, mProfile->mFillColor );
  201. }
  202. //// Render Border.
  203. //if( mProfile->mBorder || mStateOn )
  204. // dglDrawRect(ctrlRect, mProfile->mBorderColor);
  205. // Valid Scene Object?
  206. if ( !mSelectedSceneObject.isNull() )
  207. {
  208. RectI objRect = updateRect;
  209. objRect.inset( mMargin, mMargin );
  210. RectI ctrlRectInset = ctrlRect;
  211. ctrlRectInset.inset( mMargin, mMargin);
  212. // Draw Canvas color for object
  213. if( mHasTexture )
  214. renderUniversalRect( objRect, mProfile, GuiControlState::DisabledState);
  215. else
  216. dglDrawRectFill( objRect, mProfile->mFillColorNA );
  217. // Yes, so fetch object clip boundary.
  218. const b2Vec2* pClipBoundary = mSelectedSceneObject->getRenderOOBB();
  219. // Calculate the GUI-Control Clip Boundary.
  220. const F32 xscale = (pClipBoundary[1].x - pClipBoundary[0].x) / ctrlRectInset.extent.x;
  221. const F32 yscale = (pClipBoundary[2].y - pClipBoundary[0].y) / ctrlRectInset.extent.y;
  222. F32 x1 = pClipBoundary[0].x + ( objRect.point.x - ctrlRectInset.point.x) * xscale;
  223. F32 x2 = pClipBoundary[1].x + ( objRect.point.x + objRect.extent.x - ctrlRectInset.extent.x - ctrlRectInset.point.x) * xscale;
  224. F32 y1 = pClipBoundary[0].y + ( objRect.point.y - ctrlRectInset.point.y) * yscale;
  225. F32 y2 = pClipBoundary[2].y + ( objRect.point.y + objRect.extent.y - ctrlRectInset.extent.y - ctrlRectInset.point.y) * yscale;
  226. Vector2 size = mSelectedSceneObject->getSize();
  227. if (size.x > size.y)
  228. {
  229. S32 center = ctrlRectInset.point.y + (ctrlRectInset.extent.y / 2);
  230. // Save the base state of the objRect before transforming it
  231. S32 baseTop = objRect.point.y;
  232. S32 baseExtent = objRect.extent.y;
  233. S32 baseBottom = baseTop + baseExtent;
  234. // Transform the objRect extent by the aspect ratio
  235. objRect.extent.y = (S32)(ctrlRectInset.extent.y * (size.y / size.x));
  236. // Save the transformed positions of the objRect before clipping
  237. S32 targetTop = (S32)(center - ((ctrlRectInset.extent.y * (size.y / size.x)) / 2));
  238. S32 targetExtent = (S32)(objRect.extent.y);
  239. S32 targetBottom = (S32)(targetTop + objRect.extent.y);
  240. // Set the objRect position based on its aspect ratio
  241. objRect.point.y = (S32)(center - ((ctrlRectInset.extent.y * (size.y / size.x)) / 2));
  242. // Reset the clipping bounds
  243. y1 = pClipBoundary[0].y;
  244. y2 = pClipBoundary[2].y;
  245. // If the object clips of the top or bottom, adjust the extent and clipping bounds accordingly
  246. if (baseTop > targetTop)
  247. {
  248. // Adjust the position and extent
  249. objRect.point.y = baseTop;
  250. objRect.extent.y = getMax(targetBottom - baseTop, 0);
  251. // Set the top clipping boundary
  252. F32 clipRatio = 1.0f - ((1.0f * objRect.extent.y)/targetExtent);
  253. y1 = pClipBoundary[0].y + (pClipBoundary[2].y - pClipBoundary[0].y)*(clipRatio);
  254. }
  255. if (baseBottom < targetBottom)
  256. {
  257. // Adjust the extent
  258. objRect.extent.y = getMax(baseBottom - targetTop, 0);
  259. // Set the bottom clipping boundary
  260. F32 clipRatio = 1.0f - ((1.0f * objRect.extent.y)/targetExtent);
  261. y2 = pClipBoundary[2].y - (pClipBoundary[2].y - pClipBoundary[0].y)*(clipRatio);
  262. }
  263. }
  264. else
  265. {
  266. S32 center = ctrlRectInset.point.x + (ctrlRectInset.extent.x / 2);
  267. // Save the base state of the objRect before transforming it
  268. S32 baseLeft = objRect.point.x;
  269. S32 baseExtent = objRect.extent.x;
  270. S32 baseRight = baseLeft + baseExtent;
  271. // Transform the objRect extent by the aspect ratio
  272. objRect.extent.x = (S32)(ctrlRectInset.extent.x * (size.x / size.y));
  273. // Save the transformed positions of the objRect before clipping
  274. S32 targetLeft = (S32)(center - ((ctrlRectInset.extent.x * (size.x / size.y)) / 2));
  275. S32 targetExtent = (S32)(objRect.extent.x);
  276. S32 targetRight = (S32)(targetLeft + objRect.extent.x);
  277. // Set the objRect position based on its aspect ratio
  278. objRect.point.x = (S32)(center - ((ctrlRectInset.extent.x * (size.x / size.y)) / 2));
  279. // Reset the clipping bounds
  280. x1 = pClipBoundary[0].x;
  281. x2 = pClipBoundary[1].x;
  282. // If the object clips of the left or right, adjust the extent and clipping bounds accordingly
  283. if (baseLeft > targetLeft)
  284. {
  285. // Adjust the position and extent
  286. objRect.point.x = baseLeft;
  287. objRect.extent.x = getMax(targetRight - baseLeft, 0);
  288. // Set the left clipping boundary
  289. F32 clipRatio = 1.0f - ((1.0f * objRect.extent.x)/targetExtent);
  290. x1 = pClipBoundary[0].x + (pClipBoundary[1].x - pClipBoundary[0].x)*(clipRatio);
  291. }
  292. if (baseRight < targetRight)
  293. {
  294. // Adjust the extent
  295. objRect.extent.x = getMax(baseRight - targetLeft, 0);
  296. // Set the right clipping boundary
  297. F32 clipRatio = 1.0f - ((1.0f * objRect.extent.x)/targetExtent);
  298. x2 = pClipBoundary[1].x - (pClipBoundary[1].x - pClipBoundary[0].x)*(clipRatio);
  299. }
  300. }
  301. // Negate the y-clippingpoints to convert to positive-y-up coordinate system of the object
  302. y1 *= -1;
  303. y2 *= -1;
  304. // Setup new logical coordinate system.
  305. glMatrixMode(GL_PROJECTION);
  306. glPushMatrix();
  307. glLoadIdentity();
  308. RectI viewport;
  309. dglGetViewport(&viewport);
  310. if (x1 > x2)
  311. {
  312. F32 temp = x1;
  313. x1 = x2;
  314. x2 = temp;
  315. }
  316. if (y1 > y2)
  317. {
  318. F32 temp = y1;
  319. y1 = y2;
  320. y2 = temp;
  321. }
  322. // Setup Orthographic Projection for Object Area.
  323. #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID)
  324. glOrthof( x1, x2, y1, y2, 0.0f, MAX_LAYERS_SUPPORTED );
  325. #else
  326. glOrtho( x1, x2, y1, y2, 0.0f, MAX_LAYERS_SUPPORTED );
  327. #endif
  328. // Setup new viewport.
  329. dglSetViewport(objRect);
  330. // Set ModelView.
  331. glMatrixMode(GL_MODELVIEW);
  332. glPushMatrix();
  333. glLoadIdentity();
  334. // Enable Alpha Test.
  335. glEnable ( GL_ALPHA_TEST );
  336. glAlphaFunc ( GL_GREATER, 0.0f );
  337. // Calculate maximal clip bounds.
  338. RectF clipBounds( -x1,-y1, x2-x1, y2-y1 );
  339. DebugStats debugStats;
  340. // Render Object in GUI-space.
  341. SceneRenderState guiSceneRenderState(
  342. clipBounds,
  343. clipBounds.centre(),
  344. 0.0f,
  345. MASK_ALL,
  346. MASK_ALL,
  347. Vector2::getOne(),
  348. &debugStats,
  349. this );
  350. SceneRenderRequest guiSceneRenderRequest;
  351. guiSceneRenderRequest.set(
  352. mSelectedSceneObject,
  353. mSelectedSceneObject->getRenderPosition(),
  354. 0.0f );
  355. mSelectedSceneObject->sceneRender( &guiSceneRenderState, &guiSceneRenderRequest, &mBatchRenderer );
  356. // Restore Standard Settings.
  357. glDisable ( GL_DEPTH_TEST );
  358. glDisable ( GL_ALPHA_TEST );
  359. // Restore Matrices.
  360. glMatrixMode(GL_MODELVIEW);
  361. glPopMatrix();
  362. glMatrixMode(GL_PROJECTION);
  363. glPopMatrix();
  364. }
  365. else
  366. {
  367. // No Object so reset name.
  368. mSceneObjectName = NULL;
  369. }
  370. RectI captionRect = ctrlRect;
  371. captionRect.point.y += (captionRect.extent.y / 8);
  372. captionRect.inset(1, 1);
  373. dglSetBitmapModulation( ColorI(0,0,0,255) );
  374. renderText(captionRect.point, captionRect.extent, mCaption, mProfile);
  375. captionRect.inset(1, 1);
  376. dglSetBitmapModulation( mProfile->mFontColor );
  377. renderText(captionRect.point, captionRect.extent, mCaption, mProfile);
  378. // Render Child Controls.
  379. renderChildControls(offset, mBounds, updateRect);
  380. }