datablock-temp-clone -- Implements creation of temporary datablock clones to allow late substitution of datablock fields.

This commit is contained in:
Marc Chapman 2017-07-26 21:10:43 +01:00
parent 83c533249f
commit 43815793d1
24 changed files with 865 additions and 11 deletions

View file

@ -117,6 +117,85 @@ DebrisData::DebrisData()
ignoreWater = true;
}
//#define TRACK_DEBRIS_DATA_CLONES
#ifdef TRACK_DEBRIS_DATA_CLONES
static int debris_data_clones = 0;
#endif
DebrisData::DebrisData(const DebrisData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
#ifdef TRACK_DEBRIS_DATA_CLONES
debris_data_clones++;
if (debris_data_clones == 1)
Con::errorf("DebrisData -- Clones are on the loose!");
#endif
velocity = other.velocity;
velocityVariance = other.velocityVariance;
friction = other.friction;
elasticity = other.elasticity;
lifetime = other.lifetime;
lifetimeVariance = other.lifetimeVariance;
numBounces = other.numBounces;
bounceVariance = other.bounceVariance;
minSpinSpeed = other.minSpinSpeed;
maxSpinSpeed = other.maxSpinSpeed;
explodeOnMaxBounce = other.explodeOnMaxBounce;
staticOnMaxBounce = other.staticOnMaxBounce;
snapOnMaxBounce = other.snapOnMaxBounce;
fade = other.fade;
useRadiusMass = other.useRadiusMass;
baseRadius = other.baseRadius;
gravModifier = other.gravModifier;
terminalVelocity = other.terminalVelocity;
ignoreWater = other.ignoreWater;
shapeName = other.shapeName;
shape = other.shape; // -- TSShape loaded using shapeName
textureName = other.textureName;
explosionId = other.explosionId; // -- for pack/unpack of explosion ptr
explosion = other.explosion;
dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
}
DebrisData::~DebrisData()
{
if (!isTempClone())
return;
#ifdef TRACK_DEBRIS_DATA_CLONES
if (debris_data_clones > 0)
{
debris_data_clones--;
if (debris_data_clones == 0)
Con::errorf("DebrisData -- Clones eliminated!");
}
else
Con::errorf("DebrisData -- Too many clones deleted!");
#endif
}
DebrisData* DebrisData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
{
if (!owner || getSubstitutionCount() == 0)
return this;
DebrisData* sub_debris_db = new DebrisData(*this, true);
performSubstitutions(sub_debris_db, owner, index);
return sub_debris_db;
}
void DebrisData::onPerformSubstitutions()
{
if( shapeName && shapeName[0] != '\0')
{
shape = ResourceManager::get().load(shapeName);
if( bool(shape) == false )
Con::errorf("DebrisData::onPerformSubstitutions(): failed to load shape \"%s\"", shapeName);
}
}
bool DebrisData::onAdd()
{
if(!Parent::onAdd())
@ -458,6 +537,8 @@ Debris::Debris()
// Only allocated client side.
mNetFlags.set( IsGhost );
ss_object = 0;
ss_index = 0;
}
Debris::~Debris()
@ -473,6 +554,12 @@ Debris::~Debris()
delete mPart;
mPart = NULL;
}
if (mDataBlock && mDataBlock->isTempClone())
{
delete mDataBlock;
mDataBlock = 0;
}
}
void Debris::initPersistFields()
@ -502,6 +589,8 @@ bool Debris::onNewDataBlock( GameBaseData *dptr, bool reload )
if( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
return false;
if (mDataBlock->isTempClone())
return true;
scriptOnNewDataBlock();
return true;
@ -526,7 +615,7 @@ bool Debris::onAdd()
if( mDataBlock->emitterList[i] != NULL )
{
ParticleEmitter * pEmitter = new ParticleEmitter;
pEmitter->onNewDataBlock( mDataBlock->emitterList[i], false );
pEmitter->onNewDataBlock(mDataBlock->emitterList[i]->cloneAndPerformSubstitutions(ss_object, ss_index), false);
if( !pEmitter->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
@ -805,7 +894,8 @@ void Debris::explode()
Point3F explosionPos = getPosition();
Explosion* pExplosion = new Explosion;
pExplosion->onNewDataBlock(mDataBlock->explosion, false);
pExplosion->setSubstitutionData(ss_object, ss_index);
pExplosion->onNewDataBlock(mDataBlock->explosion->cloneAndPerformSubstitutions(ss_object, ss_index), false);
MatrixF trans( true );
trans.setPosition( getPosition() );

View file

@ -20,6 +20,11 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _DEBRIS_H_
#define _DEBRIS_H_
@ -97,6 +102,12 @@ struct DebrisData : public GameBaseData
DECLARE_CONOBJECT(DebrisData);
public:
/*C*/ DebrisData(const DebrisData&, bool = false);
/*D*/ ~DebrisData();
DebrisData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual void onPerformSubstitutions();
virtual bool allowSubstitutions() const { return true; }
};
//**************************************************************************
@ -165,6 +176,11 @@ public:
DECLARE_CONOBJECT(Debris);
private:
SimObject* ss_object;
S32 ss_index;
public:
void setSubstitutionData(SimObject* obj, S32 idx=0) { ss_object = obj; ss_index = idx; }
};

View file

@ -24,6 +24,7 @@
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "platform/platform.h"
#include "T3D/fx/explosion.h"
@ -54,6 +55,8 @@
#include "renderInstance/renderPassManager.h"
#include "console/engineAPI.h"
#include "sfx/sfxProfile.h"
IMPLEMENT_CONOBJECT(Explosion);
ConsoleDocClass( Explosion,
@ -285,6 +288,105 @@ ExplosionData::ExplosionData()
lightNormalOffset = 0.1f;
}
//#define TRACK_EXPLOSION_DATA_CLONES
#ifdef TRACK_EXPLOSION_DATA_CLONES
static int explosion_data_clones = 0;
#endif
ExplosionData::ExplosionData(const ExplosionData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
#ifdef TRACK_EXPLOSION_DATA_CLONES
explosion_data_clones++;
if (explosion_data_clones == 1)
Con::errorf("ExplosionData -- Clones are on the loose!");
#endif
dtsFileName = other.dtsFileName;
faceViewer = other.faceViewer;
particleDensity = other.particleDensity;
particleRadius = other.particleRadius;
soundProfile = other.soundProfile;
particleEmitter = other.particleEmitter;
particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
explosionScale = other.explosionScale;
playSpeed = other.playSpeed;
explosionShape = other.explosionShape; // -- TSShape loaded using dtsFileName
explosionAnimation = other.explosionAnimation; // -- from explosionShape sequence "ambient"
dMemcpy( emitterList, other.emitterList, sizeof( emitterList ) );
dMemcpy( emitterIDList, other.emitterIDList, sizeof( emitterIDList ) ); // -- for pack/unpack of emitterList ptrs
dMemcpy( debrisList, other.debrisList, sizeof( debrisList ) );
dMemcpy( debrisIDList, other.debrisIDList, sizeof( debrisIDList ) ); // -- for pack/unpack of debrisList ptrs
debrisThetaMin = other.debrisThetaMin;
debrisThetaMax = other.debrisThetaMax;
debrisPhiMin = other.debrisPhiMin;
debrisPhiMax = other.debrisPhiMax;
debrisNum = other.debrisNum;
debrisNumVariance = other.debrisNumVariance;
debrisVelocity = other.debrisVelocity;
debrisVelocityVariance = other.debrisVelocityVariance;
dMemcpy( explosionList, other.explosionList, sizeof( explosionList ) );
dMemcpy( explosionIDList, other.explosionIDList, sizeof( explosionIDList ) ); // -- for pack/unpack of explosionList ptrs
delayMS = other.delayMS;
delayVariance = other.delayVariance;
lifetimeMS = other.lifetimeMS;
lifetimeVariance = other.lifetimeVariance;
offset = other.offset;
dMemcpy( sizes, other.times, sizeof( sizes ) );
dMemcpy( times, other.times, sizeof( times ) );
shakeCamera = other.shakeCamera;
camShakeFreq = other.camShakeFreq;
camShakeAmp = other.camShakeAmp;
camShakeDuration = other.camShakeDuration;
camShakeRadius = other.camShakeRadius;
camShakeFalloff = other.camShakeFalloff;
lightStartRadius = other.lightStartRadius;
lightEndRadius = other.lightEndRadius;
lightStartColor = other.lightStartColor;
lightEndColor = other.lightEndColor;
lightStartBrightness = other.lightStartBrightness;
lightEndBrightness = other.lightEndBrightness;
lightNormalOffset = other.lightNormalOffset;
// Note - Explosion calls mDataBlock->getName() in warning messages but
// that should be safe.
}
ExplosionData::~ExplosionData()
{
if (!isTempClone())
return;
if (soundProfile && soundProfile->isTempClone())
{
delete soundProfile;
soundProfile = 0;
}
// particleEmitter, emitterList[*], debrisList[*], explosionList[*] will delete themselves
#ifdef TRACK_EXPLOSION_DATA_CLONES
if (explosion_data_clones > 0)
{
explosion_data_clones--;
if (explosion_data_clones == 0)
Con::errorf("ExplosionData -- Clones eliminated!");
}
else
Con::errorf("ExplosionData -- Too many clones deleted!");
#endif
}
ExplosionData* ExplosionData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
{
if (!owner || getSubstitutionCount() == 0)
return this;
ExplosionData* sub_explosion_db = new ExplosionData(*this, true);
performSubstitutions(sub_explosion_db, owner, index);
return sub_explosion_db;
}
void ExplosionData::initPersistFields()
{
addField( "explosionShape", TypeShapeFilename, Offset(dtsFileName, ExplosionData),
@ -818,6 +920,10 @@ Explosion::Explosion()
mLight = LIGHTMGR->createLightInfo();
mNetFlags.set( IsGhost );
ss_object = 0;
ss_index = 0;
mDataBlock = 0;
soundProfile_clone = 0;
}
Explosion::~Explosion()
@ -830,6 +936,18 @@ Explosion::~Explosion()
}
SAFE_DELETE(mLight);
if (soundProfile_clone)
{
delete soundProfile_clone;
soundProfile_clone = 0;
}
if (mDataBlock && mDataBlock->isTempClone())
{
delete mDataBlock;
mDataBlock = 0;
}
}
@ -988,6 +1106,8 @@ bool Explosion::onNewDataBlock( GameBaseData *dptr, bool reload )
if (!mDataBlock || !Parent::onNewDataBlock( dptr, reload ))
return false;
if (mDataBlock->isTempClone())
return true;
scriptOnNewDataBlock();
return true;
}
@ -1200,7 +1320,8 @@ void Explosion::launchDebris( Point3F &axis )
launchDir *= debrisVel;
Debris *debris = new Debris;
debris->setDataBlock( mDataBlock->debrisList[0] );
debris->setSubstitutionData(ss_object, ss_index);
debris->setDataBlock(mDataBlock->debrisList[0]->cloneAndPerformSubstitutions(ss_object, ss_index));
debris->setTransform( getTransform() );
debris->init( pos, launchDir );
@ -1228,7 +1349,8 @@ void Explosion::spawnSubExplosions()
{
MatrixF trans = getTransform();
Explosion* pExplosion = new Explosion;
pExplosion->setDataBlock( mDataBlock->explosionList[i] );
pExplosion->setSubstitutionData(ss_object, ss_index);
pExplosion->setDataBlock(mDataBlock->explosionList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
pExplosion->setTransform( trans );
pExplosion->setInitialState( trans.getPosition(), mInitialNormal, 1);
if (!pExplosion->registerObject())
@ -1266,12 +1388,18 @@ bool Explosion::explode()
resetWorldBox();
}
if (mDataBlock->soundProfile)
SFX->playOnce( mDataBlock->soundProfile, &getTransform() );
SFXProfile* sound_prof = dynamic_cast<SFXProfile*>(mDataBlock->soundProfile);
if (sound_prof)
{
soundProfile_clone = sound_prof->cloneAndPerformSubstitutions(ss_object, ss_index);
SFX->playOnce( soundProfile_clone, &getTransform() );
if (!soundProfile_clone->isTempClone())
soundProfile_clone = 0;
}
if (mDataBlock->particleEmitter) {
mMainEmitter = new ParticleEmitter;
mMainEmitter->setDataBlock(mDataBlock->particleEmitter);
mMainEmitter->setDataBlock(mDataBlock->particleEmitter->cloneAndPerformSubstitutions(ss_object, ss_index));
mMainEmitter->registerObject();
mMainEmitter->emitParticles(getPosition(), mInitialNormal, mDataBlock->particleRadius,
@ -1283,7 +1411,7 @@ bool Explosion::explode()
if( mDataBlock->emitterList[i] != NULL )
{
ParticleEmitter * pEmitter = new ParticleEmitter;
pEmitter->setDataBlock( mDataBlock->emitterList[i] );
pEmitter->setDataBlock(mDataBlock->emitterList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
if( !pEmitter->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );

View file

@ -20,6 +20,11 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _EXPLOSION_H_
#define _EXPLOSION_H_
@ -42,6 +47,7 @@ class TSThread;
class SFXTrack;
struct DebrisData;
class SFXProfile;
//--------------------------------------------------------------------------
class ExplosionData : public GameBaseData {
public:
@ -126,6 +132,11 @@ class ExplosionData : public GameBaseData {
static void initPersistFields();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
public:
/*C*/ ExplosionData(const ExplosionData&, bool = false);
/*D*/ ~ExplosionData();
ExplosionData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual bool allowSubstitutions() const { return true; }
};
@ -188,6 +199,12 @@ class Explosion : public GameBase, public ISceneLight
DECLARE_CONOBJECT(Explosion);
static void initPersistFields();
private:
SimObject* ss_object;
S32 ss_index;
SFXProfile* soundProfile_clone;
public:
void setSubstitutionData(SimObject* obj, S32 idx=0) { ss_object = obj; ss_index = idx; }
};
#endif // _H_EXPLOSION

View file

@ -19,6 +19,11 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "particle.h"
#include "console/consoleTypes.h"
#include "console/typeValidators.h"
@ -653,3 +658,78 @@ DefineEngineMethod(ParticleData, reload, void, (),,
char errorBuffer[256];
object->reload(errorBuffer);
}
//#define TRACK_PARTICLE_DATA_CLONES
#ifdef TRACK_PARTICLE_DATA_CLONES
static int particle_data_clones = 0;
#endif
ParticleData::ParticleData(const ParticleData& other, bool temp_clone) : SimDataBlock(other, temp_clone)
{
#ifdef TRACK_PARTICLE_DATA_CLONES
particle_data_clones++;
if (particle_data_clones == 1)
Con::errorf("ParticleData -- Clones are on the loose!");
#endif
dragCoefficient = other.dragCoefficient;
windCoefficient = other.windCoefficient;
gravityCoefficient = other.gravityCoefficient;
inheritedVelFactor = other.inheritedVelFactor;
constantAcceleration = other.constantAcceleration;
lifetimeMS = other.lifetimeMS;
lifetimeVarianceMS = other.lifetimeVarianceMS;
spinSpeed = other.spinSpeed;
spinRandomMin = other.spinRandomMin;
spinRandomMax = other.spinRandomMax;
useInvAlpha = other.useInvAlpha;
animateTexture = other.animateTexture;
numFrames = other.numFrames; // -- calc from other fields
framesPerSec = other.framesPerSec;
dMemcpy( colors, other.colors, sizeof( colors ) );
dMemcpy( sizes, other.sizes, sizeof( sizes ) );
dMemcpy( times, other.times, sizeof( times ) );
animTexUVs = other.animTexUVs; // -- calc from other fields
dMemcpy( texCoords, other.texCoords, sizeof( texCoords ) );
animTexTiling = other.animTexTiling;
animTexFramesString = other.animTexFramesString;
animTexFrames = other.animTexFrames; // -- parsed from animTexFramesString
textureName = other.textureName;
textureHandle = other.textureHandle;
spinBias = other.spinBias;
randomizeSpinDir = other.randomizeSpinDir;
textureExtName = other.textureExtName;
textureExtHandle = other.textureExtHandle;
constrain_pos = other.constrain_pos;
start_angle = other.start_angle;
angle_variance = other.angle_variance;
sizeBias = other.sizeBias;
}
ParticleData::~ParticleData()
{
if (animTexUVs)
{
delete [] animTexUVs;
}
if (!isTempClone())
return;
#ifdef TRACK_PARTICLE_DATA_CLONES
if (particle_data_clones > 0)
{
particle_data_clones--;
if (particle_data_clones == 0)
Con::errorf("ParticleData -- Clones eliminated!");
}
else
Con::errorf("ParticleData -- Too many clones deleted!");
#endif
}
void ParticleData::onPerformSubstitutions()
{
char errorBuffer[256];
reload(errorBuffer);
}

View file

@ -102,6 +102,10 @@ class ParticleData : public SimDataBlock
static void initPersistFields();
bool reload(char errorBuffer[256]);
public:
/*C*/ ParticleData(const ParticleData&, bool = false);
virtual void onPerformSubstitutions();
virtual bool allowSubstitutions() const { return true; }
public:
bool loadParameters();
bool reload(String &errorStr);

View file

@ -712,6 +712,134 @@ void ParticleEmitterData::allocPrimBuffer( S32 overrideSize )
delete [] indices;
}
//#define TRACK_PARTICLE_EMITTER_DATA_CLONES
#ifdef TRACK_PARTICLE_EMITTER_DATA_CLONES
static int emitter_data_clones = 0;
#endif
ParticleEmitterData::ParticleEmitterData(const ParticleEmitterData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
#ifdef TRACK_PARTICLE_EMITTER_DATA_CLONES
emitter_data_clones++;
if (emitter_data_clones == 1)
Con::errorf("ParticleEmitterData -- Clones are on the loose!");
#endif
ejectionPeriodMS = other.ejectionPeriodMS;
periodVarianceMS = other.periodVarianceMS;
ejectionVelocity = other.ejectionVelocity;
velocityVariance = other.velocityVariance;
ejectionOffset = other.ejectionOffset;
ejectionOffsetVariance = other.ejectionOffsetVariance;
thetaMin = other.thetaMin;
thetaMax = other.thetaMax;
phiReferenceVel = other.phiReferenceVel;
phiVariance = other.phiVariance;
softnessDistance = other.softnessDistance;
ambientFactor = other.ambientFactor;
lifetimeMS = other.lifetimeMS;
lifetimeVarianceMS = other.lifetimeVarianceMS;
overrideAdvance = other.overrideAdvance;
orientParticles = other.orientParticles;
orientOnVelocity = other.orientOnVelocity;
useEmitterSizes = other.useEmitterSizes;
useEmitterColors = other.useEmitterColors;
alignParticles = other.alignParticles;
alignDirection = other.alignDirection;
particleString = other.particleString;
particleDataBlocks = other.particleDataBlocks; // -- derived from particleString
dataBlockIds = other.dataBlockIds; // -- derived from particleString
partListInitSize = other.partListInitSize; // -- approx calc from other fields
primBuff = other.primBuff;
blendStyle = other.blendStyle;
sortParticles = other.sortParticles;
reverseOrder = other.reverseOrder;
textureName = other.textureName;
textureHandle = other.textureHandle; // -- TextureHandle loads using textureName
highResOnly = other.highResOnly;
renderReflection = other.renderReflection;
fade_color = other.fade_color;
fade_size = other.fade_size;
fade_alpha = other.fade_alpha;
ejectionInvert = other.ejectionInvert;
parts_per_eject = other.parts_per_eject; // -- set to 1 (used by subclasses)
use_emitter_xfm = other.use_emitter_xfm;
#if defined(AFX_CAP_PARTICLE_POOLS)
pool_datablock = other.pool_datablock;
pool_index = other.pool_index;
pool_depth_fade = other.pool_depth_fade;
pool_radial_fade = other.pool_radial_fade;
do_pool_id_convert = other.do_pool_id_convert; // -- flags pool id conversion need
#endif
}
ParticleEmitterData::~ParticleEmitterData()
{
if (!isTempClone())
return;
for (S32 i = 0; i < particleDataBlocks.size(); i++)
{
if (particleDataBlocks[i] && particleDataBlocks[i]->isTempClone())
{
delete particleDataBlocks[i];
particleDataBlocks[i] = 0;
}
}
#ifdef TRACK_PARTICLE_EMITTER_DATA_CLONES
if (emitter_data_clones > 0)
{
emitter_data_clones--;
if (emitter_data_clones == 0)
Con::errorf("ParticleEmitterData -- Clones eliminated!");
}
else
Con::errorf("ParticleEmitterData -- Too many clones deleted!");
#endif
}
ParticleEmitterData* ParticleEmitterData::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
{
if (!owner)
return this;
bool clone_parts_db = false;
// note -- this could be checked when the particle blocks are evaluated
for (S32 i = 0; i < this->particleDataBlocks.size(); i++)
{
if (this->particleDataBlocks[i] && (this->particleDataBlocks[i]->getSubstitutionCount() > 0))
{
clone_parts_db = true;
break;
}
}
ParticleEmitterData* sub_emitter_db = this;
if (this->getSubstitutionCount() > 0 || clone_parts_db)
{
sub_emitter_db = new ParticleEmitterData(*this, true);
performSubstitutions(sub_emitter_db, owner, index);
if (clone_parts_db)
{
for (S32 i = 0; i < sub_emitter_db->particleDataBlocks.size(); i++)
{
if (sub_emitter_db->particleDataBlocks[i] && (sub_emitter_db->particleDataBlocks[i]->getSubstitutionCount() > 0))
{
ParticleData* orig_db = sub_emitter_db->particleDataBlocks[i];
sub_emitter_db->particleDataBlocks[i] = new ParticleData(*orig_db, true);
orig_db->performSubstitutions(sub_emitter_db->particleDataBlocks[i], owner, index);
}
}
}
}
return sub_emitter_db;
}
//-----------------------------------------------------------------------------
// ParticleEmitter
@ -743,6 +871,7 @@ ParticleEmitter::ParticleEmitter()
// ParticleEmitter should be allocated on the client only.
mNetFlags.set( IsGhost );
mDataBlock = 0;
}
//-----------------------------------------------------------------------------
@ -754,6 +883,19 @@ ParticleEmitter::~ParticleEmitter()
{
delete [] part_store[i];
}
if (db_temp_clone && mDataBlock && mDataBlock->isTempClone())
{
for (S32 i = 0; i < mDataBlock->particleDataBlocks.size(); i++)
{
if (mDataBlock->particleDataBlocks[i] && mDataBlock->particleDataBlocks[i]->isTempClone())
{
delete mDataBlock->particleDataBlocks[i];
mDataBlock->particleDataBlocks[i] = 0;
}
}
delete mDataBlock;
mDataBlock = 0;
}
}
//-----------------------------------------------------------------------------
@ -832,6 +974,11 @@ bool ParticleEmitter::onNewDataBlock( GameBaseData *dptr, bool reload )
part_list_head.next = NULL;
n_parts = 0;
}
if (mDataBlock->isTempClone())
{
db_temp_clone = true;
return true;
}
scriptOnNewDataBlock();
return true;

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _H_PARTICLE_EMITTER
#define _H_PARTICLE_EMITTER
@ -113,6 +117,11 @@ class ParticleEmitterData : public GameBaseData
bool glow; ///< Renders this emitter into the glow buffer.
bool reload();
public:
/*C*/ ParticleEmitterData(const ParticleEmitterData&, bool = false);
/*D*/ ~ParticleEmitterData();
virtual ParticleEmitterData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual bool allowSubstitutions() const { return true; }
};
//*****************************************************************************

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "platform/platform.h"
#include "T3D/gameBase/gameBase.h"
#include "console/consoleTypes.h"
@ -122,6 +126,12 @@ GameBaseData::GameBaseData()
category = "";
packed = false;
}
GameBaseData::GameBaseData(const GameBaseData& other, bool temp_clone) : SimDataBlock(other, temp_clone)
{
packed = other.packed;
category = other.category;
//mReloadSignal = other.mReloadSignal; // DO NOT copy the mReloadSignal member.
}
void GameBaseData::inspectPostApply()
{
@ -290,6 +300,9 @@ bool GameBase::onNewDataBlock( GameBaseData *dptr, bool reload )
if ( !mDataBlock )
return false;
// Don't set mask when new datablock is a temp-clone.
if (mDataBlock->isTempClone())
return true;
setMaskBits(DataBlockMask);
return true;

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _GAMEBASE_H_
#define _GAMEBASE_H_
@ -113,6 +117,8 @@ public:
DECLARE_CALLBACK( void, onMount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) );
DECLARE_CALLBACK( void, onUnmount, ( SceneObject* obj, SceneObject* mountObj, S32 node ) );
/// @}
public:
GameBaseData(const GameBaseData&, bool = false);
};
//----------------------------------------------------------------------------

