mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-03-01 03:23:52 +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
350
Engine/source/sfx/sfxParameter.cpp
Normal file
350
Engine/source/sfx/sfxParameter.cpp
Normal file
|
|
@ -0,0 +1,350 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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/sfxParameter.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "console/engineAPI.h"
|
||||
#include "console/simSet.h"
|
||||
#include "math/mMathFn.h"
|
||||
#include "math/mathTypes.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "core/stream/bitStream.h"
|
||||
#include "platform/typetraits.h"
|
||||
|
||||
|
||||
IMPLEMENT_CONOBJECT( SFXParameter );
|
||||
|
||||
ConsoleDocClass( SFXParameter,
|
||||
"@brief A sound channel value that can be bound to multiple sound sources.\n\n"
|
||||
|
||||
"Parameters are special objects that isolate a specific property that sound sources can have and allows to bind "
|
||||
"this isolated instance to multiple sound sources such that when the value of the parameter changes, all sources "
|
||||
"bound to the parameter will have their respective property changed.\n\n"
|
||||
|
||||
"Parameters are identified and referenced by their #internalName. This means that the SFXDescription::parameters and "
|
||||
"SFXTrack::parameters fields should contain the #internalNames of the SFXParameter objects which should be attached to "
|
||||
"the SFXSources when they are created. No two SFXParameters should have the same #internalName.\n\n"
|
||||
|
||||
"All SFXParameter instances are automatically made children of the SFXParameterGroup.\n\n"
|
||||
|
||||
"@note To simply control the volume and/or pitch levels of a group of sounds, it is easier and more efficient to use "
|
||||
"a sound source group rather than SFXParameters (see @ref SFXSource_hierarchies). Simply create a SFXSource object representing the group, assign "
|
||||
"SFXDescription::sourceGroup of the sounds appropriately, and then set the volume and/or pitch level of the group to "
|
||||
"modulate the respective properties of all children.\n\n"
|
||||
|
||||
"@section SFXParameter_updates Parameter Updates\n"
|
||||
|
||||
"Parameters are periodically allowed to update their own values. This makes it possible to attach custom logic to a parameter "
|
||||
"and have individual parameters synchronize their values autonomously. Use the onUpdate() callback to attach "
|
||||
"script code to a parameter update.\n\n"
|
||||
|
||||
"@tsexample\n"
|
||||
"new SFXParameter( EngineRPMLevel )\n"
|
||||
"{\n"
|
||||
" // Set the name by which this parameter is identified.\n"
|
||||
" internalName = \"EngineRPMLevel\";\n"
|
||||
"\n"
|
||||
" // Let this parameter control the pitch of attached sources to simulate engine RPM ramping up and down.\n"
|
||||
" channel = \"Pitch\";\n"
|
||||
"\n"
|
||||
" // Start out with unmodified pitch.\n"
|
||||
" defaultValue = 1;\n"
|
||||
"\n"
|
||||
" // Add a texture description of what this parameter does.\n"
|
||||
" description = \"Engine RPM Level\";\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"// Create a description that automatically attaches the engine RPM parameter.\n"
|
||||
"singleton SFXDescription( EngineRPMSound : AudioLoop2D )\n"
|
||||
"{\n"
|
||||
" parameters[ 0 ] = \"EngineRPMLevel\";\n"
|
||||
"};\n"
|
||||
"\n"
|
||||
"// Create sound sources for the engine.\n"
|
||||
"sfxCreateSource( EngineRPMSound, \"art/sound/engine/enginePrimary\" );\n"
|
||||
"sfxCreateSource( EngineRPMSound, \"art/sound/engine/engineSecondary\" );\n"
|
||||
"\n"
|
||||
"// Setting the parameter value will now affect the pitch level of both sound sources.\n"
|
||||
"EngineRPMLevel.value = 0.5;\n"
|
||||
"EngineRPMLevel.value = 1.5;\n"
|
||||
"@endtsexample\n\n"
|
||||
|
||||
"@ref SFX_interactive\n\n"
|
||||
"@ingroup SFX"
|
||||
);
|
||||
|
||||
|
||||
IMPLEMENT_CALLBACK( SFXParameter, onUpdate, void, (), (),
|
||||
"Called when the sound system triggers an update on the parameter.\n"
|
||||
"This occurs periodically during system operation." );
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SFXParameter::SFXParameter()
|
||||
: mValue( 1.f ),
|
||||
mRange( 0.f, 1.f ),
|
||||
mChannel( SFXChannelVolume ),
|
||||
mDefaultValue( 1.f )
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SFXParameter::~SFXParameter()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::initPersistFields()
|
||||
{
|
||||
addGroup( "Sound" );
|
||||
|
||||
addProtectedField( "value", TypeF32, Offset( mValue, SFXParameter ),
|
||||
&SFXParameter::_setValue, &defaultProtectedGetFn,
|
||||
"Current value of the audio parameter.\n"
|
||||
"All attached sources are notified when this value changes." );
|
||||
addProtectedField( "range", TypePoint2F, Offset( mRange, SFXParameter ),
|
||||
&SFXParameter::_setRange, &defaultProtectedGetFn,
|
||||
"Permitted range for #value.\n"
|
||||
"Minimum and maximum allowed value for the parameter. Both inclusive.\n\n"
|
||||
"For all but the User0-3 channels, this property is automatically set up by SFXParameter." );
|
||||
addProtectedField( "channel", TYPEID< SFXChannel >(), Offset( mChannel, SFXParameter ),
|
||||
&SFXParameter::_setChannel, &defaultProtectedGetFn,
|
||||
"Channel that the parameter controls.\n"
|
||||
"This controls which property of the sources it is attached to the parameter controls." );
|
||||
addProtectedField( "defaultValue", TypeF32, Offset( mDefaultValue, SFXParameter ),
|
||||
&SFXParameter::_setDefaultValue, &defaultProtectedGetFn,
|
||||
"Value to which the parameter is initially set.\n"
|
||||
"When the parameter is first added to the system, #value will be set to #defaultValue." );
|
||||
addField( "description", TypeRealString,Offset( mDescription, SFXParameter ),
|
||||
"Textual description of the parameter.\n"
|
||||
"Primarily for use in the Audio Parameters dialog of the editor to allow for easier identification "
|
||||
"of parameters." );
|
||||
|
||||
endGroup( "Sound" );
|
||||
|
||||
Parent::initPersistFields();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SFXParameter::_setValue( void *object, const char *index, const char *data )
|
||||
{
|
||||
reinterpret_cast< SFXParameter* >( object )->setValue( dAtof( data ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SFXParameter::_setRange( void *object, const char *index, const char *data )
|
||||
{
|
||||
Point2F range = EngineUnmarshallData< Point2F >()( data );
|
||||
reinterpret_cast< SFXParameter* >( object )->setRange( range );
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SFXParameter::_setChannel( void *object, const char *index, const char *data )
|
||||
{
|
||||
SFXChannel channel = EngineUnmarshallData< SFXChannel >()( data );
|
||||
reinterpret_cast< SFXParameter* >( object )->setChannel( channel );
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SFXParameter::_setDefaultValue( void *object, const char *index, const char *data )
|
||||
{
|
||||
reinterpret_cast< SFXParameter* >( object )->setDefaultValue( dAtof( data ) );
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool SFXParameter::onAdd()
|
||||
{
|
||||
if( !Parent::onAdd() )
|
||||
return false;
|
||||
|
||||
mValue = mDefaultValue;
|
||||
|
||||
// Make sure the parameter has a name.
|
||||
|
||||
if( !getInternalName() || !getInternalName()[ 0 ] )
|
||||
{
|
||||
Con::errorf( "SFXParameter::onAdd - %i (%s): parameter object does not have a name", getId(), getName() );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Make sure the parameter has a unique name.
|
||||
|
||||
if( find( getInternalName() ) )
|
||||
{
|
||||
Con::errorf( "SFXParameter::onAdd - %i (%s): a parameter called '%s' already exists", getId(), getName(), getInternalName() );
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add us to the SFXParameter group.
|
||||
|
||||
Sim::getSFXParameterGroup()->addObject( this );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::onRemove()
|
||||
{
|
||||
mEventSignal.trigger( this, SFXParameterEvent_Deleted );
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::update()
|
||||
{
|
||||
onUpdate_callback();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::reset()
|
||||
{
|
||||
setValue( mDefaultValue );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::setValue( F32 value )
|
||||
{
|
||||
if( value == mValue )
|
||||
return;
|
||||
|
||||
mValue = mClampF( value, mRange.x, mRange.y );
|
||||
mEventSignal.trigger( this, SFXParameterEvent_ValueChanged );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::setDefaultValue( F32 value )
|
||||
{
|
||||
mDefaultValue = mClampF( value, mRange.x, mRange.y );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::setRange( const Point2F& range )
|
||||
{
|
||||
if( range == mRange )
|
||||
return;
|
||||
|
||||
mRange = range;
|
||||
|
||||
F32 value = mClampF( mValue, mRange.x, mRange.y );
|
||||
if( value != mValue )
|
||||
setValue( value );
|
||||
|
||||
mDefaultValue = mClampF( mDefaultValue, mRange.x, mRange.y );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SFXParameter::setChannel( SFXChannel channel )
|
||||
{
|
||||
if( mChannel == channel )
|
||||
return;
|
||||
|
||||
mChannel = channel;
|
||||
|
||||
F32 value = mValue;
|
||||
switch( channel )
|
||||
{
|
||||
case SFXChannelVolume:
|
||||
case SFXChannelConeOutsideVolume:
|
||||
setRange( 0.f, 1.0f );
|
||||
break;
|
||||
|
||||
case SFXChannelConeInsideAngle:
|
||||
case SFXChannelConeOutsideAngle:
|
||||
setRange( 0.f, 360.f );
|
||||
break;
|
||||
|
||||
case SFXChannelPitch:
|
||||
case SFXChannelMinDistance:
|
||||
case SFXChannelMaxDistance:
|
||||
case SFXChannelCursor:
|
||||
setRange( 0.f, TypeTraits< F32 >::MAX );
|
||||
break;
|
||||
|
||||
case SFXChannelStatus:
|
||||
setRange( F32( SFXStatusPlaying ), F32( SFXStatusStopped ) );
|
||||
break;
|
||||
|
||||
default:
|
||||
setRange( TypeTraits< F32 >::MIN, TypeTraits< F32 >::MAX );
|
||||
break;
|
||||
}
|
||||
|
||||
// If the range setting did not result in the value already
|
||||
// being changed, fire a value-change signal now so that sources
|
||||
// can catch on to the new semantics. Unfortunately, we can't
|
||||
// do something about the old semantic's value having been
|
||||
// changed by us.
|
||||
|
||||
if( mValue == value )
|
||||
mEventSignal.trigger( this, SFXParameterEvent_ValueChanged );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SFXParameter* SFXParameter::find( StringTableEntry name )
|
||||
{
|
||||
return dynamic_cast< SFXParameter* >(
|
||||
Sim::getSFXParameterGroup()->findObjectByInternalName( name )
|
||||
);
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
// Console Methods.
|
||||
//=============================================================================
|
||||
// MARK: ---- Console Methods ----
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXParameter, getParameterName, String, (),,
|
||||
"Get the name of the parameter.\n"
|
||||
"@return The paramete name." )
|
||||
{
|
||||
return object->getInternalName();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
DefineEngineMethod( SFXParameter, reset, void, (),,
|
||||
"Reset the parameter's value to its default.\n"
|
||||
"@see SFXParameter::defaultValue\n" )
|
||||
{
|
||||
object->reset();
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue