mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-20 20:54:46 +00:00
Added navigation history to AB, as well as ability to navigate via forward and backward buttons and breadcrumb buttons Added folder 'asset type', allowing you to create, rename, delete and move folders via the asset browser for better organization Adjusted various behaviors to work with the address-driven navigation/organization of the AB Expanded visibility options for the AB and integrated them into editor settings so they are retained Added Search field for searching the folder structure, in addition to the existing preview tiles search Adjusted drag-n-drop behavior of the platform code so it accepts dropping folders Added ability to dump active PostEffects list to see what is currently running Added ability to mark specific items in GuiTreeViewCtrl as hidden Made reflection probe bounds boxes translucent rather than wireframe to improve editing visibility Added expanded loose file references to LevelAsset for common companion files like decals and posteffect scrips Added editor setting for Editor Layout Mode, allowing you to set the editor into 'Modern' layout. Added editor settings to set default import config ruleset, and also ability to set auto-import. If both of these are set, then as long as the importing assets have no errors, they will auto-process and the user doesn't need to manually check and confirm them via the asset import window
390 lines
10 KiB
C++
390 lines
10 KiB
C++
//-----------------------------------------------------------------------------
|
|
// Copyright (c) 2012 GarageGames, LLC
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to
|
|
// deal in the Software without restriction, including without limitation the
|
|
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
// sell copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
|
// IN THE SOFTWARE.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "platform/platform.h"
|
|
#include "postFx/postEffectManager.h"
|
|
|
|
#include "postFx/postEffect.h"
|
|
#include "postFx/postEffectVis.h"
|
|
#include "renderInstance/renderBinManager.h"
|
|
#include "scene/sceneManager.h"
|
|
#include "scene/sceneRenderState.h"
|
|
#include "console/consoleTypes.h"
|
|
#include "core/module.h"
|
|
|
|
|
|
MODULE_BEGIN( PostEffectManager )
|
|
|
|
MODULE_SHUTDOWN_AFTER( Sim )
|
|
|
|
MODULE_INIT
|
|
{
|
|
ManagedSingleton< PostEffectManager >::createSingleton();
|
|
}
|
|
|
|
MODULE_SHUTDOWN
|
|
{
|
|
ManagedSingleton< PostEffectManager >::deleteSingleton();
|
|
}
|
|
|
|
MODULE_END;
|
|
|
|
|
|
bool PostEffectManager::smRenderEffects = true;
|
|
|
|
PostEffectManager::PostEffectManager() :
|
|
mLastBackBufferTarget( NULL ),
|
|
mFrameStateSwitch( false )
|
|
{
|
|
GFXDevice::getDeviceEventSignal().notify( this, &PostEffectManager::_handleDeviceEvent );
|
|
RenderPassManager::getRenderBinSignal().notify( this, &PostEffectManager::_handleBinEvent );
|
|
SceneManager::getPostRenderSignal().notify( this, &PostEffectManager::_onPostRenderPass );
|
|
|
|
Con::addVariable("pref::enablePostEffects", TypeBool, &smRenderEffects,
|
|
"@brief If true, post effects will be eanbled.\n\n"
|
|
"@ingroup Game");
|
|
}
|
|
|
|
PostEffectManager::~PostEffectManager()
|
|
{
|
|
GFXDevice::getDeviceEventSignal().remove( this, &PostEffectManager::_handleDeviceEvent );
|
|
RenderPassManager::getRenderBinSignal().remove( this, &PostEffectManager::_handleBinEvent );
|
|
SceneManager::getPostRenderSignal().remove( this, &PostEffectManager::_onPostRenderPass );
|
|
}
|
|
|
|
bool PostEffectManager::_handleDeviceEvent( GFXDevice::GFXDeviceEventType evt )
|
|
{
|
|
switch( evt )
|
|
{
|
|
case GFXDevice::deStartOfFrame:
|
|
PFXVIS->onStartOfFrame();
|
|
|
|
// Fall through
|
|
|
|
case GFXDevice::deDestroy:
|
|
|
|
// Free the back buffer as the device or
|
|
// its content is now invalid.
|
|
releaseBackBufferTex();
|
|
|
|
break;
|
|
|
|
case GFXDevice::deEndOfFrame:
|
|
|
|
renderEffects( NULL, PFXEndOfFrame );
|
|
|
|
// Toggle frame state history switch
|
|
mFrameStateSwitch = !mFrameStateSwitch;
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void PostEffectManager::_handleBinEvent( RenderBinManager *bin,
|
|
const SceneRenderState* sceneState,
|
|
bool isBinStart )
|
|
{
|
|
if ( sceneState->isShadowPass() ||
|
|
sceneState->isOtherPass() )
|
|
return;
|
|
|
|
// We require a bin name to process effects... without
|
|
// it we can skip the bin entirely.
|
|
String binName( bin->getName() );
|
|
if ( binName.isEmpty() )
|
|
return;
|
|
|
|
renderEffects( sceneState, isBinStart ? PFXBeforeBin : PFXAfterBin, binName );
|
|
}
|
|
|
|
void PostEffectManager::_onPostRenderPass( SceneManager *sceneGraph, const SceneRenderState *sceneState )
|
|
{
|
|
if ( !sceneState->isDiffusePass() )
|
|
return;
|
|
|
|
renderEffects( sceneState, PFXAfterDiffuse );
|
|
}
|
|
|
|
GFXTextureObject* PostEffectManager::getBackBufferTex()
|
|
{
|
|
GFXTarget *target = GFX->getActiveRenderTarget();
|
|
|
|
if ( mBackBufferCopyTex.isNull() ||
|
|
target != mLastBackBufferTarget )
|
|
{
|
|
const Point2I &targetSize = target->getSize();
|
|
GFXFormat targetFormat = target->getFormat();
|
|
|
|
mBackBufferCopyTex.set( targetSize.x, targetSize.y,
|
|
targetFormat,
|
|
&PostFxTargetProfile, "mBackBufferCopyTex" );
|
|
|
|
target->resolveTo( mBackBufferCopyTex );
|
|
mLastBackBufferTarget = target;
|
|
}
|
|
|
|
return mBackBufferCopyTex;
|
|
}
|
|
|
|
void PostEffectManager::releaseBackBufferTex()
|
|
{
|
|
mBackBufferCopyTex = NULL;
|
|
mLastBackBufferTarget = NULL;
|
|
}
|
|
|
|
bool PostEffectManager::_addEffect( PostEffect *effect )
|
|
{
|
|
EffectVector *effects = NULL;
|
|
|
|
const String &binName = effect->getRenderBin();
|
|
|
|
switch( effect->getRenderTime() )
|
|
{
|
|
case PFXAfterDiffuse:
|
|
effects = &mAfterDiffuseList;
|
|
break;
|
|
|
|
case PFXEndOfFrame:
|
|
effects = &mEndOfFrameList;
|
|
break;
|
|
|
|
case PFXBeforeBin:
|
|
effects = &mBeforeBinMap[binName];
|
|
break;
|
|
|
|
case PFXAfterBin:
|
|
effects = &mAfterBinMap[binName];
|
|
break;
|
|
|
|
case PFXTexGenOnDemand:
|
|
break;
|
|
}
|
|
|
|
if ( effects == NULL )
|
|
return false;
|
|
|
|
effects->push_back( effect );
|
|
|
|
// Resort the effects by priority.
|
|
effects->sort( &_effectPrioritySort );
|
|
|
|
return true;
|
|
}
|
|
|
|
bool PostEffectManager::_removeEffect( PostEffect *effect )
|
|
{
|
|
// Check the end of frame list.
|
|
EffectVector::iterator iter = T3D::find( mEndOfFrameList.begin(), mEndOfFrameList.end(), effect );
|
|
if ( iter != mEndOfFrameList.end() )
|
|
{
|
|
mEndOfFrameList.erase( iter );
|
|
return true;
|
|
}
|
|
|
|
// Check the diffuse list.
|
|
iter = T3D::find( mAfterDiffuseList.begin(), mAfterDiffuseList.end(), effect );
|
|
if ( iter != mAfterDiffuseList.end() )
|
|
{
|
|
mAfterDiffuseList.erase( iter );
|
|
return true;
|
|
}
|
|
|
|
// Now check the bin maps.
|
|
EffectMap::Iterator mapIter = mAfterBinMap.begin();
|
|
for( ; mapIter != mAfterBinMap.end(); mapIter++ )
|
|
{
|
|
EffectVector &effects = mapIter->value;
|
|
iter = T3D::find( effects.begin(), effects.end(), effect );
|
|
if ( iter != effects.end() )
|
|
{
|
|
effects.erase( iter );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
mapIter = mBeforeBinMap.begin();
|
|
for( ; mapIter != mBeforeBinMap.end(); mapIter++ )
|
|
{
|
|
EffectVector &effects = mapIter->value;
|
|
iter = T3D::find( effects.begin(), effects.end(), effect );
|
|
if ( iter != effects.end() )
|
|
{
|
|
effects.erase( iter );
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void PostEffectManager::renderEffects( const SceneRenderState *state,
|
|
const PFXRenderTime effectTiming,
|
|
const String &binName )
|
|
{
|
|
|
|
// Check the global render effect state as
|
|
// well as the
|
|
if ( !smRenderEffects ||
|
|
( state && !state->usePostEffects() ))
|
|
return;
|
|
|
|
EffectVector *effects = NULL;
|
|
|
|
switch( effectTiming )
|
|
{
|
|
case PFXBeforeBin:
|
|
effects = &mBeforeBinMap[binName];
|
|
break;
|
|
|
|
case PFXAfterBin:
|
|
effects = &mAfterBinMap[binName];
|
|
break;
|
|
|
|
case PFXAfterDiffuse:
|
|
effects = &mAfterDiffuseList;
|
|
break;
|
|
|
|
case PFXEndOfFrame:
|
|
effects = &mEndOfFrameList;
|
|
break;
|
|
|
|
case PFXTexGenOnDemand:
|
|
break;
|
|
}
|
|
|
|
AssertFatal( effects != NULL, "Bad effect time" );
|
|
|
|
// Skip out if we don't have any effects.
|
|
if ( effects->empty() )
|
|
return;
|
|
|
|
// This is used to pass the output texture
|
|
// of one effect into the next effect.
|
|
GFXTexHandle chainTex;
|
|
|
|
// Process the effects.
|
|
for ( U32 i = 0; i < effects->size(); i++ )
|
|
{
|
|
PostEffect *effect = (*effects)[i];
|
|
AssertFatal( effect != NULL, "Somehow this happened" );
|
|
effect->process( state, chainTex );
|
|
}
|
|
}
|
|
|
|
void PostEffectManager::setFrameMatrices( const MatrixF &worldToCamera, const MatrixF &cameraToScreen )
|
|
{
|
|
PFXFrameState &thisFrame = mFrameState[mFrameStateSwitch];
|
|
thisFrame.worldToCamera = worldToCamera;
|
|
thisFrame.cameraToScreen = cameraToScreen;
|
|
}
|
|
|
|
S32 PostEffectManager::_effectPrioritySort( PostEffect* const *e1, PostEffect* const *e2 )
|
|
{
|
|
F32 p1 = (*e1)->getPriority();
|
|
F32 p2 = (*e2)->getPriority();
|
|
|
|
if( p1 > p2 )
|
|
return -1;
|
|
else if( p1 < p2 )
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void PostEffectManager::dumpActivePostFX()
|
|
{
|
|
EffectVector effects;
|
|
|
|
for (U32 i = 0; i < mEndOfFrameList.size(); i++)
|
|
{
|
|
PostEffect* effect = mEndOfFrameList[i];
|
|
|
|
if(effect->isEnabled())
|
|
effects.push_back(effect);
|
|
}
|
|
|
|
for (U32 i = 0; i < mAfterDiffuseList.size(); i++)
|
|
{
|
|
PostEffect* effect = mAfterDiffuseList[i];
|
|
|
|
if (effect->isEnabled())
|
|
effects.push_back(effect);
|
|
}
|
|
|
|
|
|
// Now check the bin maps.
|
|
EffectMap::Iterator mapIter = mAfterBinMap.begin();
|
|
for (; mapIter != mAfterBinMap.end(); mapIter++)
|
|
{
|
|
EffectVector& ef = mapIter->value;
|
|
|
|
for (U32 i = 0; i < ef.size(); i++)
|
|
{
|
|
PostEffect* effect = ef[i];
|
|
|
|
if (effect->isEnabled())
|
|
effects.push_back(effect);
|
|
}
|
|
}
|
|
|
|
mapIter = mBeforeBinMap.begin();
|
|
for (; mapIter != mBeforeBinMap.end(); mapIter++)
|
|
{
|
|
EffectVector& ef = mapIter->value;
|
|
|
|
for (U32 i = 0; i < ef.size(); i++)
|
|
{
|
|
PostEffect* effect = ef[i];
|
|
|
|
if (effect->isEnabled())
|
|
effects.push_back(effect);
|
|
}
|
|
}
|
|
|
|
// Resort the effects by priority.
|
|
effects.sort(&_effectPrioritySort);
|
|
|
|
Con::printf("PostEffectManager::dumpActivePostFX() - Beginning Dump");
|
|
|
|
for (U32 i = 0; i < effects.size(); i++)
|
|
{
|
|
PostEffect* effect = effects[i];
|
|
|
|
if (effect->isEnabled())
|
|
{
|
|
Con::printf("%s", effect->getName());
|
|
}
|
|
}
|
|
|
|
Con::printf("PostEffectManager::dumpActivePostFX() - Ending Dump");
|
|
}
|
|
|
|
DefineEngineFunction(dumpActivePostFX, void, (),, "")
|
|
{
|
|
PFXMGR->dumpActivePostFX();
|
|
}
|