View file

@ -194,6 +194,40 @@ ProjectileData::ProjectileData()
lightDescId = 0;
}
ProjectileData::ProjectileData(const ProjectileData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
projectileShapeName = other.projectileShapeName;
faceViewer = other.faceViewer; // -- always set to false
scale = other.scale;
velInheritFactor = other.velInheritFactor;
muzzleVelocity = other.muzzleVelocity;
impactForce = other.impactForce;
isBallistic = other.isBallistic;
bounceElasticity = other.bounceElasticity;
bounceFriction = other.bounceFriction;
gravityMod = other.gravityMod;
lifetime = other.lifetime;
armingDelay = other.armingDelay;
fadeDelay = other.fadeDelay;
explosion = other.explosion;
explosionId = other.explosionId; // -- for pack/unpack of explosion ptr
waterExplosion = other.waterExplosion;
waterExplosionId = other.waterExplosionId; // -- for pack/unpack of waterExplosion ptr
splash = other.splash;
splashId = other.splashId; // -- for pack/unpack of splash ptr
decal = other.decal;
decalId = other.decalId; // -- for pack/unpack of decal ptr
sound = other.sound;
lightDesc = other.lightDesc;
lightDescId = other.lightDescId; // -- for pack/unpack of lightDesc ptr
projectileShape = other.projectileShape; // -- TSShape loads using projectileShapeName
activateSeq = other.activateSeq; // -- from projectileShape sequence "activate"
maintainSeq = other.maintainSeq; // -- from projectileShape sequence "maintain"
particleEmitter = other.particleEmitter;
particleEmitterId = other.particleEmitterId; // -- for pack/unpack of particleEmitter ptr
particleWaterEmitter = other.particleWaterEmitter;
particleWaterEmitterId = other.particleWaterEmitterId; // -- for pack/unpack of particleWaterEmitter ptr
}
//--------------------------------------------------------------------------
void ProjectileData::initPersistFields()
@ -585,6 +619,8 @@ Projectile::Projectile()
mLightState.clear();
mLightState.setLightInfo( mLight );
mDataBlock = 0;
}
Projectile::~Projectile()
@ -593,6 +629,11 @@ Projectile::~Projectile()
delete mProjectileShape;
mProjectileShape = NULL;
if (mDataBlock && mDataBlock->isTempClone())
{
delete mDataBlock;
mDataBlock = 0;
}
}
//--------------------------------------------------------------------------

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _PROJECTILE_H_
#define _PROJECTILE_H_
@ -144,6 +148,9 @@ public:
DECLARE_CALLBACK( void, onExplode, ( Projectile* proj, Point3F pos, F32 fade ) );
DECLARE_CALLBACK( void, onCollision, ( Projectile* proj, SceneObject* col, F32 fade, Point3F pos, Point3F normal ) );
public:
ProjectileData(const ProjectileData&, bool = false);
virtual bool allowSubstitutions() const { return true; }
};

