فهرست منبع

More Implements

-Most Vehicles and FX classes
-Vehicle classes may need more preloads for assets.
marauder2k7 4 سال پیش
والد
کامیت
704eb27600

+ 0 - 1
Engine/source/T3D/fx/explosion.h

@@ -70,7 +70,6 @@ class ExplosionData : public GameBaseData {
    S32 particleDensity;
    F32 particleRadius;
 
-   //SFXTrack*        soundProfile;
    DECLARE_SOUNDASSET(ExplosionData, Sound);
    DECLARE_SOUNDASSET_SETGET(ExplosionData, Sound);
 

+ 1 - 1
Engine/source/T3D/fx/lightning.cpp

@@ -290,7 +290,7 @@ bool LightningData::preload(bool server, String &errorStr)
    //dQsort(thunderSounds, MaxThunders, sizeof(SFXTrack*), cmpSounds);
 
    for (S32 i = 0; i < MaxThunders; i++) {
-      if (mThunderSound[i] == NULL)
+      if (mThunderSound[i])
       {
          _setThunderSound(getThunderSound(i), i);
       }

+ 0 - 1
Engine/source/T3D/fx/lightning.h

@@ -63,7 +63,6 @@ class LightningData : public GameBaseData
 
    //-------------------------------------- Console set variables
   public:
-   //SFXTrack*          thunderSounds[MaxThunders];
 
    DECLARE_SOUNDASSET_ARRAY(LightningData, ThunderSound, MaxThunders);
    DECLARE_SOUNDASSET_ARRAY_SETGET(LightningData, ThunderSound);

+ 0 - 1
Engine/source/T3D/fx/precipitation.h

@@ -46,7 +46,6 @@ class PrecipitationData : public GameBaseData
    typedef GameBaseData Parent;
 
   public:
-   //SFXTrack*     soundProfile;
      DECLARE_SOUNDASSET(PrecipitationData, Sound);
      DECLARE_SOUNDASSET_SETGET(PrecipitationData, Sound);
 

+ 11 - 14
Engine/source/T3D/projectile.cpp

@@ -146,7 +146,7 @@ ProjectileData::ProjectileData()
 {
    INIT_SHAPEASSET(ProjectileShape);
 
-   sound = NULL;
+   INIT_SOUNDASSET(ProjectileSound);
 
    explosion = NULL;
    explosionId = 0;
@@ -217,7 +217,7 @@ ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : G
    splashId = other.splashId; // -- for pack/unpack of splash ptr
    decal = other.decal;
    decalId = other.decalId; // -- for pack/unpack of decal ptr
-   sound = other.sound;
+   CLONE_SOUNDASSET(ProjectileSound);
    lightDesc = other.lightDesc;
    lightDescId = other.lightDescId; // -- for pack/unpack of lightDesc ptr
    CLONE_SHAPEASSET(ProjectileShape);// -- TSShape loads using mProjectileShapeName
@@ -252,8 +252,7 @@ void ProjectileData::initPersistFields()
       "@brief Scale to apply to the projectile's size.\n\n"
       "@note This is applied after SceneObject::scale\n");
 
-   addField("sound", TypeSFXTrackName, Offset(sound, ProjectileData),
-      "@brief SFXTrack datablock used to play sounds while in flight.\n\n");
+   INITPERSISTFIELD_SOUNDASSET(ProjectileSound, ProjectileData, "The sound for the projectile.");
 
    addField("explosion", TYPEID< ExplosionData >(), Offset(explosion, ProjectileData),
       "@brief Explosion datablock used when the projectile explodes outside of water.\n\n");
@@ -368,9 +367,8 @@ bool ProjectileData::preload(bool server, String &errorStr)
          if (Sim::findObject(decalId, decal) == false)
             Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet, bad datablockId(decal): %d", decalId);
 
-      String sfxErrorStr;
-      if( !sfxResolve( &sound, sfxErrorStr ) )
-         Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid packet: %s", sfxErrorStr.c_str());
+      if( !getProjectileSound() )
+         Con::errorf(ConsoleLogEntry::General, "ProjectileData::preload: Invalid asset");
 
       if (!lightDesc && lightDescId != 0)
          if (Sim::findObject(lightDescId, lightDesc) == false)
@@ -436,8 +434,7 @@ void ProjectileData::packData(BitStream* stream)
    if (stream->writeFlag(decal != NULL))
       stream->writeRangedU32(decal->getId(), DataBlockObjectIdFirst,
                                               DataBlockObjectIdLast);
-
-   sfxWrite( stream, sound );
+   PACKDATA_SOUNDASSET(ProjectileSound);
 
    if ( stream->writeFlag(lightDesc != NULL))
       stream->writeRangedU32(lightDesc->getId(), DataBlockObjectIdFirst,
@@ -497,8 +494,8 @@ void ProjectileData::unpackData(BitStream* stream)
 
    if (stream->readFlag())
       decalId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
-   
-   sfxRead( stream, &sound );
+
+   UNPACKDATA_SOUNDASSET(ProjectileSound);
 
    if (stream->readFlag())
       lightDescId = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
@@ -882,8 +879,8 @@ bool Projectile::onNewDataBlock( GameBaseData *dptr, bool reload )
 
       SFX_DELETE( mSound );
 
-      if ( mDataBlock->sound )
-         mSound = SFX->createSource( mDataBlock->sound );
+      if ( mDataBlock->getProjectileSound() )
+         mSound = SFX->createSource( mDataBlock->getSFXProfile() );
    }
 
    return true;
@@ -1097,7 +1094,7 @@ void Projectile::explode( const Point3F &p, const Point3F &n, const U32 collideT
 
 void Projectile::updateSound()
 {
-   if (!mDataBlock->sound)
+   if (!mDataBlock->getProjectileSound())
       return;
 
    if ( mSound )

+ 9 - 1
Engine/source/T3D/projectile.h

@@ -44,6 +44,7 @@
 #include "lighting/lightInfo.h"
 #endif
 
+#include "T3D/assets/SoundAsset.h"
 #include "T3D/assets/ShapeAsset.h"
 
 class ExplosionData;
@@ -115,7 +116,14 @@ public:
    DecalData *decal;                   // (impact) Decal Datablock
    S32 decalId;                        // (impact) Decal ID
 
-   SFXTrack* sound;                    // Projectile Sound
+   DECLARE_SOUNDASSET(ProjectileData, ProjectileSound);
+   DECLARE_SOUNDASSET_SETGET(ProjectileData, ProjectileSound);
+   SFXProfile* getSFXProfile() {
+      if (mProjectileSoundAsset.notNull())
+         return mProjectileSoundAsset->getSfxProfile();
+      else
+         return NULL;
+   }
    
    LightDescription *lightDesc;
    S32 lightDescId;   

+ 32 - 26
Engine/source/T3D/rigidShape.cpp

@@ -238,7 +238,7 @@ RigidShapeData::RigidShapeData()
    density = 4;
 
    for (S32 i = 0; i < Body::MaxSounds; i++)
-      body.sound[i] = 0;
+      INIT_SOUNDASSET_ARRAY(BodySounds, i);
 
    dustEmitter = NULL;
    dustID = 0;
@@ -256,7 +256,8 @@ RigidShapeData::RigidShapeData()
    hardSplashSoundVel = 3.0;
    enablePhysicsRep = true;
 
-   dMemset(waterSound, 0, sizeof(waterSound));
+   for (S32 i = 0; i < Sounds::MaxSounds; i++)
+      INIT_SOUNDASSET_ARRAY(WaterSounds, i);
 
    dragForce            = 0;
    vertFactor           = 0.25;
@@ -299,7 +300,10 @@ bool RigidShapeData::preload(bool server, String &errorStr)
    // Resolve objects transmitted from server
    if (!server) {
       for (S32 i = 0; i < Body::MaxSounds; i++)
-         sfxResolve( &body.sound[ i ], errorStr );
+         if (mBodySounds[i])
+         {
+            _setBodySounds(getBodySounds(i), i);
+         }
    }
 
    if( !dustEmitter && dustID != 0 )
@@ -354,8 +358,10 @@ void RigidShapeData::packData(BitStream* stream)
 
    stream->write(body.restitution);
    stream->write(body.friction);
-   for( U32 i = 0; i < Body::MaxSounds; ++ i )
-      sfxWrite( stream, body.sound[ i ] );
+   for (U32 i = 0; i < Body::MaxSounds; ++i)
+   {
+      PACKDATA_SOUNDASSET_ARRAY(BodySounds, i);
+   }
 
    stream->write(minImpactSpeed);
    stream->write(softImpactSpeed);
@@ -384,8 +390,10 @@ void RigidShapeData::packData(BitStream* stream)
    stream->write(enablePhysicsRep);
 
    // write the water sound profiles
-   for( U32 i = 0; i < MaxSounds; ++ i )
-      sfxWrite( stream, waterSound[ i ] );
+   for (U32 i = 0; i < Sounds::MaxSounds; ++i)
+   {
+      PACKDATA_SOUNDASSET_ARRAY(WaterSounds, i);
+   }
 
    if (stream->writeFlag( dustEmitter ))
       stream->writeRangedU32( dustEmitter->getId(), DataBlockObjectIdFirst,  DataBlockObjectIdLast );
@@ -413,8 +421,10 @@ void RigidShapeData::unpackData(BitStream* stream)
    stream->read(&body.restitution);
    stream->read(&body.friction);
 
-   for( U32 i = 0; i < Body::MaxSounds; i++)
-      sfxRead( stream, &body.sound[ i ] );
+   for (U32 i = 0; i < Body::Sounds::MaxSounds; i++)
+   {
+      UNPACKDATA_SOUNDASSET_ARRAY(BodySounds, i);
+   }
 
    stream->read(&minImpactSpeed);
    stream->read(&softImpactSpeed);
@@ -443,8 +453,10 @@ void RigidShapeData::unpackData(BitStream* stream)
    stream->read(&enablePhysicsRep);
 
    // write the water sound profiles
-   for( U32 i = 0; i < MaxSounds; ++ i )
-      sfxRead( stream, &waterSound[ i ] );
+   for (U32 i = 0; i < Sounds::MaxSounds; ++i)
+   {
+      UNPACKDATA_SOUNDASSET_ARRAY(WaterSounds, i);
+   }
 
    if( stream->readFlag() )
       dustID = (S32) stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
@@ -516,21 +528,15 @@ void RigidShapeData::initPersistFields()
    
    addGroup( "Sounds" );
 
-      addField("softImpactSound", TypeSFXTrackName, Offset(body.sound[Body::SoftImpactSound], RigidShapeData),
-         "Sound to play when body impacts with at least softImageSpeed but less than hardImpactSpeed." );
-      addField("hardImpactSound", TypeSFXTrackName, Offset(body.sound[Body::HardImpactSound], RigidShapeData),
-         "Sound to play when body impacts with at least hardImpactSpeed." );
+      INITPERSISTFIELD_SOUNDASSET_ARRAY(BodySounds, Body::Sounds::MaxSounds, RigidShapeData, "Sounds for body.");
 
       addField("exitSplashSoundVelocity", TypeF32,       Offset(exitSplashSoundVel, RigidShapeData), "The minimum velocity at which the exit splash sound will be played when emerging from water.\n");
       addField("softSplashSoundVelocity", TypeF32,       Offset(softSplashSoundVel, RigidShapeData),"The minimum velocity at which the soft splash sound will be played when impacting water.\n");
       addField("mediumSplashSoundVelocity", TypeF32,     Offset(medSplashSoundVel, RigidShapeData), "The minimum velocity at which the medium splash sound will be played when impacting water.\n");
       addField("hardSplashSoundVelocity", TypeF32,       Offset(hardSplashSoundVel, RigidShapeData), "The minimum velocity at which the hard splash sound will be played when impacting water.\n");
-      addField("exitingWater",      TypeSFXTrackName,   Offset(waterSound[ExitWater],   RigidShapeData), "The AudioProfile will be used to produce sounds when emerging from water.\n");
-      addField("impactWaterEasy",   TypeSFXTrackName,   Offset(waterSound[ImpactSoft],   RigidShapeData), "The AudioProfile will be used to produce sounds when a soft impact with water occurs.\n");
-      addField("impactWaterMedium", TypeSFXTrackName,   Offset(waterSound[ImpactMedium],   RigidShapeData), "The AudioProfile will be used to produce sounds when a medium impact with water occurs.\n");
-      addField("impactWaterHard",   TypeSFXTrackName,   Offset(waterSound[ImpactHard],   RigidShapeData), "The AudioProfile will be used to produce sounds when a hard impact with water occurs.\n");
-      addField("waterWakeSound",    TypeSFXTrackName,   Offset(waterSound[Wake],   RigidShapeData), "The AudioProfile will be used to produce sounds when a water wake is displayed.\n");
       
+      INITPERSISTFIELD_SOUNDASSET_ARRAY(WaterSounds, Sounds::MaxSounds, RigidShapeData, "Sounds for interacting with water.");
+
    endGroup( "Sounds" );
    
    addGroup( "Camera" );
@@ -1155,27 +1161,27 @@ void RigidShape::updatePos(F32 dt)
             if (collSpeed >= mDataBlock->softImpactSpeed)
                impactSound = RigidShapeData::Body::SoftImpactSound;
 
-         if (impactSound != -1 && mDataBlock->body.sound[impactSound] != NULL)
-            SFX->playOnce(mDataBlock->body.sound[impactSound], &getTransform());
+         if (impactSound != -1 && mDataBlock->getBodySounds(impactSound) != NULL)
+            SFX->playOnce(mDataBlock->getBodySoundProfile(impactSound), &getTransform());
       }
 
       // Water volume sounds
       F32 vSpeed = getVelocity().len();
       if (!inLiquid && mWaterCoverage >= 0.8f) {
          if (vSpeed >= mDataBlock->hardSplashSoundVel)
-            SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactHard], &getTransform());
+            SFX->playOnce(mDataBlock->getWaterSoundProfile(RigidShapeData::ImpactHard), &getTransform());
          else
             if (vSpeed >= mDataBlock->medSplashSoundVel)
-               SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactMedium], &getTransform());
+               SFX->playOnce(mDataBlock->getWaterSoundProfile(RigidShapeData::ImpactMedium), &getTransform());
             else
                if (vSpeed >= mDataBlock->softSplashSoundVel)
