postEffectVis.cpp 13 KB

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