2018-01-28 20:48:02 +00:00
//-----------------------------------------------------------------------------
// Copyright (c) 2013 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.
//-----------------------------------------------------------------------------
# ifndef SOUND_ASSET_H
# include "SoundAsset.h"
# endif
# ifndef _ASSET_MANAGER_H_
# include "assets/assetManager.h"
# endif
# ifndef _CONSOLETYPES_H_
# include "console/consoleTypes.h"
# endif
# ifndef _TAML_
# include "persistence/taml/taml.h"
# endif
# ifndef _ASSET_PTR_H_
# include "assets/assetPtr.h"
# endif
2021-08-31 05:54:05 +00:00
# ifndef _SFXSOURCE_H_
# include "sfx/sfxSource.h"
# endif
2023-10-21 22:19:02 +00:00
# ifndef _SFXPROFILE_H_
# include "sfx/sfxProfile.h"
# endif // !_SFXPROFILE_H_
2018-01-28 20:48:02 +00:00
// Debug Profiling.
# include "platform/profiler.h"
2021-07-19 06:07:08 +00:00
# include "sfx/sfxTypes.h"
2018-01-28 20:48:02 +00:00
2022-08-29 22:40:51 +00:00
# include "SoundAssetInspectors.h"
2025-03-09 16:53:23 +00:00
# include "console/typeValidators.h"
2022-08-29 22:40:51 +00:00
2018-01-28 20:48:02 +00:00
//-----------------------------------------------------------------------------
IMPLEMENT_CONOBJECT ( SoundAsset ) ;
2021-07-19 06:07:08 +00:00
ConsoleType ( SoundAssetPtr , TypeSoundAssetPtr , const char * , ASSET_ID_FIELD_PREFIX )
2018-01-28 20:48:02 +00:00
//-----------------------------------------------------------------------------
ConsoleGetType ( TypeSoundAssetPtr )
{
// Fetch asset Id.
2021-07-19 06:07:08 +00:00
return * ( ( const char * * ) ( dptr ) ) ;
2018-01-28 20:48:02 +00:00
}
//-----------------------------------------------------------------------------
ConsoleSetType ( TypeSoundAssetPtr )
{
// Was a single argument specified?
if ( argc = = 1 )
{
// Yes, so fetch field value.
2021-07-19 06:07:08 +00:00
* ( ( const char * * ) dptr ) = StringTable - > insert ( argv [ 0 ] ) ;
2018-01-28 20:48:02 +00:00
2021-07-19 06:07:08 +00:00
return ;
}
2018-01-28 20:48:02 +00:00
2021-07-19 06:07:08 +00:00
// Warn.
Con : : warnf ( " (TypeSoundAssetPtr) - Cannot set multiple args to a single asset. " ) ;
}
//-----------------------------------------------------------------------------
2018-01-28 20:48:02 +00:00
2021-07-19 06:07:08 +00:00
ConsoleType ( assetIdString , TypeSoundAssetId , const char * , ASSET_ID_FIELD_PREFIX )
ConsoleGetType ( TypeSoundAssetId )
{
// Fetch asset Id.
return * ( ( const char * * ) ( dptr ) ) ;
}
ConsoleSetType ( TypeSoundAssetId )
{
// Was a single argument specified?
if ( argc = = 1 )
{
// Yes, so fetch field value.
* ( ( const char * * ) dptr ) = StringTable - > insert ( argv [ 0 ] ) ;
2018-01-28 20:48:02 +00:00
return ;
}
// Warn.
2021-07-19 06:07:08 +00:00
Con : : warnf ( " (TypeAssetId) - Cannot set multiple args to a single asset. " ) ;
2018-01-28 20:48:02 +00:00
}
2023-10-08 18:19:43 +00:00
const String SoundAsset : : mErrCodeStrings [ ] =
{
" BadProfile " ,
" BadDescription " ,
" BadBufferData " ,
" UnKnown "
} ;
2018-01-28 20:48:02 +00:00
//-----------------------------------------------------------------------------
SoundAsset : : SoundAsset ( )
2021-09-20 09:49:34 +00:00
: AssetBase ( )
2018-01-28 20:48:02 +00:00
{
2023-10-21 22:19:02 +00:00
dMemset ( mPlaylist . mSlots . mReplayMode , 0 , sizeof ( mPlaylist . mSlots . mReplayMode ) ) ;
dMemset ( mPlaylist . mSlots . mTransitionIn , 0 , sizeof ( mPlaylist . mSlots . mTransitionIn ) ) ;
dMemset ( mPlaylist . mSlots . mRepeatCount , 0 , sizeof ( mPlaylist . mSlots . mRepeatCount ) ) ;
dMemset ( mPlaylist . mSlots . mState , 0 , sizeof ( mPlaylist . mSlots . mState ) ) ;
dMemset ( mPlaylist . mSlots . mTrack , 0 , sizeof ( mPlaylist . mSlots . mTrack ) ) ;
dMemset ( mPlaylist . mSlots . mStateMode , 0 , sizeof ( mPlaylist . mSlots . mStateMode ) ) ;
for ( U32 i = 0 ; i < SFXPlayList : : NUM_SLOTS ; i + + )
{
mSoundFile [ i ] = StringTable - > EmptyString ( ) ;
mSoundPath [ i ] = StringTable - > EmptyString ( ) ;
mPlaylist . mSlots . mTransitionOut [ i ] = SFXPlayList : : TRANSITION_Wait ;
mPlaylist . mSlots . mVolumeScale . mValue [ i ] = 1.f ;
mPlaylist . mSlots . mPitchScale . mValue [ i ] = 1.f ;
mPlaylist . mSlots . mFadeTimeIn . mValue [ i ] = - 1.f ; // Don't touch by default.
mPlaylist . mSlots . mFadeTimeOut . mValue [ i ] = - 1.f ; // Don't touch by default.
mPlaylist . mSlots . mMinDistance . mValue [ i ] = - 1.f ; // Don't touch by default.
mPlaylist . mSlots . mMaxDistance . mValue [ i ] = - 1.f ; // Don't touch by default.
}
2021-07-19 06:07:08 +00:00
mSubtitleString = StringTable - > EmptyString ( ) ;
mLoadedState = AssetErrCode : : NotLoaded ;
mPreload = false ;
// SFX description inits
// reverb is useless here, reverb is inacted on listener.
mProfileDesc . mPitch = 1 ;
mProfileDesc . mVolume = 1 ;
mProfileDesc . mIs3D = false ;
mProfileDesc . mIsLooping = false ;
mProfileDesc . mIsStreaming = false ;
mProfileDesc . mUseHardware = false ;
mProfileDesc . mMinDistance = 1 ;
mProfileDesc . mMaxDistance = 100 ;
mProfileDesc . mConeInsideAngle = 360 ;
mProfileDesc . mConeOutsideAngle = 360 ;
mProfileDesc . mConeOutsideVolume = 1 ;
mProfileDesc . mRolloffFactor = - 1.0f ;
mProfileDesc . mScatterDistance = Point3F ( 0.f , 0.f , 0.f ) ;
mProfileDesc . mPriority = 1.0f ;
mProfileDesc . mSourceGroup = NULL ;
2025-09-30 22:14:30 +00:00
mProfileDesc . mFadeInEase = EaseF ( ) ;
2023-10-21 22:19:02 +00:00
mIsPlaylist = false ;
mPlaylist . mNumSlotsToPlay = SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ;
mPlaylist . mRandomMode = SFXPlayList : : RANDOM_NotRandom ;
mPlaylist . mTrace = false ;
mPlaylist . mLoopMode = SFXPlayList : : LOOP_All ;
2024-02-05 20:23:11 +00:00
mPlaylist . mActiveSlots = 1 ;
2023-10-21 22:19:02 +00:00
2018-01-28 20:48:02 +00:00
}
//-----------------------------------------------------------------------------
SoundAsset : : ~ SoundAsset ( )
{
}
//-----------------------------------------------------------------------------
void SoundAsset : : initPersistFields ( )
{
2023-01-27 07:13:15 +00:00
docsURL ;
2018-01-28 20:48:02 +00:00
// Call parent.
Parent : : initPersistFields ( ) ;
2024-02-06 03:02:41 +00:00
addGroup ( " SoundSlots " ) ;
2023-10-21 22:19:02 +00:00
addArray ( " slots " , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ) ;
addProtectedField ( " soundFile " , TypeAssetLooseFilePath , Offset ( mSoundFile , SoundAsset ) ,
2024-02-05 20:23:11 +00:00
& _setSoundFile , & defaultProtectedGetFn , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS , " Path to the sound file. " ) ;
2023-10-21 22:19:02 +00:00
addField ( " replay " , TYPEID < SFXPlayList : : EReplayMode > ( ) , Offset ( mPlaylist . mSlots . mReplayMode , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Behavior when an already playing sound is encountered on this slot from a previous cycle. \n "
" Each slot can have an arbitrary number of sounds playing on it from previous cycles. This field determines "
" how SFXController will handle these sources. " ) ;
addField ( " transitionIn " , TYPEID < SFXPlayList : : ETransitionMode > ( ) , Offset ( mPlaylist . mSlots . mTransitionIn , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Behavior when moving into this slot. \n "
" After the delayIn time has expired (if any), this slot determines what the controller "
" will do before actually playing the slot. " ) ;
addField ( " transitionOut " , TYPEID < SFXPlayList : : ETransitionMode > ( ) , Offset ( mPlaylist . mSlots . mTransitionOut , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Behavior when moving out of this slot. \n "
" After the #detailTimeOut has expired (if any), this slot determines what the controller "
" will do before moving on to the next slot. " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " delayTimeIn " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mDelayTimeIn . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Seconds to wait after moving into slot before #transitionIn. " ) ;
addField ( " delayTimeInVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mDelayTimeIn . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Bounds on randomization of #delayTimeIn. \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " delayTimeOut " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mDelayTimeOut . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Seconds to wait before moving out of slot after #transitionOut. " ) ;
addField ( " delayTimeOutVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mDelayTimeOut . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Bounds on randomization of #delayTimeOut. \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " fadeTimeIn " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mFadeTimeIn . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Seconds to fade sound in (-1 to use the track's own fadeInTime.) \n "
" @see SFXDescription::fadeTimeIn " ) ;
addField ( " fadeTimeInVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mFadeTimeIn . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Bounds on randomization of #fadeInTime. \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " fadeTimeOut " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mFadeTimeOut . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Seconds to fade sound out (-1 to use the track's own fadeOutTime.) \n "
" @see SFXDescription::fadeTimeOut " ) ;
addField ( " fadeTimeOutVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mFadeTimeOut . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Bounds on randomization of #fadeOutTime \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " referenceDistance " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mMinDistance . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" @c referenceDistance to set for 3D sounds in this slot (<1 to use @c referenceDistance of track's own description). \n "
" @see SFXDescription::referenceDistance " ) ;
addField ( " referenceDistanceVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mMinDistance . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Bounds on randomization of #referenceDistance. \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-09-30 22:14:30 +00:00
addFieldV ( " maxSlotDistance " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mMaxDistance . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" @c maxDistance to apply to 3D sounds in this slot (<1 to use @c maxDistance of track's own description). \n "
" @see SFXDescription::maxDistance " ) ;
2025-09-30 22:14:30 +00:00
addField ( " maxSlotDistanceVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mMaxDistance . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Bounds on randomization of #maxDistance. \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " volumeScale " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mVolumeScale . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Scale factor to apply to volume of sounds played on this list slot. \n "
" This value will scale the actual volume level set on the track assigned to the slot, i.e. a value of 0.5 will "
" cause the track to play at half-volume. " ) ;
addField ( " volumeScaleVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mVolumeScale . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Bounds on randomization of #volumeScale. \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " pitchScale " , TypeRangedF32 , Offset ( mPlaylist . mSlots . mPitchScale . mValue , SoundAsset ) , & CommonValidators : : PositiveFloat , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Scale factor to apply to pitch of sounds played on this list slot. \n "
" This value will scale the actual pitch set on the track assigned to the slot, i.e. a value of 0.5 will "
" cause the track to play at half its assigned speed. " ) ;
addField ( " pitchScaleVariance " , TypePoint2F , Offset ( mPlaylist . mSlots . mPitchScale . mVariance , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Bounds on randomization of #pitchScale. \n \n "
" @ref SFXPlayList_randomization \n " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " repeatCount " , TypeRangedS32 , Offset ( mPlaylist . mSlots . mRepeatCount , SoundAsset ) , & CommonValidators : : PositiveInt , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
2023-10-21 22:19:02 +00:00
" Number of times to loop this slot. " ) ;
addField ( " state " , TypeSFXStateName , Offset ( mPlaylist . mSlots . mState , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" State that must be active for this slot to play. \n \n "
" @ref SFXPlayList_states " ) ;
addField ( " stateMode " , TYPEID < SFXPlayList : : EStateMode > ( ) , Offset ( mPlaylist . mSlots . mStateMode , SoundAsset ) , SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ,
" Behavior when assigned state is deactivated while slot is playing. \n \n "
" @ref SFXPlayList_states " ) ;
endArray ( " slots " ) ;
2024-02-06 03:02:41 +00:00
endGroup ( " SoundSlots " ) ;
2018-01-28 20:48:02 +00:00
2024-02-06 03:02:41 +00:00
addGroup ( " General Profile " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " pitchAdjust " , TypeRangedF32 , Offset ( mProfileDesc . mPitch , SoundAsset ) , & CommonValidators : : PositiveFloat , " Adjustment of the pitch value 1 is default. " ) ;
addFieldV ( " volumeAdjust " , TypeRangedF32 , Offset ( mProfileDesc . mVolume , SoundAsset ) , & CommonValidators : : PositiveFloat , " Adjustment to the volume. " ) ;
2021-07-19 06:07:08 +00:00
addField ( " is3D " , TypeBool , Offset ( mProfileDesc . mIs3D , SoundAsset ) , " Set this sound to 3D. " ) ;
addField ( " isLooping " , TypeBool , Offset ( mProfileDesc . mIsLooping , SoundAsset ) , " Does this sound loop. " ) ;
// if streaming, a default packet size should be chosen for all sounds.
addField ( " isStreaming " , TypeBool , Offset ( mProfileDesc . mIsStreaming , SoundAsset ) , " Use streaming. " ) ;
//....why?
addField ( " useHardware " , TypeBool , Offset ( mProfileDesc . mUseHardware , SoundAsset ) , " Use hardware mixing for this sound. " ) ;
addField ( " sourceGroup " , TypeSFXSourceName , Offset ( mProfileDesc . mSourceGroup , SoundAsset ) , " Group that sources playing with this description should be put into. " ) ;
2023-10-21 22:19:02 +00:00
addField ( " preload " , TypeBool , Offset ( mPreload , SoundAsset ) , " Whether to preload sound data when the profile is added to system. " ) ;
2024-02-06 03:02:41 +00:00
endGroup ( " General Profile " ) ;
2023-10-21 22:19:02 +00:00
addGroup ( " Fading " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " fadeInTime " , TypeRangedF32 , Offset ( mProfileDesc . mFadeInTime , SoundAsset ) , & CommonValidators : : PositiveFloat , " Number of seconds to gradually fade in volume from zero when playback starts. " ) ;
addFieldV ( " fadeOutTime " , TypeRangedF32 , Offset ( mProfileDesc . mFadeOutTime , SoundAsset ) , & CommonValidators : : PositiveFloat , " Number of seconds to gradually fade out volume down to zero when playback is stopped or paused. " ) ;
2023-10-21 22:19:02 +00:00
addField ( " fadeInEase " , TypeEaseF , Offset ( mProfileDesc . mFadeInEase , SoundAsset ) , " Easing curve for fade-in transition. " ) ;
addField ( " fadeOutEase " , TypeEaseF , Offset ( mProfileDesc . mFadeOutEase , SoundAsset ) , " Easing curve for fade-out transition. " ) ;
addField ( " fadeLoops " , TypeBool , Offset ( mProfileDesc . mFadeLoops , SoundAsset ) , " Fade each cycle of a loop in and/or out; otherwise only fade-in first cycle. " ) ;
endGroup ( " Fading " ) ;
addGroup ( " 3D " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " minDistance " , TypeRangedF32 , Offset ( mProfileDesc . mMinDistance , SoundAsset ) , & CommonValidators : : PositiveFloat , " Minimum distance for sound. " ) ;
addFieldV ( " maxDistance " , TypeRangedF32 , Offset ( mProfileDesc . mMaxDistance , SoundAsset ) , & CommonValidators : : PositiveFloat , " Max distance for sound. " ) ;
addFieldV ( " coneInsideAngle " , TypeRangedS32 , Offset ( mProfileDesc . mConeInsideAngle , SoundAsset ) , & CommonValidators : : S32_PosDegreeRange , " Cone inside angle. " ) ;
addFieldV ( " coneOutsideAngle " , TypeRangedS32 , Offset ( mProfileDesc . mConeOutsideAngle , SoundAsset ) , & CommonValidators : : S32_PosDegreeRange , " Cone outside angle. " ) ;
addFieldV ( " coneOutsideVolume " , TypeRangedF32 , Offset ( mProfileDesc . mConeOutsideVolume , SoundAsset ) , & CommonValidators : : NormalizedFloat , " Cone outside volume. " ) ;
2025-03-18 19:06:33 +00:00
addFieldV ( " rolloffFactor " , TypeRangedF32 , Offset ( mProfileDesc . mRolloffFactor , SoundAsset ) , & CommonValidators : : NegDefaultF32 , " Rolloff factor. " ) ;
2023-10-21 22:19:02 +00:00
addField ( " scatterDistance " , TypePoint3F , Offset ( mProfileDesc . mScatterDistance , SoundAsset ) , " Randomization to the spacial position of the sound. " ) ;
endGroup ( " 3D " ) ;
addGroup ( " Playlist settings " ) ;
addField ( " random " , TYPEID < SFXPlayList : : ERandomMode > ( ) , Offset ( mPlaylist . mRandomMode , SoundAsset ) , " Slot playback order randomization pattern. " ) ;
addField ( " loopMode " , TYPEID < SFXPlayList : : ELoopMode > ( ) , Offset ( mPlaylist . mLoopMode , SoundAsset ) , " Behavior when description has looping enabled. " ) ;
2025-03-09 16:53:23 +00:00
addFieldV ( " numSlotsToPlay " , TypeRangedS32 , Offset ( mPlaylist . mNumSlotsToPlay , SoundAsset ) , & playlistSlotRange , " Number of slots to play. " ) ;
2023-10-21 22:19:02 +00:00
addField ( " trace " , TypeBool , Offset ( mPlaylist . mTrace , SoundAsset ) , " Enable/disable execution tracing for this playlist (local only). " ) ;
endGroup ( " Playlist settings " ) ;
2018-01-28 20:48:02 +00:00
}
//------------------------------------------------------------------------------
void SoundAsset : : copyTo ( SimObject * object )
{
// Call to parent.
Parent : : copyTo ( object ) ;
}
void SoundAsset : : initializeAsset ( void )
{
2021-07-19 06:07:08 +00:00
Parent : : initializeAsset ( ) ;
2023-10-21 22:19:02 +00:00
for ( U32 i = 0 ; i < SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ; i + + )
{
if ( i = = 0 & & mSoundFile [ i ] = = StringTable - > EmptyString ( ) )
return ;
2021-07-19 06:07:08 +00:00
2023-10-21 22:19:02 +00:00
if ( mSoundFile [ i ] = = StringTable - > EmptyString ( ) )
break ;
mSoundPath [ i ] = getOwned ( ) ? expandAssetFilePath ( mSoundFile [ i ] ) : mSoundPath [ i ] ;
2024-02-05 20:23:11 +00:00
if ( ! Torque : : FS : : IsFile ( mSoundPath [ i ] ) )
Con : : errorf ( " SoundAsset::initializeAsset (%s)[%d] could not find %s! " , getAssetName ( ) , i , mSoundPath [ i ] ) ;
2023-10-21 22:19:02 +00:00
}
2021-07-19 06:07:08 +00:00
}
void SoundAsset : : _onResourceChanged ( const Torque : : Path & path )
{
2023-10-21 22:19:02 +00:00
for ( U32 i = 0 ; i < SFXPlayList : : NUM_SLOTS ; i + + )
{
2021-07-19 06:07:08 +00:00
2023-10-21 22:19:02 +00:00
if ( path ! = Torque : : Path ( mSoundPath [ i ] ) )
return ;
}
2021-07-19 06:07:08 +00:00
refreshAsset ( ) ;
2018-01-28 20:48:02 +00:00
}
void SoundAsset : : onAssetRefresh ( void )
{
2023-10-21 22:19:02 +00:00
for ( U32 i = 0 ; i < SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ; i + + )
{
if ( i = = 0 & & mSoundFile [ i ] = = StringTable - > EmptyString ( ) )
return ;
if ( mSoundFile [ i ] = = StringTable - > EmptyString ( ) )
break ;
2021-07-19 06:07:08 +00:00
2023-10-21 22:19:02 +00:00
mSoundPath [ i ] = getOwned ( ) ? expandAssetFilePath ( mSoundFile [ i ] ) : mSoundPath [ i ] ;
}
2021-07-19 06:07:08 +00:00
}
2023-11-12 22:33:17 +00:00
U32 SoundAsset : : load ( )
2021-07-19 06:07:08 +00:00
{
2023-11-12 22:33:17 +00:00
if ( mLoadedState = = AssetErrCode : : Ok ) return mLoadedState ;
2023-10-21 22:19:02 +00:00
// find out how many active slots we have.
U32 numSlots = 0 ;
for ( U32 i = 0 ; i < SFXPlayList : : SFXPlaylistSettings : : NUM_SLOTS ; i + + )
2021-07-19 06:07:08 +00:00
{
2023-10-21 22:19:02 +00:00
if ( i = = 0 & & mSoundPath [ i ] = = StringTable - > EmptyString ( ) )
2021-07-19 06:07:08 +00:00
return false ;
2023-10-21 22:19:02 +00:00
if ( mSoundPath [ i ] = = StringTable - > EmptyString ( ) )
break ;
numSlots + + ;
}
if ( numSlots > 1 )
{
mIsPlaylist = true ;
for ( U32 i = 0 ; i < numSlots ; i + + )
{
if ( mSoundPath [ i ] )
{
if ( ! Torque : : FS : : IsFile ( mSoundPath [ i ] ) )
{
Con : : errorf ( " SoundAsset::initializeAsset: Attempted to load file %s but it was not valid! " , mSoundFile [ i ] ) ;
mLoadedState = BadFileReference ;
mSFXProfile [ i ] . setDescription ( NULL ) ;
mSFXProfile [ i ] . setSoundFileName ( StringTable - > insert ( StringTable - > EmptyString ( ) ) ) ;
mSFXProfile [ i ] . setPreload ( false ) ;
2023-11-12 22:33:17 +00:00
return mLoadedState ;
2023-10-21 22:19:02 +00:00
}
else
{ // = new SFXProfile(mProfileDesc, mSoundFile, mPreload);
if ( mProfileDesc . mSourceGroup = = NULL )
mProfileDesc . mSourceGroup = dynamic_cast < SFXSource * > ( Sim : : findObject ( " AudioChannelMaster " ) ) ;
SFXProfile * trackProfile = new SFXProfile ( ) ;
trackProfile - > setDescription ( & mProfileDesc ) ;
trackProfile - > setSoundFileName ( mSoundPath [ i ] ) ;
trackProfile - > setPreload ( mPreload ) ;
trackProfile - > getBuffer ( ) ;
mSFXProfile [ i ] = * trackProfile ;
mPlaylist . mSlots . mTrack [ i ] = trackProfile ;
}
}
2021-07-19 06:07:08 +00:00
}
2023-10-21 22:19:02 +00:00
mPlaylist . setDescription ( & mProfileDesc ) ;
2021-07-19 06:07:08 +00:00
}
2023-10-21 22:19:02 +00:00
else
{
if ( mSoundPath [ 0 ] )
{
if ( ! Torque : : FS : : IsFile ( mSoundPath [ 0 ] ) )
{
Con : : errorf ( " SoundAsset::initializeAsset: Attempted to load file %s but it was not valid! " , mSoundFile [ 0 ] ) ;
mLoadedState = BadFileReference ;
mSFXProfile [ 0 ] . setDescription ( NULL ) ;
mSFXProfile [ 0 ] . setSoundFileName ( StringTable - > insert ( StringTable - > EmptyString ( ) ) ) ;
mSFXProfile [ 0 ] . setPreload ( false ) ;
2023-11-12 22:33:17 +00:00
return mLoadedState ;
2023-10-21 22:19:02 +00:00
}
else
{ // = new SFXProfile(mProfileDesc, mSoundFile, mPreload);
if ( mProfileDesc . mSourceGroup = = NULL )
mProfileDesc . mSourceGroup = dynamic_cast < SFXSource * > ( Sim : : findObject ( " AudioChannelMaster " ) ) ;
mSFXProfile [ 0 ] . setDescription ( & mProfileDesc ) ;
mSFXProfile [ 0 ] . setSoundFileName ( mSoundPath [ 0 ] ) ;
mSFXProfile [ 0 ] . setPreload ( mPreload ) ;
//give it a nudge to preload if required
mSFXProfile [ 0 ] . getBuffer ( ) ;
}
}
}
2021-07-19 06:07:08 +00:00
mChangeSignal . trigger ( ) ;
mLoadedState = Ok ;
2023-11-12 22:33:17 +00:00
return mLoadedState ;
2019-05-04 16:49:42 +00:00
}
2024-02-05 20:23:11 +00:00
bool SoundAsset : : _setSoundFile ( void * object , const char * index , const char * data )
2023-10-21 22:19:02 +00:00
{
2024-02-05 20:23:11 +00:00
SoundAsset * pData = static_cast < SoundAsset * > ( object ) ;
2019-05-04 16:49:42 +00:00
2024-02-05 20:23:11 +00:00
U32 id = 0 ;
if ( index )
id = dAtoui ( index ) ;
2019-05-04 16:49:42 +00:00
// Update.
2024-02-06 00:41:07 +00:00
pData - > mSoundFile [ id ] = StringTable - > insert ( data , true ) ;
2024-02-05 20:23:11 +00:00
if ( pData - > mSoundFile [ id ] = = StringTable - > EmptyString ( ) )
pData - > mSoundPath [ id ] = StringTable - > EmptyString ( ) ;
2019-05-04 16:49:42 +00:00
// Refresh the asset.
2024-02-05 20:23:11 +00:00
pData - > refreshAsset ( ) ;
2024-02-05 20:40:24 +00:00
return true ;
2019-05-04 16:49:42 +00:00
}
2020-08-25 01:24:50 +00:00
2021-08-31 05:54:05 +00:00
StringTableEntry SoundAsset : : getAssetIdByFileName ( StringTableEntry fileName )
{
if ( fileName = = StringTable - > EmptyString ( ) )
return StringTable - > EmptyString ( ) ;
2022-01-04 02:57:10 +00:00
StringTableEntry soundAssetId = StringTable - > EmptyString ( ) ;
2021-08-31 05:54:05 +00:00
AssetQuery query ;
U32 foundCount = AssetDatabase . findAssetType ( & query , " SoundAsset " ) ;
if ( foundCount ! = 0 )
{
2023-05-09 02:18:23 +00:00
for ( U32 i = 0 ; i < foundCount & & soundAssetId = = StringTable - > EmptyString ( ) ; i + + )
2021-08-31 05:54:05 +00:00
{
SoundAsset * soundAsset = AssetDatabase . acquireAsset < SoundAsset > ( query . mAssetList [ i ] ) ;
2023-05-09 02:18:23 +00:00
if ( soundAsset )
2021-08-31 05:54:05 +00:00
{
2023-05-09 02:18:23 +00:00
if ( soundAsset - > getSoundPath ( ) = = fileName )
soundAssetId = soundAsset - > getAssetId ( ) ;
2021-08-31 05:54:05 +00:00
AssetDatabase . releaseAsset ( query . mAssetList [ i ] ) ;
}
}
}
2022-01-04 02:57:10 +00:00
return soundAssetId ;
2021-08-31 05:54:05 +00:00
}
2021-09-28 12:56:35 +00:00
U32 SoundAsset : : getAssetById ( StringTableEntry assetId , AssetPtr < SoundAsset > * soundAsset )
2021-08-31 05:54:05 +00:00
{
2021-09-28 12:56:35 +00:00
( * soundAsset ) = assetId ;
2021-08-31 05:54:05 +00:00
2021-09-28 12:56:35 +00:00
if ( soundAsset - > notNull ( ) )
2021-08-31 05:54:05 +00:00
{
2021-09-28 12:56:35 +00:00
return ( * soundAsset ) - > mLoadedState ;
2021-08-31 05:54:05 +00:00
}
else
{
//Well that's bad, loading the fallback failed.
2021-09-28 12:56:35 +00:00
Con : : warnf ( " SoundAsset::getAssetById - Finding of asset with id %s failed with no fallback asset " , assetId ) ;
2021-08-31 05:54:05 +00:00
return AssetErrCode : : Failed ;
}
}
U32 SoundAsset : : getAssetByFileName ( StringTableEntry fileName , AssetPtr < SoundAsset > * soundAsset )
{
AssetQuery query ;
U32 foundAssetcount = AssetDatabase . findAssetType ( & query , " SoundAsset " ) ;
if ( foundAssetcount = = 0 )
{
//Well that's bad, loading the fallback failed.
Con : : warnf ( " MaterialAsset::getAssetByMaterialName - Finding of asset associated with filename %s failed with no fallback asset " , fileName ) ;
return AssetErrCode : : Failed ;
}
else
{
for ( U32 i = 0 ; i < foundAssetcount ; i + + )
{
SoundAsset * tSoundAsset = AssetDatabase . acquireAsset < SoundAsset > ( query . mAssetList [ i ] ) ;
if ( tSoundAsset & & tSoundAsset - > getSoundPath ( ) = = fileName )
{
soundAsset - > setAssetId ( query . mAssetList [ i ] ) ;
AssetDatabase . releaseAsset ( query . mAssetList [ i ] ) ;
return ( * soundAsset ) - > mLoadedState ;
}
AssetDatabase . releaseAsset ( query . mAssetList [ i ] ) ; //cleanup if that's not the one we needed
}
}
//No good match
return AssetErrCode : : Failed ;
}
2020-08-25 01:24:50 +00:00
DefineEngineMethod ( SoundAsset , getSoundPath , const char * , ( ) , , " " )
{
return object - > getSoundPath ( ) ;
}
2021-07-19 06:07:08 +00:00
2021-08-31 05:54:05 +00:00
DefineEngineMethod ( SoundAsset , playSound , S32 , ( Point3F position ) , ( Point3F : : Zero ) ,
2022-01-04 02:57:10 +00:00
" Plays the sound for this asset. \n "
" @return (sound plays). \n " )
2021-08-31 05:54:05 +00:00
{
2023-10-21 22:19:02 +00:00
if ( object - > getSFXTrack ( ) )
2021-08-31 05:54:05 +00:00
{
MatrixF transform ;
transform . setPosition ( position ) ;
2024-02-04 02:16:45 +00:00
SFXSource * source ;
if ( position = = Point3F : : Zero | | ! object - > is3D ( ) )
source = SFX - > playOnce ( object - > getSFXTrack ( ) ) ;
else
source = SFX - > playOnce ( object - > getSFXTrack ( ) , & transform , NULL , - 1 ) ;
2022-06-03 07:04:39 +00:00
if ( source )
return source - > getId ( ) ;
else
return 0 ;
2021-08-31 05:54:05 +00:00
}
else
return 0 ;
}
2021-09-05 08:43:41 +00:00
# ifdef TORQUE_TOOLS
DefineEngineStaticMethod ( SoundAsset , getAssetIdByFilename , const char * , ( const char * filePath ) , ( " " ) ,
" Queries the Asset Database to see if any asset exists that is associated with the provided file path. \n "
" @return The AssetId of the associated asset, if any. " )
{
return SoundAsset : : getAssetIdByFileName ( StringTable - > insert ( filePath ) ) ;
}
2021-07-19 06:07:08 +00:00
IMPLEMENT_CONOBJECT ( GuiInspectorTypeSoundAssetPtr ) ;
ConsoleDocClass ( GuiInspectorTypeSoundAssetPtr ,
" @brief Inspector field type for Sounds \n \n "
" Editor use only. \n \n "
" @internal "
) ;
void GuiInspectorTypeSoundAssetPtr : : consoleInit ( )
{
Parent : : consoleInit ( ) ;
ConsoleBaseType : : getType ( TypeSoundAssetPtr ) - > setInspectorFieldType ( " GuiInspectorTypeSoundAssetPtr " ) ;
}
GuiControl * GuiInspectorTypeSoundAssetPtr : : constructEditControl ( )
{
2021-08-31 05:54:05 +00:00
// Create base filename edit controls
GuiControl * retCtrl = Parent : : constructEditControl ( ) ;
if ( retCtrl = = NULL )
return retCtrl ;
// Change filespec
char szBuffer [ 512 ] ;
dSprintf ( szBuffer , sizeof ( szBuffer ) , " AssetBrowser.showDialog( \" SoundAsset \" , \" AssetBrowser.changeAsset \" , %s, \" \" ); " ,
getIdString ( ) ) ;
mBrowseButton - > setField ( " Command " , szBuffer ) ;
setDataField ( StringTable - > insert ( " targetObject " ) , NULL , mInspector - > getInspectObject ( ) - > getIdString ( ) ) ;
// Create "Open in Editor" button
mEditButton = new GuiBitmapButtonCtrl ( ) ;
dSprintf ( szBuffer , sizeof ( szBuffer ) , " AssetBrowser.editAsset(%d.getText()); " , retCtrl - > getId ( ) ) ;
mEditButton - > setField ( " Command " , szBuffer ) ;
char bitmapName [ 512 ] = " ToolsModule:SFXEmitter_image " ;
mEditButton - > setBitmap ( StringTable - > insert ( bitmapName ) ) ;
mEditButton - > setDataField ( StringTable - > insert ( " Profile " ) , NULL , " GuiButtonProfile " ) ;
mEditButton - > setDataField ( StringTable - > insert ( " tooltipprofile " ) , NULL , " GuiToolTipProfile " ) ;
mEditButton - > setDataField ( StringTable - > insert ( " hovertime " ) , NULL , " 1000 " ) ;
mEditButton - > setDataField ( StringTable - > insert ( " tooltip " ) , NULL , " Test play this sound " ) ;
mEditButton - > registerObject ( ) ;
addObject ( mEditButton ) ;
return retCtrl ;
2021-07-19 06:07:08 +00:00
}
bool GuiInspectorTypeSoundAssetPtr : : updateRects ( )
{
2021-08-31 05:54:05 +00:00
S32 dividerPos , dividerMargin ;
mInspector - > getDivider ( dividerPos , dividerMargin ) ;
Point2I fieldExtent = getExtent ( ) ;
Point2I fieldPos = getPosition ( ) ;
mCaptionRect . set ( 0 , 0 , fieldExtent . x - dividerPos - dividerMargin , fieldExtent . y ) ;
mEditCtrlRect . set ( fieldExtent . x - dividerPos + dividerMargin , 1 , dividerPos - dividerMargin - 34 , fieldExtent . y ) ;
bool resized = mEdit - > resize ( mEditCtrlRect . point , mEditCtrlRect . extent ) ;
if ( mBrowseButton ! = NULL )
{
mBrowseRect . set ( fieldExtent . x - 32 , 2 , 14 , fieldExtent . y - 4 ) ;
resized | = mBrowseButton - > resize ( mBrowseRect . point , mBrowseRect . extent ) ;
}
if ( mEditButton ! = NULL )
{
RectI shapeEdRect ( fieldExtent . x - 16 , 2 , 14 , fieldExtent . y - 4 ) ;
resized | = mEditButton - > resize ( shapeEdRect . point , shapeEdRect . extent ) ;
}
return resized ;
2021-07-19 06:07:08 +00:00
}
IMPLEMENT_CONOBJECT ( GuiInspectorTypeSoundAssetId ) ;
ConsoleDocClass ( GuiInspectorTypeSoundAssetId ,
" @brief Inspector field type for Sounds \n \n "
" Editor use only. \n \n "
" @internal "
) ;
void GuiInspectorTypeSoundAssetId : : consoleInit ( )
{
Parent : : consoleInit ( ) ;
ConsoleBaseType : : getType ( TypeSoundAssetId ) - > setInspectorFieldType ( " GuiInspectorTypeSoundAssetId " ) ;
}
2022-06-13 17:38:08 +00:00
# endif