mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Should render fallback for namedTarget if namedTarget fails Add safety around namedtarget getTexture to stop assert Missing assets should revert to fallback image and print a warning to console Remove REFACTOR tag from all macros.
377 lines
12 KiB
C++
377 lines
12 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 "T3D/levelInfo.h"
|
|
|
|
#include "console/consoleTypes.h"
|
|
#include "core/stream/bitStream.h"
|
|
#include "scene/sceneManager.h"
|
|
#include "lighting/advanced/advancedLightManager.h"
|
|
#include "lighting/advanced/advancedLightBinManager.h"
|
|
#include "sfx/sfxAmbience.h"
|
|
#include "sfx/sfxSoundscape.h"
|
|
#include "sfx/sfxSystem.h"
|
|
#include "sfx/sfxTypes.h"
|
|
#include "console/engineAPI.h"
|
|
#include "math/mathIO.h"
|
|
|
|
#include "torqueConfig.h"
|
|
#include "T3D/accumulationVolume.h"
|
|
#include "console/typeValidators.h"
|
|
#include "materials/materialManager.h"
|
|
|
|
IMPLEMENT_CO_NETOBJECT_V1(LevelInfo);
|
|
|
|
ConsoleDocClass( LevelInfo,
|
|
"@brief Stores and controls the rendering and status information for a game level.\n\n"
|
|
|
|
"@tsexample\n"
|
|
"new LevelInfo(theLevelInfo)\n"
|
|
"{\n"
|
|
" visibleDistance = \"1000\";\n"
|
|
" fogColor = \"0.6 0.6 0.7 1\";\n"
|
|
" fogDensity = \"0\";\n"
|
|
" fogDensityOffset = \"700\";\n"
|
|
" fogAtmosphereHeight = \"0\";\n"
|
|
" canvasClearColor = \"0 0 0 255\";\n"
|
|
" canSaveDynamicFields = \"1\";\n"
|
|
" levelName = \"Blank Room\";\n"
|
|
" desc0 = \"A blank room ready to be populated with Torque objects.\";\n"
|
|
" Enabled = \"1\";\n"
|
|
"};\n"
|
|
"@endtsexample\n"
|
|
"@ingroup enviroMisc\n"
|
|
);
|
|
|
|
|
|
/// The color used to clear the canvas.
|
|
/// @see GuiCanvas
|
|
extern ColorI gCanvasClearColor;
|
|
|
|
/// @see DecalManager
|
|
extern F32 gDecalBias;
|
|
|
|
/// @see AccumulationVolume
|
|
extern GFXTexHandle gLevelAccuMap;
|
|
|
|
/// Default SFXAmbience used to reset the global soundscape.
|
|
extern SFXAmbience* sDefaultAmbience;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
LevelInfo::LevelInfo()
|
|
: mWorldSize( 10000.0f ),
|
|
mNearClip( 0.1f ),
|
|
mVisibleDistance( 1000.0f ),
|
|
mVisibleGhostDistance ( 0 ),
|
|
mDecalBias( 0.0015f ),
|
|
mCanvasClearColor( 255, 0, 255, 255 ),
|
|
mAmbientLightBlendPhase( 1.f ),
|
|
mSoundAmbience( NULL ),
|
|
mSoundDistanceModel( SFXDistanceModelLinear ),
|
|
mSoundscape( NULL ),
|
|
mDampness(0.0)
|
|
{
|
|
mFogData.density = 0.0f;
|
|
mFogData.densityOffset = 0.0f;
|
|
mFogData.atmosphereHeight = 0.0f;
|
|
mFogData.color.set( 0.5f, 0.5f, 0.5f, 1.0f ),
|
|
|
|
mNetFlags.set( ScopeAlways | Ghostable );
|
|
|
|
mAdvancedLightmapSupport = true;
|
|
|
|
// Register with the light manager activation signal, and we need to do it first
|
|
// so the advanced light bin manager can be instructed about MRT lightmaps
|
|
LightManager::smActivateSignal.notify(this, &LevelInfo::_onLMActivate, 0.01f);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
LevelInfo::~LevelInfo()
|
|
{
|
|
LightManager::smActivateSignal.remove(this, &LevelInfo::_onLMActivate);
|
|
if (!mAccuTextureAsset.isNull())
|
|
{
|
|
gLevelAccuMap.free();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LevelInfo::initPersistFields()
|
|
{
|
|
docsURL;
|
|
addGroup( "Visibility" );
|
|
|
|
addFieldV( "nearClip", TypeRangedF32, Offset( mNearClip, LevelInfo ), &CommonValidators::PositiveFloat, "Closest distance from the camera's position to render the world." );
|
|
addFieldV( "visibleDistance", TypeRangedF32, Offset( mVisibleDistance, LevelInfo ), &CommonValidators::PositiveFloat, "Furthest distance from the camera's position to render the world." );
|
|
addFieldV( "visibleGhostDistance", TypeRangedF32, Offset( mVisibleGhostDistance, LevelInfo ), &CommonValidators::PositiveFloat, "Furthest distance from the camera's position to render players. Defaults to visibleDistance." );
|
|
addFieldV( "decalBias", TypeRangedF32, Offset( mDecalBias, LevelInfo ), &CommonValidators::PositiveFloat,
|
|
"NearPlane bias used when rendering Decal and DecalRoad. This should be tuned to the visibleDistance in your level." );
|
|
|
|
addFieldV("dampness", TypeRangedF32, Offset(mDampness, LevelInfo), &CommonValidators::NormalizedFloat,
|
|
"@brief dampness influence");
|
|
endGroup( "Visibility" );
|
|
|
|
addGroup( "Fog" );
|
|
|
|
addField( "fogColor", TypeColorF, Offset( mFogData.color, LevelInfo ),
|
|
"The default color for the scene fog." );
|
|
|
|
addFieldV( "fogDensity", TypeRangedF32, Offset( mFogData.density, LevelInfo ), &CommonValidators::NormalizedFloat,
|
|
"The 0 to 1 density value for the exponential fog falloff." );
|
|
|
|
addFieldV( "fogDensityOffset", TypeRangedF32, Offset( mFogData.densityOffset, LevelInfo ), &CommonValidators::PositiveFloat,
|
|
"An offset from the camera in meters for moving the start of the fog effect." );
|
|
|
|
addFieldV( "fogAtmosphereHeight", TypeRangedF32, Offset( mFogData.atmosphereHeight, LevelInfo ), &CommonValidators::PositiveFloat,
|
|
"A height in meters for altitude fog falloff." );
|
|
|
|
endGroup( "Fog" );
|
|
|
|
addGroup( "LevelInfo" );
|
|
|
|
addField( "canvasClearColor", TypeColorI, Offset( mCanvasClearColor, LevelInfo ),
|
|
"The color used to clear the background before the scene or any GUIs are rendered." );
|
|
|
|
endGroup( "LevelInfo" );
|
|
|
|
addGroup( "Lighting" );
|
|
|
|
addFieldV( "ambientLightBlendPhase", TypeRangedF32, Offset( mAmbientLightBlendPhase, LevelInfo ), &CommonValidators::PositiveFloat,
|
|
"Number of seconds it takes to blend from one ambient light color to a different one." );
|
|
|
|
addField( "ambientLightBlendCurve", TypeEaseF, Offset( mAmbientLightBlendCurve, LevelInfo ),
|
|
"Interpolation curve to use for blending from one ambient light color to a different one." );
|
|
|
|
//addField( "advancedLightmapSupport", TypeBool, Offset( mAdvancedLightmapSupport, LevelInfo ),
|
|
// "Enable expanded support for mixing static and dynamic lighting (more costly)" );
|
|
|
|
INITPERSISTFIELD_IMAGEASSET(AccuTexture, LevelInfo, "Accumulation texture.");
|
|
|
|
endGroup( "Lighting" );
|
|
|
|
addGroup( "Sound" );
|
|
|
|
addField( "soundAmbience", TypeSFXAmbienceName, Offset( mSoundAmbience, LevelInfo ), "The global ambient sound environment." );
|
|
addField( "soundDistanceModel", TypeSFXDistanceModel, Offset( mSoundDistanceModel, LevelInfo ), "The distance attenuation model to use." );
|
|
|
|
endGroup( "Sound" );
|
|
|
|
Parent::initPersistFields();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LevelInfo::inspectPostApply()
|
|
{
|
|
_updateSceneGraph();
|
|
setMaskBits( 0xFFFFFFFF );
|
|
|
|
Parent::inspectPostApply();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
U32 LevelInfo::packUpdate(NetConnection *conn, U32 mask, BitStream *stream)
|
|
{
|
|
U32 retMask = Parent::packUpdate(conn, mask, stream);
|
|
|
|
stream->write( mNearClip );
|
|
stream->write( mVisibleDistance );
|
|
stream->write( mDecalBias );
|
|
stream->write(mDampness);
|
|
|
|
stream->write( mFogData.density );
|
|
stream->write( mFogData.densityOffset );
|
|
stream->write( mFogData.atmosphereHeight );
|
|
stream->write( mFogData.color );
|
|
|
|
stream->write( mCanvasClearColor );
|
|
stream->write( mWorldSize );
|
|
|
|
stream->writeFlag( mAdvancedLightmapSupport );
|
|
stream->write( mAmbientLightBlendPhase );
|
|
mathWrite( *stream, mAmbientLightBlendCurve );
|
|
|
|
sfxWrite( stream, mSoundAmbience );
|
|
stream->writeInt( mSoundDistanceModel, 1 );
|
|
|
|
PACK_ASSET_REFACTOR(conn, AccuTexture);
|
|
|
|
return retMask;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LevelInfo::unpackUpdate(NetConnection *conn, BitStream *stream)
|
|
{
|
|
Parent::unpackUpdate(conn, stream);
|
|
|
|
stream->read( &mNearClip );
|
|
stream->read( &mVisibleDistance );
|
|
stream->read( &mDecalBias );
|
|
stream->read(&mDampness);
|
|
MATMGR->setDampness(mDampness);
|
|
|
|
stream->read( &mFogData.density );
|
|
stream->read( &mFogData.densityOffset );
|
|
stream->read( &mFogData.atmosphereHeight );
|
|
stream->read( &mFogData.color );
|
|
|
|
stream->read( &mCanvasClearColor );
|
|
stream->read( &mWorldSize );
|
|
|
|
mAdvancedLightmapSupport = stream->readFlag();
|
|
stream->read( &mAmbientLightBlendPhase );
|
|
mathRead( *stream, &mAmbientLightBlendCurve );
|
|
|
|
String errorStr;
|
|
if( !sfxReadAndResolve( stream, &mSoundAmbience, errorStr ) )
|
|
Con::errorf( "%s", errorStr.c_str() );
|
|
mSoundDistanceModel = ( SFXDistanceModel ) stream->readInt( 1 );
|
|
|
|
if( isProperlyAdded() )
|
|
{
|
|
_updateSceneGraph();
|
|
|
|
if( mSoundscape )
|
|
{
|
|
if( mSoundAmbience )
|
|
mSoundscape->setAmbience( mSoundAmbience );
|
|
else
|
|
mSoundscape->setAmbience( sDefaultAmbience );
|
|
}
|
|
|
|
SFX->setDistanceModel( mSoundDistanceModel );
|
|
}
|
|
|
|
UNPACK_ASSET_REFACTOR(conn, AccuTexture);
|
|
setLevelAccuTexture();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
bool LevelInfo::onAdd()
|
|
{
|
|
if ( !Parent::onAdd() )
|
|
return false;
|
|
|
|
// If no sound ambience has been set, default to
|
|
// 'AudioAmbienceDefault'.
|
|
|
|
if( !mSoundAmbience )
|
|
Sim::findObject( "AudioAmbienceDefault", mSoundAmbience );
|
|
|
|
// Set up sound on client.
|
|
|
|
if( isClientObject() )
|
|
{
|
|
SFX->setDistanceModel( mSoundDistanceModel );
|
|
|
|
// Set up the global ambient soundscape.
|
|
|
|
mSoundscape = SFX->getSoundscapeManager()->getGlobalSoundscape();
|
|
if( mSoundAmbience )
|
|
mSoundscape->setAmbience( mSoundAmbience );
|
|
}
|
|
|
|
_updateSceneGraph();
|
|
|
|
return true;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LevelInfo::onRemove()
|
|
{
|
|
if( mSoundscape )
|
|
mSoundscape->setAmbience( sDefaultAmbience );
|
|
|
|
Parent::onRemove();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LevelInfo::_updateSceneGraph()
|
|
{
|
|
// Clamp above zero before setting on the sceneGraph.
|
|
// If we don't we get serious crashes.
|
|
if ( mNearClip <= 0.0f )
|
|
mNearClip = 0.001f;
|
|
|
|
SceneManager* scene = isClientObject() ? gClientSceneGraph : gServerSceneGraph;
|
|
|
|
scene->setNearClip( mNearClip );
|
|
scene->setVisibleDistance( mVisibleDistance );
|
|
scene->setVisibleGhostDistance( mVisibleGhostDistance );
|
|
|
|
gDecalBias = mDecalBias;
|
|
|
|
// Set ambient lighting properties.
|
|
|
|
scene->setAmbientLightTransitionTime( mAmbientLightBlendPhase * 1000.f );
|
|
scene->setAmbientLightTransitionCurve( mAmbientLightBlendCurve );
|
|
|
|
// Copy our AirFogData into the sceneGraph.
|
|
scene->setFogData( mFogData );
|
|
|
|
// If the level info specifies that MRT pre-pass should be used in this scene
|
|
// enable it via the appropriate light manager
|
|
// (Basic lighting doesn't do anything different right now)
|
|
#ifndef TORQUE_DEDICATED
|
|
if(isClientObject())
|
|
_onLMActivate(LIGHTMGR->getId(), true);
|
|
#endif
|
|
|
|
// TODO: This probably needs to be moved.
|
|
gCanvasClearColor = mCanvasClearColor;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
void LevelInfo::_onLMActivate(const char *lm, bool enable)
|
|
{
|
|
#ifndef TORQUE_DEDICATED
|
|
// Advanced light manager
|
|
if(enable && String(lm) == String("ADVLM"))
|
|
{
|
|
AssertFatal(dynamic_cast<AdvancedLightManager *>(LIGHTMGR), "Bad light manager type!");
|
|
AdvancedLightManager *lightMgr = static_cast<AdvancedLightManager *>(LIGHTMGR);
|
|
lightMgr->getLightBinManager()->MRTLightmapsDuringDeferred(mAdvancedLightmapSupport);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void LevelInfo::setLevelAccuTexture()
|
|
{
|
|
if (isClientObject() && mAccuTextureAsset.notNull())
|
|
{
|
|
gLevelAccuMap = getAccuTexture();
|
|
}
|
|
|
|
AccumulationVolume::refreshVolumes();
|
|
}
|