View file

@ -200,6 +200,66 @@ ShapeBaseData::ShapeBaseData()
dMemset( mountPointNode, -1, sizeof( S32 ) * SceneObject::NumMountPoints );
}
ShapeBaseData::ShapeBaseData(const ShapeBaseData& other, bool temp_clone) : GameBaseData(other, temp_clone)
{
shadowEnable = other.shadowEnable;
shadowSize = other.shadowSize;
shadowMaxVisibleDistance = other.shadowMaxVisibleDistance;
shadowProjectionDistance = other.shadowProjectionDistance;
shadowSphereAdjust = other.shadowSphereAdjust;
shapeName = other.shapeName;
cloakTexName = other.cloakTexName;
cubeDescName = other.cubeDescName;
cubeDescId = other.cubeDescId;
reflectorDesc = other.reflectorDesc;
debris = other.debris;
debrisID = other.debrisID; // -- for pack/unpack of debris ptr
debrisShapeName = other.debrisShapeName;
debrisShape = other.debrisShape; // -- TSShape loaded using debrisShapeName
explosion = other.explosion;
explosionID = other.explosionID; // -- for pack/unpack of explosion ptr
underwaterExplosion = other.underwaterExplosion;
underwaterExplosionID = other.underwaterExplosionID; // -- for pack/unpack of underwaterExplosion ptr
mass = other.mass;
drag = other.drag;
density = other.density;
maxEnergy = other.maxEnergy;
maxDamage = other.maxDamage;
repairRate = other.repairRate;
disabledLevel = other.disabledLevel;
destroyedLevel = other.destroyedLevel;
cameraMaxDist = other.cameraMaxDist;
cameraMinDist = other.cameraMinDist;
cameraDefaultFov = other.cameraDefaultFov;
cameraMinFov = other.cameraMinFov;
cameraMaxFov = other.cameraMaxFov;
cameraCanBank = other.cameraCanBank;
mountedImagesBank = other.mountedImagesBank;
mShape = other.mShape; // -- TSShape loaded using shapeName
mCRC = other.mCRC; // -- from shape, used to verify client shape
computeCRC = other.computeCRC;
eyeNode = other.eyeNode; // -- from shape node "eye"
earNode = other.earNode; // -- from shape node "ear"
cameraNode = other.cameraNode; // -- from shape node "cam"
dMemcpy(mountPointNode, other.mountPointNode, sizeof(mountPointNode)); // -- from shape nodes "mount#" 0-31
debrisDetail = other.debrisDetail; // -- from shape detail "Debris-17"
damageSequence = other.damageSequence; // -- from shape sequence "Damage"
hulkSequence = other.hulkSequence; // -- from shape sequence "Visibility"
observeThroughObject = other.observeThroughObject;
collisionDetails = other.collisionDetails; // -- calc from shape (this is a Vector copy)
collisionBounds = other.collisionBounds; // -- calc from shape (this is a Vector copy)
LOSDetails = other.LOSDetails; // -- calc from shape (this is a Vector copy)
firstPersonOnly = other.firstPersonOnly;
useEyePoint = other.useEyePoint;
isInvincible = other.isInvincible;
renderWhenDestroyed = other.renderWhenDestroyed;
inheritEnergyFromMount = other.inheritEnergyFromMount;
remap_txr_tags = other.remap_txr_tags;
remap_buffer = other.remap_buffer;
txr_tag_remappings = other.txr_tag_remappings;
silent_bbox_check = other.silent_bbox_check;
}
struct ShapeBaseDataProto
{
F32 mass;

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _SHAPEBASE_H_
#define _SHAPEBASE_H_
@ -654,6 +658,8 @@ public:
DECLARE_CALLBACK(void, onEndSequence, (ShapeBase* obj, S32 slot, const char* name));
DECLARE_CALLBACK( void, onForceUncloak, ( ShapeBase* obj, const char* reason ) );
/// @}
public:
ShapeBaseData(const ShapeBaseData&, bool = false);
};

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "platform/platform.h"
#include "core/dnet.h"
#include "core/stream/bitStream.h"
@ -97,6 +101,14 @@ StaticShapeData::StaticShapeData()
noIndividualDamage = false;
}
StaticShapeData::StaticShapeData(const StaticShapeData& other, bool temp_clone) : ShapeBaseData(other, temp_clone)
{
noIndividualDamage = other.noIndividualDamage;
dynamicTypeField = other.dynamicTypeField;
isShielded = other.isShielded; // -- uninitialized, unused
energyPerDamagePoint = other.energyPerDamagePoint; // -- uninitialized, unused
}
void StaticShapeData::initPersistFields()
{
addField("noIndividualDamage", TypeBool, Offset(noIndividualDamage, StaticShapeData), "Deprecated\n\n @internal");

View file

@ -20,6 +20,11 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _STATICSHAPE_H_
#define _STATICSHAPE_H_
@ -38,12 +43,16 @@ struct StaticShapeData: public ShapeBaseData {
bool noIndividualDamage;
S32 dynamicTypeField;
bool isShielded;
F32 energyPerDamagePoint; // Re-added for AFX
//
DECLARE_CONOBJECT(StaticShapeData);
static void initPersistFields();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
public:
StaticShapeData(const StaticShapeData&, bool = false);
virtual bool allowSubstitutions() const { return true; }
};

View file

@ -92,12 +92,17 @@ SimObject::SimObject()
mCopySource = NULL;
mPersistentId = NULL;
is_temp_clone = false;
}
//-----------------------------------------------------------------------------
SimObject::~SimObject()
{
// if this is a temp-clone, we don't delete any members that were shallow-copied
// over from the source datablock.
if (is_temp_clone)
return;
if( mFieldDictionary )
{
delete mFieldDictionary;
@ -1327,6 +1332,43 @@ void SimObject::setDataFieldType(const char *typeName, StringTableEntry slotName
}
}
// This is the copy-constructor used to create temporary datablock clones.
// The <temp_clone> argument is added to distinguish this copy-constructor
// from any general-purpose copy-constructor that might be needed in the
// future. <temp_clone> should always be true when creating temporary
// datablock clones.
//
SimObject::SimObject(const SimObject& other, bool temp_clone)
{
is_temp_clone = temp_clone;
objectName = other.objectName;
mOriginalName = other.mOriginalName;
nextNameObject = other.nextNameObject;
nextManagerNameObject = other.nextManagerNameObject;
nextIdObject = other.nextIdObject;
mGroup = other.mGroup;
mFlags = other.mFlags;
mCopySource = other.mCopySource;
mFieldDictionary = other.mFieldDictionary;
//mIdString = other.mIdString; // special treatment (see below)
mFilename = other.mFilename;
mDeclarationLine = other.mDeclarationLine;
mNotifyList = other.mNotifyList;
mId = other.mId;
mInternalName = other.mInternalName;
mCanSaveFieldDictionary = other.mCanSaveFieldDictionary;
mPersistentId = other.mPersistentId;
mNameSpace = other.mNameSpace;
mClassName = other.mClassName;
mSuperClassName = other.mSuperClassName;
preventNameChanging = other.preventNameChanging;
if (mId)
dSprintf( mIdString, sizeof( mIdString ), "%u", mId );
else
mIdString[ 0 ] = '\0';
}
//-----------------------------------------------------------------------------
void SimObject::dumpClassHierarchy()

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _SIMOBJECT_H_
#define _SIMOBJECT_H_
@ -970,6 +974,12 @@ class SimObject: public ConsoleObject, public TamlCallbacks
// EngineObject.
virtual void destroySelf();
protected:
bool is_temp_clone;
public:
/*C*/ SimObject(const SimObject&, bool = false);
bool isTempClone() const { return is_temp_clone; }
virtual bool allowSubstitutions() const { return false; }
};

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "platform/platform.h"
#include "sfx/sfxDescription.h"
@ -176,6 +180,37 @@ SFXDescription::SFXDescription( const SFXDescription& desc )
//-----------------------------------------------------------------------------
SFXDescription::SFXDescription(const SFXDescription& other, bool temp_clone)
: SimDataBlock(other, temp_clone),
mVolume( other.mVolume ),
mPitch( other.mPitch ),
mIsLooping( other.mIsLooping ),
mIsStreaming( other.mIsStreaming ),
mIs3D( other.mIs3D ),
mUseHardware( other.mUseHardware ),
mMinDistance( other.mMinDistance ),
mMaxDistance( other.mMaxDistance ),
mConeInsideAngle( other.mConeInsideAngle ),
mConeOutsideAngle( other.mConeOutsideAngle ),
mConeOutsideVolume( other.mConeOutsideVolume ),
mRolloffFactor( other.mRolloffFactor ),
mSourceGroup( other.mSourceGroup ),
mFadeInTime( other.mFadeInTime ),
mFadeOutTime( other.mFadeOutTime ),
mFadeInEase( other.mFadeInEase ),
mFadeOutEase( other.mFadeOutEase ),
mFadeLoops( other.mFadeLoops ),
mStreamPacketSize( other.mStreamPacketSize ),
mStreamReadAhead( other.mStreamReadAhead ),
mUseReverb( other.mUseReverb ),
mReverb( other.mReverb ),
mPriority( other.mPriority ),
mScatterDistance( other.mScatterDistance )
{
for( U32 i = 0; i < MaxNumParameters; ++ i )
mParameters[ i ] = other.mParameters[ i ];
}
void SFXDescription::initPersistFields()
{
addGroup( "Playback" );

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _SFXDESCRIPTION_H_
#define _SFXDESCRIPTION_H_
@ -192,6 +196,9 @@ class SFXDescription : public SimDataBlock
/// Validates the description fixing any
/// parameters that are out of range.
void validate();
public:
SFXDescription(const SFXDescription&, bool);
virtual bool allowSubstitutions() const { return true; }
};