-                  SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ImpactSoft], &getTransform());
+                  SFX->playOnce(mDataBlock->getWaterSoundProfile(RigidShapeData::ImpactSoft), &getTransform());
          inLiquid = true;
       }
       else
          if (inLiquid && mWaterCoverage < 0.8f) {
             if (vSpeed >= mDataBlock->exitSplashSoundVel)
-               SFX->playOnce(mDataBlock->waterSound[RigidShapeData::ExitWater], &getTransform());
+               SFX->playOnce(mDataBlock->getWaterSoundProfile(RigidShapeData::ExitWater), &getTransform());
             inLiquid = false;
          }
    }

+ 23 - 2
Engine/source/T3D/rigidShape.h

@@ -35,6 +35,8 @@
 #include "T3D/physics/physicsBody.h"
 #endif
 
+#include "T3D/assets/SoundAsset.h"
+
 class ParticleEmitter;
 class ParticleEmitterData;
 class ClippedPolyList;
@@ -57,11 +59,21 @@ class RigidShapeData : public ShapeBaseData
          HardImpactSound,
          MaxSounds,
       };
-      SFXTrack* sound[MaxSounds];
       F32 restitution;
       F32 friction;
    } body;
 
+   DECLARE_SOUNDASSET_ARRAY(RigidShapeData, BodySounds, Body::Sounds::MaxSounds)
+   DECLARE_SOUNDASSET_ARRAY_SETGET(RigidShapeData, BodySounds);
+
+   SFXProfile* getBodySoundProfile(U32 id)
+   {
+      if (mBodySoundsAsset[id] != NULL)
+         return mBodySoundsAsset[id]->getSfxProfile();
+      else
+         return NULL;
+   }
+
    enum RigidShapeConsts
    {
       VC_NUM_DUST_EMITTERS = 1,
@@ -79,7 +91,16 @@ class RigidShapeData : public ShapeBaseData
       Wake,
       MaxSounds
    };
