sfxFMODEvent.cpp
Engine/source/sfx/fmod/sfxFMODEvent.cpp
Public Functions
ConsoleDocClass(SFXFMODEvent , "@brief A playable sound event in an FMOD Designer audio <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">project.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXFMOD\n</a>" "@ingroup Datablocks" )
Detailed Description
Public Functions
ConsoleDocClass(SFXFMODEvent , "@brief A playable sound event in an FMOD Designer audio <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">project.\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">SFXFMOD\n</a>" "@ingroup Datablocks" )
IMPLEMENT_CO_DATABLOCK_V1(SFXFMODEvent )
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 "platform/platform.h" 25#include "sfx/fmod/sfxFMODEvent.h" 26#include "sfx/fmod/sfxFMODEventGroup.h" 27#include "sfx/fmod/sfxFMODProject.h" 28#include "sfx/fmod/sfxFMODDevice.h" 29#include "sfx/sfxParameter.h" 30#include "sfx/sfxDescription.h" 31#include "core/stream/bitStream.h" 32 33 34IMPLEMENT_CO_DATABLOCK_V1( SFXFMODEvent ); 35 36 37ConsoleDocClass( SFXFMODEvent, 38 "@brief A playable sound event in an FMOD Designer audio project.\n\n" 39 40 "@ingroup SFXFMOD\n" 41 "@ingroup Datablocks" 42); 43 44 45//----------------------------------------------------------------------------- 46 47SFXFMODEvent::SFXFMODEvent() 48 : mGroup( NULL ), 49 mHandle( NULL ), 50 mGroupId( 0 ), 51 mSibling( NULL ) 52{ 53 dMemset( mParameterRanges, 0, sizeof( mParameterRanges ) ); 54 dMemset( mParameterValues, 0, sizeof( mParameterValues ) ); 55} 56 57//----------------------------------------------------------------------------- 58 59SFXFMODEvent::SFXFMODEvent( SFXFMODEventGroup* group, FMOD_EVENT* handle ) 60 : mGroup( group ), 61 mHandle( handle ), 62 mGroupId( 0 ), 63 mSibling( NULL ) 64{ 65 dMemset( mParameterRanges, 0, sizeof( mParameterRanges ) ); 66 dMemset( mParameterValues, 0, sizeof( mParameterValues ) ); 67 68 // Fetch name. 69 70 int index; 71 char* name = NULL; 72 73 SFXFMODDevice::smFunc->FMOD_Event_GetInfo( mHandle, &index, &name, ( FMOD_EVENT_INFO* ) 0 ); 74 75 mName = name; 76 77 // Read out the parameter info so we can immediately create 78 // the events on the client-side without having to open and 79 // read all the project info there. 80 81 int numParameters; 82 SFXFMODDevice::smFunc->FMOD_Event_GetNumParameters( mHandle, &numParameters ); 83 if( numParameters > MaxNumParameters ) 84 { 85 Con::errorf( "SFXFMODEvent::SFXFMODEvent - event '%s' has more parameters (%i) than supported per SFXTrack (%i)", 86 getQualifiedName().c_str(), 87 numParameters, 88 MaxNumParameters ); 89 numParameters = MaxNumParameters; 90 } 91 92 for( U32 i = 0; i < numParameters; ++ i ) 93 { 94 FMOD_EVENTPARAMETER* parameter; 95 SFXFMODDevice::smFunc->FMOD_Event_GetParameterByIndex( mHandle, i, ¶meter ); 96 97 SFXFMODDevice::smFunc->FMOD_EventParameter_GetInfo( parameter, &index, &name ); 98 setParameter( i, name ); 99 100 // Get value and range of parameter. 101 102 SFXFMODDevice::smFunc->FMOD_EventParameter_GetValue( parameter, &mParameterValues[ i ] ); 103 SFXFMODDevice::smFunc->FMOD_EventParameter_GetRange( parameter, &mParameterRanges[ i ].x, &mParameterRanges[ i ].y ); 104 } 105 106 // Read out the properties and create a custom SFXDescription for the event. 107 108 mDescription = new SFXDescription; 109 if( !group->isClientOnly() ) 110 mDescription->assignId(); 111 112 mDescription->registerObject( 113 String::ToString( "%s_%s_Description", 114 group->getName(), 115 FMODEventPathToTorqueName( mName ).c_str() 116 ) 117 ); 118 if( group->isClientOnly() ) 119 Sim::getRootGroup()->addObject( mDescription ); 120 121 FMOD_MODE modeValue; 122 float floatValue; 123 124 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_MODE, &modeValue, true ) == FMOD_OK ) 125 mDescription->mIs3D = ( modeValue == FMOD_3D ); 126 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_VOLUME, &floatValue, true ) == FMOD_OK ) 127 mDescription->mVolume = floatValue; 128 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_PITCH, &floatValue, true ) == FMOD_OK ) 129 mDescription->mPitch = floatValue; 130 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_MINDISTANCE, &floatValue, true ) == FMOD_OK ) 131 mDescription->mMinDistance = floatValue; 132 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_MAXDISTANCE, &floatValue, true ) == FMOD_OK ) 133 mDescription->mMaxDistance = floatValue; 134 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_CONEINSIDEANGLE, &floatValue, true ) == FMOD_OK ) 135 mDescription->mConeInsideAngle = floatValue; 136 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_CONEOUTSIDEANGLE, &floatValue, true ) == FMOD_OK ) 137 mDescription->mConeOutsideAngle = floatValue; 138 if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_CONEOUTSIDEVOLUME, &floatValue, true ) == FMOD_OK ) 139 mDescription->mConeOutsideVolume = floatValue; 140 141 // Don't read out fade values as we want to leave fade-effects to 142 // FMOD rather than having the fading system built into SFX pick 143 // these values up. 144} 145 146//----------------------------------------------------------------------------- 147 148SFXFMODEvent::~SFXFMODEvent() 149{ 150} 151 152//----------------------------------------------------------------------------- 153 154void SFXFMODEvent::initPersistFields() 155{ 156 addGroup( "DO NOT MODIFY!!" ); 157 addField( "fmodGroup", TYPEID< SFXFMODEventGroup >(), Offset( mGroup, SFXFMODEvent ), "DO NOT MODIFY!!" ); 158 addField( "fmodName", TypeRealString, Offset( mName, SFXFMODEvent ), "DO NOT MODIFY!!" ); 159 addField( "fmodParameterRanges", TypePoint2F, Offset( mParameterRanges, SFXFMODEvent ), MaxNumParameters, "DO NOT MODIFY!!" ); 160 addField( "fmodParameterValues", TypeF32, Offset( mParameterValues, SFXFMODEvent ), MaxNumParameters, "DO NOT MODIFY!!" ); 161 endGroup( "DO NOT MODIFY!!" ); 162 163 Parent::initPersistFields(); 164} 165 166//----------------------------------------------------------------------------- 167 168bool SFXFMODEvent::onAdd() 169{ 170 if( !Parent::onAdd() ) 171 return false; 172 173 if( !mGroup ) 174 { 175 Con::errorf( "SFXFMODEvent::onAdd - no group set; this event was not properly constructed" ); 176 return false; 177 } 178 179 mGroup->_addEvent( this ); 180 mGroup->mProject->_addEvent( this ); 181 182 // For non-networked event datablocks, create the parameter 183 // instances now. 184 185 if( isClientOnly() ) 186 _createParameters(); 187 188 return true; 189} 190 191//----------------------------------------------------------------------------- 192 193void SFXFMODEvent::onRemove() 194{ 195 Parent::onRemove(); 196 197 if( !mGroup ) 198 return; 199 200 release(); 201 mGroup->_removeEvent( this ); 202} 203 204//----------------------------------------------------------------------------- 205 206bool SFXFMODEvent::preload( bool server, String& errorStr ) 207{ 208 if( !Parent::preload( server, errorStr ) ) 209 return false; 210 211 if( !server ) 212 { 213 if( !Sim::findObject( mGroupId, mGroup ) ) 214 { 215 errorStr = String::ToString( "SFXFMODEvent - group '%i' does not exist", mGroupId ); 216 return false; 217 } 218 219 // Create parameters. 220 221 _createParameters(); 222 } 223 224 return true; 225} 226 227//----------------------------------------------------------------------------- 228 229void SFXFMODEvent::packData( BitStream* stream ) 230{ 231 Parent::packData( stream ); 232 233 stream->write( mName ); 234 stream->writeRangedS32( mGroup->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast ); 235 236 for( U32 i = 0; i < MaxNumParameters; ++ i ) 237 if( stream->writeFlag( mParameters[ i ] ) ) 238 { 239 stream->write( mParameterValues[ i ] ); 240 stream->write( mParameterRanges[ i ].x ); 241 stream->write( mParameterRanges[ i ].y ); 242 } 243} 244 245//----------------------------------------------------------------------------- 246 247void SFXFMODEvent::unpackData( BitStream* stream ) 248{ 249 Parent::unpackData( stream ); 250 251 stream->read( &mName ); 252 mGroupId = stream->readRangedS32( DataBlockObjectIdFirst, DataBlockObjectIdLast ); 253 254 for( U32 i = 0; i < MaxNumParameters; ++ i ) 255 if( stream->readFlag() ) 256 { 257 stream->read( &mParameterValues[ i ] ); 258 stream->read( &mParameterRanges[ i ].x ); 259 stream->read( &mParameterRanges[ i ].y ); 260 } 261 else 262 { 263 mParameterValues[ i ] = 0.f; 264 mParameterRanges[ i ].x = 0.f; 265 mParameterRanges[ i ].y = 0.f; 266 } 267} 268 269//----------------------------------------------------------------------------- 270 271void SFXFMODEvent::acquire() 272{ 273 if( mHandle ) 274 return; 275 276 mGroup->acquire(); 277 if( SFXFMODDevice::smFunc->FMOD_EventGroup_GetEvent( 278 mGroup->mHandle, mName.c_str(), FMOD_EVENT_INFOONLY, &mHandle ) != FMOD_OK ) 279 { 280 Con::errorf( "SFXFMODEvent::acquire() - failed to acquire event '%s'", getQualifiedName().c_str() ); 281 return; 282 } 283} 284 285//----------------------------------------------------------------------------- 286 287void SFXFMODEvent::release() 288{ 289 if( !mHandle ) 290 return; 291 292 SFXFMODDevice::smFunc->FMOD_Event_Release( mHandle, true, false ); 293 mHandle = NULL; 294} 295 296//----------------------------------------------------------------------------- 297 298String SFXFMODEvent::getQualifiedName() const 299{ 300 return String::ToString( "%s/%s", getEventGroup()->getQualifiedName().c_str(), mName.c_str() ); 301} 302 303//----------------------------------------------------------------------------- 304 305void SFXFMODEvent::_createParameters() 306{ 307 const String& projectFileName = getEventGroup()->getProject()->getFileName(); 308 const String qualifiedGroupName = getEventGroup()->getQualifiedName(); 309 const String description = String::ToString( "FMOD Event Parameter (%s)", projectFileName.c_str() ); 310 311 for( U32 i = 0; i < MaxNumParameters; ++ i ) 312 { 313 StringTableEntry name = getParameter( i ); 314 if( !name ) 315 continue; 316 317 SFXParameter* parameter = SFXParameter::find( name ); 318 if( !parameter ) 319 { 320 parameter = new SFXParameter(); 321 parameter->setInternalName( name ); 322 parameter->registerObject(); 323 324 // Set up parameter. 325 326 parameter->setChannel( SFXChannelUser0 ); 327 parameter->setRange( mParameterRanges[ i ] ); 328 parameter->setDefaultValue( mParameterValues[ i ] ); 329 parameter->setValue( mParameterValues[ i ] ); 330 parameter->setDescription( description ); 331 332 // Set categories for easy filtering. 333 334 static StringTableEntry sCategories = StringTable->insert( "categories" ); 335 parameter->setDataField( sCategories, "0", "FMOD" ); 336 parameter->setDataField( sCategories, "1", avar( "FMOD Project: %s", projectFileName.c_str() ) ); 337 parameter->setDataField( sCategories, "2", avar( "FMOD Group: %s", qualifiedGroupName.c_str() ) ); 338 } 339 } 340} 341