123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- //-----------------------------------------------------------------------------
- // 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 "sfx/fmod/sfxFMODEvent.h"
- #include "sfx/fmod/sfxFMODEventGroup.h"
- #include "sfx/fmod/sfxFMODProject.h"
- #include "sfx/fmod/sfxFMODDevice.h"
- #include "sfx/sfxParameter.h"
- #include "sfx/sfxDescription.h"
- #include "core/stream/bitStream.h"
- IMPLEMENT_CO_DATABLOCK_V1( SFXFMODEvent );
- ConsoleDocClass( SFXFMODEvent,
- "@brief A playable sound event in an FMOD Designer audio project.\n\n"
-
- "@ingroup SFXFMOD\n"
- "@ingroup Datablocks"
- );
- //-----------------------------------------------------------------------------
- SFXFMODEvent::SFXFMODEvent()
- : mGroup( NULL ),
- mHandle( NULL ),
- mGroupId( 0 ),
- mSibling( NULL )
- {
- dMemset( mParameterRanges, 0, sizeof( mParameterRanges ) );
- dMemset( mParameterValues, 0, sizeof( mParameterValues ) );
- }
- //-----------------------------------------------------------------------------
- SFXFMODEvent::SFXFMODEvent( SFXFMODEventGroup* group, FMOD_EVENT* handle )
- : mGroup( group ),
- mHandle( handle ),
- mGroupId( 0 ),
- mSibling( NULL )
- {
- dMemset( mParameterRanges, 0, sizeof( mParameterRanges ) );
- dMemset( mParameterValues, 0, sizeof( mParameterValues ) );
-
- // Fetch name.
-
- int index;
- char* name = NULL;
-
- SFXFMODDevice::smFunc->FMOD_Event_GetInfo( mHandle, &index, &name, ( FMOD_EVENT_INFO* ) 0 );
-
- mName = name;
-
- // Read out the parameter info so we can immediately create
- // the events on the client-side without having to open and
- // read all the project info there.
-
- int numParameters;
- SFXFMODDevice::smFunc->FMOD_Event_GetNumParameters( mHandle, &numParameters );
- if( numParameters > MaxNumParameters )
- {
- Con::errorf( "SFXFMODEvent::SFXFMODEvent - event '%s' has more parameters (%i) than supported per SFXTrack (%i)",
- getQualifiedName().c_str(),
- numParameters,
- MaxNumParameters );
- numParameters = MaxNumParameters;
- }
-
- for( U32 i = 0; i < numParameters; ++ i )
- {
- FMOD_EVENTPARAMETER* parameter;
- SFXFMODDevice::smFunc->FMOD_Event_GetParameterByIndex( mHandle, i, ¶meter );
-
- SFXFMODDevice::smFunc->FMOD_EventParameter_GetInfo( parameter, &index, &name );
- setParameter( i, name );
-
- // Get value and range of parameter.
-
- SFXFMODDevice::smFunc->FMOD_EventParameter_GetValue( parameter, &mParameterValues[ i ] );
- SFXFMODDevice::smFunc->FMOD_EventParameter_GetRange( parameter, &mParameterRanges[ i ].x, &mParameterRanges[ i ].y );
- }
-
- // Read out the properties and create a custom SFXDescription for the event.
-
- mDescription = new SFXDescription;
- if( !group->isClientOnly() )
- mDescription->assignId();
-
- mDescription->registerObject(
- String::ToString( "%s_%s_Description",
- group->getName(),
- FMODEventPathToTorqueName( mName ).c_str()
- )
- );
- if( group->isClientOnly() )
- Sim::getRootGroup()->addObject( mDescription );
-
- FMOD_MODE modeValue;
- float floatValue;
-
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_MODE, &modeValue, true ) == FMOD_OK )
- mDescription->mIs3D = ( modeValue == FMOD_3D );
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_VOLUME, &floatValue, true ) == FMOD_OK )
- mDescription->mVolume = floatValue;
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_PITCH, &floatValue, true ) == FMOD_OK )
- mDescription->mPitch = floatValue;
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_MINDISTANCE, &floatValue, true ) == FMOD_OK )
- mDescription->mMinDistance = floatValue;
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_MAXDISTANCE, &floatValue, true ) == FMOD_OK )
- mDescription->mMaxDistance = floatValue;
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_CONEINSIDEANGLE, &floatValue, true ) == FMOD_OK )
- mDescription->mConeInsideAngle = floatValue;
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_CONEOUTSIDEANGLE, &floatValue, true ) == FMOD_OK )
- mDescription->mConeOutsideAngle = floatValue;
- if( SFXFMODDevice::smFunc->FMOD_Event_GetPropertyByIndex( mHandle, FMOD_EVENTPROPERTY_3D_CONEOUTSIDEVOLUME, &floatValue, true ) == FMOD_OK )
- mDescription->mConeOutsideVolume = floatValue;
-
- // Don't read out fade values as we want to leave fade-effects to
- // FMOD rather than having the fading system built into SFX pick
- // these values up.
- }
- //-----------------------------------------------------------------------------
- SFXFMODEvent::~SFXFMODEvent()
- {
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEvent::initPersistFields()
- {
- addGroup( "DO NOT MODIFY!!" );
- addField( "fmodGroup", TYPEID< SFXFMODEventGroup >(), Offset( mGroup, SFXFMODEvent ), "DO NOT MODIFY!!" );
- addField( "fmodName", TypeRealString, Offset( mName, SFXFMODEvent ), "DO NOT MODIFY!!" );
- addField( "fmodParameterRanges", TypePoint2F, Offset( mParameterRanges, SFXFMODEvent ), MaxNumParameters, "DO NOT MODIFY!!" );
- addField( "fmodParameterValues", TypeF32, Offset( mParameterValues, SFXFMODEvent ), MaxNumParameters, "DO NOT MODIFY!!" );
- endGroup( "DO NOT MODIFY!!" );
-
- Parent::initPersistFields();
- }
- //-----------------------------------------------------------------------------
- bool SFXFMODEvent::onAdd()
- {
- if( !Parent::onAdd() )
- return false;
-
- if( !mGroup )
- {
- Con::errorf( "SFXFMODEvent::onAdd - no group set; this event was not properly constructed" );
- return false;
- }
-
- mGroup->_addEvent( this );
- mGroup->mProject->_addEvent( this );
-
- // For non-networked event datablocks, create the parameter
- // instances now.
-
- if( isClientOnly() )
- _createParameters();
-
- return true;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEvent::onRemove()
- {
- Parent::onRemove();
-
- if( !mGroup )
- return;
-
- release();
- mGroup->_removeEvent( this );
- }
- //-----------------------------------------------------------------------------
- bool SFXFMODEvent::preload( bool server, String& errorStr )
- {
- if( !Parent::preload( server, errorStr ) )
- return false;
-
- if( !server )
- {
- if( !Sim::findObject( mGroupId, mGroup ) )
- {
- errorStr = String::ToString( "SFXFMODEvent - group '%i' does not exist", mGroupId );
- return false;
- }
- // Create parameters.
- _createParameters();
- }
-
- return true;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEvent::packData( BitStream* stream )
- {
- Parent::packData( stream );
-
- stream->write( mName );
- stream->writeRangedS32( mGroup->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
-
- for( U32 i = 0; i < MaxNumParameters; ++ i )
- if( stream->writeFlag( mParameters[ i ] ) )
- {
- stream->write( mParameterValues[ i ] );
- stream->write( mParameterRanges[ i ].x );
- stream->write( mParameterRanges[ i ].y );
- }
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEvent::unpackData( BitStream* stream )
- {
- Parent::unpackData( stream );
- stream->read( &mName );
- mGroupId = stream->readRangedS32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
-
- for( U32 i = 0; i < MaxNumParameters; ++ i )
- if( stream->readFlag() )
- {
- stream->read( &mParameterValues[ i ] );
- stream->read( &mParameterRanges[ i ].x );
- stream->read( &mParameterRanges[ i ].y );
- }
- else
- {
- mParameterValues[ i ] = 0.f;
- mParameterRanges[ i ].x = 0.f;
- mParameterRanges[ i ].y = 0.f;
- }
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEvent::acquire()
- {
- if( mHandle )
- return;
-
- mGroup->acquire();
- if( SFXFMODDevice::smFunc->FMOD_EventGroup_GetEvent(
- mGroup->mHandle, mName.c_str(), FMOD_EVENT_INFOONLY, &mHandle ) != FMOD_OK )
- {
- Con::errorf( "SFXFMODEvent::acquire() - failed to acquire event '%s'", getQualifiedName().c_str() );
- return;
- }
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEvent::release()
- {
- if( !mHandle )
- return;
-
- SFXFMODDevice::smFunc->FMOD_Event_Release( mHandle, true, false );
- mHandle = NULL;
- }
- //-----------------------------------------------------------------------------
- String SFXFMODEvent::getQualifiedName() const
- {
- return String::ToString( "%s/%s", getEventGroup()->getQualifiedName().c_str(), mName.c_str() );
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEvent::_createParameters()
- {
- const String& projectFileName = getEventGroup()->getProject()->getFileName();
- const String qualifiedGroupName = getEventGroup()->getQualifiedName();
- const String description = String::ToString( "FMOD Event Parameter (%s)", projectFileName.c_str() );
-
- for( U32 i = 0; i < MaxNumParameters; ++ i )
- {
- StringTableEntry name = getParameter( i );
- if( !name )
- continue;
-
- SFXParameter* parameter = SFXParameter::find( name );
- if( !parameter )
- {
- parameter = new SFXParameter();
- parameter->setInternalName( name );
- parameter->registerObject();
-
- // Set up parameter.
-
- parameter->setChannel( SFXChannelUser0 );
- parameter->setRange( mParameterRanges[ i ] );
- parameter->setDefaultValue( mParameterValues[ i ] );
- parameter->setValue( mParameterValues[ i ] );
- parameter->setDescription( description );
-
- // Set categories for easy filtering.
-
- static StringTableEntry sCategories = StringTable->insert( "categories" );
- parameter->setDataField( sCategories, "0", "FMOD" );
- parameter->setDataField( sCategories, "1", avar( "FMOD Project: %s", projectFileName.c_str() ) );
- parameter->setDataField( sCategories, "2", avar( "FMOD Group: %s", qualifiedGroupName.c_str() ) );
- }
- }
- }
|