-   SFXTrack* waterSound[MaxSounds];
+   DECLARE_SOUNDASSET_ARRAY(RigidShapeData, WaterSounds, Sounds::MaxSounds)
+   DECLARE_SOUNDASSET_ARRAY_SETGET(RigidShapeData, WaterSounds);
+
+   SFXProfile* getWaterSoundProfile(U32 id)
+   {
+      if (mWaterSoundsAsset[id] != NULL)
+         return mWaterSoundsAsset[id]->getSfxProfile();
+      else
+         return NULL;
+   }
 
    F32 exitSplashSoundVel;
    F32 softSplashSoundVel;

+ 20 - 23
Engine/source/T3D/vehicles/hoverVehicle.cpp

@@ -152,7 +152,7 @@ HoverVehicleData::HoverVehicleData()
       jetEmitter[j] = 0;
 
    for (S32 i = 0; i < MaxSounds; i++)
-      sound[i] = 0;
+      INIT_SOUNDASSET_ARRAY(HoverSounds, i);
 }
 
 HoverVehicleData::~HoverVehicleData()
@@ -232,14 +232,8 @@ void HoverVehicleData::initPersistFields()
    addField( "pitchForce", TypeF32, Offset(pitchForce, HoverVehicleData),
       "Pitch (rotation about the X-axis) force applied when steering in the y-axis direction." );
 