View file

@ -24,6 +24,7 @@
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "platform/platform.h"
#include "sfx/sfxProfile.h"
@ -96,9 +97,6 @@ SFXProfile::SFXProfile( SFXDescription* desc, const String& filename, bool prelo
//-----------------------------------------------------------------------------
SFXProfile::~SFXProfile()
{
}
//-----------------------------------------------------------------------------
@ -380,3 +378,95 @@ DefineEngineMethod( SFXProfile, getSoundDuration, F32, (),,
{
return ( F32 ) object->getSoundDuration() * 0.001f;
}
// enable this to help verify that temp-clones of AudioProfile are being deleted
//#define TRACK_AUDIO_PROFILE_CLONES
#ifdef TRACK_AUDIO_PROFILE_CLONES
static int audio_prof_clones = 0;
#endif
SFXProfile::SFXProfile(const SFXProfile& other, bool temp_clone) : SFXTrack(other, temp_clone)
{
#ifdef TRACK_AUDIO_PROFILE_CLONES
audio_prof_clones++;
if (audio_prof_clones == 1)
Con::errorf("SFXProfile -- Clones are on the loose!");
#endif
mResource = other.mResource;
mFilename = other.mFilename;
mPreload = other.mPreload;
mBuffer = other.mBuffer; // -- AudioBuffer loaded using mFilename
mChangedSignal = other.mChangedSignal;
}
SFXProfile::~SFXProfile()
{
if (!isTempClone())
return;
// cleanup after a temp-clone
if (mDescription && mDescription->isTempClone())
{
delete mDescription;
mDescription = 0;
}
#ifdef TRACK_AUDIO_PROFILE_CLONES
if (audio_prof_clones > 0)
{
audio_prof_clones--;
if (audio_prof_clones == 0)
Con::errorf("SFXProfile -- Clones eliminated!");
}
else
Con::errorf("SFXProfile -- Too many clones deleted!");
#endif
}
// Clone and perform substitutions on the SFXProfile and on any SFXDescription
// it references.
SFXProfile* SFXProfile::cloneAndPerformSubstitutions(const SimObject* owner, S32 index)
{
if (!owner)
return this;
SFXProfile* sub_profile_db = this;
// look for mDescriptionObject subs
SFXDescription* desc_db;
if (mDescription && mDescription->getSubstitutionCount() > 0)
{
SFXDescription* orig_db = mDescription;
desc_db = new SFXDescription(*orig_db, true);
orig_db->performSubstitutions(desc_db, owner, index);
}
else
desc_db = 0;
if (this->getSubstitutionCount() > 0 || desc_db)
{
sub_profile_db = new SFXProfile(*this, true);
performSubstitutions(sub_profile_db, owner, index);
if (desc_db)
sub_profile_db->mDescription = desc_db;
}
return sub_profile_db;
}
void SFXProfile::onPerformSubstitutions()
{
if ( SFX )
{
// If preload is enabled we load the resource
// and device buffer now to avoid a delay on
// first playback.
if ( mPreload && !_preloadBuffer() )
Con::errorf( "SFXProfile(%s)::onPerformSubstitutions: The preload failed!", getName() );
// We need to get device change notifications.
SFX->getEventSignal().notify( this, &SFXProfile::_onDeviceEvent );
}
}

View file

@ -20,6 +20,11 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _SFXPROFILE_H_
#define _SFXPROFILE_H_
@ -175,6 +180,11 @@ class SFXProfile : public SFXTrack
///
ChangedSignal& getChangedSignal() { return mChangedSignal; }
public:
/*C*/ SFXProfile(const SFXProfile&, bool = false);
SFXProfile* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual void onPerformSubstitutions();
virtual bool allowSubstitutions() const { return true; }
};

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#include "sfx/sfxTrack.h"
#include "sfx/sfxTypes.h"
#include "sfx/sfxDescription.h"
@ -65,6 +69,11 @@ SFXTrack::SFXTrack( SFXDescription* description )
dMemset( mParameters, 0, sizeof( mParameters ) );
}
SFXTrack::SFXTrack(const SFXTrack& other, bool temp_clone) : SimDataBlock(other, temp_clone)
{
mDescription = other.mDescription;
dMemcpy(mParameters, other.mParameters, sizeof(mParameters));
}
//-----------------------------------------------------------------------------
void SFXTrack::initPersistFields()

View file

@ -20,6 +20,10 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
#ifndef _SFXTRACK_H_
#define _SFXTRACK_H_
@ -92,6 +96,8 @@ class SFXTrack : public SimDataBlock
DECLARE_CONOBJECT( SFXTrack );
DECLARE_CATEGORY( "SFX" );
DECLARE_DESCRIPTION( "Abstract base class for any kind of data that can be turned into SFXSources." );
public:
/*C*/ SFXTrack(const SFXTrack&, bool = false);
};
#endif // !_SFXTRACK_H_