sfxParameter.cpp
Engine/source/sfx/sfxParameter.cpp
Public Functions
ConsoleDocClass(SFXParameter , "@brief A sound channel <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> that can be bound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> multiple sound <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sources.\n\n</a>" "Parameters are special objects that isolate <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific property that sound sources can have and allows <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> bind " "this isolated instance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> multiple sound sources such that when the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the parameter changes, all sources " "bound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the parameter will have their respective property <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed.\n\n</a>" "Parameters are identified and referenced by their #internalName. This means that the SFXDescription::parameters and " "SFXTrack::parameters fields should contain the #internalNames of the <a href="/coding/class/classsfxparameter/">SFXParameter</a> objects which should be attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "the SFXSources when they are created. No two SFXParameters should have the same #<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">internalName.\n\n</a>" "All <a href="/coding/class/classsfxparameter/">SFXParameter</a> instances are automatically made children of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXParameterGroup.\n\n</a>" " @note To simply <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> the volume and/or pitch levels of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> group of sounds, it is easier and more efficient <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use " "<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> sound <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> group rather than SFXParameters(see @ref SFXSource_hierarchies). Simply create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsfxsource/">SFXSource</a> object representing the group, assign " "SFXDescription::sourceGroup of the sounds appropriately)
DefineEngineMethod(SFXParameter , getParameterName , String , () , "Get the name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameter.\n</a>" "@return The paramete name." )
DefineEngineMethod(SFXParameter , reset , void , () , "Reset the parameter's <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">default.\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXParameter::defaultValue\n</a>" )
IMPLEMENT_CALLBACK(SFXParameter , onUpdate , void , () , () , "Called when the sound system triggers an update on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameter.\n</a>" "This occurs periodically during system operation." )
Detailed Description
Public Functions
ConsoleDocClass(SFXParameter , "@brief A sound channel <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> that can be bound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> multiple sound <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">sources.\n\n</a>" "Parameters are special objects that isolate <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> specific property that sound sources can have and allows <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> bind " "this isolated instance <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> multiple sound sources such that when the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the parameter changes, all sources " "bound <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the parameter will have their respective property <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">changed.\n\n</a>" "Parameters are identified and referenced by their #internalName. This means that the SFXDescription::parameters and " "SFXTrack::parameters fields should contain the #internalNames of the <a href="/coding/class/classsfxparameter/">SFXParameter</a> objects which should be attached <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> " "the SFXSources when they are created. No two SFXParameters should have the same #<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">internalName.\n\n</a>" "All <a href="/coding/class/classsfxparameter/">SFXParameter</a> instances are automatically made children of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXParameterGroup.\n\n</a>" " @note To simply <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> the volume and/or pitch levels of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> group of sounds, it is easier and more efficient <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use " "<a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> sound <a href="/coding/file/pointer_8h/#pointer_8h_1adb82dfe18535e9a30aa97d275f82bd55">source</a> group rather than SFXParameters(see @ref SFXSource_hierarchies). Simply create <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classsfxsource/">SFXSource</a> object representing the group, assign " "SFXDescription::sourceGroup of the sounds appropriately)
DefineEngineMethod(SFXParameter , getParameterName , String , () , "Get the name of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameter.\n</a>" "@return The paramete name." )
DefineEngineMethod(SFXParameter , reset , void , () , "Reset the parameter's <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> its <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">default.\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXParameter::defaultValue\n</a>" )
IMPLEMENT_CALLBACK(SFXParameter , onUpdate , void , () , () , "Called when the sound system triggers an update on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameter.\n</a>" "This occurs periodically during system operation." )
IMPLEMENT_CONOBJECT(SFXParameter )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "sfx/sfxParameter.h" 25#include "console/consoleTypes.h" 26#include "console/simBase.h" 27#include "console/engineAPI.h" 28#include "console/simSet.h" 29#include "math/mMathFn.h" 30#include "math/mathTypes.h" 31#include "math/mathIO.h" 32#include "core/stream/bitStream.h" 33#include "platform/typetraits.h" 34 35 36IMPLEMENT_CONOBJECT( SFXParameter ); 37 38ConsoleDocClass( SFXParameter, 39 "@brief A sound channel value that can be bound to multiple sound sources.\n\n" 40 41 "Parameters are special objects that isolate a specific property that sound sources can have and allows to bind " 42 "this isolated instance to multiple sound sources such that when the value of the parameter changes, all sources " 43 "bound to the parameter will have their respective property changed.\n\n" 44 45 "Parameters are identified and referenced by their #internalName. This means that the SFXDescription::parameters and " 46 "SFXTrack::parameters fields should contain the #internalNames of the SFXParameter objects which should be attached to " 47 "the SFXSources when they are created. No two SFXParameters should have the same #internalName.\n\n" 48 49 "All SFXParameter instances are automatically made children of the SFXParameterGroup.\n\n" 50 51 "@note To simply control the volume and/or pitch levels of a group of sounds, it is easier and more efficient to use " 52 "a sound source group rather than SFXParameters (see @ref SFXSource_hierarchies). Simply create a SFXSource object representing the group, assign " 53 "SFXDescription::sourceGroup of the sounds appropriately, and then set the volume and/or pitch level of the group to " 54 "modulate the respective properties of all children.\n\n" 55 56 "@section SFXParameter_updates Parameter Updates\n" 57 58 "Parameters are periodically allowed to update their own values. This makes it possible to attach custom logic to a parameter " 59 "and have individual parameters synchronize their values autonomously. Use the onUpdate() callback to attach " 60 "script code to a parameter update.\n\n" 61 62 "@tsexample\n" 63 "new SFXParameter( EngineRPMLevel )\n" 64 "{\n" 65 " // Set the name by which this parameter is identified.\n" 66 " internalName = \"EngineRPMLevel\";\n" 67 "\n" 68 " // Let this parameter control the pitch of attached sources to simulate engine RPM ramping up and down.\n" 69 " channel = \"Pitch\";\n" 70 "\n" 71 " // Start out with unmodified pitch.\n" 72 " defaultValue = 1;\n" 73 "\n" 74 " // Add a texture description of what this parameter does.\n" 75 " description = \"Engine RPM Level\";\n" 76 "};\n" 77 "\n" 78 "// Create a description that automatically attaches the engine RPM parameter.\n" 79 "singleton SFXDescription( EngineRPMSound : AudioLoop2D )\n" 80 "{\n" 81 " parameters[ 0 ] = \"EngineRPMLevel\";\n" 82 "};\n" 83 "\n" 84 "// Create sound sources for the engine.\n" 85 "sfxCreateSource( EngineRPMSound, \"art/sound/engine/enginePrimary\" );\n" 86 "sfxCreateSource( EngineRPMSound, \"art/sound/engine/engineSecondary\" );\n" 87 "\n" 88 "// Setting the parameter value will now affect the pitch level of both sound sources.\n" 89 "EngineRPMLevel.value = 0.5;\n" 90 "EngineRPMLevel.value = 1.5;\n" 91 "@endtsexample\n\n" 92 93 "@ref SFX_interactive\n\n" 94 "@ingroup SFX" 95); 96 97 98IMPLEMENT_CALLBACK( SFXParameter, onUpdate, void, (), (), 99 "Called when the sound system triggers an update on the parameter.\n" 100 "This occurs periodically during system operation." ); 101 102 103//----------------------------------------------------------------------------- 104 105SFXParameter::SFXParameter() 106 : mValue( 1.f ), 107 mRange( 0.f, 1.f ), 108 mChannel( SFXChannelVolume ), 109 mDefaultValue( 1.f ) 110{ 111} 112 113//----------------------------------------------------------------------------- 114 115SFXParameter::~SFXParameter() 116{ 117} 118 119//----------------------------------------------------------------------------- 120 121void SFXParameter::initPersistFields() 122{ 123 addGroup( "Sound" ); 124 125 addProtectedField( "value", TypeF32, Offset( mValue, SFXParameter ), 126 &SFXParameter::_setValue, &defaultProtectedGetFn, 127 "Current value of the audio parameter.\n" 128 "All attached sources are notified when this value changes." ); 129 addProtectedField( "range", TypePoint2F, Offset( mRange, SFXParameter ), 130 &SFXParameter::_setRange, &defaultProtectedGetFn, 131 "Permitted range for #value.\n" 132 "Minimum and maximum allowed value for the parameter. Both inclusive.\n\n" 133 "For all but the User0-3 channels, this property is automatically set up by SFXParameter." ); 134 addProtectedField( "channel", TYPEID< SFXChannel >(), Offset( mChannel, SFXParameter ), 135 &SFXParameter::_setChannel, &defaultProtectedGetFn, 136 "Channel that the parameter controls.\n" 137 "This controls which property of the sources it is attached to the parameter controls." ); 138 addProtectedField( "defaultValue", TypeF32, Offset( mDefaultValue, SFXParameter ), 139 &SFXParameter::_setDefaultValue, &defaultProtectedGetFn, 140 "Value to which the parameter is initially set.\n" 141 "When the parameter is first added to the system, #value will be set to #defaultValue." ); 142 addField( "description", TypeRealString,Offset( mDescription, SFXParameter ), 143 "Textual description of the parameter.\n" 144 "Primarily for use in the Audio Parameters dialog of the editor to allow for easier identification " 145 "of parameters." ); 146 147 endGroup( "Sound" ); 148 149 Parent::initPersistFields(); 150} 151 152//----------------------------------------------------------------------------- 153 154bool SFXParameter::_setValue( void *object, const char *index, const char *data ) 155{ 156 reinterpret_cast< SFXParameter* >( object )->setValue( dAtof( data ) ); 157 return false; 158} 159 160//----------------------------------------------------------------------------- 161 162bool SFXParameter::_setRange( void *object, const char *index, const char *data ) 163{ 164 Point2F range = EngineUnmarshallData< Point2F>()( data ); 165 reinterpret_cast< SFXParameter* >( object )->setRange( range ); 166 return false; 167} 168 169//----------------------------------------------------------------------------- 170 171bool SFXParameter::_setChannel( void *object, const char *index, const char *data ) 172{ 173 SFXChannel channel = EngineUnmarshallData< SFXChannel>()( data ); 174 reinterpret_cast< SFXParameter* >( object )->setChannel( channel ); 175 return false; 176} 177 178//----------------------------------------------------------------------------- 179 180bool SFXParameter::_setDefaultValue( void *object, const char *index, const char *data ) 181{ 182 reinterpret_cast< SFXParameter* >( object )->setDefaultValue( dAtof( data ) ); 183 return false; 184} 185 186//----------------------------------------------------------------------------- 187 188bool SFXParameter::onAdd() 189{ 190 if( !Parent::onAdd() ) 191 return false; 192 193 mValue = mDefaultValue; 194 195 // Make sure the parameter has a name. 196 197 if( !getInternalName() || !getInternalName()[ 0 ] ) 198 { 199 Con::errorf( "SFXParameter::onAdd - %i (%s): parameter object does not have a name", getId(), getName() ); 200 return false; 201 } 202 203 // Make sure the parameter has a unique name. 204 205 if( find( getInternalName() ) ) 206 { 207 Con::errorf( "SFXParameter::onAdd - %i (%s): a parameter called '%s' already exists", getId(), getName(), getInternalName() ); 208 return false; 209 } 210 211 // Add us to the SFXParameter group. 212 213 Sim::getSFXParameterGroup()->addObject( this ); 214 215 return true; 216} 217 218//----------------------------------------------------------------------------- 219 220void SFXParameter::onRemove() 221{ 222 mEventSignal.trigger( this, SFXParameterEvent_Deleted ); 223 Parent::onRemove(); 224} 225 226//----------------------------------------------------------------------------- 227 228void SFXParameter::update() 229{ 230 onUpdate_callback(); 231} 232 233//----------------------------------------------------------------------------- 234 235void SFXParameter::reset() 236{ 237 setValue( mDefaultValue ); 238} 239 240//----------------------------------------------------------------------------- 241 242void SFXParameter::setValue( F32 value ) 243{ 244 if( value == mValue ) 245 return; 246 247 mValue = mClampF( value, mRange.x, mRange.y ); 248 mEventSignal.trigger( this, SFXParameterEvent_ValueChanged ); 249} 250 251//----------------------------------------------------------------------------- 252 253void SFXParameter::setDefaultValue( F32 value ) 254{ 255 mDefaultValue = mClampF( value, mRange.x, mRange.y ); 256} 257 258//----------------------------------------------------------------------------- 259 260void SFXParameter::setRange( const Point2F& range ) 261{ 262 if( range == mRange ) 263 return; 264 265 mRange = range; 266 267 F32 value = mClampF( mValue, mRange.x, mRange.y ); 268 if( value != mValue ) 269 setValue( value ); 270 271 mDefaultValue = mClampF( mDefaultValue, mRange.x, mRange.y ); 272} 273 274//----------------------------------------------------------------------------- 275 276void SFXParameter::setChannel( SFXChannel channel ) 277{ 278 if( mChannel == channel ) 279 return; 280 281 mChannel = channel; 282 283 F32 value = mValue; 284 switch( channel ) 285 { 286 case SFXChannelVolume: 287 case SFXChannelConeOutsideVolume: 288 setRange( 0.f, 1.0f ); 289 break; 290 291 case SFXChannelConeInsideAngle: 292 case SFXChannelConeOutsideAngle: 293 setRange( 0.f, 360.f ); 294 break; 295 296 case SFXChannelPitch: 297 case SFXChannelMinDistance: 298 case SFXChannelMaxDistance: 299 case SFXChannelCursor: 300 setRange( 0.f, TypeTraits< F32 >::MAX ); 301 break; 302 303 case SFXChannelStatus: 304 setRange( F32( SFXStatusPlaying ), F32( SFXStatusStopped ) ); 305 break; 306 307 default: 308 setRange( TypeTraits< F32 >::MIN, TypeTraits< F32 >::MAX ); 309 break; 310 } 311 312 // If the range setting did not result in the value already 313 // being changed, fire a value-change signal now so that sources 314 // can catch on to the new semantics. Unfortunately, we can't 315 // do something about the old semantic's value having been 316 // changed by us. 317 318 if( mValue == value ) 319 mEventSignal.trigger( this, SFXParameterEvent_ValueChanged ); 320} 321 322//----------------------------------------------------------------------------- 323 324SFXParameter* SFXParameter::find( StringTableEntry name ) 325{ 326 return dynamic_cast< SFXParameter* >( 327 Sim::getSFXParameterGroup()->findObjectByInternalName( name ) 328 ); 329} 330 331//============================================================================= 332// Console Methods. 333//============================================================================= 334// MARK: ---- Console Methods ---- 335 336//----------------------------------------------------------------------------- 337 338DefineEngineMethod( SFXParameter, getParameterName, String, (),, 339 "Get the name of the parameter.\n" 340 "@return The paramete name." ) 341{ 342 return object->getInternalName(); 343} 344 345//----------------------------------------------------------------------------- 346 347DefineEngineMethod( SFXParameter, reset, void, (),, 348 "Reset the parameter's value to its default.\n" 349 "@see SFXParameter::defaultValue\n" ) 350{ 351 object->reset(); 352} 353