-   addField( "jetSound", TYPEID< SFXProfile >(), Offset(sound[JetSound], HoverVehicleData),
-      "Looping sound played when the vehicle is jetting." );
-   addField( "engineSound", TYPEID< SFXProfile >(), Offset(sound[EngineSound], HoverVehicleData),
-      "Looping engine sound.\nThe volume is dynamically adjusted based on the "
-      "current thrust level." );
-   addField( "floatSound", TYPEID< SFXProfile >(), Offset(sound[FloatSound], HoverVehicleData),
-      "Looping sound played while the vehicle is floating.\n\n@see stabMinLen" );
-
+   INITPERSISTFIELD_SOUNDASSET_ARRAY(HoverSounds, Sounds::MaxSounds, HoverVehicleData, "Sounds for hover vehicle.");
+   
    addField( "dustTrailEmitter", TYPEID< ParticleEmitterData >(), Offset(dustTrailEmitter, HoverVehicleData),
       "Emitter to generate particles for the vehicle's dust trail.\nThe trail "
       "of dust particles is generated only while the vehicle is moving." );
@@ -312,8 +306,11 @@ bool HoverVehicleData::preload(bool server, String &errorStr)
    // Resolve objects transmitted from server
    if (!server) {
       for (S32 i = 0; i < MaxSounds; i++)
-         if (sound[i])
-            Sim::findObject(SimObjectId((uintptr_t)sound[i]),sound[i]);
+         if (mHoverSounds[i])
+         {
+            _setHoverSounds(getHoverSounds(i), i);
+         }
+
       for (S32 j = 0; j < MaxJetEmitters; j++)
          if (jetEmitter[j])
             Sim::findObject(SimObjectId((uintptr_t)jetEmitter[j]),jetEmitter[j]);
@@ -361,9 +358,9 @@ void HoverVehicleData::packData(BitStream* stream)
    stream->write(dustTrailFreqMod);
 
    for (S32 i = 0; i < MaxSounds; i++)
-      if (stream->writeFlag(sound[i]))
-         stream->writeRangedU32(mPacked ? SimObjectId((uintptr_t)sound[i]):
-                                sound[i]->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
+   {
+      PACKDATA_SOUNDASSET_ARRAY(HoverSounds, i);
+   }
 
    for (S32 j = 0; j < MaxJetEmitters; j++)
    {
@@ -410,9 +407,9 @@ void HoverVehicleData::unpackData(BitStream* stream)
    stream->read(&dustTrailFreqMod);
 
    for (S32 i = 0; i < MaxSounds; i++)
-      sound[i] = stream->readFlag()?
-         (SFXProfile*)(uintptr_t)stream->readRangedU32(DataBlockObjectIdFirst,
-                                               DataBlockObjectIdLast): 0;
+   {
+      UNPACKDATA_SOUNDASSET_ARRAY(HoverSounds, i);
+   }
 
    for (S32 j = 0; j < MaxJetEmitters; j++) {
       jetEmitter[j] = NULL;
@@ -539,14 +536,14 @@ bool HoverVehicle::onNewDataBlock(GameBaseData* dptr, bool reload)
       SFX_DELETE( mFloatSound );
       SFX_DELETE( mJetSound );
 
-      if ( mDataBlock->sound[HoverVehicleData::EngineSound] )
-         mEngineSound = SFX->createSource( mDataBlock->sound[HoverVehicleData::EngineSound], &getTransform() );
+      if ( mDataBlock->getHoverSounds(HoverVehicleData::EngineSound) )
+         mEngineSound = SFX->createSource( mDataBlock->getHoverSoundProfile(HoverVehicleData::EngineSound), &getTransform() );
 
-      if ( !mDataBlock->sound[HoverVehicleData::FloatSound] )
-         mFloatSound = SFX->createSource( mDataBlock->sound[HoverVehicleData::FloatSound], &getTransform() );
+      if ( !mDataBlock->getHoverSounds(HoverVehicleData::FloatSound) )
+         mFloatSound = SFX->createSource( mDataBlock->getHoverSoundProfile(HoverVehicleData::FloatSound), &getTransform() );
 
-      if ( mDataBlock->sound[HoverVehicleData::JetSound] )
-         mJetSound = SFX->createSource( mDataBlock->sound[HoverVehicleData::JetSound], &getTransform() );
+      if ( mDataBlock->getHoverSounds(HoverVehicleData::JetSound) )
+         mJetSound = SFX->createSource( mDataBlock->getHoverSoundProfile(HoverVehicleData::JetSound), &getTransform() );
    }
 
    // Todo: Uncomment if this is a "leaf" class

+ 9 - 1
Engine/source/T3D/vehicles/hoverVehicle.h

@@ -46,7 +46,15 @@ class HoverVehicleData : public VehicleData
       FloatSound,
       MaxSounds
    };
-   SFXProfile* sound[MaxSounds];
+   DECLARE_SOUNDASSET_ARRAY(HoverVehicleData, HoverSounds, Sounds::MaxSounds);
+   DECLARE_SOUNDASSET_ARRAY_SETGET(HoverVehicleData, HoverSounds);
+   SFXProfile* getHoverSoundProfile(U32 id)
+   {
+      if (mHoverSoundsAsset[id] != NULL)
+         return mHoverSoundsAsset[id]->getSfxProfile();
+      else
+         return NULL;
+   }
 
    enum Jets {
       // These enums index into a static name list.

+ 35 - 51
Engine/source/T3D/vehicles/vehicle.cpp

@@ -166,7 +166,9 @@ VehicleData::VehicleData()
    powerSteering = false;
 
    for (S32 i = 0; i < Body::MaxSounds; i++)
-      body.sound[i] = 0;
+   {
+      INIT_SOUNDASSET_ARRAY(VehicleBodySounds, i);
+   }
 
    dustEmitter = NULL;
    dustID = 0;
@@ -189,7 +191,8 @@ VehicleData::VehicleData()
    medSplashSoundVel = 2.0;
    hardSplashSoundVel = 3.0;
 
-   dMemset(waterSound, 0, sizeof(waterSound));
+   for (S32 i = 0; i < Sounds::MaxSounds; i++)
+      INIT_SOUNDASSET_ARRAY(VehicleWaterSounds, i);
 
    collDamageThresholdVel = 20;
    collDamageMultiplier = 0.05f;
@@ -215,8 +218,10 @@ bool VehicleData::preload(bool server, String &errorStr)
    // Resolve objects transmitted from server
    if (!server) {
       for (S32 i = 0; i < Body::MaxSounds; i++)
-         if (body.sound[i])
-            Sim::findObject(SimObjectId((uintptr_t)body.sound[i]),body.sound[i]);
+         if (mVehicleBodySounds[i])
+         {
+            _setVehicleBodySounds(getVehicleBodySounds(i), i);
+         }
    }
 
    if( !dustEmitter && dustID != 0 )
@@ -264,10 +269,9 @@ void VehicleData::packData(BitStream* stream)
    stream->write(body.restitution);
    stream->write(body.friction);
    for (i = 0; i < Body::MaxSounds; i++)
-      if (stream->writeFlag(body.sound[i]))
-         stream->writeRangedU32(mPacked ? SimObjectId((uintptr_t)body.sound[i]):
-                                body.sound[i]->getId(),DataBlockObjectIdFirst,
-                                DataBlockObjectIdLast);
+   {
+      PACKDATA_SOUNDASSET_ARRAY(VehicleBodySounds, i);
+   }
 
    stream->write(minImpactSpeed);
    stream->write(softImpactSpeed);
@@ -308,9 +312,10 @@ void VehicleData::packData(BitStream* stream)
    stream->write(enablePhysicsRep);
 
    // write the water sound profiles
-   for(i = 0; i < MaxSounds; i++)
-      if(stream->writeFlag(waterSound[i]))
-         stream->writeRangedU32(waterSound[i]->getId(), DataBlockObjectIdFirst,  DataBlockObjectIdLast);
+   for (i = 0; i < MaxSounds; i++)
+   {
+      PACKDATA_SOUNDASSET_ARRAY(VehicleWaterSounds, i);
+   }
 
    if (stream->writeFlag( dustEmitter ))
    {
@@ -359,11 +364,9 @@ void VehicleData::unpackData(BitStream* stream)
    stream->read(&body.restitution);
    stream->read(&body.friction);
    S32 i;
-   for (i = 0; i < Body::MaxSounds; i++) {
-      body.sound[i] = NULL;
-      if (stream->readFlag())
-         body.sound[i] = (SFXProfile*)(uintptr_t)stream->readRangedU32(DataBlockObjectIdFirst,
-                                                              DataBlockObjectIdLast);
+   for (i = 0; i < Body::MaxSounds; i++)
+   {
+      UNPACKDATA_SOUNDASSET_ARRAY(VehicleBodySounds, i);
    }
 
    stream->read(&minImpactSpeed);
@@ -405,12 +408,10 @@ void VehicleData::unpackData(BitStream* stream)
    stream->read(&enablePhysicsRep);
 
    // write the water sound profiles
-   for(i = 0; i < MaxSounds; i++)
-      if(stream->readFlag())
-      {
-         U32 id = stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast);
-         waterSound[i] = dynamic_cast<SFXProfile*>( Sim::findObject(id) );
-      }
+   for (i = 0; i < Sounds::MaxSounds; i++)
+   {
+      UNPACKDATA_SOUNDASSET_ARRAY(VehicleWaterSounds, i);
+   }
 
    if( stream->readFlag() )
    {
@@ -491,15 +492,8 @@ void VehicleData::initPersistFields()
    addField( "bodyFriction", TypeF32, Offset(body.friction, VehicleData),
       "Collision friction coefficient.\nHow well this object will slide against "
       "objects it collides with." );
-   addField( "softImpactSound", TYPEID< SFXProfile >(), Offset(body.sound[Body::SoftImpactSound], VehicleData),
-      "@brief Sound to play on a 'soft' impact.\n\n"
-      "This sound is played if the impact speed is < hardImpactSpeed and >= "
-      "softImpactSpeed.\n\n"
-      "@see softImpactSpeed" );
-   addField( "hardImpactSound", TYPEID< SFXProfile >(), Offset(body.sound[Body::HardImpactSound], VehicleData),
-      "@brief Sound to play on a 'hard' impact.\n\n"
-      "This sound is played if the impact speed >= hardImpactSpeed.\n\n"
-      "@see hardImpactSpeed" );
+
+   INITPERSISTFIELD_SOUNDASSET_ARRAY(VehicleBodySounds, Body::Sounds::MaxSounds, VehicleData, "Sounds for vehicle body impacts.");
 
    addField( "minImpactSpeed", TypeF32, Offset(minImpactSpeed, VehicleData),
       "Minimum collision speed for the onImpact callback to be invoked." );
@@ -596,18 +590,8 @@ void VehicleData::initPersistFields()
    addField( "hardSplashSoundVelocity", TypeF32, Offset(hardSplashSoundVel, VehicleData),
       "Minimum velocity when entering the water for the imapactWaterHard sound "
       "to play.\n\n@see impactWaterHard" );
-   addField( "exitingWater", TYPEID< SFXProfile >(), Offset(waterSound[ExitWater], VehicleData),
-      "Sound to play when exiting the water." );
-   addField( "impactWaterEasy", TYPEID< SFXProfile >(), Offset(waterSound[ImpactSoft], VehicleData),
-      "Sound to play when entering the water with speed >= softSplashSoundVelocity "
-      "and < mediumSplashSoundVelocity." );
-   addField( "impactWaterMedium", TYPEID< SFXProfile >(), Offset(waterSound[ImpactMedium], VehicleData),
-      "Sound to play when entering the water with speed >= mediumSplashSoundVelocity "
-      "and < hardSplashSoundVelocity." );
-   addField( "impactWaterHard", TYPEID< SFXProfile >(), Offset(waterSound[ImpactHard], VehicleData),
-      "Sound to play when entering the water with speed >= hardSplashSoundVelocity." );
-   addField( "waterWakeSound", TYPEID< SFXProfile >(), Offset(waterSound[Wake], VehicleData),
-      "Looping sound to play while moving through the water." );
+
+   INITPERSISTFIELD_SOUNDASSET_ARRAY(WaterSounds, Sounds::MaxSounds, VehicleData, "Sounds for interacting with water.");
 
    addField( "collDamageThresholdVel", TypeF32, Offset(collDamageThresholdVel, VehicleData),
       "Minimum collision velocity to cause damage to this vehicle.\nCurrently unused." );
@@ -876,8 +860,8 @@ bool Vehicle::onNewDataBlock(GameBaseData* dptr,bool reload)
       // costs and makes the system easier to understand.
       SFX_DELETE( mWakeSound );
 
-      if ( mDataBlock->waterSound[VehicleData::Wake] )
-         mWakeSound = SFX->createSource( mDataBlock->waterSound[VehicleData::Wake], &getTransform() );
+      if ( mDataBlock->getVehicleWaterSounds(VehicleData::Wake) != NULL )
+         mWakeSound = SFX->createSource( mDataBlock->getVehicleWaterSoundProfile(VehicleData::Wake), &getTransform() );
    }
 
    return true;
@@ -1140,27 +1124,27 @@ void Vehicle::updatePos(F32 dt)
             if (collSpeed >= mDataBlock->softImpactSpeed)
                impactSound = VehicleData::Body::SoftImpactSound;
 
-         if (impactSound != -1 && mDataBlock->body.sound[impactSound] != NULL)
-            SFX->playOnce( mDataBlock->body.sound[impactSound], &getTransform() );
+         if (impactSound != -1 && mDataBlock->getVehicleBodySounds(impactSound) != NULL)
+            SFX->playOnce( mDataBlock->getVehicleBodySoundProfile(impactSound), &getTransform() );
       }
 
       // Water volume sounds
       F32 vSpeed = getVelocity().len();
       if (!inLiquid && mWaterCoverage >= 0.8f) {
          if (vSpeed >= mDataBlock->hardSplashSoundVel)
-            SFX->playOnce( mDataBlock->waterSound[VehicleData::ImpactHard], &getTransform() );
+            SFX->playOnce( mDataBlock->getVehicleWaterSoundProfile(VehicleData::ImpactHard), &getTransform() );
          else
             if (vSpeed >= mDataBlock->medSplashSoundVel)
-               SFX->playOnce( mDataBlock->waterSound[VehicleData::ImpactMedium], &getTransform() );
+               SFX->playOnce( mDataBlock->getVehicleWaterSoundProfile(VehicleData::ImpactMedium), &getTransform() );
          else
             if (vSpeed >= mDataBlock->softSplashSoundVel)
-               SFX->playOnce( mDataBlock->waterSound[VehicleData::ImpactSoft], &getTransform() );
+               SFX->playOnce( mDataBlock->getVehicleWaterSoundProfile(VehicleData::ImpactSoft), &getTransform() );
          inLiquid = true;
       }
       else
          if(inLiquid && mWaterCoverage < 0.8f) {
             if (vSpeed >= mDataBlock->exitSplashSoundVel)
-               SFX->playOnce( mDataBlock->waterSound[VehicleData::ExitWater], &getTransform() );
+               SFX->playOnce( mDataBlock->getVehicleWaterSoundProfile(VehicleData::ExitWater), &getTransform() );
          inLiquid = false;
       }
    }

+ 24 - 2
Engine/source/T3D/vehicles/vehicle.h

@@ -45,11 +45,22 @@ struct VehicleData : public RigidShapeData
          HardImpactSound,
          MaxSounds,
       };
-      SFXProfile* sound[MaxSounds];
       F32 restitution;
       F32 friction;
    } body;
 
