postEffectVis.cpp 13 KB

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