Merge pull request #1072 from Azaezel/alpha41/sfxEmitterWipWork

sfxemitter misc cleanups
This commit is contained in:
Brian Roberts 2023-08-17 22:03:32 -05:00 committed by GitHub
commit 1473a162a8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 210 additions and 263 deletions

View file

@ -105,7 +105,7 @@ SFXEmitter::SFXEmitter()
mDescription.mIsStreaming = false; mDescription.mIsStreaming = false;
mDescription.mFadeInTime = -1.f; mDescription.mFadeInTime = -1.f;
mDescription.mFadeOutTime = -1.f; mDescription.mFadeOutTime = -1.f;
mInstanceDescription = &mDescription;
mLocalProfile.mFilename = StringTable->EmptyString(); mLocalProfile.mFilename = StringTable->EmptyString();
mLocalProfile._registerSignals(); mLocalProfile._registerSignals();
@ -119,8 +119,7 @@ SFXEmitter::SFXEmitter()
SFXEmitter::~SFXEmitter() SFXEmitter::~SFXEmitter()
{ {
mLocalProfile._unregisterSignals(); mLocalProfile.onRemove();
SFX_DELETE( mSource ); SFX_DELETE( mSource );
} }
@ -268,11 +267,11 @@ void SFXEmitter::initPersistFields()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
U32 SFXEmitter::packUpdate( NetConnection *con, U32 mask, BitStream *stream ) U32 SFXEmitter::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
{ {
U32 retMask = Parent::packUpdate( con, mask, stream ); U32 retMask = Parent::packUpdate(con, mask, stream);
if( stream->writeFlag( mask & InitialUpdateMask ) ) if (stream->writeFlag(mask & InitialUpdateMask))
{ {
// If this is the initial update then all the source // If this is the initial update then all the source
// values are dirty and must be transmitted. // values are dirty and must be transmitted.
@ -284,81 +283,81 @@ U32 SFXEmitter::packUpdate( NetConnection *con, U32 mask, BitStream *stream )
mask &= ~AllSourceMasks; mask &= ~AllSourceMasks;
} }
stream->writeFlag( mPlayOnAdd ); stream->writeFlag(mPlayOnAdd);
// transform // transform
if( stream->writeFlag( mask & TransformUpdateMask ) ) if (stream->writeFlag(mask & TransformUpdateMask))
stream->writeAffineTransform( mObjToWorld ); stream->writeAffineTransform(mObjToWorld);
// track // track
PACK_ASSET(con, Sound); if (stream->writeFlag(mask & DirtyUpdateMask))
PACK_ASSET(con, Sound);
//if (stream->writeFlag(mDirty.test(Track))) //if (stream->writeFlag(mDirty.test(Track)))
// sfxWrite( stream, mTrack ); // sfxWrite( stream, mTrack );
// filename // filename
//if( stream->writeFlag( mDirty.test( Filename ) ) ) //if( stream->writeFlag( mDirty.test( Filename ) ) )
// stream->writeString( mLocalProfile.mFilename ); // stream->writeString( mLocalProfile.mFilename );
if (!stream->writeFlag(mUseTrackDescriptionOnly))
{
// volume
if (stream->writeFlag(mDirty.test(Volume)))
stream->write(mDescription.mVolume);
// volume // pitch
if( stream->writeFlag( mDirty.test( Volume ) ) ) if (stream->writeFlag(mDirty.test(Pitch)))
stream->write( mDescription.mVolume ); stream->write(mDescription.mPitch);
// pitch // islooping
if( stream->writeFlag( mDirty.test( Pitch ) ) ) if (stream->writeFlag(mDirty.test(IsLooping)))
stream->write( mDescription.mPitch ); stream->writeFlag(mDescription.mIsLooping);
// islooping // isStreaming
if( stream->writeFlag( mDirty.test( IsLooping ) ) ) if (stream->writeFlag(mDirty.test(IsStreaming)))
stream->writeFlag( mDescription.mIsLooping ); stream->writeFlag(mDescription.mIsStreaming);
// isStreaming // is3d
if( stream->writeFlag( mDirty.test( IsStreaming ) ) ) if (stream->writeFlag(mDirty.test(Is3D)))
stream->writeFlag( mDescription.mIsStreaming ); stream->writeFlag(mDescription.mIs3D);
// is3d // minDistance
if( stream->writeFlag( mDirty.test( Is3D ) ) ) if (stream->writeFlag(mDirty.test(MinDistance)))
stream->writeFlag( mDescription.mIs3D ); stream->write(mDescription.mMinDistance);
// minDistance // maxdistance
if( stream->writeFlag( mDirty.test( MinDistance ) ) ) if (stream->writeFlag(mDirty.test(MaxDistance)))
stream->write( mDescription.mMinDistance ); stream->write(mDescription.mMaxDistance);
// maxdistance // coneinsideangle
if( stream->writeFlag( mDirty.test( MaxDistance) ) ) if (stream->writeFlag(mDirty.test(ConeInsideAngle)))
stream->write( mDescription.mMaxDistance ); stream->write(mDescription.mConeInsideAngle);
// coneinsideangle // coneoutsideangle
if( stream->writeFlag( mDirty.test( ConeInsideAngle ) ) ) if (stream->writeFlag(mDirty.test(ConeOutsideAngle)))
stream->write( mDescription.mConeInsideAngle ); stream->write(mDescription.mConeOutsideAngle);
// coneoutsideangle // coneoutsidevolume
if( stream->writeFlag( mDirty.test( ConeOutsideAngle ) ) ) if (stream->writeFlag(mDirty.test(ConeOutsideVolume)))
stream->write( mDescription.mConeOutsideAngle ); stream->write(mDescription.mConeOutsideVolume);
// coneoutsidevolume // sourcegroup
if( stream->writeFlag( mDirty.test( ConeOutsideVolume ) ) ) if (stream->writeFlag(mDirty.test(SourceGroup)))
stream->write( mDescription.mConeOutsideVolume ); sfxWrite(stream, mDescription.mSourceGroup);
// sourcegroup // fadein
if( stream->writeFlag( mDirty.test( SourceGroup ) ) ) if (stream->writeFlag(mDirty.test(FadeInTime)))
sfxWrite( stream, mDescription.mSourceGroup ); stream->write(mDescription.mFadeInTime);
// fadein // fadeout
if( stream->writeFlag( mDirty.test( FadeInTime ) ) ) if (stream->writeFlag(mDirty.test(FadeOutTime)))
stream->write( mDescription.mFadeInTime ); stream->write(mDescription.mFadeOutTime);
// fadeout
if( stream->writeFlag( mDirty.test( FadeOutTime ) ) )
stream->write( mDescription.mFadeOutTime );
// scatterdistance
if( stream->writeFlag( mDirty.test( ScatterDistance ) ) )
mathWrite( *stream, mDescription.mScatterDistance );
// scatterdistance
if (stream->writeFlag(mDirty.test(ScatterDistance)))
mathWrite(*stream, mDescription.mScatterDistance);
}
mDirty.clear(); mDirty.clear();
stream->writeFlag( mUseTrackDescriptionOnly );
// We should never have both source masks // We should never have both source masks
// enabled at the same time! // enabled at the same time!
AssertFatal( ( mask & AllSourceMasks ) != AllSourceMasks, AssertFatal( ( mask & AllSourceMasks ) != AllSourceMasks,
@ -402,7 +401,11 @@ void SFXEmitter::unpackUpdate( NetConnection *conn, BitStream *stream )
} }
// track // track
UNPACK_ASSET(conn, Sound); if (stream->readFlag()) // DirtyUpdateMask
{
initialUpdate = false;
UNPACK_ASSET(conn, Sound);
}
/*if (_readDirtyFlag(stream, Track)) /*if (_readDirtyFlag(stream, Track))
{ {
String errorStr; String errorStr;
@ -414,69 +417,71 @@ void SFXEmitter::unpackUpdate( NetConnection *conn, BitStream *stream )
if ( _readDirtyFlag( stream, Filename ) ) if ( _readDirtyFlag( stream, Filename ) )
mLocalProfile.mFilename = stream->readSTString();*/ mLocalProfile.mFilename = stream->readSTString();*/
// volume
if ( _readDirtyFlag( stream, Volume ) )
stream->read( &mDescription.mVolume );
// pitch
if( _readDirtyFlag( stream, Pitch ) )
stream->read( &mDescription.mPitch );
// islooping
if ( _readDirtyFlag( stream, IsLooping ) )
mDescription.mIsLooping = stream->readFlag();
if( _readDirtyFlag( stream, IsStreaming ) )
mDescription.mIsStreaming = stream->readFlag();
// is3d
if ( _readDirtyFlag( stream, Is3D ) )
mDescription.mIs3D = stream->readFlag();
// mindistance
if ( _readDirtyFlag( stream, MinDistance ) )
stream->read( &mDescription.mMinDistance );
// maxdistance
if ( _readDirtyFlag( stream, MaxDistance ) )
{
stream->read( &mDescription.mMaxDistance );
mObjScale.set( mDescription.mMaxDistance, mDescription.mMaxDistance, mDescription.mMaxDistance );
}
// coneinsideangle
if ( _readDirtyFlag( stream, ConeInsideAngle ) )
stream->read( &mDescription.mConeInsideAngle );
// coneoutsideangle
if ( _readDirtyFlag( stream, ConeOutsideAngle ) )
stream->read( &mDescription.mConeOutsideAngle );
// coneoutsidevolume
if ( _readDirtyFlag( stream, ConeOutsideVolume ) )
stream->read( &mDescription.mConeOutsideVolume );
// sourcegroup
if ( _readDirtyFlag( stream, SourceGroup ) )
{
String errorStr;
if( !sfxReadAndResolve( stream, &mDescription.mSourceGroup, errorStr ) )
Con::errorf( "%s", errorStr.c_str() );
}
// fadein
if ( _readDirtyFlag( stream, FadeInTime ) )
stream->read( &mDescription.mFadeInTime );
// fadeout
if( _readDirtyFlag( stream, FadeOutTime ) )
stream->read( &mDescription.mFadeOutTime );
// scatterdistance
if( _readDirtyFlag( stream, ScatterDistance ) )
mathRead( *stream, &mDescription.mScatterDistance );
mUseTrackDescriptionOnly = stream->readFlag(); mUseTrackDescriptionOnly = stream->readFlag();
if (!mUseTrackDescriptionOnly)
{
// volume
if (_readDirtyFlag(stream, Volume))
stream->read(&mDescription.mVolume);
// pitch
if (_readDirtyFlag(stream, Pitch))
stream->read(&mDescription.mPitch);
// islooping
if (_readDirtyFlag(stream, IsLooping))
mDescription.mIsLooping = stream->readFlag();
if (_readDirtyFlag(stream, IsStreaming))
mDescription.mIsStreaming = stream->readFlag();
// is3d
if (_readDirtyFlag(stream, Is3D))
mDescription.mIs3D = stream->readFlag();
// mindistance
if (_readDirtyFlag(stream, MinDistance))
stream->read(&mDescription.mMinDistance);
// maxdistance
if (_readDirtyFlag(stream, MaxDistance))
{
stream->read(&mDescription.mMaxDistance);
mObjScale.set(mDescription.mMaxDistance, mDescription.mMaxDistance, mDescription.mMaxDistance);
}
// coneinsideangle
if (_readDirtyFlag(stream, ConeInsideAngle))
stream->read(&mDescription.mConeInsideAngle);
// coneoutsideangle
if (_readDirtyFlag(stream, ConeOutsideAngle))
stream->read(&mDescription.mConeOutsideAngle);
// coneoutsidevolume
if (_readDirtyFlag(stream, ConeOutsideVolume))
stream->read(&mDescription.mConeOutsideVolume);
// sourcegroup
if (_readDirtyFlag(stream, SourceGroup))
{
String errorStr;
if (!sfxReadAndResolve(stream, &mDescription.mSourceGroup, errorStr))
Con::errorf("%s", errorStr.c_str());
}
// fadein
if (_readDirtyFlag(stream, FadeInTime))
stream->read(&mDescription.mFadeInTime);
// fadeout
if (_readDirtyFlag(stream, FadeOutTime))
stream->read(&mDescription.mFadeOutTime);
// scatterdistance
if (_readDirtyFlag(stream, ScatterDistance))
mathRead(*stream, &mDescription.mScatterDistance);
}
// update the emitter now? // update the emitter now?
if ( !initialUpdate ) if ( !initialUpdate )
@ -505,8 +510,7 @@ void SFXEmitter::onStaticModified( const char* slotName, const char* newValue )
static StringTableEntry slotPosition = StringTable->lookup( "position" ); static StringTableEntry slotPosition = StringTable->lookup( "position" );
static StringTableEntry slotRotation = StringTable->lookup( "rotation" ); static StringTableEntry slotRotation = StringTable->lookup( "rotation" );
static StringTableEntry slotScale = StringTable->lookup( "scale" ); static StringTableEntry slotScale = StringTable->lookup( "scale" );
static StringTableEntry slotTrack = StringTable->lookup( "track" ); static StringTableEntry slotTrack = StringTable->lookup( "SoundAsset" );
static StringTableEntry slotFilename = StringTable->lookup( "fileName" );
static StringTableEntry slotVolume = StringTable->lookup( "volume" ); static StringTableEntry slotVolume = StringTable->lookup( "volume" );
static StringTableEntry slotPitch = StringTable->lookup( "pitch" ); static StringTableEntry slotPitch = StringTable->lookup( "pitch" );
static StringTableEntry slotIsLooping = StringTable->lookup( "isLooping" ); static StringTableEntry slotIsLooping = StringTable->lookup( "isLooping" );
@ -533,9 +537,6 @@ void SFXEmitter::onStaticModified( const char* slotName, const char* newValue )
else if( slotName == slotTrack ) else if( slotName == slotTrack )
mDirty.set( Track ); mDirty.set( Track );
else if( slotName == slotFilename )
mDirty.set( Filename );
else if( slotName == slotVolume ) else if( slotName == slotVolume )
mDirty.set( Volume ); mDirty.set( Volume );
@ -611,45 +612,7 @@ bool SFXEmitter::onAdd()
{ {
// Validate the data we'll be passing across // Validate the data we'll be passing across
// the network to the client. // the network to the client.
mDescription.validate(); mInstanceDescription->validate();
// Read an old 'profile' field for backwards-compatibility.
/*
if(mSoundAsset.isNull() || !mSoundAsset->getSfxProfile())
{
static const char* sProfile = StringTable->insert( "profile" );
const char* profileName = getDataField( sProfile, NULL );
if( profileName && profileName[ 0 ] )
{
if( !Sim::findObject( profileName, mTrack ) )
Con::errorf( "SFXEmitter::onAdd - No SFXTrack '%s' in SFXEmitter '%i' (%s)", profileName, getId(), getName() );
else
{
// Remove the old 'profile' field.
setDataField( sProfile, NULL, "" );
}
}
}
// Convert a legacy 'channel' field, if we have one.
static const char* sChannel = StringTable->insert( "channel" );
const char* channelValue = getDataField( sChannel, NULL );
if( channelValue && channelValue[ 0 ] )
{
const char* group = Con::evaluatef( "return sfxOldChannelToGroup( %s );", channelValue );
SFXSource* sourceGroup;
if( !Sim::findObject( group, sourceGroup ) )
Con::errorf( "SFXEmitter::onAdd - could not resolve channel '%s' to SFXSource", channelValue );
else
{
static const char* sSourceGroup = StringTable->insert( "sourceGroup" );
setDataField( sSourceGroup, NULL, sourceGroup->getIdString() );
// Remove the old 'channel' field.
setDataField( sChannel, NULL, "" );
}
}*/
} }
else else
{ {
@ -662,7 +625,7 @@ bool SFXEmitter::onAdd()
// Setup the bounds. // Setup the bounds.
mObjScale.set( mDescription.mMaxDistance, mDescription.mMaxDistance, mDescription.mMaxDistance ); mObjScale.set(mInstanceDescription->mMaxDistance, mInstanceDescription->mMaxDistance, mInstanceDescription->mMaxDistance );
resetWorldBox(); resetWorldBox();
addToScene(); addToScene();
@ -683,67 +646,52 @@ void SFXEmitter::onRemove()
void SFXEmitter::_update() void SFXEmitter::_update()
{ {
AssertFatal( isClientObject(), "SFXEmitter::_update() - This shouldn't happen on the server!" ); AssertFatal(isClientObject(), "SFXEmitter::_update() - This shouldn't happen on the server!");
// Store the playback status so we // Store the playback status so we
// we can restore it. // we can restore it.
SFXStatus prevState = mSource ? mSource->getStatus() : SFXStatusNull; SFXStatus prevState = mSource ? mSource->getStatus() : SFXStatusNull;
if (mSoundAsset.notNull() && mDirty.test(Track | Filename)) // are we overriding the asset properties?
{ bool useTrackDescriptionOnly = (mUseTrackDescriptionOnly && mSoundAsset.notNull() && mSoundAsset->getSfxProfile());
mDescription = *mSoundAsset->getSfxDescription();
}
if (mSoundAsset.notNull())
{
if (useTrackDescriptionOnly)
mInstanceDescription = mSoundAsset->getSfxDescription();
else
mInstanceDescription = &mDescription;
mLocalProfile = *mSoundAsset->getSfxProfile();
}
// Make sure all the settings are valid. // Make sure all the settings are valid.
mDescription.validate(); mInstanceDescription->validate();
mLocalProfile.setDescription(mInstanceDescription);
const MatrixF& transform = getTransform(); const MatrixF& transform = getTransform();
const VectorF& velocity = getVelocity(); const VectorF& velocity = getVelocity();
// Did we change the source? // Did we change the source?
if( mDirty.test( Track | Filename | Is3D | IsLooping | IsStreaming | TrackOnly ) ) if( mDirty.test( Track | Is3D | IsLooping | IsStreaming | TrackOnly ) )
{ {
SFX_DELETE( mSource ); SFX_DELETE( mSource );
if (mLocalProfile.getSoundFileName().isNotEmpty())
// Do we have a track?
if( mSoundAsset && mSoundAsset->getSfxProfile() )
{ {
mSource = SFX->createSource(mSoundAsset->getSfxProfile(), &transform, &velocity ); mSource = SFX->createSource(&mLocalProfile, &transform, &velocity);
if( !mSource ) if (!mSource)
Con::errorf( "SFXEmitter::_update() - failed to create sound for track %i (%s)", Con::errorf("SFXEmitter::_update() - failed to create sound for track %i (%s)",
mSoundAsset->getSfxProfile()->getId(), mSoundAsset->getSfxProfile()->getName() ); mSoundAsset->getSfxProfile()->getId(), mSoundAsset->getSfxProfile()->getName());
// If we're supposed to play when the emitter is // If we're supposed to play when the emitter is
// added to the scene then also restart playback // added to the scene then also restart playback
// when the profile changes. // when the profile changes.
prevState = mPlayOnAdd ? SFXStatusPlaying : prevState; prevState = mPlayOnAdd ? SFXStatusPlaying : prevState;
// Force an update of properties set on the local description.
mDirty.set( AllDirtyMask );
} }
// Force an update of properties set on the local description.
// Else take the local profile mDirty.set(AllDirtyMask);
else mDirty.clear( Track | Is3D | IsLooping | IsStreaming | TrackOnly );
{
// Clear the resource and buffer on profile
// to force reload.
mLocalProfile.mResource = NULL;
mLocalProfile.mBuffer = NULL;
if( mLocalProfile.mFilename != StringTable->EmptyString() )
{
mSource = SFX->createSource( &mLocalProfile, &transform, &velocity );
if( !mSource )
Con::errorf( "SFXEmitter::_update() - failed to create sound for: %s",
mLocalProfile.mFilename );
prevState = mPlayOnAdd ? SFXStatusPlaying : prevState;
}
}
mDirty.clear( Track | Filename | Is3D | IsLooping | IsStreaming | TrackOnly );
} }
// Cheat if the editor is open and the looping state // Cheat if the editor is open and the looping state
@ -755,26 +703,24 @@ void SFXEmitter::_update()
mDirty.test( IsLooping ) ) mDirty.test( IsLooping ) )
prevState = SFXStatusPlaying; prevState = SFXStatusPlaying;
bool useTrackDescriptionOnly = ( mUseTrackDescriptionOnly && mSoundAsset.notNull() && mSoundAsset->getSfxProfile());
// The rest only applies if we have a source. // The rest only applies if we have a source.
if( mSource ) if( mSource )
{ {
// Set the volume irrespective of the profile. // Set the volume irrespective of the profile.
if( mDirty.test( Volume ) && !useTrackDescriptionOnly ) if (mDirty.test(Volume))
mSource->setVolume( mDescription.mVolume ); mSource->setVolume(mInstanceDescription->mVolume);
if( mDirty.test( Pitch ) && !useTrackDescriptionOnly ) if (mDirty.test(Pitch))
mSource->setPitch( mDescription.mPitch ); mSource->setPitch(mInstanceDescription->mPitch);
if( mDirty.test( FadeInTime | FadeOutTime ) && !useTrackDescriptionOnly ) if (mDirty.test(FadeInTime | FadeOutTime))
mSource->setFadeTimes( mDescription.mFadeInTime, mDescription.mFadeOutTime ); mSource->setFadeTimes(mInstanceDescription->mFadeInTime, mInstanceDescription->mFadeOutTime);
if( mDirty.test( SourceGroup ) && mDescription.mSourceGroup && !useTrackDescriptionOnly )
mDescription.mSourceGroup->addObject( mSource );
if (mDirty.test(SourceGroup) && mInstanceDescription->mSourceGroup)
mInstanceDescription->mSourceGroup->addObject(mSource);
// Skip these 3d only settings. // Skip these 3d only settings.
if( mDescription.mIs3D ) if(mInstanceDescription->mIs3D )
{ {
if( mDirty.test( Transform ) ) if( mDirty.test( Transform ) )
{ {
@ -782,19 +728,18 @@ void SFXEmitter::_update()
mSource->setVelocity( velocity ); mSource->setVelocity( velocity );
} }
if( mDirty.test( MinDistance | MaxDistance ) && !useTrackDescriptionOnly ) if (mDirty.test(MinDistance | MaxDistance))
{ {
mSource->setMinMaxDistance( mDescription.mMinDistance, mSource->setMinMaxDistance(mInstanceDescription->mMinDistance,
mDescription.mMaxDistance ); mInstanceDescription->mMaxDistance);
} }
if( mDirty.test( ConeInsideAngle | ConeOutsideAngle | ConeOutsideVolume ) && !useTrackDescriptionOnly ) if (mDirty.test(ConeInsideAngle | ConeOutsideAngle | ConeOutsideVolume))
{ {
mSource->setCone( F32( mDescription.mConeInsideAngle ), mSource->setCone(F32(mInstanceDescription->mConeInsideAngle),
F32( mDescription.mConeOutsideAngle ), F32(mInstanceDescription->mConeOutsideAngle),
mDescription.mConeOutsideVolume ); mInstanceDescription->mConeOutsideVolume);
} }
mDirty.clear( Transform | MinDistance | MaxDistance | ConeInsideAngle | ConeOutsideAngle | ConeOutsideVolume ); mDirty.clear( Transform | MinDistance | MaxDistance | ConeInsideAngle | ConeOutsideAngle | ConeOutsideVolume );
} }
@ -884,7 +829,7 @@ void SFXEmitter::_render3DVisualFeedback()
// Render the max range sphere. // Render the max range sphere.
if( smRenderColorRangeSphere.alpha > 0 ) if( smRenderColorRangeSphere.alpha > 0 )
GFX->getDrawUtil()->drawSphere( desc, mDescription.mMaxDistance, Point3F( 0.f, 0.f, 0.f ), smRenderColorRangeSphere ); GFX->getDrawUtil()->drawSphere( desc, mInstanceDescription->mMaxDistance, Point3F( 0.f, 0.f, 0.f ), smRenderColorRangeSphere );
//TODO: some point size support in GFX would be nice //TODO: some point size support in GFX would be nice
@ -899,7 +844,7 @@ void SFXEmitter::_render3DVisualFeedback()
{ {
numPoints = mCeil( 360.f / radialIncrements ) * numPoints = mCeil( 360.f / radialIncrements ) *
mCeil( 360.f / sweepIncrements ) * mCeil( 360.f / sweepIncrements ) *
( mDescription.mMaxDistance / pointDistance ); (mInstanceDescription->mMaxDistance / pointDistance );
if( numPoints < 65536 ) if( numPoints < 65536 )
break; break;
@ -917,15 +862,15 @@ void SFXEmitter::_render3DVisualFeedback()
radialIncrements, radialIncrements,
sweepIncrements, sweepIncrements,
pointDistance, pointDistance,
mDescription.mConeInsideAngle, 0.f, mInstanceDescription->mConeInsideAngle, 0.f,
mDescription.mVolume, mDescription.mVolume, mInstanceDescription->mVolume, mInstanceDescription->mVolume,
smRenderColorInnerCone ); smRenderColorInnerCone );
// Outer Cone and Outside volume only get rendered if mConeOutsideVolume > 0 // Outer Cone and Outside volume only get rendered if mConeOutsideVolume > 0
if( mDescription.mConeOutsideVolume > 0.f ) if(mInstanceDescription->mConeOutsideVolume > 0.f )
{ {
const F32 outsideVolume = mDescription.mVolume * mDescription.mConeOutsideVolume; const F32 outsideVolume = mInstanceDescription->mVolume * mInstanceDescription->mConeOutsideVolume;
// Render outer cone. // Render outer cone.
@ -933,8 +878,8 @@ void SFXEmitter::_render3DVisualFeedback()
radialIncrements, radialIncrements,
sweepIncrements, sweepIncrements,
pointDistance, pointDistance,
mDescription.mConeOutsideAngle, mDescription.mConeInsideAngle, mInstanceDescription->mConeOutsideAngle, mInstanceDescription->mConeInsideAngle,
outsideVolume, mDescription.mVolume, outsideVolume, mInstanceDescription->mVolume,
smRenderColorOuterCone ); smRenderColorOuterCone );
// Render outside volume. // Render outside volume.
@ -943,7 +888,7 @@ void SFXEmitter::_render3DVisualFeedback()
radialIncrements, radialIncrements,
sweepIncrements, sweepIncrements,
pointDistance, pointDistance,
360.f, mDescription.mConeOutsideAngle, 360.f, mInstanceDescription->mConeOutsideAngle,
outsideVolume, outsideVolume, outsideVolume, outsideVolume,
smRenderColorOutsideVolume ); smRenderColorOutsideVolume );
} }
@ -990,7 +935,7 @@ void SFXEmitter::_renderCone( F32 radialIncrements, F32 sweepIncrements,
// Do a radial sweep each step along the distance axis. For each step, volume is // Do a radial sweep each step along the distance axis. For each step, volume is
// the same for any point on the sweep circle. // the same for any point on the sweep circle.
for( F32 y = pointDistance; y <= mDescription.mMaxDistance; y += pointDistance ) for( F32 y = pointDistance; y <= mInstanceDescription->mMaxDistance; y += pointDistance )
{ {
ColorI c = color; ColorI c = color;
@ -1007,8 +952,8 @@ void SFXEmitter::_renderCone( F32 radialIncrements, F32 sweepIncrements,
F32 attenuatedVolume = SFXDistanceAttenuation( F32 attenuatedVolume = SFXDistanceAttenuation(
SFX->getDistanceModel(), SFX->getDistanceModel(),
mDescription.mMinDistance, mInstanceDescription->mMinDistance,
mDescription.mMaxDistance, mInstanceDescription->mMaxDistance,
y, y,
volume, volume,
SFX->getRolloffFactor() ); //RDTODO SFX->getRolloffFactor() ); //RDTODO
@ -1101,20 +1046,20 @@ bool SFXEmitter::is3D() const
if( mSoundAsset.notNull() && mSoundAsset->getSfxProfile() != NULL ) if( mSoundAsset.notNull() && mSoundAsset->getSfxProfile() != NULL )
return mSoundAsset->getSfxProfile()->getDescription()->mIs3D; return mSoundAsset->getSfxProfile()->getDescription()->mIs3D;
else else
return mDescription.mIs3D; return mInstanceDescription->mIs3D;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool SFXEmitter::isInRange() const bool SFXEmitter::isInRange() const
{ {
if( !mDescription.mIs3D ) if( !mInstanceDescription->mIs3D )
return false; return false;
const SFXListenerProperties& listener = SFX->getListener(); const SFXListenerProperties& listener = SFX->getListener();
const Point3F listenerPos = listener.getTransform().getPosition(); const Point3F listenerPos = listener.getTransform().getPosition();
const Point3F emitterPos = getPosition(); const Point3F emitterPos = getPosition();
const F32 dist = mDescription.mMaxDistance; const F32 dist = mInstanceDescription->mMaxDistance;
return ( ( emitterPos - listenerPos ).len() <= dist ); return ( ( emitterPos - listenerPos ).len() <= dist );
} }
@ -1141,9 +1086,9 @@ void SFXEmitter::setScale( const VectorF &scale )
{ {
// Use the average of the three coords. // Use the average of the three coords.
maxDistance = ( scale.x + scale.y + scale.z ) / 3.0f; maxDistance = ( scale.x + scale.y + scale.z ) / 3.0f;
maxDistance = getMax( maxDistance, mDescription.mMinDistance ); maxDistance = getMax( maxDistance, mInstanceDescription->mMinDistance );
mDescription.mMaxDistance = maxDistance; mInstanceDescription->mMaxDistance = maxDistance;
mDirty.set( MaxDistance ); mDirty.set( MaxDistance );
setMaskBits( DirtyUpdateMask ); setMaskBits( DirtyUpdateMask );

View file

@ -79,24 +79,23 @@ class SFXEmitter : public SceneObject
enum Dirty enum Dirty
{ {
Track = BIT( 0 ), Track = BIT( 0 ),
Filename = BIT( 2 ), Volume = BIT( 1 ),
Volume = BIT( 4 ), IsLooping = BIT( 3 ),
IsLooping = BIT( 5 ), Is3D = BIT( 4 ),
Is3D = BIT( 6 ), MinDistance = BIT( 5 ),
MinDistance = BIT( 7 ), MaxDistance = BIT( 6 ),
MaxDistance = BIT( 8 ), ConeInsideAngle = BIT( 7 ),
ConeInsideAngle = BIT( 9 ), ConeOutsideAngle = BIT( 8 ),
ConeOutsideAngle = BIT( 10 ), ConeOutsideVolume = BIT( 9 ),
ConeOutsideVolume = BIT( 11 ), Transform = BIT( 10 ),
Transform = BIT( 12 ), SourceGroup = BIT( 11 ),
SourceGroup = BIT( 13 ), OutsideAmbient = BIT( 12 ),
OutsideAmbient = BIT( 14 ), IsStreaming = BIT( 13 ),
IsStreaming = BIT( 15 ), FadeInTime = BIT( 14 ),
FadeInTime = BIT( 16 ), FadeOutTime = BIT( 15 ),
FadeOutTime = BIT( 17 ), Pitch = BIT( 16 ),
Pitch = BIT( 18 ), ScatterDistance = BIT( 17 ),
ScatterDistance = BIT( 19 ), TrackOnly = BIT( 18 ),
TrackOnly = BIT( 20 ),
AllDirtyMask = 0xFFFFFFFF, AllDirtyMask = 0xFFFFFFFF,
}; };
@ -122,6 +121,9 @@ class SFXEmitter : public SceneObject
/// The description used by the local profile. /// The description used by the local profile.
SFXDescription mDescription; SFXDescription mDescription;
/// The description used by the local profile.
SFXDescription *mInstanceDescription;
/// If true playback starts when the emitter /// If true playback starts when the emitter
/// is added to the scene. /// is added to the scene.
bool mPlayOnAdd; bool mPlayOnAdd;