+   DECLARE_SOUNDASSET_ARRAY(VehicleData, VehicleBodySounds, Body::Sounds::MaxSounds)
+   DECLARE_SOUNDASSET_ARRAY_SETGET(VehicleData, VehicleBodySounds);
+
+   SFXProfile* getVehicleBodySoundProfile(U32 id)
+   {
+      if (mVehicleBodySoundsAsset[id] != NULL)
+         return mVehicleBodySoundsAsset[id]->getSfxProfile();
+      else
+         return NULL;
+   }
+
+
    enum VehicleConsts
    {
       VC_NUM_DUST_EMITTERS = 1,
@@ -69,7 +80,18 @@ struct VehicleData : public RigidShapeData
       Wake,
       MaxSounds
    };
-   SFXProfile* waterSound[MaxSounds];
+
+  DECLARE_SOUNDASSET_ARRAY(VehicleData, VehicleWaterSounds, Sounds::MaxSounds)
+  DECLARE_SOUNDASSET_ARRAY_SETGET(VehicleData, VehicleWaterSounds);
+
+  SFXProfile* getVehicleWaterSoundProfile(U32 id)
+  {
+     if (mVehicleWaterSoundsAsset[id] != NULL)
+        return mVehicleWaterSoundsAsset[id]->getSfxProfile();
+     else
+        return NULL;
+  }
+
    F32 exitSplashSoundVel;
    F32 softSplashSoundVel;
    F32 medSplashSoundVel;

