postEffectVis.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 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 "platform/platform.h"
  23. #include "postFx/postEffectVis.h"
  24. #include "gui/containers/guiWindowCtrl.h"
  25. #include "gui/controls/guiBitmapCtrl.h"
  26. #include "gui/core/guiCanvas.h"
  27. #include "postFx/postEffectManager.h"
  28. #include "core/module.h"
  29. ConsoleDoc(
  30. "@class PfxVis\n"
  31. "@brief Singleton class that exposes ConsoleStaticFunctions for debug visualizing PostEffects.\n\n"
  32. "@tsexample\n"
  33. "// Script interface...\n"
  34. "PfxVis::open( PostEffect ) // Multiple PostEffects can be visualized at the same time\n"
  35. "PfxVis::clear() // Clear all visualizer windows\n"
  36. "PfxVis::hide() // Hide all windows (are not destroyed)\n"
  37. "PfxVis::show()\n"
  38. "@endtsexample\n\n"
  39. "@ingroup GFX\n"
  40. );
  41. IMPLEMENT_STATIC_CLASS(PfxVis, , "")
  42. MODULE_BEGIN( PostEffectVis )
  43. MODULE_INIT
  44. {
  45. ManagedSingleton< PostEffectVis >::createSingleton();
  46. }
  47. MODULE_SHUTDOWN
  48. {
  49. ManagedSingleton< PostEffectVis >::deleteSingleton();
  50. }
  51. MODULE_END;
  52. PostEffectVis::PostEffectVis()
  53. : mContent( NULL )
  54. {
  55. }
  56. PostEffectVis::~PostEffectVis()
  57. {
  58. }
  59. void PostEffectVis::open( PostEffect *pfx )
  60. {
  61. GuiControl *content = _getContentControl();
  62. // If we already have this PostEffect added
  63. // remove it first so we can recreate its controls.
  64. VisVector::iterator itr = mWindows.begin();
  65. for ( ; itr != mWindows.end(); itr++ )
  66. {
  67. if ( itr->pfx == pfx )
  68. {
  69. for ( U32 i = 0; i < TexCount; i++ )
  70. {
  71. // Deleting the GuiWindowCtrl will automatically also delete
  72. // any child controls we have allocated.
  73. if ( itr->window[i] )
  74. itr->window[i]->deleteObject();
  75. }
  76. mWindows.erase_fast( itr );
  77. break;
  78. }
  79. }
  80. // Allocate VisWindow struct.
  81. mWindows.increment();
  82. VisWindow &window = mWindows.last();
  83. window.pfx = pfx;
  84. for ( U32 i = 0; i < TexCount; i++ )
  85. {
  86. // Only allocate window/bitmaps for input textures that are actually used.
  87. if ( i > Target )
  88. {
  89. if ( pfx->mTextureName[i-1] == StringTable->EmptyString())
  90. {
  91. window.window[i] = NULL;
  92. window.bmp[i] = NULL;
  93. continue;
  94. }
  95. }
  96. // Allocate GuiWindowCtrl
  97. GuiWindowCtrl *winCtrl = new GuiWindowCtrl();
  98. winCtrl->setPosition( Point2I( 50, 50 ) + Point2I( 15, 15 ) * i );
  99. winCtrl->setExtent( 347, 209 );
  100. winCtrl->setMinExtent( Point2I( 150, 100 ) );
  101. winCtrl->setMobility( true, true, true, true, false, false );
  102. winCtrl->setCanResize( true, true );
  103. winCtrl->setDataField( StringTable->insert( "closeCommand" ), NULL, "PfxVis::onWindowClosed( $ThisControl );" );
  104. winCtrl->registerObject();
  105. window.window[i] = winCtrl;
  106. _setDefaultCaption( window, i );
  107. // Allocate background GuiBitmapCtrl
  108. GuiBitmapCtrl *bmpCtrl = new GuiBitmapCtrl();
  109. bmpCtrl->setPosition( 3, 23 );
  110. bmpCtrl->setSizing( GuiControl::horizResizeWidth, GuiControl::vertResizeHeight );
  111. bmpCtrl->setExtent( 341, 181 );
  112. bmpCtrl->setDataField( StringTable->insert( "wrap" ), NULL, "1" );
  113. bmpCtrl->setBitmap( "ToolsModule:transp_grid_image" );
  114. bmpCtrl->registerObject();
  115. winCtrl->addObject( bmpCtrl );
  116. // Allocate GuiBitmapCtrl
  117. bmpCtrl = new GuiBitmapCtrl();
  118. bmpCtrl->setPosition( 3, 23 );
  119. bmpCtrl->setSizing( GuiControl::horizResizeWidth, GuiControl::vertResizeHeight );
  120. bmpCtrl->setExtent( 341, 181 );
  121. bmpCtrl->registerObject();
  122. winCtrl->addObject( bmpCtrl );
  123. window.bmp[i] = bmpCtrl;
  124. content->addObject( winCtrl );
  125. }
  126. // Make sure we visible.
  127. setVisible( true );
  128. }
  129. void PostEffectVis::setVisible( bool visible )
  130. {
  131. GuiCanvas *canvas = NULL;
  132. if ( !Sim::findObject( "Canvas", canvas ) )
  133. {
  134. Con::errorf( "PostEffectVis::setVisible, Canvas was not found." );
  135. return;
  136. }
  137. GuiControl *content = _getContentControl();
  138. if ( visible && !content->isAwake() )
  139. canvas->pushDialogControl( content, 100 );
  140. if ( !visible && content->isAwake() )
  141. canvas->popDialogControl( content );
  142. }
  143. void PostEffectVis::clear()
  144. {
  145. GuiControl *content = _getContentControl();
  146. content->clear();
  147. mWindows.clear();
  148. }
  149. void PostEffectVis::onStartOfFrame()
  150. {
  151. if ( mWindows.empty() )
  152. return;
  153. if ( !_getContentControl()->isAwake() )
  154. return;
  155. // Restore vis windows to a default state.
  156. // This ensures to users that open PostEffects that are not
  157. // actively being processed are obvious.
  158. VisVector::iterator itr = mWindows.begin();
  159. for ( ; itr != mWindows.end(); itr++ )
  160. {
  161. for ( U32 i = 0; i < TexCount; i++ )
  162. {
  163. if ( !itr->bmp[i] || itr->pfx->getRenderTime() == PFXTexGenOnDemand )
  164. continue;
  165. itr->bmp[i]->setBitmap( NULL );
  166. _setDefaultCaption( *itr, i );
  167. }
  168. }
  169. }
  170. void PostEffectVis::onPFXProcessed( PostEffect *pfx )
  171. {
  172. // If we have no windows we can early out before even testing
  173. // isAwake so we avoid creating the content control unnecessarily.
  174. if ( mWindows.empty() )
  175. return;
  176. if ( !_getContentControl()->isAwake() )
  177. return;
  178. VisVector::iterator itr = mWindows.begin();
  179. for ( ; itr != mWindows.end(); itr++ )
  180. {
  181. if ( itr->pfx == pfx )
  182. {
  183. GuiBitmapCtrl *pBmpCtrl = NULL;
  184. GuiWindowCtrl *pWinCtrl = NULL;
  185. if ( itr->bmp[Target] != NULL )
  186. {
  187. pBmpCtrl = itr->bmp[Target];
  188. pWinCtrl = itr->window[Target];
  189. GFXTextureObject *tex;
  190. if ( pfx->mTargetTex )
  191. tex = pfx->mTargetTex;
  192. else
  193. tex = PFXMGR->getBackBufferTex();
  194. pBmpCtrl->setBitmapHandle( tex );
  195. char caption[256];
  196. char name[256];
  197. if ( pfx->getName() == NULL || dStrlen( pfx->getName() ) == 0 )
  198. dSprintf( name, 256, "(none)" );
  199. else
  200. dSprintf( name, 256, "%s", pfx->getName() );
  201. if ( tex )
  202. dSprintf( caption, 256, "%s[%i] target - %s [ %ix%i ]", name, pfx->getId(), pfx->mTargetName.c_str(), tex->getWidth(), tex->getHeight() );
  203. else
  204. dSprintf( caption, 256, "%s[%i] target", name, pfx->getId() );
  205. pWinCtrl->setDataField( StringTable->insert("text"), NULL, caption );
  206. }
  207. for ( U32 i = Input1; i < TexCount; i++ )
  208. {
  209. if ( itr->bmp[i] == NULL )
  210. continue;
  211. pBmpCtrl = itr->bmp[i];
  212. pWinCtrl = itr->window[i];
  213. GFXTextureObject *tex = pfx->mActiveTextures[i-1];
  214. pBmpCtrl->setBitmapHandle( tex );
  215. char caption[256];
  216. char name[256];
  217. if ( pfx->getName() == NULL || dStrlen( pfx->getName() ) == 0 )
  218. dSprintf( name, 256, "(none)" );
  219. else
  220. dSprintf( name, 256, "%s", pfx->getName() );
  221. if ( tex )
  222. dSprintf( caption, 256, "%s[%i] input%i - %s [ %ix%i ]", name, pfx->getId(), i-1, pfx->mTextureName[i-1], tex->getWidth(), tex->getHeight() );
  223. else
  224. dSprintf( caption, 256, "%s[%i] input%i - %s", name, pfx->getId(), i-1, pfx->mTextureName[i-1] );
  225. pWinCtrl->setDataField( StringTable->insert("text"), NULL, caption );
  226. }
  227. }
  228. }
  229. }
  230. void PostEffectVis::onWindowClosed( GuiWindowCtrl *ctrl )
  231. {
  232. VisVector::iterator itr = mWindows.begin();
  233. for ( ; itr != mWindows.end(); itr++ )
  234. {
  235. for ( U32 i = 0; i < TexCount; i++ )
  236. {
  237. if ( itr->window[i] == ctrl )
  238. {
  239. itr->window[i] = NULL;
  240. itr->bmp[i] = NULL;
  241. ctrl->setVisible( false );
  242. // Avoid deleting immediately since this happens in response to a
  243. // script callback.
  244. Con::evaluate( "%i.schedule( 1, \"delete\" );" );
  245. return;
  246. }
  247. }
  248. }
  249. Con::errorf( "PostEffectVis::onWindowClosed, passed window (%s) [%i] was found.", StringTable->insert( ctrl->getName() ), ctrl->getId() );
  250. }
  251. GuiControl* PostEffectVis::_getContentControl()
  252. {
  253. if ( mContent == NULL )
  254. {
  255. GuiCanvas *canvas = NULL;
  256. if ( !Sim::findObject( "Canvas", canvas ) )
  257. {
  258. AssertFatal( false, "PostEffectVis::_getContentControl, Canvas not found." );
  259. return NULL;
  260. }
  261. mContent = new GuiControl();
  262. mContent->setPosition( 0, 0 );
  263. mContent->setExtent( 1024, 768 );
  264. mContent->setDataField( StringTable->insert( "noCursor" ), NULL, "1" );
  265. mContent->setDataField( StringTable->insert( "profile" ), NULL, "GuiModelessDialogProfile" );
  266. mContent->registerObject( "PfxVisContent" );
  267. canvas->pushDialogControl( mContent, 100 );
  268. }
  269. return mContent;
  270. }
  271. void PostEffectVis::_setDefaultCaption( VisWindow &vis, U32 texIndex )
  272. {
  273. PostEffect *pfx = vis.pfx;
  274. GuiWindowCtrl *winCtrl = vis.window[texIndex];
  275. if ( texIndex == Target )
  276. {
  277. char caption[256];
  278. char name[256];
  279. if ( pfx->getName() == NULL || dStrlen( pfx->getName() ) == 0 )
  280. dSprintf( name, 256, "(none)" );
  281. else
  282. dSprintf( name, 256, "%s", pfx->getName() );
  283. dSprintf( caption, 256, "%s[%i] target [NOT ENABLED]", name, pfx->getId() );
  284. winCtrl->setDataField( StringTable->insert("text"), NULL, caption );
  285. }
  286. else
  287. {
  288. char caption[256];
  289. char name[256];
  290. if ( pfx->getName() == NULL || dStrlen( pfx->getName() ) == 0 )
  291. dSprintf( name, 256, "(none)" );
  292. else
  293. dSprintf( name, 256, "%s", pfx->getName() );
  294. dSprintf( caption, 256, "%s[%i] input%i - %s [NOT ENABLED]", name, pfx->getId(), texIndex-1, pfx->mTextureName[texIndex-1] );
  295. winCtrl->setDataField( StringTable->insert("text"), NULL, caption );
  296. }
  297. }
  298. static ConsoleDocFragment _PfxVisclear(
  299. "@brief Close all visualization windows.\n\n"
  300. "@tsexample\n"
  301. "PfxVis::clear();"
  302. "@endtsexample\n\n",
  303. "PfxVis",
  304. "void clear();" );
  305. DefineEngineStaticMethod( PfxVis, clear, void, (),,
  306. "@hide")
  307. {
  308. PFXVIS->clear();
  309. }
  310. static ConsoleDocFragment _PfxVisopen(
  311. "@brief Open visualization windows for all input and target textures.\n\n"
  312. "@param effect Name of the PostEffect to open\n"
  313. "@param clear True to close all visualization windows before opening the effect\n\n"
  314. "@tsexample\n"
  315. "// Multiple PostEffects can be visualized at the same time\n"
  316. "PfxVis::open( PostEffect )\n"
  317. "@endtsexample\n\n",
  318. "PfxVis",
  319. "void open(PostEffect effect, bool clear);" );
  320. DefineEngineStaticMethod( PfxVis, open, void, (PostEffect* pfx, bool clear), (false), "( PostEffect, [bool clear = false] )"
  321. "@hide")
  322. {
  323. if ( clear )
  324. PFXVIS->clear();
  325. if ( !pfx )
  326. {
  327. Con::errorf( "PfxVis::add, argument was not a PostEffect");
  328. return;
  329. }
  330. PFXVIS->open( pfx );
  331. }
  332. static ConsoleDocFragment _PfxVishide(
  333. "@brief Hide all visualization windows (they are not destroyed).\n\n"
  334. "@tsexample\n"
  335. "PfxVis::hide();"
  336. "@endtsexample\n\n",
  337. "PfxVis",
  338. "void hide();" );
  339. DefineEngineStaticMethod( PfxVis, hide, void, (),,
  340. "@hide")
  341. {
  342. PFXVIS->setVisible( false );
  343. }
  344. static ConsoleDocFragment _PfxVisshow(
  345. "@brief Show all visualization windows.\n\n"
  346. "@tsexample\n"
  347. "PfxVis::show();"
  348. "@endtsexample\n\n",
  349. "PfxVis",
  350. "void show();" );
  351. DefineEngineStaticMethod( PfxVis, show, void, (),,
  352. "@hide")
  353. {
  354. PFXVIS->setVisible( true );
  355. }
  356. static ConsoleDocFragment _PfxVisonWindowClosed(
  357. "@brief Callback when a visualization window is closed.\n\n"
  358. "@param ctrl Name of the GUI control being closed\n"
  359. "@tsexample\n"
  360. "PfxVis::onWindowClosed( VisWindow )\n"
  361. "@endtsexample\n\n",
  362. "PfxVis",
  363. "void onWindowClosed(GuiWindowCtrl *ctrl);" );
  364. DefineEngineStaticMethod( PfxVis, onWindowClosed, void, (GuiWindowCtrl* ctrl),,
  365. "@hide")
  366. {
  367. if ( !ctrl )
  368. {
  369. Con::errorf( "PfxVis::onWindowClosed, argument was not a GuiWindowCtrl");
  370. return;
  371. }
  372. PFXVIS->onWindowClosed( ctrl );
  373. }