guiOffscreenCanvas.cpp 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294
  1. #include "gui/core/guiOffscreenCanvas.h"
  2. #include "gfx/gfxDrawUtil.h"
  3. #include "gfx/gfxTextureManager.h"
  4. #include "gfx/gfxAPI.h"
  5. #include "gfx/gfxDebugEvent.h"
  6. #include "console/consoleTypes.h"
  7. #include "console/console.h"
  8. IMPLEMENT_CONOBJECT(GuiOffscreenCanvas);
  9. GuiOffscreenCanvas* GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL;
  10. Vector<GuiOffscreenCanvas*> GuiOffscreenCanvas::sList;
  11. GuiOffscreenCanvas::GuiOffscreenCanvas()
  12. {
  13. mTargetFormat = GFXFormatR8G8B8A8;
  14. mTargetSize = Point2I(256,256);
  15. mTargetName = "offscreenCanvas";
  16. mTargetDirty = true;
  17. mDynamicTarget = false;
  18. mUseDepth = false;
  19. }
  20. GuiOffscreenCanvas::~GuiOffscreenCanvas()
  21. {
  22. }
  23. void GuiOffscreenCanvas::initPersistFields()
  24. {
  25. docsURL;
  26. addField( "targetSize", TypePoint2I, Offset( mTargetSize, GuiOffscreenCanvas ),"" );
  27. addField( "targetFormat", TypeGFXFormat, Offset( mTargetFormat, GuiOffscreenCanvas ), "");
  28. addField( "targetName", TypeRealString, Offset( mTargetName, GuiOffscreenCanvas ), "");
  29. addField( "dynamicTarget", TypeBool, Offset( mDynamicTarget, GuiOffscreenCanvas ), "");
  30. addField( "useDepth", TypeBool, Offset( mUseDepth, GuiOffscreenCanvas ), "");
  31. addField("canInteract", TypeBool, Offset(mCanInteract, GuiOffscreenCanvas), "");
  32. addField("maxInteractDistance", TypeF32, Offset(mMaxInteractDistance, GuiOffscreenCanvas), "");
  33. Parent::initPersistFields();
  34. }
  35. bool GuiOffscreenCanvas::onAdd()
  36. {
  37. if (GuiControl::onAdd()) // jamesu - skip GuiCanvas onAdd since it sets up GFX which is bad
  38. {
  39. // ensure that we have a cursor
  40. setCursor(dynamic_cast<GuiCursor*>(Sim::findObject("DefaultCursor")));
  41. mRenderFront = true;
  42. sList.push_back(this);
  43. //Con::printf("Registering target %s...", mTargetName.c_str());
  44. mNamedTarget.registerWithName( mTargetName );
  45. _setupTargets();
  46. GFXTextureManager::addEventDelegate( this, &GuiOffscreenCanvas::_onTextureEvent );
  47. return true;
  48. }
  49. return false;
  50. }
  51. void GuiOffscreenCanvas::onRemove()
  52. {
  53. GFXTextureManager::removeEventDelegate( this, &GuiOffscreenCanvas::_onTextureEvent );
  54. _teardownTargets();
  55. U32 idx = sList.find_next(this);
  56. if (idx != (U32)-1)
  57. {
  58. sList.erase(idx);
  59. }
  60. mTarget = NULL;
  61. mTargetTexture = NULL;
  62. mTargetDepth = NULL;
  63. Parent::onRemove();
  64. }
  65. void GuiOffscreenCanvas::_setupTargets()
  66. {
  67. _teardownTargets();
  68. if (!mTarget.isValid())
  69. {
  70. mTarget = GFX->allocRenderToTextureTarget();
  71. }
  72. // Update color
  73. if (!mTargetTexture.isValid() || mTargetSize != mTargetTexture.getWidthHeight())
  74. {
  75. mTargetTexture.set( mTargetSize.x, mTargetSize.y, mTargetFormat, &GFXRenderTargetSRGBProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ), 1, 0 );
  76. }
  77. // Update depth if needed
  78. if (mUseDepth && (!mTargetDepth.isValid() || mTargetSize != mTargetDepth.getWidthHeight()))
  79. {
  80. mTargetDepth.set( mTargetSize.x, mTargetSize.y, GFXFormatD24S8, &GFXRenderTargetProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ), 1, 0 );
  81. mTarget->attachTexture( GFXTextureTarget::RenderSlot(GFXTextureTarget::DepthStencil), mTargetDepth );
  82. }
  83. mTarget->attachTexture( GFXTextureTarget::RenderSlot(GFXTextureTarget::Color0), mTargetTexture );
  84. mNamedTarget.setTexture(0, mTargetTexture);
  85. }
  86. void GuiOffscreenCanvas::_teardownTargets()
  87. {
  88. mNamedTarget.release();
  89. mTargetTexture = NULL;
  90. mTargetDepth = NULL;
  91. mTargetDirty = true;
  92. }
  93. void GuiOffscreenCanvas::renderFrame(bool preRenderOnly, bool bufferSwap /* = true */)
  94. {
  95. if (!mTargetDirty)
  96. return;
  97. #ifdef TORQUE_ENABLE_GFXDEBUGEVENTS
  98. char buf[256];
  99. dSprintf(buf, sizeof(buf), "OffsceenCanvas %s", getName() ? getName() : getIdString());
  100. GFXDEBUGEVENT_SCOPE_EX(GuiOffscreenCanvas_renderFrame, ColorI::GREEN, buf);
  101. #endif
  102. PROFILE_START(OffscreenCanvasPreRender);
  103. #ifdef TORQUE_GFX_STATE_DEBUG
  104. GFX->getDebugStateManager()->startFrame();
  105. #endif
  106. if (mTarget->getSize() != mTargetSize)
  107. {
  108. _setupTargets();
  109. mNamedTarget.setViewport( RectI( Point2I::Zero, mTargetSize ) );
  110. }
  111. // Make sure the root control is the size of the canvas.
  112. Point2I size = mTarget->getSize();
  113. if(size.x == 0 || size.y == 0)
  114. {
  115. PROFILE_END();
  116. return;
  117. }
  118. RectI screenRect(0, 0, size.x, size.y);
  119. maintainSizing();
  120. //preRender (recursive) all controls
  121. preRender();
  122. PROFILE_END();
  123. // Are we just doing pre-render?
  124. if(preRenderOnly)
  125. {
  126. return;
  127. }
  128. resetUpdateRegions();
  129. PROFILE_START(OffscreenCanvasRenderControls);
  130. GuiCursor *mouseCursor = NULL;
  131. bool cursorVisible = true;
  132. Point2I cursorPos((S32)mCursorPt.x, (S32)mCursorPt.y);
  133. mouseCursor = mDefaultCursor;
  134. mLastCursorEnabled = cursorVisible;
  135. mLastCursor = mouseCursor;
  136. mLastCursorPt = cursorPos;
  137. // Set active target
  138. GFX->pushActiveRenderTarget();
  139. GFX->setActiveRenderTarget(mTarget);
  140. // Clear the current viewport area
  141. GFX->setViewport( screenRect );
  142. GFX->clear( GFXClearTarget, LinearColorF(0,0,0,0), 1.0f, 0 );
  143. resetUpdateRegions();
  144. // Make sure we have a clean matrix state
  145. // before we start rendering anything!
  146. GFX->setWorldMatrix( MatrixF::Identity );
  147. GFX->setViewMatrix( MatrixF::Identity );
  148. GFX->setProjectionMatrix( MatrixF::Identity );
  149. RectI contentRect(Point2I(0,0), mTargetSize);
  150. {
  151. // Render active GUI Dialogs
  152. for(iterator i = begin(); i != end(); i++)
  153. {
  154. // Get the control
  155. GuiControl *contentCtrl = static_cast<GuiControl*>(*i);
  156. GFX->setClipRect( contentRect );
  157. GFX->setStateBlock(mDefaultGuiSB);
  158. contentCtrl->onRender(contentCtrl->getPosition(), contentRect);
  159. }
  160. // Fill Blue if no Dialogs
  161. if(this->size() == 0)
  162. GFX->clear( GFXClearTarget, LinearColorF(0,0,0,1), 1.0f, 0 );
  163. GFX->setClipRect( contentRect );
  164. // Draw cursor
  165. //
  166. if (mCursorEnabled && mouseCursor && mShowCursor)
  167. {
  168. Point2I pos((S32)mCursorPt.x, (S32)mCursorPt.y);
  169. Point2I spot = mouseCursor->getHotSpot();
  170. pos -= spot;
  171. mouseCursor->render(pos);
  172. }
  173. GFX->getDrawUtil()->clearBitmapModulation();
  174. }
  175. mTarget->resolve();
  176. GFX->popActiveRenderTarget();
  177. PROFILE_END();
  178. // Keep track of the last time we rendered.
  179. mLastRenderMs = Platform::getRealMilliseconds();
  180. mTargetDirty = mDynamicTarget;
  181. onFrameRendered();
  182. }
  183. void GuiOffscreenCanvas::onFrameRendered()
  184. {
  185. }
  186. Point2I GuiOffscreenCanvas::getWindowSize()
  187. {
  188. return mTargetSize;
  189. }
  190. Point2I GuiOffscreenCanvas::getCursorPos()
  191. {
  192. return Point2I(mCursorPt.x, mCursorPt.y);
  193. }
  194. void GuiOffscreenCanvas::setCursorPos(const Point2I &pt)
  195. {
  196. mCursorPt.x = F32( pt.x );
  197. mCursorPt.y = F32( pt.y );
  198. }
  199. void GuiOffscreenCanvas::showCursor(bool state)
  200. {
  201. mShowCursor = state;
  202. }
  203. bool GuiOffscreenCanvas::isCursorShown()
  204. {
  205. return mShowCursor;
  206. }
  207. void GuiOffscreenCanvas::_onTextureEvent( GFXTexCallbackCode code )
  208. {
  209. switch(code)
  210. {
  211. case GFXZombify:
  212. _teardownTargets();
  213. break;
  214. case GFXResurrect:
  215. _setupTargets();
  216. break;
  217. }
  218. }
  219. DefineEngineMethod(GuiOffscreenCanvas, resetTarget, void, (), , "")
  220. {
  221. object->_setupTargets();
  222. }
  223. DefineEngineMethod(GuiOffscreenCanvas, markDirty, void, (), , "")
  224. {
  225. object->markDirty();
  226. }