+ 16 - 22
Engine/source/T3D/vehicles/wheeledVehicle.cpp

@@ -301,7 +301,7 @@ WheeledVehicleData::WheeledVehicleData()
    wheelCount = 0;
    dMemset(&wheel, 0, sizeof(wheel));
    for (S32 i = 0; i < MaxSounds; i++)
-      sound[i] = 0;
+      INIT_SOUNDASSET_ARRAY(WheeledVehicleSounds, i);
 }
 
 
@@ -335,10 +335,9 @@ bool WheeledVehicleData::preload(bool server, String &errorStr)
    if (!server) {
       for (S32 i = 0; i < MaxSounds; i++)
       {
-         if (!sfxResolve(&sound[i], errorStr))
+         if (mWheeledVehicleSounds[i])
          {
-            delete si;
-            return false;
+            _setWheeledVehicleSounds(getWheeledVehicleSounds(i), i);
          }
       }
 
@@ -438,16 +437,7 @@ bool WheeledVehicleData::mirrorWheel(Wheel* we)
 
 void WheeledVehicleData::initPersistFields()
 {
-   addField( "jetSound", TYPEID< SFXTrack >(), Offset(sound[JetSound], WheeledVehicleData),
-      "Looping sound played when the vehicle is jetting." );
-   addField( "engineSound", TYPEID< SFXTrack >(), Offset(sound[EngineSound], WheeledVehicleData),
-      "@brief Looping engine sound.\n\n"
-      "The pitch is dynamically adjusted based on the current engine RPM" );
-   addField("squealSound", TYPEID< SFXTrack >(), Offset(sound[SquealSound], WheeledVehicleData),
-      "@brief Looping sound played while any of the wheels is slipping.\n\n"
-      "The volume is dynamically adjusted based on how much the wheels are slipping." );
-   addField("WheelImpactSound", TYPEID< SFXTrack >(), Offset(sound[WheelImpactSound], WheeledVehicleData),
-      "Sound played when the wheels impact the ground.\nCurrently unused." );
+   INITPERSISTFIELD_SOUNDASSET_ARRAY(WheeledVehicleSounds, Sounds::MaxSounds, WheeledVehicleData, "Sounds related to wheeled vehicle.");
 
    addField("tireEmitter",TYPEID< ParticleEmitterData >(), Offset(tireEmitter, WheeledVehicleData),
       "ParticleEmitterData datablock used to generate particles from each wheel "
@@ -481,7 +471,9 @@ void WheeledVehicleData::packData(BitStream* stream)
          tireEmitter->getId(),DataBlockObjectIdFirst,DataBlockObjectIdLast);
 
    for (S32 i = 0; i < MaxSounds; i++)
-      sfxWrite( stream, sound[ i ] );
+   {
+      PACKDATA_SOUNDASSET_ARRAY(WheeledVehicleSounds, i);
+   }
 
    stream->write(maxWheelSpeed);
    stream->write(engineTorque);
@@ -498,7 +490,9 @@ void WheeledVehicleData::unpackData(BitStream* stream)
          DataBlockObjectIdLast): 0;
 
    for (S32 i = 0; i < MaxSounds; i++)
-      sfxRead( stream, &sound[ i ] );
+   {
+      UNPACKDATA_SOUNDASSET_ARRAY(WheeledVehicleSounds, i);
+   }
 
    stream->read(&maxWheelSpeed);
    stream->read(&engineTorque);
@@ -683,14 +677,14 @@ bool WheeledVehicle::onNewDataBlock(GameBaseData* dptr, bool reload)
       SFX_DELETE( mSquealSound );
       SFX_DELETE( mJetSound );
 
-      if ( mDataBlock->sound[WheeledVehicleData::EngineSound] )
-         mEngineSound = SFX->createSource( mDataBlock->sound[WheeledVehicleData::EngineSound], &getTransform() );
+      if ( mDataBlock->getWheeledVehicleSounds(WheeledVehicleData::EngineSound) )
+         mEngineSound = SFX->createSource( mDataBlock->getWheeledVehicleSound(WheeledVehicleData::EngineSound), &getTransform() );
 
-      if ( mDataBlock->sound[WheeledVehicleData::SquealSound] )
-         mSquealSound = SFX->createSource( mDataBlock->sound[WheeledVehicleData::SquealSound], &getTransform() );
+      if ( mDataBlock->getWheeledVehicleSounds(WheeledVehicleData::SquealSound) )
+         mSquealSound = SFX->createSource( mDataBlock->getWheeledVehicleSound(WheeledVehicleData::SquealSound), &getTransform() );
 
-      if ( mDataBlock->sound[WheeledVehicleData::JetSound] )
-         mJetSound = SFX->createSource( mDataBlock->sound[WheeledVehicleData::JetSound], &getTransform() );
+      if ( mDataBlock->getWheeledVehicleSounds(WheeledVehicleData::JetSound) )
+         mJetSound = SFX->createSource( mDataBlock->getWheeledVehicleSound(WheeledVehicleData::JetSound), &getTransform() );
    }
 
    scriptOnNewDataBlock();

+ 11 - 1
Engine/source/T3D/vehicles/wheeledVehicle.h

@@ -118,7 +118,17 @@ struct WheeledVehicleData: public VehicleData
       WheelImpactSound,
       MaxSounds,
    };
-   SFXTrack* sound[MaxSounds];
+   DECLARE_SOUNDASSET_ARRAY(WheeledVehicleData, WheeledVehicleSounds, Sounds::MaxSounds);
+   DECLARE_SOUNDASSET_ARRAY_SETGET(WheeledVehicleData, WheeledVehicleSounds);
+
+   SFXProfile* getWheeledVehicleSound(U32 id)
+   {
+      if (mWheeledVehicleSoundsAsset[id] != NULL)
+         return mWheeledVehicleSoundsAsset[id]->getSfxProfile();
+      else
+         return NULL;
+   }
+
 
    ParticleEmitterData* tireEmitter;