From 943cf8351b1702943061a6c55770a5d2a5cfe5e9 Mon Sep 17 00:00:00 2001 From: JeffR Date: Fri, 3 Jun 2022 02:04:39 -0500 Subject: [PATCH 1/3] Adds safety check to SoundAsset's playSound so if we don't have a source, it doesn't crash Adds logic to SoundAsset's load sound to 'nudge' the SFX system to load the required data for first use Shifts SimSoundAssetEvent constructor to utilize assetId instead of raw asset so we can safely fail if for whatever reason we end up default constructor'ing blanks Standardizes the shapeImage playList lookup a bit into a common function and ensures that on packet receive we force an update of the state's sound --- Engine/source/T3D/assets/SoundAsset.cpp | 8 +++- Engine/source/T3D/gameBase/gameConnection.cpp | 11 ++--- .../T3D/gameBase/gameConnectionEvents.cpp | 6 +-- .../T3D/gameBase/gameConnectionEvents.h | 2 +- Engine/source/T3D/shapeBase.h | 2 + Engine/source/T3D/shapeImage.cpp | 41 ++++++++++++------- 6 files changed, 43 insertions(+), 27 deletions(-) diff --git a/Engine/source/T3D/assets/SoundAsset.cpp b/Engine/source/T3D/assets/SoundAsset.cpp index 06a30b7e4..a3b1aed81 100644 --- a/Engine/source/T3D/assets/SoundAsset.cpp +++ b/Engine/source/T3D/assets/SoundAsset.cpp @@ -228,6 +228,9 @@ bool SoundAsset::loadSound() mSFXProfile.setDescription(&mProfileDesc); mSFXProfile.setSoundFileName(mSoundPath); mSFXProfile.setPreload(mPreload); + + //give it a nudge to preload if required + mSFXProfile.getBuffer(); } } @@ -341,7 +344,10 @@ DefineEngineMethod(SoundAsset, playSound, S32, (Point3F position), (Point3F::Zer MatrixF transform; transform.setPosition(position); SFXSource* source = SFX->playOnce(object->getSfxProfile(), &transform, NULL, -1); - return source->getId(); + if(source) + return source->getId(); + else + return 0; } else return 0; diff --git a/Engine/source/T3D/gameBase/gameConnection.cpp b/Engine/source/T3D/gameBase/gameConnection.cpp index 0331e3764..b88bde05e 100644 --- a/Engine/source/T3D/gameBase/gameConnection.cpp +++ b/Engine/source/T3D/gameBase/gameConnection.cpp @@ -1566,12 +1566,7 @@ void GameConnection::play2D(StringTableEntry assetId) { if (AssetDatabase.isDeclaredAsset(assetId)) { - - AssetPtr tempSoundAsset; - tempSoundAsset = assetId; - - postNetEvent(new SimSoundAssetEvent(tempSoundAsset)); - + postNetEvent(new SimSoundAssetEvent(assetId)); } } @@ -1587,7 +1582,7 @@ void GameConnection::play3D(StringTableEntry assetId, const MatrixF *transform) tempSoundAsset = assetId; if (!mControlObject) - postNetEvent(new SimSoundAssetEvent(tempSoundAsset, transform)); + postNetEvent(new SimSoundAssetEvent(assetId, *transform)); else { // TODO: Maybe improve this to account for the duration @@ -1601,7 +1596,7 @@ void GameConnection::play3D(StringTableEntry assetId, const MatrixF *transform) transform->getColumn(3, &pos); mControlObject->getTransform().getColumn(3, &ear); if ((ear - pos).len() < tempSoundAsset->getSfxDescription()->mMaxDistance) - postNetEvent(new SimSoundAssetEvent(tempSoundAsset, transform)); + postNetEvent(new SimSoundAssetEvent(assetId, *transform)); } } diff --git a/Engine/source/T3D/gameBase/gameConnectionEvents.cpp b/Engine/source/T3D/gameBase/gameConnectionEvents.cpp index d2c3badce..184d504bf 100644 --- a/Engine/source/T3D/gameBase/gameConnectionEvents.cpp +++ b/Engine/source/T3D/gameBase/gameConnectionEvents.cpp @@ -297,13 +297,13 @@ void SimDataBlockEvent::process(NetConnection *cptr) static F32 SoundPosAccuracy = 0.5; static S32 SoundRotBits = 8; -SimSoundAssetEvent::SimSoundAssetEvent(AssetPtr asset, const MatrixF* mat) +SimSoundAssetEvent::SimSoundAssetEvent(StringTableEntry assetId, const MatrixF& mat) { // cant get here unless the asset is declared. - mAsset = asset; + mAsset = assetId; if (mat) - mTransform = *mat; + mTransform = mat; } void SimSoundAssetEvent::pack(NetConnection* con, BitStream* stream) diff --git a/Engine/source/T3D/gameBase/gameConnectionEvents.h b/Engine/source/T3D/gameBase/gameConnectionEvents.h index ede198645..755e02957 100644 --- a/Engine/source/T3D/gameBase/gameConnectionEvents.h +++ b/Engine/source/T3D/gameBase/gameConnectionEvents.h @@ -114,7 +114,7 @@ private: public: typedef NetEvent Parent; - SimSoundAssetEvent(AssetPtr asset = NULL, const MatrixF* mat = NULL); + SimSoundAssetEvent(StringTableEntry assetId = StringTable->EmptyString(), const MatrixF& mat = MatrixF::Identity); void pack(NetConnection*, BitStream* bstream); void write(NetConnection*, BitStream* bstream); void unpack(NetConnection*, BitStream* bstream); diff --git a/Engine/source/T3D/shapeBase.h b/Engine/source/T3D/shapeBase.h index 6ef0fd985..035e6c55c 100644 --- a/Engine/source/T3D/shapeBase.h +++ b/Engine/source/T3D/shapeBase.h @@ -504,6 +504,8 @@ struct ShapeBaseImageData: public GameBaseData { void inspectPostApply(); + void handleStateSoundTrack(const U32& stateId); + /// @} /// @name Callbacks diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index 88d5f837c..38a7fda2a 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -372,20 +372,8 @@ bool ShapeBaseImageData::onAdd() s.shapeSequenceScale = stateScaleShapeSequence[i]; //_setstateSound(getstateSound(i),i); - s.sound = getstateSoundAsset(i); - if (s.sound == NULL && mstateSoundName[i] != StringTable->EmptyString()) - { - //ok, so we've got some sort of special-case here like a fallback or SFXPlaylist. So do the hook-up now - SFXTrack* sndTrack; - if (!Sim::findObject(mstateSoundName[i], sndTrack)) - { - Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %s but failed!", mstateSoundName[i]); - } - else - { - s.soundTrack = sndTrack; - } - } + handleStateSoundTrack(i); + s.script = stateScript[i]; s.emitter = stateEmitter[i]; s.emitterTime = stateEmitterTime[i]; @@ -591,6 +579,30 @@ bool ShapeBaseImageData::preload(bool server, String &errorStr) return true; } +void ShapeBaseImageData::handleStateSoundTrack(const U32& stateId) +{ + if (stateId > MaxStates) + return; + + StateData& s = state[stateId]; + + s.sound = getstateSoundAsset(stateId); + + if (s.sound == NULL && mstateSoundName[stateId] != StringTable->EmptyString()) + { + //ok, so we've got some sort of special-case here like a fallback or SFXPlaylist. So do the hook-up now + SFXTrack* sndTrack; + if (!Sim::findObject(mstateSoundName[stateId], sndTrack)) + { + Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %s but failed!", mstateSoundName[stateId]); + } + else + { + s.soundTrack = sndTrack; + } + } +} + S32 ShapeBaseImageData::lookupState(const char* name) { if (!name || !name[0]) @@ -1366,6 +1378,7 @@ void ShapeBaseImageData::unpackData(BitStream* stream) s.emitter = 0; UNPACKDATA_ASSET_ARRAY(stateSound, i); + handleStateSoundTrack(i); } } From 448a453e5185446d780891032604bfb31d6ba429 Mon Sep 17 00:00:00 2001 From: JeffR Date: Fri, 3 Jun 2022 03:23:27 -0500 Subject: [PATCH 2/3] Fixes logic check for sound asset macros so if the defined field value is an object, we consider it valid, as it's almost certainly an SFXPlaylist or track. This removes some unneeded error spam --- Engine/source/T3D/assets/SoundAsset.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Engine/source/T3D/assets/SoundAsset.h b/Engine/source/T3D/assets/SoundAsset.h index 5cb6a3564..be1866030 100644 --- a/Engine/source/T3D/assets/SoundAsset.h +++ b/Engine/source/T3D/assets/SoundAsset.h @@ -253,7 +253,7 @@ public: \ Con::errorf("%s(%s)::_set%s() - sound asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name), _in, SoundAsset::getAssetErrstrn(m##name##Asset->getStatus()).c_str());\ return false; \ }\ - else if (!m##name)\ + else if (!m##name && (m##name##Name != StringTable->EmptyString() && !Sim::findObject(m##name##Name)))\ {\ Con::errorf("%s(%s)::_set%s() - Couldn't load sound \"%s\"", macroText(className), getName(), macroText(name), _in);\ return false;\ @@ -417,7 +417,7 @@ public: \ Con::errorf("%s(%s)::_set%s(%i) - sound asset failure\"%s\" due to [%s]", macroText(className), getName(), macroText(name),index, _in, SoundAsset::getAssetErrstrn(m##name##Asset[index]->getStatus()).c_str());\ return false; \ }\ - else if (!m##name[index])\ + else if (!m##name[index] && (m##name##Name[index] != StringTable->EmptyString() && !Sim::findObject(m##name##Name[index])))\ {\ Con::errorf("%s(%s)::_set%s(%i) - Couldn't load sound \"%s\"", macroText(className), getName(), macroText(name),index, _in);\ return false;\ From 7efab038d1c0a4237d7e42e257452a19a34d6bc8 Mon Sep 17 00:00:00 2001 From: JeffR Date: Sat, 4 Jun 2022 00:59:06 -0500 Subject: [PATCH 3/3] Adjusts handling for special-case networking of sound assets where we may need to account for stuff like SFXPlaylists. DB names aren't transported, so we need to do Id lookups --- Engine/source/T3D/assets/SoundAsset.h | 86 ++++++++++++++++++++++++--- Engine/source/T3D/fx/explosion.cpp | 5 +- Engine/source/T3D/shapeImage.cpp | 35 +++++++---- 3 files changed, 105 insertions(+), 21 deletions(-) diff --git a/Engine/source/T3D/assets/SoundAsset.h b/Engine/source/T3D/assets/SoundAsset.h index be1866030..13613ab6e 100644 --- a/Engine/source/T3D/assets/SoundAsset.h +++ b/Engine/source/T3D/assets/SoundAsset.h @@ -186,6 +186,7 @@ public: AssetPtr m##name##Asset = NULL;\ SFXProfile* m##name##Profile = NULL;\ SFXDescription* m##name##Desc = NULL;\ + SimObjectId m##name##SFXId = NULL;\ public: \ const StringTableEntry get##name##File() const { return m##name##Name; }\ void set##name##File(const FileName &_in) { m##name##Name = StringTable->insert(_in.c_str());}\ @@ -310,31 +311,57 @@ public: \ #define PACKDATA_SOUNDASSET(name)\ if (stream->writeFlag(m##name##Asset.notNull()))\ {\ - if (m##name##Profile)\ - m##name##Profile->packData(stream);\ - sfxWrite(stream, m##name##Desc);\ + stream->writeString(m##name##Asset.getAssetId());\ }\ else\ - stream->writeString(m##name##Name); + {\ + if(stream->writeFlag(Sim::findObject(m##name##Name)))\ + {\ + SFXTrack* sndTrack;\ + Sim::findObject(m##name##Name, sndTrack);\ + stream->writeRangedU32(SimObjectId(sndTrack->getId()), DataBlockObjectIdFirst, DataBlockObjectIdLast);\ + }\ + else\ + {\ + stream->writeString(m##name##Name);\ + }\ + } + //network recieve - datablock #define UNPACKDATA_SOUNDASSET(name)\ if (stream->readFlag())\ {\ - if (m##name##Profile)\ - m##name##Profile->unpackData(stream);\ - sfxRead(stream, &m##name##Desc);\ + m##name##AssetId = stream->readSTString();\ + _set##name(m##name##AssetId);\ }\ else\ {\ - m##name##Name = stream->readSTString();\ - _set##name(m##name##Name);\ + if(stream->readFlag())\ + {\ + m##name##SFXId = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );\ + }\ + else\ + {\ + m##name##Name = stream->readSTString(); \ + _set##name(m##name##Name); \ + }\ } #pragma endregion #pragma region Arrayed Asset Macros +#define INIT_SOUNDASSET_ARRAY(name, index) \ +{\ + m##name##Name[index] = StringTable->EmptyString(); \ + m##name##AssetId[index] = StringTable->EmptyString(); \ + m##name##Asset[index] = NULL;\ + m##name[index] = NULL;\ + m##name##Profile[index] = NULL;\ + m##name##SFXId[index] = 0;\ +} + #define DECLARE_SOUNDASSET_ARRAY(className,name,max) public: \ static const U32 sm##name##Count = max;\ Resource m##name[max];\ @@ -342,6 +369,7 @@ public: \ StringTableEntry m##name##AssetId[max];\ AssetPtr m##name##Asset[max];\ SFXProfile* m##name##Profile[max];\ + SimObjectId m##name##SFXId[max];\ public: \ const StringTableEntry get##name##File(const U32& index) const { return m##name##Name[index]; }\ void set##name##File(const FileName &_in, const U32& index) { m##name##Name[index] = StringTable->insert(_in.c_str());}\ @@ -489,6 +517,46 @@ if (m##name##AssetId[index] != StringTable->EmptyString())\ addField(assetEnumNameConcat(enumString, Asset), TypeSoundAssetId, Offset(m##name##AssetId[0], consoleClass) + sizeof(m##name##AssetId[0])*i, assetText(name, asset reference.));\ }\ } + +#define PACKDATA_SOUNDASSET_ARRAY(name, index)\ + if (stream->writeFlag(m##name##Asset[index].notNull()))\ + {\ + stream->writeString(m##name##Asset[index].getAssetId());\ + }\ + else\ + {\ + if(stream->writeFlag(Sim::findObject(m##name##Name[index])))\ + {\ + SFXTrack* sndTrack;\ + Sim::findObject(m##name##Name[index], sndTrack);\ + stream->writeRangedU32(SimObjectId(sndTrack->getId()), DataBlockObjectIdFirst, DataBlockObjectIdLast);\ + }\ + else\ + {\ + stream->writeString(m##name##Name[index]);\ + }\ + } + + +//network recieve - datablock +#define UNPACKDATA_SOUNDASSET_ARRAY(name, index)\ + if (stream->readFlag())\ + {\ + m##name##AssetId[index] = stream->readSTString();\ + _set##name(m##name##AssetId[index], index);\ + }\ + else\ + {\ + if(stream->readFlag())\ + {\ + m##name##SFXId[index] = stream->readRangedU32( DataBlockObjectIdFirst, DataBlockObjectIdLast );\ + }\ + else\ + {\ + m##name##Name[index] = stream->readSTString(); \ + _set##name(m##name##Name[index], index); \ + }\ + } #pragma endregion #endif // _ASSET_BASE_H_ diff --git a/Engine/source/T3D/fx/explosion.cpp b/Engine/source/T3D/fx/explosion.cpp index cfa5d8ef4..b59e87447 100644 --- a/Engine/source/T3D/fx/explosion.cpp +++ b/Engine/source/T3D/fx/explosion.cpp @@ -652,7 +652,8 @@ void ExplosionData::packData(BitStream* stream) PACKDATA_ASSET(ExplosionShape); - PACKDATA_SOUNDASSET(Sound); + //PACKDATA_SOUNDASSET(Sound); + PACKDATA_ASSET(Sound); if (stream->writeFlag(particleEmitter)) stream->writeRangedU32(particleEmitter->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast); @@ -756,7 +757,7 @@ void ExplosionData::unpackData(BitStream* stream) UNPACKDATA_ASSET(ExplosionShape); - UNPACKDATA_SOUNDASSET(Sound); + UNPACKDATA_ASSET(Sound); if (stream->readFlag()) particleEmitterId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast); diff --git a/Engine/source/T3D/shapeImage.cpp b/Engine/source/T3D/shapeImage.cpp index 38a7fda2a..4161dbaf7 100644 --- a/Engine/source/T3D/shapeImage.cpp +++ b/Engine/source/T3D/shapeImage.cpp @@ -258,7 +258,7 @@ ShapeBaseImageData::ShapeBaseImageData() stateShapeSequence[i] = 0; stateScaleShapeSequence[i] = false; - INIT_ASSET_ARRAY(stateSound, i); + INIT_SOUNDASSET_ARRAY(stateSound, i); stateScript[i] = 0; stateEmitter[i] = 0; stateEmitterTime[i] = 0; @@ -588,17 +588,32 @@ void ShapeBaseImageData::handleStateSoundTrack(const U32& stateId) s.sound = getstateSoundAsset(stateId); - if (s.sound == NULL && mstateSoundName[stateId] != StringTable->EmptyString()) + if (s.sound == NULL) { - //ok, so we've got some sort of special-case here like a fallback or SFXPlaylist. So do the hook-up now - SFXTrack* sndTrack; - if (!Sim::findObject(mstateSoundName[stateId], sndTrack)) + if (mstateSoundName[stateId] != StringTable->EmptyString()) { - Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %s but failed!", mstateSoundName[stateId]); + //ok, so we've got some sort of special-case here like a fallback or SFXPlaylist. So do the hook-up now + SFXTrack* sndTrack; + if (!Sim::findObject(mstateSoundName[stateId], sndTrack)) + { + Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %s but failed!", mstateSoundName[stateId]); + } + else + { + s.soundTrack = sndTrack; + } } - else + else if (mstateSoundSFXId[stateId] != 0) { - s.soundTrack = sndTrack; + SFXTrack* sndTrack; + if (!Sim::findObject(mstateSoundSFXId[stateId], sndTrack)) + { + Con::errorf("ShapeBaseImageData::onAdd() - attempted to find sound %i but failed!", mstateSoundSFXId[stateId]); + } + else + { + s.soundTrack = sndTrack; + } } } } @@ -1172,7 +1187,7 @@ void ShapeBaseImageData::packData(BitStream* stream) } } - PACKDATA_ASSET_ARRAY(stateSound, i); + PACKDATA_SOUNDASSET_ARRAY(stateSound, i); } stream->write(maxConcurrentSounds); stream->writeFlag(useRemainderDT); @@ -1377,7 +1392,7 @@ void ShapeBaseImageData::unpackData(BitStream* stream) else s.emitter = 0; - UNPACKDATA_ASSET_ARRAY(stateSound, i); + UNPACKDATA_SOUNDASSET_ARRAY(stateSound, i); handleStateSoundTrack(i); } }