mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-07-08 21:24:34 +00:00
Engine directory for ticket #1
This commit is contained in:
parent
352279af7a
commit
7dbfe6994d
3795 changed files with 1363358 additions and 0 deletions
397
Engine/source/sfx/sfxState.cpp
Normal file
397
Engine/source/sfx/sfxState.cpp
Normal file
|
|
@ -0,0 +1,397 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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 "sfx/sfxState.h"
|
||||
#include "sfx/sfxTypes.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "console/engineAPI.h"
|
||||
|
||||
|
||||
//#define DEBUG_SPEW
|
||||
|
||||
|
||||
IMPLEMENT_CO_DATABLOCK_V1( SFXState );
|
||||
|
||||
|
||||
ConsoleDocClass( SFXState,
|
||||
"@brief A boolean switch used to modify playlist behavior.\n\n"
|
||||
|
||||
"Sound system states are used to allow playlist controllers to make decisions based on global state. This is useful, for "
|
||||
"example, to couple audio playback to gameplay state. Certain states may, for example, represent different locations that the "
|
||||
"listener can be in, like underwater, in open space, or indoors. Other states could represent moods of the current gameplay "
|
||||
"situation, like, for example, an aggressive mood during combat.\n\n"
|
||||
|
||||
"By activating and deactivating sound states according to gameplay state, a set of concurrently running playlists may "
|
||||
"react and adapt to changes in the game.\n\n"
|
||||
|
||||
"@section SFXState_activation Activation and Deactivation\n"
|
||||
|
||||
"At any time, a given state can be either active or inactive. Calling activate() on a state increases an internal "
|
||||
"counter and calling deactivate() decreases the counter. Only when the count reaches zero will the state be "
|
||||
"deactivated.\n\n"
|
||||
|
||||
"In addition to the activation count, states also maintain a disabling count. Calling disable() increases this count "
|
||||
"and calling enable() decreases it. As long as this count is greater than zero, a given state will not be activated "
|
||||
"even if its activation count is non-zero. Calling disable() on an active state will not only increase the disabling "
|
||||
"count but also deactivate the state. Calling enable() on a state with a positive activation count will re-activate "
|
||||
"the state when the disabling count reaches zero.\n\n"
|
||||
|
||||
"@section SFXState_dependencies State Dependencies\n"
|
||||
|
||||
"By listing other states in in its #includedStates and #excludedStates fields, a state may automatically trigger the "
|
||||
"activation or disabling of other states in the sytem when it is activated. This allows to form dependency chains "
|
||||
"between individual states.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"// State indicating that the listener is submerged.\n"
|
||||
"singleton SFXState( AudioLocationUnderwater )\n"
|
||||
"{\n"
|
||||
" parentGroup = AudioLocation;\n"
|
||||
" // AudioStateExclusive is a class defined in the core scripts that will automatically\n"
|
||||
" // ensure for a state to deactivate all the sibling SFXStates in its parentGroup when it\n"
|
||||
" // is activated.\n"
|
||||
" className = \"AudioStateExclusive\";\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"// State suitable e.g. for combat.\n"
|
||||
"singleton SFXState( AudioMoodAggressive )\n"
|
||||
"{\n"
|
||||
" parentGroup = AudioMood;\n"
|
||||
" className = \"AudioStateExclusive\";\n"
|
||||
"};\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@see SFXPlayList\n"
|
||||
"@see SFXController\n"
|
||||
"@see SFXPlayList::state\n"
|
||||
"@see SFXPlayList::stateMode\n\n"
|
||||
"@ref SFX_interactive\n\n"
|
||||
|
||||
"@ingroup SFX\n"
|
||||
"@ingroup Datablocks"
|
||||
);
|
||||
|
||||
|
||||
IMPLEMENT_CALLBACK( SFXState, onActivate, void, (), (),
|
||||
"Called when the state goes from inactive to active." );
|
||||
IMPLEMENT_CALLBACK( SFXState, onDeactivate, void, (), (),
|
||||
"called when the state goes from active to deactive." );
|
||||
|
||||
|
||||
static Vector< SFXState* > sgActiveStates( __FILE__, __LINE__ );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SFXState::SFXState()
|
||||
: mActiveCount( 0 ),
|
||||
mDisableCount( 0 )
|
||||
{
|
||||
dMemset( mIncludedStates, 0, sizeof( mIncludedStates ) );
|
||||
dMemset( mExcludedStates, 0, sizeof( mExcludedStates ) );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::initPersistFields()
|
||||
{
|
||||
addGroup( "State" );
|
||||
|
||||
addField( "includedStates", TypeSFXStateName, Offset( mIncludedStates, SFXState ),
|
||||
MaxIncludedStates,
|
||||
"States that will automatically be activated when this state is activated.\n\n"
|
||||
"@ref SFXState_activation" );
|
||||
addField( "excludedStates", TypeSFXStateName, Offset( mExcludedStates, SFXState ),
|
||||
MaxExcludedStates,
|
||||
"States that will automatically be disabled when this state is activated.\n\n"
|
||||
"@ref SFXState_activation" );
|
||||
|
||||
endGroup( "State" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::activate()
|
||||
{
|
||||
mActiveCount ++;
|
||||
if( mActiveCount == 1 && !isDisabled() )
|
||||
_onActivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::deactivate()
|
||||
{
|
||||
if( !mActiveCount )
|
||||
return;
|
||||
|
||||
mActiveCount --;
|
||||
if( !mActiveCount && !isDisabled() )
|
||||
_onDeactivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::enable()
|
||||
{
|
||||
if( !mDisableCount )
|
||||
return;
|
||||
|
||||
mDisableCount --;
|
||||
|
||||
if( !mDisableCount && mActiveCount > 0 )
|
||||
_onActivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::disable()
|
||||
{
|
||||
mDisableCount ++;
|
||||
|
||||
if( mDisableCount == 1 && mActiveCount > 0 )
|
||||
_onDeactivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SFXState::onAdd()
|
||||
{
|
||||
if( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
Sim::getSFXStateSet()->addObject( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SFXState::preload( bool server, String& errorStr )
|
||||
{
|
||||
if( !Parent::preload( server, errorStr ) )
|
||||
return false;
|
||||
|
||||
if( !server )
|
||||
{
|
||||
for( U32 i = 0; i < MaxIncludedStates; ++ i )
|
||||
if( !sfxResolve( &mIncludedStates[ i ], errorStr ) )
|
||||
return false;
|
||||
|
||||
for( U32 i = 0; i < MaxExcludedStates; ++ i )
|
||||
if( !sfxResolve( &mExcludedStates[ i ], errorStr ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::packData( BitStream* stream )
|
||||
{
|
||||
Parent::packData( stream );
|
||||
|
||||
for( U32 i = 0; i < MaxIncludedStates; ++ i )
|
||||
sfxWrite( stream, mIncludedStates[ i ] );
|
||||
for( U32 i = 0; i < MaxExcludedStates; ++ i )
|
||||
sfxWrite( stream, mExcludedStates[ i ] );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::unpackData( BitStream* stream )
|
||||
{
|
||||
Parent::unpackData( stream );
|
||||
|
||||
for( U32 i = 0; i < MaxIncludedStates; ++ i )
|
||||
sfxRead( stream, &mIncludedStates[ i ] );
|
||||
for( U32 i = 0; i < MaxExcludedStates; ++ i )
|
||||
sfxRead( stream, &mExcludedStates[ i ] );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::_onActivate()
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[SFXState] Activating '%s'", getName() );
|
||||
#endif
|
||||
|
||||
onActivate_callback();
|
||||
|
||||
// Add the state to the list.
|
||||
|
||||
sgActiveStates.push_back( this );
|
||||
|
||||
// Activate included states.
|
||||
|
||||
for( U32 i = 0; i < MaxIncludedStates; ++ i )
|
||||
if( mIncludedStates[ i ] )
|
||||
mIncludedStates[ i ]->activate();
|
||||
|
||||
// Disable excluded states.
|
||||
|
||||
for( U32 i = 0; i < MaxExcludedStates; ++ i )
|
||||
if( mExcludedStates[ i ] )
|
||||
mExcludedStates[ i ]->disable();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXState::_onDeactivate()
|
||||
{
|
||||
#ifdef DEBUG_SPEW
|
||||
Platform::outputDebugString( "[SFXState] Deactivating '%s'", getName() );
|
||||
#endif
|
||||
|
||||
onDeactivate_callback();
|
||||
|
||||
// Remove the state from the list.
|
||||
|
||||
for( U32 i = 0; i < sgActiveStates.size(); ++ i )
|
||||
if( sgActiveStates[ i ] == this )
|
||||
{
|
||||
sgActiveStates.erase_fast( i );
|
||||
break;
|
||||
}
|
||||
|
||||
// Deactivate included states.
|
||||
|
||||
for( U32 i = 0; i < MaxIncludedStates; ++ i )
|
||||
if( mIncludedStates[ i ] )
|
||||
mIncludedStates[ i ]->deactivate();
|
||||
|
||||
// Enable excluded states.
|
||||
|
||||
for( U32 i = 0; i < MaxExcludedStates; ++ i )
|
||||
if( mExcludedStates[ i ] )
|
||||
mExcludedStates[ i ]->enable();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Console Methods.
|
||||
//=============================================================================
|
||||
// MARK: ---- Console Methods ----
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXState, isActive, bool, (),,
|
||||
"Test whether the state is currently active.\n"
|
||||
"This is true when the activation count is >0 and the disabling count is =0.\n"
|
||||
"@return True if the state is currently active.\n"
|
||||
"@see activate" )
|
||||
{
|
||||
return object->isActive();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXState, activate, void, (),,
|
||||
"Increase the activation count on the state.\n"
|
||||
"If the state isn't already active and it is not disabled, the state will be activated.\n"
|
||||
"@see isActive\n"
|
||||
"@see deactivate\n" )
|
||||
{
|
||||
object->activate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXState, deactivate, void, (),,
|
||||
"Decrease the activation count on the state.\n"
|
||||
"If the count reaches zero and the state was not disabled, the state will be deactivated.\n"
|
||||
"@see isActive\n"
|
||||
"@see activate\n" )
|
||||
{
|
||||
object->deactivate();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXState, isDisabled, bool, (),,
|
||||
"Test whether the state is currently disabled.\n"
|
||||
"This is true when the disabling count of the state is non-zero.\n"
|
||||
"@return True if the state is disabled.\n\n"
|
||||
"@see disable\n" )
|
||||
{
|
||||
return object->isDisabled();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXState, disable, void, (),,
|
||||
"Increase the disabling count of the state.\n"
|
||||
"If the state is currently active, it will be deactivated.\n"
|
||||
"@see isDisabled\n" )
|
||||
{
|
||||
object->disable();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXState, enable, void, (),,
|
||||
"Decrease the disabling count of the state.\n"
|
||||
"If the disabling count reaches zero while the activation count is still non-zero, "
|
||||
"the state will be reactivated again.\n"
|
||||
"@see isDisabled\n" )
|
||||
{
|
||||
object->enable();
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Console Functions.
|
||||
//=============================================================================
|
||||
// MARK: ---- Console Functions ----
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineFunction( sfxGetActiveStates, const char*, (),,
|
||||
"Return a newline-separated list of all active states.\n"
|
||||
"@return A list of the form\n"
|
||||
"@verbatim\n"
|
||||
"stateName1 NL stateName2 NL stateName3 ...\n"
|
||||
"@endverbatim\n"
|
||||
"where each element is the name of an active state object.\n\n"
|
||||
"@tsexample\n"
|
||||
"// Disable all active states.\n"
|
||||
"foreach$( %state in sfxGetActiveStates() )\n"
|
||||
" %state.disable();\n"
|
||||
"@endtsexample\n\n"
|
||||
"@ingroup SFX" )
|
||||
{
|
||||
StringBuilder str;
|
||||
|
||||
bool isFirst = true;
|
||||
for( U32 i = 0; i < sgActiveStates.size(); ++ i )
|
||||
{
|
||||
if( !isFirst )
|
||||
str.append( ' ' );
|
||||
|
||||
str.append( sgActiveStates[ i ]->getName() );
|
||||
isFirst = false;
|
||||
}
|
||||
|
||||
return Con::getReturnBuffer( str );
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue