123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510 |
- //-----------------------------------------------------------------------------
- // 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/fmod/sfxFMODEventGroup.h"
- #include "sfx/fmod/sfxFMODDevice.h"
- #include "sfx/fmod/sfxFMODEvent.h"
- #include "sfx/fmod/sfxFMODProject.h"
- #include "core/stream/bitStream.h"
- #include "console/engineAPI.h"
- IMPLEMENT_CO_DATABLOCK_V1( SFXFMODEventGroup );
- ConsoleDocClass( SFXFMODEventGroup,
- "@brief A group of events in an imported FMOD Designer project.\n\n"
-
- ""
-
- "@note Instances of this class \n\n"
-
- "@ingroup SFXFMOD\n"
- "@ingroup Datablocks"
- );
- //-----------------------------------------------------------------------------
- SFXFMODEventGroup::SFXFMODEventGroup()
- : mProject( NULL ),
- mHandle( NULL ),
- mParent( NULL ),
- mChildren( NULL ),
- mSibling( NULL ),
- mLoadCount( 0 ),
- mEvents( NULL ),
- mNumEvents( 0 ),
- mNumGroups( 0 ),
- mParentId( 0 ),
- mProjectId( 0 )
- {
- }
- //-----------------------------------------------------------------------------
- SFXFMODEventGroup::SFXFMODEventGroup( SFXFMODProject* project, FMOD_EVENTGROUP* handle, SFXFMODEventGroup* parent )
- : mProject( project ),
- mHandle( handle ),
- mParent( parent ),
- mChildren( NULL ),
- mSibling( NULL ),
- mLoadCount( 0 ),
- mEvents( NULL ),
- mNumEvents( 0 ),
- mNumGroups( 0 ),
- mParentId( 0 ),
- mProjectId( 0 )
- {
- AssertFatal( project != NULL, "SFXFMODEventGroup::SFXFMODEventGroup - got a NULL project!" );
- AssertFatal( handle != NULL, "SFXFMODEventGroup::SFXFMODEventGroup - got a NULL group handle!" );
-
- // Fetch the name.
-
- int index;
- char* name = NULL;
-
- SFXFMODDevice::smFunc->FMOD_EventGroup_GetInfo( handle, &index, &name );
-
- mName = name;
- }
- //-----------------------------------------------------------------------------
- SFXFMODEventGroup::~SFXFMODEventGroup()
- {
- AssertFatal( mEvents == NULL, "SFXFMODEventGroup::~SFXFMODEventGroup - group still has events attached" );
- AssertFatal( mChildren == NULL, "SFXFMODEventGroup::~SFXFMODEventGroup - group still has subgroups attached" );
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::initPersistFields()
- {
- addGroup( "DO NOT MODIFY!!" );
- addField( "fmodProject", TYPEID< SFXFMODProject >(), Offset( mProject, SFXFMODEventGroup ), "DO NOT MODIFY!!" );
- addField( "fmodGroup", TYPEID< SFXFMODEventGroup >(), Offset( mParent, SFXFMODEventGroup ), "DO NOT MODIFY!!" );
- addField( "fmodName", TypeRealString, Offset( mName, SFXFMODEventGroup ), "DO NOT MODIFY!!" );
- endGroup( "DO NOT MODIFY!!" );
-
- Parent::initPersistFields();
- }
- //-----------------------------------------------------------------------------
- bool SFXFMODEventGroup::onAdd()
- {
- if( !Parent::onAdd() )
- return false;
-
- if( !mProject )
- {
- Con::errorf( "SFXFMODEventGroup - not part of a project" );
- return false;
- }
-
- if( mParent )
- mParent->_addGroup( this );
-
- mProject->_addGroup( this );
-
- return true;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::onRemove()
- {
- Parent::onRemove();
-
- if( !mProject )
- return;
-
- release();
-
- while( mEvents )
- mEvents->deleteObject();
- while( mChildren )
- mChildren->deleteObject();
-
- if( mParent )
- mParent->_removeGroup( this );
-
- mProject->_removeGroup( this );
- }
- //-----------------------------------------------------------------------------
- bool SFXFMODEventGroup::preload( bool server, String& errorStr )
- {
- if( !Parent::preload( server, errorStr ) )
- return false;
-
- if( !server )
- {
- if( mParentId != 0 && !Sim::findObject( mParentId, mParent ) )
- {
- errorStr = String::ToString( "SFXFMODEventGroup - parent group '%i' does not exist", mParentId );
- return false;
- }
- if( !Sim::findObject( mProjectId, mProject ) )
- {
- errorStr = String::ToString( "SFXFMODEventGroup - project '%i' does not exist", mProjectId );
- return false;
- }
- }
-
- return true;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::packData( BitStream* stream )
- {
- Parent::packData( stream );
-
- stream->write( mName );
- stream->writeRangedS32( mProject->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
- if( stream->writeFlag( mParent ) )
- stream->writeRangedS32( mParent->getId(), DataBlockObjectIdFirst, DataBlockObjectIdLast );
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::unpackData( BitStream* stream )
- {
- Parent::unpackData( stream );
-
- stream->read( &mName );
-
- mProjectId = stream->readRangedS32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
- if( stream->readFlag() )
- mParentId = stream->readRangedS32( DataBlockObjectIdFirst, DataBlockObjectIdLast );
- else
- mParentId = 0;
- }
- //-----------------------------------------------------------------------------
- String SFXFMODEventGroup::getQualifiedName() const
- {
- if( mParent )
- return String::ToString( "%s/%s", mParent->getQualifiedName().c_str(), mName.c_str() );
- else
- return mName;
- }
- //-----------------------------------------------------------------------------
- bool SFXFMODEventGroup::isDataLoaded() const
- {
- // Check whether we or any of our parents has triggered a load.
-
- for( const SFXFMODEventGroup* group = this; group != NULL; group = group->mParent )
- if( group->mLoadCount > 0 )
- return true;
-
- return false;
- }
- //-----------------------------------------------------------------------------
- bool SFXFMODEventGroup::loadData( bool samples, bool streams )
- {
- if( !mHandle )
- acquire();
-
- if( !mLoadCount )
- {
- FMOD_EVENT_RESOURCE resource;
- if( samples && streams )
- resource = FMOD_EVENT_RESOURCE_STREAMS_AND_SAMPLES;
- else if( samples )
- resource = FMOD_EVENT_RESOURCE_SAMPLES;
- else if( streams )
- resource = FMOD_EVENT_RESOURCE_STREAMS;
- else
- return true;
-
- FMOD_RESULT result = SFXFMODDevice::smFunc->FMOD_EventGroup_LoadEventData( mHandle, resource, FMOD_EVENT_DEFAULT );
- if( result != FMOD_OK )
- {
- Con::errorf( "SFXFMODEventGroup::loadData - could not load data: %s", FMODResultToString( result ).c_str() );
- return false;
- }
-
- SFXFMODDevice::instance()->updateMemUsageStats();
- Con::printf( "SFXFMODProject - %s: Loaded data for group '%s'", mProject->getName(), getQualifiedName().c_str() );
- }
-
- mLoadCount ++;
- return true;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::freeData( bool force )
- {
- bool isLoaded = ( mLoadCount > 0 );
-
- if( !isLoaded )
- isLoaded = ( mParent ? mParent->isDataLoaded() : false );
- else
- {
- if( force )
- mLoadCount = 0;
- else
- -- mLoadCount;
- }
-
- if( !mLoadCount && isLoaded )
- {
- FMOD_RESULT result = SFXFMODDevice::smFunc->FMOD_EventGroup_FreeEventData( mHandle, ( FMOD_EVENT* ) NULL, false );
- if( result != FMOD_OK )
- Con::errorf( "SFXFMODEventGroup - failed freeing event data: %s", FMODResultToString( result ).c_str() );
-
- SFXFMODDevice::instance()->updateMemUsageStats();
- Con::printf( "SFXFMODProject - %s: Cleared data for group '%s'", mProject->getName(), getQualifiedName().c_str() );
- }
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::acquire( bool recursive )
- {
- // Make sure the project is acquired.
-
- mProject->acquire();
-
- // Acquire the group.
-
- if( !mHandle )
- {
- if( mParent )
- {
- mParent->acquire();
- SFXFMODDevice::smFunc->FMOD_EventGroup_GetGroup( mParent->mHandle, mName, true, &mHandle );
- }
- else
- {
- mProject->acquire();
- SFXFMODDevice::smFunc->FMOD_EventProject_GetGroup( mProject->mHandle, mName, true, &mHandle );
- }
- }
-
- // Acquite events and subgroups.
-
- if( recursive )
- {
- for( SFXFMODEvent* event = mEvents; event != NULL; event = event->mSibling )
- event->acquire();
-
- for( SFXFMODEventGroup* group = mChildren; group != NULL; group = group->mSibling )
- group->acquire( true );
- }
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::release()
- {
- if( !mHandle )
- return;
-
- // Free the event data if we still have it loaded.
-
- if( isDataLoaded() )
- freeData( true );
-
- // Release events.
-
- for( SFXFMODEvent* event = mEvents; event != NULL; event = event->mSibling )
- event->release();
-
- // Release children.
-
- for( SFXFMODEventGroup* child = mChildren; child != NULL; child = child->mSibling )
- child->release();
-
- // Release our handle.
-
- freeData();
- mHandle = NULL;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::_load()
- {
- // Make sure we have the group open.
-
- if( !mHandle )
- acquire();
-
- // Fetch info.
-
- int numEvents;
- int numGroups;
- SFXFMODDevice::smFunc->FMOD_EventGroup_GetNumEvents( mHandle, &numEvents );
- SFXFMODDevice::smFunc->FMOD_EventGroup_GetNumGroups( mHandle, &numGroups );
-
- // Load events.
-
- for( U32 i = 0; i < numEvents; ++ i )
- {
- FMOD_EVENT* handle;
- if( SFXFMODDevice::smFunc->FMOD_EventGroup_GetEventByIndex( mHandle, i, FMOD_EVENT_INFOONLY, &handle ) == FMOD_OK )
- {
- SFXFMODEvent* event = new SFXFMODEvent( this, handle );
- if( !isClientOnly() )
- event->assignId();
-
- event->registerObject( String::ToString( "%s_%s", getName(), FMODEventPathToTorqueName( event->getEventName() ).c_str() ) );
- if( isClientOnly() )
- Sim::getRootGroup()->addObject( event );
- }
- }
-
- // Load subgroups.
-
- for( U32 i = 0; i < numGroups; ++ i )
- {
- FMOD_EVENTGROUP* handle;
- if( SFXFMODDevice::smFunc->FMOD_EventGroup_GetGroupByIndex( mHandle, i, true, &handle ) == FMOD_OK )
- {
- SFXFMODEventGroup* group = new SFXFMODEventGroup( mProject, handle, this );
- if( !isClientOnly() )
- group->assignId();
-
- group->registerObject( String::ToString( "%s_%s", getName(), FMODEventPathToTorqueName( group->getGroupName() ).c_str() ) );
- if( isClientOnly() )
- Sim::getRootGroup()->addObject( group );
-
- group->_load();
- }
- }
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::_addEvent( SFXFMODEvent* event )
- {
- event->mSibling = mEvents;
- mEvents = event;
- mNumEvents ++;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::_removeEvent( SFXFMODEvent* event )
- {
- if( mEvents == event )
- {
- mEvents = event->mSibling;
- event->mSibling = NULL;
- mNumEvents --;
- }
- else
- {
- SFXFMODEvent* p = mEvents;
- while( p != NULL && p->mSibling != event )
- p = p->mSibling;
-
- if( p )
- {
- p->mSibling = event->mSibling;
- event->mSibling = NULL;
- mNumEvents --;
- }
- }
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::_addGroup( SFXFMODEventGroup* group )
- {
- group->mSibling = mChildren;
- mChildren = group;
- mNumGroups ++;
- }
- //-----------------------------------------------------------------------------
- void SFXFMODEventGroup::_removeGroup( SFXFMODEventGroup* group )
- {
- if( mChildren == group )
- {
- mChildren = group->mSibling;
- group->mSibling = NULL;
- mNumGroups --;
- }
- else
- {
- SFXFMODEventGroup* p = mChildren;
- while( p != NULL && p->mSibling != group )
- p = p->mSibling;
-
- if( p )
- {
- p->mSibling = group->mSibling;
- group->mSibling = NULL;
- mNumGroups --;
- }
- }
- }
- //=============================================================================
- // Console Methods.
- //=============================================================================
- // MARK: ---- Console Methods ----
- //-----------------------------------------------------------------------------
- DefineEngineMethod( SFXFMODEventGroup, isDataLoaded, bool, (),,
- "Test whether the resource data for this group has been loaded.\n\n"
- "@return True if the resource data for this group is currently loaded.\n" )
- {
- return object->isDataLoaded();
- }
- //-----------------------------------------------------------------------------
- DefineEngineMethod( SFXFMODEventGroup, loadData, bool, ( bool loadStreams, bool loadSamples ), ( true, true ),
- "Load the resource data for this group, if it has not already been loaded (either directly "
- "or indirectly through a parent group).\n"
- "This method works recursively and thus data for direct and indirect child groups to this group will be "
- "loaded as well.\n\n"
- "@param loadStreams Whether to open streams.\n"
- "@param loadSamples Whether to load sample banks.\n"
- "@return True if the data has been successfully loaded; false otherwise.\n\n"
- "@see SFXFMODProject_resources" )
- {
- return object->loadData( loadSamples, loadStreams );
- }
- //-----------------------------------------------------------------------------
- DefineEngineMethod( SFXFMODEventGroup, freeData, void, (),,
- "Release the resource data for this group and its subgroups.\n\n"
- "@see SFXFMODProject_resources" )
- {
- object->freeData();
- }
|