2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// 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"
2014-11-06 04:14:39 +00:00
# include "torqueConfig.h"
2016-06-20 22:02:34 +00:00
# include "T3D/accumulationVolume.h"
2012-09-19 15:15:01 +00:00
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 ;
2016-06-09 17:51:43 +00:00
/// @see AccumulationVolume
extern GFXTexHandle gLevelAccuMap ;
2012-09-19 15:15:01 +00:00
/// Default SFXAmbience used to reset the global soundscape.
static SFXAmbience sDefaultAmbience ;
//-----------------------------------------------------------------------------
LevelInfo : : LevelInfo ( )
2016-10-14 23:16:55 +00:00
: mWorldSize ( 10000.0f ) ,
mNearClip ( 0.1f ) ,
2012-09-19 15:15:01 +00:00
mVisibleDistance ( 1000.0f ) ,
2014-12-07 08:11:10 +00:00
mVisibleGhostDistance ( 0 ) ,
2012-09-19 15:15:01 +00:00
mDecalBias ( 0.0015f ) ,
mCanvasClearColor ( 255 , 0 , 255 , 255 ) ,
2016-10-14 23:16:55 +00:00
mAmbientLightBlendPhase ( 1.f ) ,
2012-09-19 15:15:01 +00:00
mSoundAmbience ( NULL ) ,
mSoundDistanceModel ( SFXDistanceModelLinear ) ,
2016-10-14 23:16:55 +00:00
mSoundscape ( NULL )
2012-09-19 15:15:01 +00:00
{
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 = false ;
2016-06-09 17:51:43 +00:00
mAccuTextureName = " " ;
mAccuTexture = NULL ;
2012-09-19 15:15:01 +00:00
// 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 ) ;
2016-06-19 21:59:16 +00:00
if ( ! mAccuTexture . isNull ( ) )
{
mAccuTexture . free ( ) ;
gLevelAccuMap . free ( ) ;
}
2012-09-19 15:15:01 +00:00
}
//-----------------------------------------------------------------------------
void LevelInfo : : initPersistFields ( )
{
addGroup ( " Visibility " ) ;
addField ( " nearClip " , TypeF32 , Offset ( mNearClip , LevelInfo ) , " Closest distance from the camera's position to render the world. " ) ;
2014-12-07 08:11:10 +00:00
addField ( " visibleDistance " , TypeF32 , Offset ( mVisibleDistance , LevelInfo ) , " Furthest distance from the camera's position to render the world. " ) ;
addField ( " visibleGhostDistance " , TypeF32 , Offset ( mVisibleGhostDistance , LevelInfo ) , " Furthest distance from the camera's position to render players. Defaults to visibleDistance. " ) ;
2012-09-19 15:15:01 +00:00
addField ( " decalBias " , TypeF32 , Offset ( mDecalBias , LevelInfo ) ,
" NearPlane bias used when rendering Decal and DecalRoad. This should be tuned to the visibleDistance in your level. " ) ;
endGroup ( " Visibility " ) ;
addGroup ( " Fog " ) ;
addField ( " fogColor " , TypeColorF , Offset ( mFogData . color , LevelInfo ) ,
" The default color for the scene fog. " ) ;
addField ( " fogDensity " , TypeF32 , Offset ( mFogData . density , LevelInfo ) ,
" The 0 to 1 density value for the exponential fog falloff. " ) ;
addField ( " fogDensityOffset " , TypeF32 , Offset ( mFogData . densityOffset , LevelInfo ) ,
" An offset from the camera in meters for moving the start of the fog effect. " ) ;
addField ( " fogAtmosphereHeight " , TypeF32 , Offset ( mFogData . atmosphereHeight , LevelInfo ) ,
" 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 " ) ;
addField ( " ambientLightBlendPhase " , TypeF32 , Offset ( mAmbientLightBlendPhase , LevelInfo ) ,
" 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) " ) ;
2016-06-09 17:51:43 +00:00
addProtectedField ( " AccuTexture " , TypeStringFilename , Offset ( mAccuTextureName , LevelInfo ) ,
& _setLevelAccuTexture , & defaultProtectedGetFn , " Accumulation texture. " ) ;
2012-09-19 15:15:01 +00:00
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 ( 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 ) ;
2016-06-09 17:51:43 +00:00
stream - > write ( mAccuTextureName ) ;
2012-09-19 15:15:01 +00:00
return retMask ;
}
//-----------------------------------------------------------------------------
void LevelInfo : : unpackUpdate ( NetConnection * conn , BitStream * stream )
{
Parent : : unpackUpdate ( conn , stream ) ;
stream - > read ( & mNearClip ) ;
stream - > read ( & mVisibleDistance ) ;
stream - > read ( & mDecalBias ) ;
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 ) ;
}
2016-06-09 17:51:43 +00:00
stream - > read ( & mAccuTextureName ) ;
setLevelAccuTexture ( mAccuTextureName ) ;
2012-09-19 15:15:01 +00:00
}
//-----------------------------------------------------------------------------
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 ) ;
2014-11-06 04:14:39 +00:00
scene - > setVisibleGhostDistance ( mVisibleGhostDistance ) ;
2012-09-19 15:15:01 +00:00
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 ) ;
2017-04-11 05:23:14 +00:00
lightMgr - > getLightBinManager ( ) - > MRTLightmapsDuringDeferred ( mAdvancedLightmapSupport ) ;
2012-09-19 15:15:01 +00:00
}
# endif
2016-06-09 17:51:43 +00:00
}
bool LevelInfo : : _setLevelAccuTexture ( void * object , const char * index , const char * data )
{
LevelInfo * volume = reinterpret_cast < LevelInfo * > ( object ) ;
volume - > setLevelAccuTexture ( data ) ;
return false ;
}
void LevelInfo : : setLevelAccuTexture ( const String & name )
{
mAccuTextureName = name ;
if ( isClientObject ( ) & & mAccuTextureName . isNotEmpty ( ) )
{
2017-06-23 16:36:20 +00:00
mAccuTexture . set ( mAccuTextureName , & GFXStaticTextureSRGBProfile , " AccumulationVolume::mAccuTexture " ) ;
2016-06-09 17:51:43 +00:00
if ( mAccuTexture . isNull ( ) )
Con : : warnf ( " AccumulationVolume::setTexture - Unable to load texture: %s " , mAccuTextureName . c_str ( ) ) ;
else
gLevelAccuMap = mAccuTexture ;
}
2016-06-20 22:02:34 +00:00
AccumulationVolume : : refreshVolumes ( ) ;
2012-09-19 15:15:01 +00:00
}