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