@@ -20,6 +20,16 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
// enhanced-particle -- Accounts for larger number of particle size keys.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/debris.h"

@@ -116,6 +126,87 @@ DebrisData::DebrisData()
ignoreWater = true;
}

// AFX CODE BLOCK (datablock-temp-clone) <<
//#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);
}
}
// AFX CODE BLOCK (datablock-temp-clone) >>

bool DebrisData::onAdd()
{
if(!Parent::onAdd())
@@ -272,6 +363,12 @@ void DebrisData::initPersistFields()
addField("ignoreWater", TypeBool, Offset(ignoreWater, DebrisData), "If true, this debris object will not collide with water, acting as if the water is not there.");
endGroup("Behavior");

// AFX CODE BLOCK (substitutions) <<
// disallow some field substitutions
onlyKeepClearSubstitutions("emitters"); // subs resolving to "~~", or "~0" are OK
onlyKeepClearSubstitutions("explosion");
// AFX CODE BLOCK (substitutions) >>

Parent::initPersistFields();
}

@@ -454,6 +551,11 @@ Debris::Debris()

// Only allocated client side.
mNetFlags.set( IsGhost );

// AFX CODE BLOCK (datablock-temp-clone) <<
ss_object = 0;
ss_index = 0;
// AFX CODE BLOCK (datablock-temp-clone) >>
}

Debris::~Debris()
@@ -469,6 +571,14 @@ Debris::~Debris()
delete mPart;
mPart = NULL;
}

// AFX CODE BLOCK (datablock-temp-clone) <<
if (mDataBlock && mDataBlock->isTempClone())
{
delete mDataBlock;
mDataBlock = 0;
}
// AFX CODE BLOCK (datablock-temp-clone) >>
}

void Debris::initPersistFields()
@@ -498,6 +608,11 @@ bool Debris::onNewDataBlock( GameBaseData *dptr, bool reload )
if( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
return false;

// AFX CODE BLOCK (datablock-temp-clone) <<
if (mDataBlock->isTempClone())
return true;
// AFX CODE BLOCK (datablock-temp-clone) >>

scriptOnNewDataBlock();
return true;

@@ -522,7 +637,12 @@ bool Debris::onAdd()
if( mDataBlock->emitterList[i] != NULL )
{
ParticleEmitter * pEmitter = new ParticleEmitter;
// AFX CODE BLOCK (datablock-temp-clone) <<
pEmitter->onNewDataBlock(mDataBlock->emitterList[i]->cloneAndPerformSubstitutions(ss_object, ss_index), false);
/* ORIGINAL CODE
pEmitter->onNewDataBlock( mDataBlock->emitterList[i], false );
*/
// AFX CODE BLOCK (datablock-temp-clone) >>
if( !pEmitter->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
@@ -540,7 +660,13 @@ bool Debris::onAdd()
{
sizeList[0] = mSize * 0.5;
sizeList[1] = mSize;
// AFX CODE BLOCK (enhanced-particle) <<
for (U32 i = 2; i < ParticleData::PDC_NUM_KEYS; i++)
sizeList[i] = mSize * 1.5;
/* ORIGINAL CODE
sizeList[2] = mSize * 1.5;
*/
// AFX CODE BLOCK (enhanced-particle) >>

mEmitterList[0]->setSizes( sizeList );
}
@@ -549,7 +675,13 @@ bool Debris::onAdd()
{
sizeList[0] = 0.0;
sizeList[1] = mSize * 0.5;
// AFX CODE BLOCK (enhanced-particle) <<
for (U32 i = 2; i < ParticleData::PDC_NUM_KEYS; i++)
sizeList[i] = mSize;
/* ORIGINAL CODE
sizeList[2] = mSize;
*/
// AFX CODE BLOCK (enhanced-particle) >>

mEmitterList[1]->setSizes( sizeList );
}
@@ -801,7 +933,13 @@ void Debris::explode()
Point3F explosionPos = getPosition();

Explosion* pExplosion = new Explosion;
// AFX CODE BLOCK (datablock-temp-clone) <<
pExplosion->setSubstitutionData(ss_object, ss_index);
pExplosion->onNewDataBlock(mDataBlock->explosion->cloneAndPerformSubstitutions(ss_object, ss_index), false);
/* ORIGINAL CODE
pExplosion->onNewDataBlock(mDataBlock->explosion, false);
*/
// AFX CODE BLOCK (datablock-temp-clone) >>

MatrixF trans( true );
trans.setPosition( getPosition() );
@@ -20,6 +20,15 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _DEBRIS_H_
#define _DEBRIS_H_

@@ -97,6 +106,14 @@ struct DebrisData : public GameBaseData

DECLARE_CONOBJECT(DebrisData);

// AFX CODE BLOCK (datablock-temp-clone) <<
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; }
// AFX CODE BLOCK (datablock-temp-clone) >>
};

//**************************************************************************
@@ -165,6 +182,13 @@ class Debris : public GameBase

DECLARE_CONOBJECT(Debris);

// AFX CODE BLOCK (datablock-temp-clone) <<
private:
SimObject* ss_object;
S32 ss_index;
public:
void setSubstitutionData(SimObject* obj, S32 idx=0) { ss_object = obj; ss_index = idx; }
// AFX CODE BLOCK (datablock-temp-clone) >>
};


@@ -20,6 +20,15 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/fx/explosion.h"

@@ -50,6 +59,10 @@
#include "renderInstance/renderPassManager.h"
#include "console/engineAPI.h"

// AFX CODE BLOCK (datablock-temp-clone) <<
#include "sfx/sfxProfile.h"
// AFX CODE BLOCK (datablock-temp-clone) >>

IMPLEMENT_CONOBJECT(Explosion);

ConsoleDocClass( Explosion,
@@ -281,6 +294,111 @@ ExplosionData::ExplosionData()
lightNormalOffset = 0.1f;
}

// AFX CODE BLOCK (datablock-temp-clone) <<
//#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
// NOT REFERENCED BY Explosion...
shockwave = other.shockwave; // -- unused
shockwaveID = other.shockwaveID; // -- unused
shockwaveOnTerrain = other.shockwaveOnTerrain; // -- unused
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;
}
// AFX CODE BLOCK (datablock-temp-clone) >>

void ExplosionData::initPersistFields()
{
addField( "explosionShape", TypeShapeFilename, Offset(dtsFileName, ExplosionData),
@@ -412,6 +530,15 @@ void ExplosionData::initPersistFields()
"Distance (in the explosion normal direction) of the PointLight position "
"from the explosion center." );

// AFX CODE BLOCK (substitutions) <<
// disallow some field substitutions
onlyKeepClearSubstitutions("debris"); // subs resolving to "~~", or "~0" are OK
onlyKeepClearSubstitutions("emitter");
onlyKeepClearSubstitutions("particleEmitter");
onlyKeepClearSubstitutions("soundProfile");
onlyKeepClearSubstitutions("subExplosion");
// AFX CODE BLOCK (substitutions) >>

Parent::initPersistFields();
}

@@ -808,6 +935,13 @@ Explosion::Explosion()
mLight = LIGHTMGR->createLightInfo();

mNetFlags.set( IsGhost );

// AFX CODE BLOCK (datablock-temp-clone) <<
ss_object = 0;
ss_index = 0;
mDataBlock = 0;
soundProfile_clone = 0;
// AFX CODE BLOCK (datablock-temp-clone) >>
}

Explosion::~Explosion()
@@ -820,6 +954,20 @@ Explosion::~Explosion()
}

SAFE_DELETE(mLight);

// AFX CODE BLOCK (datablock-temp-clone) <<
if (soundProfile_clone)
{
delete soundProfile_clone;
soundProfile_clone = 0;
}

if (mDataBlock && mDataBlock->isTempClone())
{
delete mDataBlock;
mDataBlock = 0;
}
// AFX CODE BLOCK (datablock-temp-clone) >>
}


@@ -978,6 +1126,11 @@ bool Explosion::onNewDataBlock( GameBaseData *dptr, bool reload )
if (!mDataBlock || !Parent::onNewDataBlock( dptr, reload ))
return false;

// AFX CODE BLOCK (datablock-temp-clone) <<
if (mDataBlock->isTempClone())
return true;
// AFX CODE BLOCK (datablock-temp-clone) >>

scriptOnNewDataBlock();
return true;
}
@@ -1190,7 +1343,13 @@ void Explosion::launchDebris( Point3F &axis )
launchDir *= debrisVel;

Debris *debris = new Debris;
// AFX CODE BLOCK (datablock-temp-clone) <<
debris->setSubstitutionData(ss_object, ss_index);
debris->setDataBlock(mDataBlock->debrisList[0]->cloneAndPerformSubstitutions(ss_object, ss_index));
/* ORIGINAL CODE
debris->setDataBlock( mDataBlock->debrisList[0] );
*/
// AFX CODE BLOCK (datablock-temp-clone) >>
debris->setTransform( getTransform() );
debris->init( pos, launchDir );

@@ -1218,7 +1377,13 @@ void Explosion::spawnSubExplosions()
{
MatrixF trans = getTransform();
Explosion* pExplosion = new Explosion;
// AFX CODE BLOCK (datablock-temp-clone) <<
pExplosion->setSubstitutionData(ss_object, ss_index);
pExplosion->setDataBlock(mDataBlock->explosionList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
/* ORIGINAL CODE
pExplosion->setDataBlock( mDataBlock->explosionList[i] );
*/
// AFX CODE BLOCK (datablock-temp-clone) >>
pExplosion->setTransform( trans );
pExplosion->setInitialState( trans.getPosition(), mInitialNormal, 1);
if (!pExplosion->registerObject())
@@ -1256,12 +1421,29 @@ bool Explosion::explode()
resetWorldBox();
}

// AFX CODE BLOCK (datablock-temp-clone) <<
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;
}
/* ORIGINAL CODE
if (mDataBlock->soundProfile)
SFX->playOnce( mDataBlock->soundProfile, &getTransform() );
*/
// AFX CODE BLOCK (datablock-temp-clone) >>

if (mDataBlock->particleEmitter) {
mMainEmitter = new ParticleEmitter;
// AFX CODE BLOCK (datablock-temp-clone) <<
mMainEmitter->setDataBlock(mDataBlock->particleEmitter->cloneAndPerformSubstitutions(ss_object, ss_index));
/* ORIGINAL CODE
mMainEmitter->setDataBlock(mDataBlock->particleEmitter);
*/
// AFX CODE BLOCK (datablock-temp-clone) >>
mMainEmitter->registerObject();

mMainEmitter->emitParticles(getPosition(), mInitialNormal, mDataBlock->particleRadius,
@@ -1273,7 +1455,12 @@ bool Explosion::explode()
if( mDataBlock->emitterList[i] != NULL )
{
ParticleEmitter * pEmitter = new ParticleEmitter;
// AFX CODE BLOCK (datablock-temp-clone) <<
pEmitter->setDataBlock(mDataBlock->emitterList[i]->cloneAndPerformSubstitutions(ss_object, ss_index));
/* ORIGINAL CODE
pEmitter->setDataBlock( mDataBlock->emitterList[i] );
*/
// AFX CODE BLOCK (datablock-temp-clone) >>
if( !pEmitter->registerObject() )
{
Con::warnf( ConsoleLogEntry::General, "Could not register emitter for particle of class: %s", mDataBlock->getName() );
@@ -20,6 +20,15 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _EXPLOSION_H_
#define _EXPLOSION_H_

@@ -42,6 +51,10 @@ class TSThread;
class SFXTrack;
struct DebrisData;

// AFX CODE BLOCK (datablock-temp-clone) <<
class SFXProfile;
// AFX CODE BLOCK (datablock-temp-clone) >>

//--------------------------------------------------------------------------
class ExplosionData : public GameBaseData {
public:
@@ -126,6 +139,13 @@ class ExplosionData : public GameBaseData {
static void initPersistFields();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
// AFX CODE BLOCK (datablock-temp-clone) <<
public:
/*C*/ ExplosionData(const ExplosionData&, bool = false);
/*D*/ ~ExplosionData();
ExplosionData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual bool allowSubstitutions() const { return true; }
// AFX CODE BLOCK (datablock-temp-clone) >>
};


@@ -188,6 +208,15 @@ class Explosion : public GameBase, public ISceneLight

DECLARE_CONOBJECT(Explosion);
static void initPersistFields();

// AFX CODE BLOCK (datablock-temp-clone) <<
private:
SimObject* ss_object;
S32 ss_index;
SFXProfile* soundProfile_clone;
public:
void setSubstitutionData(SimObject* obj, S32 idx=0) { ss_object = obj; ss_index = idx; }
// AFX CODE BLOCK (datablock-temp-clone) >>
};

#endif // _H_EXPLOSION
@@ -43,6 +43,17 @@
// POTENTIAL TODO LIST:
// TODO: Clamp item alpha to fog alpha

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// ground-cover -- Adds an ambient modulation bias to control how much the foliage
// images are modulated by the sun's ambient light setting.
// full modulation -- 1.0 (default)
// no modulation -- 0.0
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/fx/fxFoliageReplicator.h"

@@ -403,6 +414,12 @@ void fxFoliageReplicator::initPersistFields()
addField( "AllowedTerrainSlope", TypeS32, Offset( mFieldData.mAllowedTerrainSlope, fxFoliageReplicator ), "Maximum surface angle allowed for foliage instances." );
endGroup( "Restrictions" ); // MM: Added Group Footer.

// AFX CODE BLOCK (ground-cover) <<
addGroup( "AFX" );
addField( "AmbientModulationBias", TypeF32, Offset( mFieldData.mAmbientModulationBias,fxFoliageReplicator ), "Multiplier controling amount foliage is modulated by sun's ambient." );
endGroup( "AFX" );
// AFX CODE BLOCK (ground-cover) >>

// Initialise parents' persistent fields.
Parent::initPersistFields();
}
@@ -1565,7 +1582,17 @@ void fxFoliageReplicator::renderObject(ObjectRenderInst *ri, SceneRenderState *s
mFoliageShaderConsts->setSafe(mFoliageShaderGroundAlphaSC, Point4F(mFieldData.mGroundAlpha, mFieldData.mGroundAlpha, mFieldData.mGroundAlpha, mFieldData.mGroundAlpha));
if (mFoliageShaderAmbientColorSC->isValid())
// AFX CODE BLOCK (ground-cover) <<
{
ColorF ambient = state->getAmbientLightColor();
ColorF ambient_inv(1.0f-ambient.red, 1.0f-ambient.green, 1.0f-ambient.blue, 0.0f);
ambient += ambient_inv*(1.0f - mFieldData.mAmbientModulationBias);
mFoliageShaderConsts->set(mFoliageShaderAmbientColorSC, ambient);
}
/* ORIGINAL CODE
mFoliageShaderConsts->set(mFoliageShaderAmbientColorSC, state->getAmbientLightColor());
*/
// AFX CODE BLOCK (ground-cover) >>
GFX->setShaderConstBuffer(mFoliageShaderConsts);
@@ -1706,6 +1733,9 @@ U32 fxFoliageReplicator::packUpdate(NetConnection * con, U32 mask, BitStream * s
stream->writeFlag(mFieldData.mShowPlacementArea); // Show Placement Area Flag.
stream->write(mFieldData.mPlacementBandHeight); // Placement Area Height.
stream->write(mFieldData.mPlaceAreaColour); // Placement Area Colour.
// AFX CODE BLOCK (ground-cover) <<
stream->write(mFieldData.mAmbientModulationBias);
// AFX CODE BLOCK (ground-cover) >>
}
// Were done ...
@@ -1783,6 +1813,10 @@ void fxFoliageReplicator::unpackUpdate(NetConnection * con, BitStream * stream)
stream->read(&mFieldData.mPlacementBandHeight); // Placement Area Height.
stream->read(&mFieldData.mPlaceAreaColour);
// AFX CODE BLOCK (ground-cover) <<
stream->read(&mFieldData.mAmbientModulationBias);
// AFX CODE BLOCK (ground-cover) >>
// Calculate Fade-In/Out Gradients.
mFadeInGradient = 1.0f / mFieldData.mFadeInRegion;
mFadeOutGradient = 1.0f / mFieldData.mFadeOutRegion;
@@ -20,6 +20,17 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// ground-cover -- Adds an ambient modulation bias to control how much the foliage
// images are modulated by the sun's ambient light setting.
// full modulation -- 1.0 (default)
// no modulation -- 0.0
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _FOLIAGEREPLICATOR_H_
#define _FOLIAGEREPLICATOR_H_

@@ -319,6 +330,10 @@ class fxFoliageReplicator : public SceneObject
U32 mPlacementBandHeight;
ColorF mPlaceAreaColour;

// AFX CODE BLOCK (ground-cover) <<
F32 mAmbientModulationBias;
// AFX CODE BLOCK (ground-cover) >>

tagFieldData()
{
// Set Defaults.
@@ -377,6 +392,10 @@ class fxFoliageReplicator : public SceneObject
mShowPlacementArea = true;
mPlacementBandHeight = 25;
mPlaceAreaColour .set(0.4f, 0, 0.8f);

// AFX CODE BLOCK (ground-cover) <<
mAmbientModulationBias = 1.0f;
// AFX CODE BLOCK (ground-cover) >>
}

} mFieldData;

Large diffs are not rendered by default.

@@ -20,6 +20,16 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// enhanced-particle -- increased keys to 8 and other mods.
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _PARTICLE_H_
#define _PARTICLE_H_

@@ -44,7 +54,14 @@ class ParticleData : public SimDataBlock
public:
enum PDConst
{
// AFX CODE BLOCK (enhanced-particle) <<
// This increase the keyframes from 4 to 8. Especially useful for premult-alpha blended particles
// for which 4 keyframes is often not enough.
PDC_NUM_KEYS = 8,
/* ORIGINAL CODE
PDC_NUM_KEYS = 4,
*/
// AFX CODE BLOCK (enhanced-particle) >>
};

F32 dragCoefficient;
@@ -97,6 +114,35 @@ class ParticleData : public SimDataBlock
static void initPersistFields();

bool reload(char errorBuffer[256]);

// AFX CODE BLOCK (datablock-temp-clone) <<
public:
/*C*/ ParticleData(const ParticleData&, bool = false);
virtual void onPerformSubstitutions();
virtual bool allowSubstitutions() const { return true; }
// AFX CODE BLOCK (datablock-temp-clone) >>

// AFX CODE BLOCK (enhanced-particle) <<
protected:
F32 spinBias;
bool randomizeSpinDir;
StringTableEntry textureExtName;
public:
GFXTexHandle textureExtHandle;
bool constrain_pos;
F32 start_angle;
F32 angle_variance;
F32 sizeBias;
// AFX CODE BLOCK (enhanced-particle) >>

// AFX CODE BLOCK (misc) >>
public:
bool loadParameters();
bool reload(String &errorStr);
/* ORIGINAL CODE
bool reload(char errorBuffer[256]);
*/
// AFX CODE BLOCK (misc) >>
};

//*****************************************************************************
@@ -123,6 +169,13 @@ struct Particle

F32 spinSpeed;
Particle * next;

// AFX CODE BLOCK (enhanced-particle) <<
Point3F pos_local;
F32 t_last;
Point3F radial_v; // radial vector for concentric effects
// note -- for non-oriented particles, we use orientDir.x to store the billboard start angle.
// AFX CODE BLOCK (enhanced-particle) >>
};


Large diffs are not rendered by default.

@@ -20,6 +20,16 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// enhanced-emitter -- numerous enhancements to ParticleEmitter class.
// pooled-particles -- optional support for pooled particles which combines
// multiple emitters in a common sorting pool.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _H_PARTICLE_EMITTER
#define _H_PARTICLE_EMITTER

@@ -46,6 +56,14 @@
class RenderPassManager;
class ParticleData;

// AFX CODE BLOCK (pooled-particles) <<
#define AFX_CAP_PARTICLE_POOLS
#if defined(AFX_CAP_PARTICLE_POOLS)
class afxParticlePoolData;
class afxParticlePool;
#endif
// AFX CODE BLOCK (pooled-particles) >>

//*****************************************************************************
// Particle Emitter Data
//*****************************************************************************
@@ -117,6 +135,33 @@ class ParticleEmitterData : public GameBaseData
bool glow; ///< Renders this emitter into the glow buffer.

bool reload();

// AFX CODE BLOCK (enhanced-emitter) <<
public:
bool fade_color;
bool fade_size;
bool fade_alpha;
bool ejectionInvert;
U8 parts_per_eject;
bool use_emitter_xfm;
// AFX CODE BLOCK (enhanced-emitter) >>

#if defined(AFX_CAP_PARTICLE_POOLS) // AFX CODE BLOCK (pooled-particles) <<
public:
afxParticlePoolData* pool_datablock;
U32 pool_index;
bool pool_depth_fade;
bool pool_radial_fade;
bool do_pool_id_convert;
#endif // AFX CODE BLOCK (pooled-particles) >>

// AFX CODE BLOCK (datablock-temp-clone) <<
public:
/*C*/ ParticleEmitterData(const ParticleEmitterData&, bool = false);
/*D*/ ~ParticleEmitterData();
virtual ParticleEmitterData* cloneAndPerformSubstitutions(const SimObject*, S32 index=0);
virtual bool allowSubstitutions() const { return true; }
// AFX CODE BLOCK (datablock-temp-clone) >>
};

//*****************************************************************************
@@ -125,6 +170,10 @@ class ParticleEmitterData : public GameBaseData
class ParticleEmitter : public GameBase
{
typedef GameBase Parent;
#if defined(AFX_CAP_PARTICLE_POOLS) // AFX CODE BLOCK (pooled-particles) <<
friend class afxParticlePool;
#endif // AFX CODE BLOCK (pooled-particles) >>


public:

@@ -198,8 +247,12 @@ class ParticleEmitter : public GameBase
/// @param axis
/// @param vel Initial velocity
/// @param axisx
// AFX CODE BLOCK (enhanced-emitter) <<
void addParticle(const Point3F &pos, const Point3F &axis, const Point3F &vel, const Point3F &axisx, const U32 age_offset);
/* ORIGINAL CODE
void addParticle(const Point3F &pos, const Point3F &axis, const Point3F &vel, const Point3F &axisx);

*/
// AFX CODE BLOCK (enhanced-emitter) >>

inline void setupBillboard( Particle *part,
Point3F *basePts,
@@ -235,7 +288,13 @@ class ParticleEmitter : public GameBase
// PEngine interface
private:

// AFX CODE BLOCK (enhanced-emitter) <<
// AFX subclasses to ParticleEmitter require access to some members and methods of
// ParticleEmitter which are normally declared with private scope. In this section,
// protected and private scope statements have been inserted inline with the original
// code to expose the necessary members and methods.
void update( U32 ms );
protected: // AFX CODE INSERT
inline void updateKeyData( Particle *part );


@@ -247,20 +306,24 @@ class ParticleEmitter : public GameBase

ParticleEmitterData* mDataBlock;

protected: // AFX CODE INSERT
U32 mInternalClock;

U32 mNextParticleTime;

Point3F mLastPosition;
bool mHasLastPosition;
private: // AFX CODE INSERT
MatrixF mBBObjToWorld;

bool mDeleteWhenEmpty;
bool mDeleteOnTick;

protected: // AFX CODE INSERT
S32 mLifetimeMS;
S32 mElapsedTimeMS;

private: // AFX CODE INSERT
F32 sizes[ ParticleData::PDC_NUM_KEYS ];
ColorF colors[ ParticleData::PDC_NUM_KEYS ];

@@ -270,6 +333,7 @@ class ParticleEmitter : public GameBase
GFXVertexBufferHandle<ParticleVertexType> mVertBuff;
#endif

protected: // AFX CODE INSERT
// These members are for implementing a link-list of the active emitter
// particles. Member part_store contains blocks of particles that can be
// chained in a link-list. Usually the first part_store block is large
@@ -280,8 +344,30 @@ class ParticleEmitter : public GameBase
Particle part_list_head;
S32 n_part_capacity;
S32 n_parts;
private: // AFX CODE INSERT
S32 mCurBuffSize;

// AFX CODE BLOCK (enhanced-emitter) >>
// AFX CODE BLOCK (enhanced-emitter) <<
protected:
F32 fade_amt;
bool forced_bbox;
bool db_temp_clone;
Point3F pos_pe;
S8 sort_priority;
virtual void sub_particleUpdate(Particle*) { }
public:
virtual void emitParticlesExt(const MatrixF& xfm, const Point3F& point, const Point3F& velocity, const U32 numMilliseconds);
void setFadeAmount(F32 amt) { fade_amt = amt; }
void setForcedObjBox(Box3F& box);
void setSortPriority(S8 priority);
#if defined(AFX_CAP_PARTICLE_POOLS)
protected:
afxParticlePool* pool;
public:
void clearPool() { pool = 0; }
void setPool(afxParticlePool* p) { pool = p; }
#endif
// AFX CODE BLOCK (enhanced-emitter) >>
};

#endif // _H_PARTICLE_EMITTER
@@ -20,6 +20,17 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// scope-tracking -- changes related to the tracking of AFX constraint objects as
// they move in and out of scope.
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/gameBase/gameBase.h"
#include "console/consoleTypes.h"
@@ -36,6 +47,10 @@
#include "T3D/aiConnection.h"
#endif

// AFX CODE BLOCK (scope-tracking) <<
#include "afx/arcaneFX.h"
// AFX CODE BLOCK (scope-tracking) >>

//----------------------------------------------------------------------------
// Ghost update relative priority values

@@ -123,6 +138,15 @@ GameBaseData::GameBaseData()
packed = false;
}

// AFX CODE BLOCK (datablock-temp-clone) <<
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.
}
// AFX CODE BLOCK (datablock-temp-clone) >>

void GameBaseData::inspectPostApply()
{
Parent::inspectPostApply();
@@ -244,6 +268,10 @@ GameBase::GameBase()

GameBase::~GameBase()
{
// AFX CODE BLOCK (scope-tracking) <<
if (scope_registered)
arcaneFX::unregisterScopedObject(this);
// AFX CODE BLOCK (scope-tracking) >>
}


@@ -256,8 +284,23 @@ bool GameBase::onAdd()

// Datablock must be initialized on the server.
// Client datablock are initialized by the initial update.

// AFX CODE BLOCK (scope-tracking) <<
if (isClientObject())
{
if (scope_id > 0 && !scope_registered)
arcaneFX::registerScopedObject(this);
}
else
{
if ( mDataBlock && !onNewDataBlock( mDataBlock, false ) )
return false;
}
/* ORIGINAL CODE
if ( isServerObject() && mDataBlock && !onNewDataBlock( mDataBlock, false ) )
return false;
*/
// AFX CODE BLOCK (scope-tracking) >>

setProcessTick( true );

@@ -266,6 +309,11 @@ bool GameBase::onAdd()

void GameBase::onRemove()
{
// AFX CODE BLOCK (scope-tracking) <<
if (scope_registered)
arcaneFX::unregisterScopedObject(this);
// AFX CODE BLOCK (scope-tracking) >>

// EDITOR FEATURE: Remove us from the reload signal of our datablock.
if ( mDataBlock )
mDataBlock->mReloadSignal.remove( this, &GameBase::_onDatablockModified );
@@ -291,6 +339,12 @@ bool GameBase::onNewDataBlock( GameBaseData *dptr, bool reload )
if ( !mDataBlock )
return false;

// AFX CODE BLOCK (datablock-temp-clone) <<
// Don't set mask when new datablock is a temp-clone.
if (mDataBlock->isTempClone())
return true;
// AFX CODE BLOCK (datablock-temp-clone) >>

setMaskBits(DataBlockMask);
return true;
}
@@ -543,6 +597,14 @@ U32 GameBase::packUpdate( NetConnection *connection, U32 mask, BitStream *stream
stream->writeFlag(mIsAiControlled);
#endif

// AFX CODE BLOCK (scope-tracking) <<
if (stream->writeFlag(mask & ScopeIdMask))
{
if (stream->writeFlag(scope_refs > 0))
stream->writeInt(scope_id, SCOPE_ID_BITS);
}
// AFX CODE BLOCK (scope-tracking) >>

return retMask;
}

@@ -581,6 +643,14 @@ void GameBase::unpackUpdate(NetConnection *con, BitStream *stream)
mTicksSinceLastMove = 0;
mIsAiControlled = stream->readFlag();
#endif

// AFX CODE BLOCK (scope-tracking) <<
if (stream->readFlag())
{
scope_id = (stream->readFlag()) ? (U16) stream->readInt(SCOPE_ID_BITS) : 0;
scope_refs = 0;
}
// AFX CODE BLOCK (scope-tracking) >>
}

void GameBase::onMount( SceneObject *obj, S32 node )
@@ -20,6 +20,17 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// scope-tracking -- changes related to the tracking of AFX constraint objects as
// they move in and out of scope.
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _GAMEBASE_H_
#define _GAMEBASE_H_

@@ -110,6 +121,11 @@ struct GameBaseData : public SimDataBlock
DECLARE_CALLBACK( void, onMount, ( GameBase* obj, SceneObject* mountObj, S32 node ) );
DECLARE_CALLBACK( void, onUnmount, ( GameBase* obj, SceneObject* mountObj, S32 node ) );
/// @}

// AFX CODE BLOCK (datablock-temp-clone) <<
public:
GameBaseData(const GameBaseData&, bool = false);
// AFX CODE BLOCK (datablock-temp-clone) >>
};

//----------------------------------------------------------------------------
@@ -226,7 +242,13 @@ class GameBase : public SceneObject
enum GameBaseMasks {
DataBlockMask = Parent::NextFreeMask << 0,
ExtendedInfoMask = Parent::NextFreeMask << 1,
// AFX CODE BLOCK (scope-tracking) <<
ScopeIdMask = Parent::NextFreeMask << 2,
NextFreeMask = Parent::NextFreeMask << 3,
/* ORIGINAL CODE
NextFreeMask = Parent::NextFreeMask << 2
*/
// AFX CODE BLOCK (scope-tracking) >>
};

// net flags added by game base
@@ -449,6 +471,11 @@ class GameBase : public SceneObject
/// within this callback.
///
void _onDatablockModified();

// AFX CODE BLOCK (scope-tracking) <<
protected:
void onScopeIdChange() { setMaskBits(ScopeIdMask); }
// AFX CODE BLOCK (scope-tracking) >>
};


Large diffs are not rendered by default.

@@ -20,6 +20,17 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// db-cache -- implementation of datablock caching system.
// obj-select -- implementation of object selection used for spell targeting.
// zoned-in -- connection is flagged as "zoned-in" when client is fully
// connected and user can interact with it.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _GAMECONNECTION_H_
#define _GAMECONNECTION_H_

@@ -57,6 +68,18 @@ struct AuthInfo;

#define GameString TORQUE_APP_NAME

// AFX CODE BLOCK (db-cache) <<
//
// To disable datablock caching, remove or comment out the AFX_CAP_DATABLOCK_CACHE define below.
// Also, at a minimum, the following script preferences should be set to false:
// $pref::Client::EnableDatablockCache = false; (in arcane.fx/client/defaults.cs)
// $Pref::Server::EnableDatablockCache = false; (in arcane.fx/server/defaults.cs)
// Alternatively, all script code marked with "DATABLOCK CACHE CODE" can be removed or
// commented out.
//
#define AFX_CAP_DATABLOCK_CACHE
// AFX CODE BLOCK (db-cache) >>

const F32 MinCameraFov = 1.f; ///< min camera FOV
const F32 MaxCameraFov = 179.f; ///< max camera FOV

@@ -366,6 +389,62 @@ class GameConnection : public NetConnection
DECLARE_CALLBACK( void, setLagIcon, (bool state) );
DECLARE_CALLBACK( void, onDataBlocksDone, (U32 sequence) );
DECLARE_CALLBACK( void, onFlash, (bool state) );

// AFX CODE BLOCK (obj-select)(zoned-in) <<
// GameConnection is modified to keep track of object selections which are used in
// spell targeting. This code stores the current object selection as well as the
// current rollover object beneath the cursor. The rollover object is treated as a
// pending object selection and actual object selection is usually made by promoting
// the rollover object to the current object selection.
private:
SimObjectPtr<SceneObject> mRolloverObj;
SimObjectPtr<SceneObject> mPreSelectedObj;
SimObjectPtr<SceneObject> mSelectedObj;
bool mChangedSelectedObj;
U32 mPreSelectTimestamp;
protected:
virtual void onDeleteNotify(SimObject*);
public:
void setRolloverObj(SceneObject*);
SceneObject* getRolloverObj() { return mRolloverObj; }
void setSelectedObj(SceneObject*, bool propagate_to_client=false);
SceneObject* getSelectedObj() { return mSelectedObj; }
void setPreSelectedObjFromRollover();
void clearPreSelectedObj();
void setSelectedObjFromPreSelected();
// Flag is added to indicate when a client is fully connected or "zoned-in".
// This information determines when AFX will startup active effects on a newly
// added client.
private:
bool zoned_in;
public:
bool isZonedIn() const { return zoned_in; }
void setZonedIn() { zoned_in = true; }
// AFX CODE BLOCK (obj-select)(zoned-in) >>
#ifdef AFX_CAP_DATABLOCK_CACHE // AFX CODE BLOCK (db-cache) <<
private:
static StringTableEntry server_cache_filename;
static StringTableEntry client_cache_filename;
static bool server_cache_on;
static bool client_cache_on;
BitStream* client_db_stream;
U32 server_cache_CRC;
public:
void repackClientDatablock(BitStream*, S32 start_pos);
void saveDatablockCache(bool on_server);
void loadDatablockCache();
bool loadDatablockCache_Begin();
bool loadDatablockCache_Continue();
void tempDisableStringBuffering(BitStream* bs) const;
void restoreStringBuffering(BitStream* bs) const;
void setServerCacheCRC(U32 crc) { server_cache_CRC = crc; }

static void resetDatablockCache();
static bool serverCacheEnabled() { return server_cache_on; }
static bool clientCacheEnabled() { return client_cache_on; }
static const char* serverCacheFilename() { return server_cache_filename; }
static const char* clientCacheFilename() { return client_cache_filename; }
#endif // AFX CODE BLOCK (db-cache) >>
};

#endif
@@ -20,6 +20,14 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// db-cache -- implementation of datablock caching system.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "core/dnet.h"
#include "core/stream/bitStream.h"
@@ -136,6 +144,9 @@ void SimDataBlockEvent::notifyDelivered(NetConnection *conn, bool )

void SimDataBlockEvent::pack(NetConnection *conn, BitStream *bstream)
{
#ifdef AFX_CAP_DATABLOCK_CACHE // AFX CODE BLOCK (db-cache) <<
((GameConnection *)conn)->tempDisableStringBuffering(bstream);
#endif // AFX CODE BLOCK (db-cache) >>
SimDataBlock* obj;
Sim::findObject(id,obj);
GameConnection *gc = (GameConnection *) conn;
@@ -157,10 +168,18 @@ void SimDataBlockEvent::pack(NetConnection *conn, BitStream *bstream)
bstream->writeInt(classId ^ DebugChecksum, 32);
#endif
}
#ifdef AFX_CAP_DATABLOCK_CACHE // AFX CODE BLOCK (db-cache) <<
((GameConnection *)conn)->restoreStringBuffering(bstream);
#endif // AFX CODE BLOCK (db-cache) >>
}

void SimDataBlockEvent::unpack(NetConnection *cptr, BitStream *bstream)
{
#ifdef AFX_CAP_DATABLOCK_CACHE // AFX CODE BLOCK (db-cache) <<
// stash the stream position prior to unpacking
S32 start_pos = bstream->getCurPos();
((GameConnection *)cptr)->tempDisableStringBuffering(bstream);
#endif // AFX CODE BLOCK (db-cache) >>
if(bstream->readFlag())
{
mProcess = true;
@@ -215,6 +234,11 @@ void SimDataBlockEvent::unpack(NetConnection *cptr, BitStream *bstream)
#endif

}
#ifdef AFX_CAP_DATABLOCK_CACHE // AFX CODE BLOCK (db-cache) <<
// rewind to stream position and then process raw bytes for caching
((GameConnection *)cptr)->repackClientDatablock(bstream, start_pos);
((GameConnection *)cptr)->restoreStringBuffering(bstream);
#endif // AFX CODE BLOCK (db-cache) >>
}

void SimDataBlockEvent::write(NetConnection *cptr, BitStream *bstream)
@@ -20,6 +20,14 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// process-order -- code to help positioning of objects in the process lists.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/gameBase/processList.h"

@@ -273,5 +281,22 @@ void ProcessList::advanceObjects()
PROFILE_END();
}

// AFX CODE BLOCK (process-order) <<
ProcessObject* ProcessList::findNearestToEnd(Vector<ProcessObject*>& objs) const
{
if (objs.empty())
return 0;

for (ProcessObject* obj = mHead.mProcessLink.prev; obj != &mHead; obj = obj->mProcessLink.prev)
{
for (S32 i = 0; i < objs.size(); i++)
{
if (obj == objs[i])
return obj;
}
}

return 0;
}
// AFX CODE BLOCK (process-order) >>

@@ -20,6 +20,14 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// process-order -- code to help positioning of objects in the process lists.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _PROCESSLIST_H_
#define _PROCESSLIST_H_

@@ -188,6 +196,12 @@ class ProcessList

PreTickSignal mPreTick;
PostTickSignal mPostTick;

// AFX CODE BLOCK (process-order) <<
// JTF: still needed?
public:
ProcessObject* findNearestToEnd(Vector<ProcessObject*>& objs) const;
// AFX CODE BLOCK (process-order) >>
};

#endif // _PROCESSLIST_H_
@@ -20,6 +20,15 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// groundplane-zodiacs -- groundPlane customizations for rendering zodiacs on them.
// special-types -- defines type bits for interior-like and terrain-like types.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/groundPlane.h"

@@ -40,6 +49,9 @@
#include "T3D/physics/physicsBody.h"
#include "T3D/physics/physicsCollision.h"

// AFX CODE BLOCK (groundplane-zodiacs) <<
#include "afx/ce/afxZodiacMgr.h"
// AFX CODE BLOCK (groundplane-zodiacs) >>

/// Minimum square size allowed. This is a cheap way to limit the amount
/// of geometry possibly generated by the GroundPlane (vertex buffers have a
@@ -77,6 +89,10 @@ GroundPlane::GroundPlane()
mNetFlags.set( Ghostable | ScopeAlways );

mConvexList = new Convex;

// AFX CODE BLOCK (special-types) <<
mTypeMask |= TerrainLikeObjectType;
// AFX CODE BLOCK (special-types) >>
}

GroundPlane::~GroundPlane()
@@ -356,6 +372,10 @@ void GroundPlane::prepRenderImage( SceneRenderState* state )
if( mVertexBuffer.isNull() )
return;

// AFX CODE BLOCK (groundplane-zodiacs) <<
afxZodiacMgr::renderGroundPlaneZodiacs(state, this);
// AFX CODE BLOCK (groundplane-zodiacs) >>

// Add a render instance.

RenderPassManager* pass = state->getRenderPass();
@@ -20,6 +20,14 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// localRenderViz -- Implements per-light renderViz setting.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/lightBase.h"

@@ -71,6 +79,10 @@ LightBase::LightBase()
mLight = LightManager::createLightInfo();

mFlareState.clear();

// AFX CODE BLOCK (localRenderViz) <<
mLocalRenderViz = false;
// AFX CODE BLOCK (localRenderViz) >>
}

LightBase::~LightBase()
@@ -202,7 +214,12 @@ void LightBase::prepRenderImage( SceneRenderState *state )

// If the light is selected or light visualization
// is enabled then register the callback.
// AFX CODE BLOCK (localRenderViz) <<
if ( mLocalRenderViz || smRenderViz || isSelectedInEditor )
/* ORIGINAL CODE
if ( smRenderViz || isSelectedInEditor )
*/
// AFX CODE BLOCK (localRenderViz) >>
{
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
ri->renderDelegate.bind( this, &LightBase::_onRenderViz );
@@ -20,6 +20,14 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// localRenderViz -- Implements per-light renderViz setting.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _LIGHTBASE_H_
#define _LIGHTBASE_H_

@@ -131,6 +139,11 @@ class LightBase : public SceneObject, public ISceneLight, public virtual ITickab
virtual void pauseAnimation( void );
virtual void playAnimation( void );
virtual void playAnimation( LightAnimData *animData );

// AFX CODE BLOCK (localRenderViz) <<
protected:
bool mLocalRenderViz;
// AFX CODE BLOCK (localRenderViz) >>
};

#endif // _LIGHTBASE_H_
@@ -20,11 +20,26 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// afxModel-type -- defines a type bit for afxModel objects.
// special-types -- defines type bits for interior-like and terrain-like types.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _OBJECTTYPES_H_
#define _OBJECTTYPES_H_

#include "platform/types.h"

// AFX CODE BLOCK (afxModel-type) <<
// Uncomment the AFX_CAP_AFXMODEL_TYPE define below to enable a type flag
// for afxModel objects.
//#define AFX_CAP_AFXMODEL_TYPE
// AFX CODE BLOCK (afxModel-type) >>

/// Types used for SceneObject type masks (SceneObject::mTypeMask)
///
/// @note If a new object type is added, don't forget to add it to
@@ -148,6 +163,14 @@ enum SceneObjectTypes
PhysicalZoneObjectType = BIT( 22 ),

/// @}

// AFX CODE BLOCK (special-types) <<
InteriorLikeObjectType = BIT(24),
TerrainLikeObjectType = BIT(25),
// AFX CODE BLOCK (special-types) >>
#if defined(AFX_CAP_AFXMODEL_TYPE) // AFX CODE BLOCK (afxModel-type) <<
afxModelObjectType = BIT(26)
#endif // AFX CODE BLOCK (afxModel-type) >>
};

enum SceneObjectTypeMasks
@@ -20,6 +20,16 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// enhanced-physical-zone -- PhysicalZone object enhanced to allow orientation
// add radial forces.
// pz-opt -- PhysicalZone network optimizations.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "T3D/physicalZone.h"
#include "core/stream/bitStream.h"
#include "collision/boxConvex.h"
@@ -33,6 +43,11 @@
#include "gfx/gfxDrawUtil.h"
#include "console/engineAPI.h"

// AFX CODE BLOCK (enhanced-physical-zone) <<
//#include "console/engineTypes.h"
#include "sim/netConnection.h"
// AFX CODE BLOCK (enhanced-physical-zone) >>

IMPLEMENT_CO_NETOBJECT_V1(PhysicalZone);

ConsoleDocClass( PhysicalZone,
@@ -103,6 +118,13 @@ PhysicalZone::PhysicalZone()
mConvexList = new Convex;
mActive = true;
// AFX CODE BLOCK (enhanced-physical-zone) <<
force_type = VECTOR;
force_mag = 0.0f;
orient_force = false;
fade_amt = 1.0f;
// AFX CODE BLOCK (enhanced-physical-zone) >>
}
PhysicalZone::~PhysicalZone()
@@ -111,6 +133,17 @@ PhysicalZone::~PhysicalZone()
mConvexList = NULL;
}
// AFX CODE BLOCK (enhanced-physical-zone) <<
ImplementEnumType( PhysicalZone_ForceType, "Possible physical zone force types.\n" "@ingroup PhysicalZone\n\n" )
{ PhysicalZone::VECTOR, "vector", "..." },
{ PhysicalZone::SPHERICAL, "spherical", "..." },
{ PhysicalZone::CYLINDRICAL, "cylindrical", "..." },
// aliases
{ PhysicalZone::SPHERICAL, "sphere", "..." },
{ PhysicalZone::CYLINDRICAL, "cylinder", "..." },
EndImplementEnumType;
// AFX CODE BLOCK (enhanced-physical-zone) >>
//--------------------------------------------------------------------------
void PhysicalZone::consoleInit()
{
@@ -129,6 +162,13 @@ void PhysicalZone::initPersistFields()
"point followed by three vectors representing the edges extending from the corner." );
endGroup("Misc");
// AFX CODE BLOCK (enhanced-physical-zone) <<
addGroup("AFX");
addField("forceType", TYPEID<PhysicalZone::ForceType>(), Offset(force_type, PhysicalZone));
addField("orientForce", TypeBool, Offset(orient_force, PhysicalZone));
endGroup("AFX");
// AFX CODE BLOCK (enhanced-physical-zone) >>
Parent::initPersistFields();
}
@@ -158,6 +198,22 @@ bool PhysicalZone::onAdd()
Polyhedron temp = mPolyhedron;
setPolyhedron(temp);
// AFX CODE BLOCK (enhanced-physical-zone) <<
switch (force_type)
{
case SPHERICAL:
force_mag = mAppliedForce.magnitudeSafe();
break;
case CYLINDRICAL:
{
Point3F force_vec = mAppliedForce;
force_vec.z = 0.0;
force_mag = force_vec.magnitudeSafe();
}
break;
}
// AFX CODE BLOCK (enhanced-physical-zone) >>
addToScene();
return true;
@@ -190,8 +246,14 @@ void PhysicalZone::setTransform(const MatrixF & mat)
base.mul(mWorldToObj);
mClippedList.setBaseTransform(base);
// AFX CODE BLOCK (pz-opt) <<
if (isServerObject())
setMaskBits(MoveMask);
/* ORIGINAL CODE
if (isServerObject())
setMaskBits(InitialUpdateMask);
*/
// AFX CODE BLOCK (pz-opt) >>
}
@@ -242,6 +304,52 @@ U32 PhysicalZone::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
U32 i;
U32 retMask = Parent::packUpdate(con, mask, stream);
// AFX CODE BLOCK (enhanced-physical-zone)(pz-opt) <<
if (stream->writeFlag(mask & PolyhedronMask))
{
// Write the polyhedron
stream->write(mPolyhedron.pointList.size());
for (i = 0; i < mPolyhedron.pointList.size(); i++)
mathWrite(*stream, mPolyhedron.pointList[i]);
stream->write(mPolyhedron.planeList.size());
for (i = 0; i < mPolyhedron.planeList.size(); i++)
mathWrite(*stream, mPolyhedron.planeList[i]);
stream->write(mPolyhedron.edgeList.size());
for (i = 0; i < mPolyhedron.edgeList.size(); i++) {
const Polyhedron::Edge& rEdge = mPolyhedron.edgeList[i];
stream->write(rEdge.face[0]);
stream->write(rEdge.face[1]);
stream->write(rEdge.vertex[0]);
stream->write(rEdge.vertex[1]);
}
}
if (stream->writeFlag(mask & MoveMask))
{
stream->writeAffineTransform(mObjToWorld);
mathWrite(*stream, mObjScale);
}
if (stream->writeFlag(mask & SettingsMask))
{
stream->write(mVelocityMod);
stream->write(mGravityMod);
mathWrite(*stream, mAppliedForce);
stream->writeInt(force_type, FORCE_TYPE_BITS);
stream->writeFlag(orient_force);
}
if (stream->writeFlag(mask & FadeMask))
{
U8 fade_byte = (U8)(fade_amt*255.0f);
stream->write(fade_byte);
}
stream->writeFlag(mActive);
/* ORIGINAL CODE
if (stream->writeFlag((mask & InitialUpdateMask) != 0)) {
// Note that we don't really care about efficiency here, since this is an
// edit-only ghost...
@@ -274,6 +382,8 @@ U32 PhysicalZone::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
} else {
stream->writeFlag(mActive);
}
*/
// AFX CODE BLOCK (enhanced-physical-zone)(pz-opt) >>

return retMask;
}
@@ -282,6 +392,76 @@ void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream)
{
Parent::unpackUpdate(con, stream);

// AFX CODE BLOCK (enhanced-physical-zone)(pz-opt) <<
bool new_ph = false;
if (stream->readFlag()) // PolyhedronMask
{
U32 i, size;
Polyhedron tempPH;

// Read the polyhedron
stream->read(&size);
tempPH.pointList.setSize(size);
for (i = 0; i < tempPH.pointList.size(); i++)
mathRead(*stream, &tempPH.pointList[i]);

stream->read(&size);
tempPH.planeList.setSize(size);
for (i = 0; i < tempPH.planeList.size(); i++)
mathRead(*stream, &tempPH.planeList[i]);

stream->read(&size);
tempPH.edgeList.setSize(size);
for (i = 0; i < tempPH.edgeList.size(); i++) {
Polyhedron::Edge& rEdge = tempPH.edgeList[i];

stream->read(&rEdge.face[0]);
stream->read(&rEdge.face[1]);
stream->read(&rEdge.vertex[0]);
stream->read(&rEdge.vertex[1]);
}

setPolyhedron(tempPH);
new_ph = true;
}

if (stream->readFlag()) // MoveMask
{
MatrixF temp;
stream->readAffineTransform(&temp);

Point3F tempScale;
mathRead(*stream, &tempScale);

//if (!new_ph)
//{
// Polyhedron rPolyhedron = mPolyhedron;
// setPolyhedron(rPolyhedron);
//}
setScale(tempScale);
setTransform(temp);
}

if (stream->readFlag()) //SettingsMask
{
stream->read(&mVelocityMod);
stream->read(&mGravityMod);
mathRead(*stream, &mAppliedForce);
force_type = stream->readInt(FORCE_TYPE_BITS); // AFX
orient_force = stream->readFlag(); // AFX
}

if (stream->readFlag()) //FadeMask
{
U8 fade_byte;
stream->read(&fade_byte);
fade_amt = ((F32)fade_byte)/255.0f;
}
else
fade_amt = 1.0f;

mActive = stream->readFlag();
/* ORIGINAL CODE
if (stream->readFlag()) {
U32 i, size;
MatrixF temp;
@@ -325,6 +505,8 @@ void PhysicalZone::unpackUpdate(NetConnection* con, BitStream* stream)
} else {
mActive = stream->readFlag();
}
*/
// AFX CODE BLOCK (enhanced-physical-zone)(pz-opt) >>
}


@@ -443,3 +625,105 @@ void PhysicalZone::deactivate()
mActive = false;
}

// AFX CODE BLOCK (enhanced-physical-zone) <<
void PhysicalZone::onStaticModified(const char* slotName, const char*newValue)
{
if (dStricmp(slotName, "appliedForce") == 0 || dStricmp(slotName, "forceType") == 0)
{
switch (force_type)
{
case SPHERICAL:
force_mag = mAppliedForce.magnitudeSafe();
break;
case CYLINDRICAL:
{
Point3F force_vec = mAppliedForce;
force_vec.z = 0.0;
force_mag = force_vec.magnitudeSafe();
}
break;
}
}
}

const Point3F& PhysicalZone::getForce(const Point3F* center) const
{
static Point3F force_vec;

if (force_type == VECTOR)
{
if (orient_force)
{
getTransform().mulV(mAppliedForce, &force_vec);
force_vec *= fade_amt;
return force_vec;
}
force_vec = mAppliedForce;
force_vec *= fade_amt;
return force_vec;
}

if (!center)
{
force_vec.zero();
return force_vec;
}

if (force_type == SPHERICAL)
{
force_vec = *center - getPosition();
force_vec.normalizeSafe();
force_vec *= force_mag*fade_amt;
return force_vec;
}

if (orient_force)
{
force_vec = *center - getPosition();
getWorldTransform().mulV(force_vec);
force_vec.z = 0.0f;
force_vec.normalizeSafe();
force_vec *= force_mag;
force_vec.z = mAppliedForce.z;
getTransform().mulV(force_vec);
force_vec *= fade_amt;
return force_vec;
}

force_vec = *center - getPosition();
force_vec.z = 0.0f;
force_vec.normalizeSafe();
force_vec *= force_mag;
force_vec *= fade_amt;
return force_vec;
}

bool PhysicalZone::isExcludedObject(SceneObject* obj) const
{
for (S32 i = 0; i < excluded_objects.size(); i++)
if (excluded_objects[i] == obj)
return true;

return false;
}

void PhysicalZone::registerExcludedObject(SceneObject* obj)
{
if (isExcludedObject(obj))
return;

excluded_objects.push_back(obj);
setMaskBits(FadeMask);
}

void PhysicalZone::unregisterExcludedObject(SceneObject* obj)
{
for (S32 i = 0; i < excluded_objects.size(); i++)
if (excluded_objects[i] == obj)
{
excluded_objects.erase(i);
setMaskBits(FadeMask);
return;
}
}
// AFX CODE BLOCK (enhanced-physical-zone) >>
@@ -20,6 +20,16 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// enhanced-physical-zone -- PhysicalZone object enhanced to allow orientation
// add radial forces.
// pz-opt -- PhysicalZone network optimizations.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _H_PHYSICALZONE
#define _H_PHYSICALZONE

@@ -40,10 +50,23 @@ class PhysicalZone : public SceneObject
{
typedef SceneObject Parent;

// AFX CODE BLOCK (pz-opt) <<
enum UpdateMasks {
ActiveMask = Parent::NextFreeMask << 0,
SettingsMask = Parent::NextFreeMask << 1,
FadeMask = Parent::NextFreeMask << 2,
PolyhedronMask = Parent::NextFreeMask << 3,
MoveMask = Parent::NextFreeMask << 4,
ExclusionMask = Parent::NextFreeMask << 5,
NextFreeMask = Parent::NextFreeMask << 6
};
/* ORIGINAL CODE
enum UpdateMasks {
ActiveMask = Parent::NextFreeMask << 0,
NextFreeMask = Parent::NextFreeMask << 1
};
*/
// AFX CODE BLOCK (pz-opt) >>

protected:
static bool smRenderPZones;
@@ -83,7 +106,15 @@ class PhysicalZone : public SceneObject

inline F32 getVelocityMod() const { return mVelocityMod; }
inline F32 getGravityMod() const { return mGravityMod; }
// AFX CODE BLOCK (enhanced-physical-zone) <<
// the scene object is now passed in to getForce() where
// it is needed to calculate the applied force when the
// force is radial.
const Point3F& getForce(const Point3F* center=0) const;
/* ORIGINAL CODE
inline const Point3F& getForce() const { return mAppliedForce; }
*/
// AFX CODE BLOCK (enhanced-physical-zone) >>

void setPolyhedron(const Polyhedron&);
bool testObject(SceneObject*);
@@ -96,7 +127,30 @@ class PhysicalZone : public SceneObject
void deactivate();
inline bool isActive() const { return mActive; }

// AFX CODE BLOCK (enhanced-physical-zone)(pz-opt) <<
protected:
friend class afxPhysicalZoneData;
friend class afxEA_PhysicalZone;
Vector<SceneObject*> excluded_objects;
S32 force_type;
F32 force_mag;
bool orient_force;
F32 fade_amt;
void setFadeAmount(F32 amt) { fade_amt = amt; if (fade_amt < 1.0f) setMaskBits(FadeMask); }
public:
enum ForceType { VECTOR, SPHERICAL, CYLINDRICAL };
enum { FORCE_TYPE_BITS = 2 };
virtual void onStaticModified(const char* slotName, const char*newValue = NULL);
bool isExcludedObject(SceneObject*) const;
void registerExcludedObject(SceneObject*);
void unregisterExcludedObject(SceneObject*);
// AFX CODE BLOCK (enhanced-physical-zone)(pz-opt) >>
};

// AFX CODE BLOCK (enhanced-physical-zone) <<
typedef PhysicalZone::ForceType PhysicalZone_ForceType;
DefineEnumType( PhysicalZone_ForceType );
// AFX CODE BLOCK (enhanced-physical-zone) >>

#endif // _H_PHYSICALZONE

Large diffs are not rendered by default.

@@ -20,6 +20,20 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// obj-select -- object selection functionality
// anim-clip -- sequence selection by afx effects
// player-look -- modified player head and arm control
// triggers -- implements effect triggers derived from player behaviors.
// player-movement -- mods allowing manipulation of player movement.
// player-puppet -- mods allowing manipulation of player via contraints.
// foot-switch -- mods for overriding built-in footstep sounds, decals, and dust.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _PLAYER_H_
#define _PLAYER_H_

@@ -395,7 +409,13 @@ class Player: public ShapeBase
ActionMask = Parent::NextFreeMask << 0,
MoveMask = Parent::NextFreeMask << 1,
ImpactMask = Parent::NextFreeMask << 2,
// AFX CODE BLOCK (player-look) <<
TriggerMask = Parent::NextFreeMask << 3,
NextFreeMask = Parent::NextFreeMask << 4
/* ORIGINAL CODE
NextFreeMask = Parent::NextFreeMask << 3
*/
// AFX CODE BLOCK (player-look) >>
};

SimObjectPtr<ParticleEmitter> mSplashEmitter[PlayerData::NUM_SPLASH_EMITTERS];
@@ -764,6 +784,111 @@ class Player: public ShapeBase
virtual void prepRenderImage( SceneRenderState* state );
virtual void renderConvex( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat );
virtual void renderMountedImage( U32 imageSlot, TSRenderState &rstate, SceneRenderState *state );

// AFX CODE BLOCK (misc) <<
private:
static void afx_consoleInit();
void afx_init();
U32 afx_packUpdate(NetConnection*, U32 mask, BitStream*, U32 retMask);
void afx_unpackUpdate(NetConnection*, BitStream*);
// AFX CODE BLOCK (misc) >>

// AFX CODE BLOCK (obj-select) <<
private:
static bool sCorpsesHiddenFromRayCast;
// AFX CODE BLOCK (obj-select) >>

// AFX CODE BLOCK (anim-clip) <<
public:
virtual void restoreAnimation(U32 tag);
virtual U32 getAnimationID(const char* name);
virtual U32 playAnimationByID(U32 anim_id, F32 pos, F32 rate, F32 trans, bool hold, bool wait, bool is_death_anim);
virtual F32 getAnimationDurationByID(U32 anim_id);
virtual bool isBlendAnimation(const char* name);
virtual const char* getLastClipName(U32 clip_tag);
virtual void unlockAnimation(U32 tag, bool force=false);
virtual U32 lockAnimation();
virtual bool isAnimationLocked() const { return ((anim_clip_flags & BLOCK_USER_CONTROL) != 0); }
// AFX CODE BLOCK (anim-clip) >>

// AFX CODE BLOCK (player-look) <<
protected:
bool overrideLookAnimation;
F32 armLookOverridePos;
F32 headVLookOverridePos;
F32 headHLookOverridePos;
public:
void setLookAnimationOverride(bool flag);
void copyHeadRotation(const Player* p) { mHead = p->mHead; }
// AFX CODE BLOCK (player-look) >>

// AFX CODE BLOCK (player-puppet) <<
public:
bool ignore_updates;
void resetContactTimer() { mContactTimer = 0; }
// AFX CODE BLOCK (player-puppet) >>

// AFX CODE BLOCK (triggers) <<
private:
U8 move_trigger_states;
U32 fx_s_triggers;
U32 mark_fx_c_triggers;
U32 fx_c_triggers;
F32 z_velocity;
bool mark_idle;
F32 idle_timer;
bool mark_s_landing;
void process_client_triggers(bool triggeredLeft, bool triggeredRight);
public:
enum {
// server events
PLAYER_MOVE_TRIGGER_0 = BIT(0),
PLAYER_MOVE_TRIGGER_1 = BIT(1),
PLAYER_MOVE_TRIGGER_2 = BIT(2),
PLAYER_MOVE_TRIGGER_3 = BIT(3),
PLAYER_MOVE_TRIGGER_4 = BIT(4),
PLAYER_MOVE_TRIGGER_5 = BIT(5),
PLAYER_LANDING_S_TRIGGER = BIT(6),

PLAYER_FIRE_S_TRIGGER = PLAYER_MOVE_TRIGGER_0,
PLAYER_FIRE_ALT_S_TRIGGER = PLAYER_MOVE_TRIGGER_1,
PLAYER_JUMP_S_TRIGGER = BIT(7),

// client events
PLAYER_LF_FOOT_C_TRIGGER = BIT(16),
PLAYER_RT_FOOT_C_TRIGGER = BIT(17),
PLAYER_LANDING_C_TRIGGER = BIT(18),
PLAYER_IDLE_C_TRIGGER = BIT(19),
};
U32 getClientEventTriggers() const { return fx_c_triggers; }
U32 getServerEventTriggers() const { return fx_s_triggers; }
// AFX CODE BLOCK (triggers) >>

// AFX CODE BLOCK (player-movement) <<
private:
F32 speed_bias;
F32 speed_bias_goal;
bool override_movement;
Point3F movement_data;
U8 movement_op;
U32 last_movement_tag;
static U32 unique_movement_tag_counter;
public:
void setMovementSpeedBias(F32 bias);
U32 setMovementOverride(F32 bias, const Point3F* mov=0, U32 op=1);
void restoreMovement(U32 tag);
// AFX CODE BLOCK (player-movement) >>

// AFX CODE BLOCK (foot-switch) <<
private:
S32 footfallDecalOverride;
S32 footfallSoundOverride;
S32 footfallDustOverride;
bool noFootfallFX;
public:
void overrideFootfallFX(bool decals=true, bool sounds=true, bool dust=true);
void restoreFootfallFX(bool decals=true, bool sounds=true, bool dust=true);
// AFX CODE BLOCK (foot-switch) >>
};

typedef Player::Pose PlayerPose;
@@ -20,6 +20,17 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// enhanced-projectile -- ...
// substitutions -- ...
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/projectile.h"

@@ -190,6 +201,43 @@ ProjectileData::ProjectileData()
lightDescId = 0;
}

// AFX CODE BLOCK (datablock-temp-clone) <<
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
}
// AFX CODE BLOCK (datablock-temp-clone) >>

//--------------------------------------------------------------------------

void ProjectileData::initPersistFields()
@@ -275,6 +323,16 @@ void ProjectileData::initPersistFields()
"The magnitude of gravity is assumed to be 9.81 m/s/s\n\n"
"@note ProjectileData::isBallistic must be true for this to have any affect.");

// AFX CODE BLOCK (substitutions) <<
// disallow some field substitutions
onlyKeepClearSubstitutions("explosion");
onlyKeepClearSubstitutions("particleEmitter");
onlyKeepClearSubstitutions("particleWaterEmitter");
onlyKeepClearSubstitutions("sound");
onlyKeepClearSubstitutions("splash");
onlyKeepClearSubstitutions("waterExplosion");
// AFX CODE BLOCK (substitutions) >>

Parent::initPersistFields();
}

@@ -574,6 +632,16 @@ Projectile::Projectile()

mLightState.clear();
mLightState.setLightInfo( mLight );

// AFX CODE BLOCK (datablock-temp-clone) <<
mDataBlock = 0;
// AFX CODE BLOCK (datablock-temp-clone) >>

// AFX CODE BLOCK (enhanced-projectile) <<
ignoreSourceTimeout = false;
dynamicCollisionMask = csmDynamicCollisionMask;
staticCollisionMask = csmStaticCollisionMask;
// AFX CODE BLOCK (enhanced-projectile) >>
}

Projectile::~Projectile()
@@ -582,6 +650,14 @@ Projectile::~Projectile()

delete mProjectileShape;
mProjectileShape = NULL;

// AFX CODE BLOCK (datablock-temp-clone) <<
if (mDataBlock && mDataBlock->isTempClone())
{
delete mDataBlock;
mDataBlock = 0;
}
// AFX CODE BLOCK (datablock-temp-clone) >>
}

//--------------------------------------------------------------------------
@@ -609,6 +685,9 @@ void Projectile::initPersistFields()
addField("sourceSlot", TypeS32, Offset(mSourceObjectSlot, Projectile),
"@brief The sourceObject's weapon slot that the projectile originates from.\n\n");

// AFX CODE BLOCK (enhanced-projectile) <<
addField("ignoreSourceTimeout", TypeBool, Offset(ignoreSourceTimeout, Projectile));
// AFX CODE BLOCK (enhanced-projectile) >>
endGroup("Source");


@@ -1088,7 +1167,12 @@ void Projectile::simulate( F32 dt )
// disable the source objects collision reponse for a short time while we
// determine if the projectile is capable of moving from the old position
// to the new position, otherwise we'll hit ourself
// AFX CODE BLOCK (enhanced-projectile) <<
bool disableSourceObjCollision = (mSourceObject.isValid() && (ignoreSourceTimeout || mCurrTick <= SourceIdTimeoutTicks));
/* ORIGINAL CODE
bool disableSourceObjCollision = (mSourceObject.isValid() && mCurrTick <= SourceIdTimeoutTicks);
*/
// AFX CODE BLOCK (enhanced-projectile) >>
if ( disableSourceObjCollision )
mSourceObject->disableCollision();
disableCollision();
@@ -1105,12 +1189,22 @@ void Projectile::simulate( F32 dt )
if ( mPhysicsWorld )
hit = mPhysicsWorld->castRay( oldPosition, newPosition, &rInfo, Point3F( newPosition - oldPosition) * mDataBlock->impactForce );
else
// AFX CODE BLOCK (enhanced-projectile) <<
hit = getContainer()->castRay(oldPosition, newPosition, dynamicCollisionMask | staticCollisionMask, &rInfo);
/* ORIGINAL CODE
hit = getContainer()->castRay(oldPosition, newPosition, csmDynamicCollisionMask | csmStaticCollisionMask, &rInfo);
*/
// AFX CODE BLOCK (enhanced-projectile) >>

if ( hit )
{
// make sure the client knows to bounce
// AFX CODE BLOCK (enhanced-projectile) <<
if(isServerObject() && (rInfo.object->getTypeMask() & staticCollisionMask) == 0)
/* ORIGINAL CODE
if ( isServerObject() && ( rInfo.object->getTypeMask() & csmStaticCollisionMask ) == 0 )
*/
// AFX CODE BLOCK (enhanced-projectile) >>
setMaskBits( BounceMask );

MatrixF xform( true );
@@ -1301,6 +1395,9 @@ U32 Projectile::packUpdate( NetConnection *con, U32 mask, BitStream *stream )
stream->writeRangedU32( U32(mSourceObjectSlot),
0,
ShapeBase::MaxMountedImages - 1 );
// AFX CODE BLOCK (enhanced-projectile) <<
stream->writeFlag(ignoreSourceTimeout);
// AFX CODE BLOCK (enhanced-projectile) >>
}
else
// have not recieved the ghost for the source object yet, try again later
@@ -1343,7 +1440,9 @@ void Projectile::unpackUpdate(NetConnection* con, BitStream* stream)
{
mSourceObjectId = stream->readRangedU32( 0, NetConnection::MaxGhostCount );
mSourceObjectSlot = stream->readRangedU32( 0, ShapeBase::MaxMountedImages - 1 );

// AFX CODE BLOCK (enhanced-projectile) <<
ignoreSourceTimeout = stream->readFlag();
// AFX CODE BLOCK (enhanced-projectile) >>
NetObject* pObject = con->resolveGhost( mSourceObjectId );
if ( pObject != NULL )
mSourceObject = dynamic_cast<ShapeBase*>( pObject );
@@ -20,6 +20,16 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// enhanced-projectile -- ...
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _PROJECTILE_H_
#define _PROJECTILE_H_

@@ -144,6 +154,12 @@ class ProjectileData : public GameBaseData

DECLARE_CALLBACK( void, onExplode, ( Projectile* proj, Point3F pos, F32 fade ) );
DECLARE_CALLBACK( void, onCollision, ( Projectile* proj, SceneObject* col, F32 fade, Point3F pos, Point3F normal ) );

// AFX CODE BLOCK (datablock-temp-clone) <<
public:
ProjectileData(const ProjectileData&, bool = false);
virtual bool allowSubstitutions() const { return true; }
// AFX CODE BLOCK (datablock-temp-clone) >>
};


@@ -279,6 +295,13 @@ class Projectile : public GameBase, public ISceneLight
Point3F mExplosionPosition;
Point3F mExplosionNormal;
U32 mCollideHitType;

// AFX CODE BLOCK (enhanced-projectile) <<
public:
bool ignoreSourceTimeout;
U32 dynamicCollisionMask;
U32 staticCollisionMask;
// AFX CODE BLOCK (enhanced-projectile) >>
};

#endif // _PROJECTILE_H_

Large diffs are not rendered by default.

@@ -20,6 +20,21 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
// collision-events -- detects object collisions for use with AFX collision event
// effects.
// remap-txr-tags -- runtime reassignment of texture tag names. (Useful for
// splitting up tags with the same name in order to map different materials
// to them.)
// bbox-check -- a change that allows disabling of a confusing error message.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _SHAPEBASE_H_
#define _SHAPEBASE_H_

@@ -654,6 +669,26 @@ struct ShapeBaseData : public GameBaseData {
DECLARE_CALLBACK(void, onEndSequence, (ShapeBase* obj, S32 slot, const char* name));
DECLARE_CALLBACK( void, onForceUncloak, ( ShapeBase* obj, const char* reason ) );
/// @}

// AFX CODE BLOCK (remap-txr-tags) <<
struct TextureTagRemapping
{
char* old_tag;
char* new_tag;
};
StringTableEntry remap_txr_tags;
char* remap_buffer;
Vector<TextureTagRemapping> txr_tag_remappings;
// AFX CODE BLOCK (remap-txr-tags) >>

// AFX CODE BLOCK (bbox-check) <<
bool silent_bbox_check;
// AFX CODE BLOCK (bbox-check) >>

// AFX CODE BLOCK (datablock-temp-clone) <<
public:
ShapeBaseData(const ShapeBaseData&, bool = false);
// AFX CODE BLOCK (datablock-temp-clone) >>
};


@@ -1840,7 +1875,65 @@ class ShapeBase : public GameBase, public ISceneLight

protected:
DECLARE_CALLBACK( F32, validateCameraFov, (F32 fov) );

// AFX CODE BLOCK (collision-events) <<
public:
class CollisionEventCallback
{
public:
virtual void collisionNotify(SceneObject* shape0, SceneObject* shape1, const VectorF& vel)=0;
};
private:
Vector<CollisionEventCallback*> collision_callbacks;
void notifyCollisionCallbacks(SceneObject*, const VectorF& vel);
public:
void registerCollisionCallback(CollisionEventCallback*);
void unregisterCollisionCallback(CollisionEventCallback*);
// AFX CODE BLOCK (collision-events) >>

// AFX CODE BLOCK (anim-clip) <<
protected:
enum {
ANIM_OVERRIDDEN = BIT(0),
BLOCK_USER_CONTROL = BIT(1),
IS_DEATH_ANIM = BIT(2),
BAD_ANIM_ID = 999999999,
BLENDED_CLIP = 0x80000000,
};
struct BlendThread
{
TSThread* thread;
U32 tag;
};
Vector<BlendThread> blend_clips;
static U32 unique_anim_tag_counter;
U8 anim_clip_flags;
S32 last_anim_id;
U32 last_anim_tag;
U32 last_anim_lock_tag;
S32 saved_seq_id;
F32 saved_pos;
F32 saved_rate;
U32 playBlendAnimation(S32 seq_id, F32 pos, F32 rate);
void restoreBlendAnimation(U32 tag);
public:
U32 playAnimation(const char* name, F32 pos, F32 rate, F32 trans, bool hold, bool wait, bool is_death_anim);
F32 getAnimationDuration(const char* name);

virtual void restoreAnimation(U32 tag);
virtual U32 getAnimationID(const char* name);
virtual U32 playAnimationByID(U32 anim_id, F32 pos, F32 rate, F32 trans, bool hold, bool wait, bool is_death_anim);
virtual F32 getAnimationDurationByID(U32 anim_id);
virtual bool isBlendAnimation(const char* name);
virtual const char* getLastClipName(U32 clip_tag);
virtual void unlockAnimation(U32 tag, bool force=false) { }
virtual U32 lockAnimation() { return 0; }
virtual bool isAnimationLocked() const { return false; }
// AFX CODE BLOCK (anim-clip) >>

// AFX CODE BLOCK (selection-highlight) <<
virtual void setSelectionFlags(U8 flags);
// AFX CODE BLOCK (selection-highlight) >>
};


@@ -20,6 +20,15 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "core/dnet.h"
#include "core/stream/bitStream.h"
@@ -97,6 +106,17 @@ StaticShapeData::StaticShapeData()
noIndividualDamage = false;
}

// AFX CODE BLOCK (datablock-temp-clone) <<
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
}
// AFX CODE BLOCK (datablock-temp-clone) >>


void StaticShapeData::initPersistFields()
{
addField("noIndividualDamage", TypeBool, Offset(noIndividualDamage, StaticShapeData), "Deprecated\n\n @internal");
@@ -20,6 +20,15 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// datablock-temp-clone -- Implements creation of temporary datablock clones to
// allow late substitution of datablock fields.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _STATICSHAPE_H_
#define _STATICSHAPE_H_

@@ -45,6 +54,11 @@ struct StaticShapeData: public ShapeBaseData {
static void initPersistFields();
virtual void packData(BitStream* stream);
virtual void unpackData(BitStream* stream);
// AFX CODE BLOCK (datablock-temp-clone) <<
public:
StaticShapeData(const StaticShapeData&, bool = false);
virtual bool allowSubstitutions() const { return true; }
// AFX CODE BLOCK (datablock-temp-clone) >>
};


@@ -20,6 +20,15 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// polysoup-zodiacs -- Changes made for rendering zodiacs on polysoup objects.
// special-types -- defines type bits for interior-like and terrain-like types. -- defines a type bit for polysoup objects.
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#include "platform/platform.h"
#include "T3D/tsStatic.h"

@@ -54,6 +63,10 @@ using namespace Torque;

extern bool gEditingMission;

// AFX CODE BLOCK (polysoup-zodiacs) <<
#include "afx/ce/afxZodiacMgr.h"
// AFX CODE BLOCK (polysoup-zodiacs) >>

IMPLEMENT_CO_NETOBJECT_V1(TSStatic);

ConsoleDocClass( TSStatic,
@@ -121,6 +134,14 @@ TSStatic::TSStatic()

mCollisionType = CollisionMesh;
mDecalType = CollisionMesh;

// AFX CODE BLOCK (polysoup-zodiacs) <<
mIgnoreZodiacs = false;
mHasGradients = false;
mInvertGradientRange = false;
mGradientRangeUser.set(0.0f, 180.0f);
afxZodiacData::convertGradientRangeFromDegrees(mGradientRange, mGradientRangeUser);
// AFX CODE BLOCK (polysoup-zodiacs) >>
}

TSStatic::~TSStatic()
@@ -214,6 +235,15 @@ void TSStatic::initPersistFields()

endGroup("Debug");

// AFX CODE BLOCK (polysoup-zodiacs) (special-types) <<
addGroup("AFX");
addField("ignoreZodiacs", TypeBool, Offset(mIgnoreZodiacs, TSStatic));
addField("useGradientRange", TypeBool, Offset(mHasGradients, TSStatic));
addField("gradientRange", TypePoint2F, Offset(mGradientRangeUser, TSStatic));
addField("invertGradientRange", TypeBool, Offset(mInvertGradientRange, TSStatic));
endGroup("AFX");
// AFX CODE BLOCK (polysoup-zodiacs) (special-types) >>

Parent::initPersistFields();
}

@@ -308,6 +338,10 @@ bool TSStatic::_createShape()
{
// Cleanup before we create.
mCollisionDetails.clear();
// AFX CODE BLOCK (polysoup-zodiacs) <<
mDecalDetails.clear();
mDecalDetailsPtr = 0;
// AFX CODE BLOCK (polysoup-zodiacs) >>
mLOSDetails.clear();
SAFE_DELETE( mPhysicsRep );
SAFE_DELETE( mShapeInstance );
@@ -339,6 +373,11 @@ bool TSStatic::_createShape()

mShapeInstance = new TSShapeInstance( mShape, isClientObject() );

// AFX CODE BLOCK (selection-highlight) <<
if (isClientObject())
mShapeInstance->cloneMaterialList();
// AFX CODE BLOCK (selection-highlight) >>

if( isGhost() )
{
// Reapply the current skin
@@ -371,11 +410,37 @@ void TSStatic::prepCollision()

// Cleanup any old collision data
mCollisionDetails.clear();
// AFX CODE BLOCK (polysoup-zodiacs) <<
mDecalDetails.clear();
mDecalDetailsPtr = 0;
// AFX CODE BLOCK (polysoup-zodiacs) >>
mLOSDetails.clear();
mConvexList->nukeList();

// AFX CODE BLOCK (polysoup-zodiacs) <<
if ( mCollisionType == CollisionMesh || mCollisionType == VisibleMesh )
{
mShape->findColDetails( mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails );
if ( mDecalType == mCollisionType )
{
mDecalDetailsPtr = &mCollisionDetails;
}
else if ( mDecalType == CollisionMesh || mDecalType == VisibleMesh )
{
mShape->findColDetails( mDecalType == VisibleMesh, &mDecalDetails, 0 );
mDecalDetailsPtr = &mDecalDetails;
}
}
else if ( mDecalType == CollisionMesh || mDecalType == VisibleMesh )
{
mShape->findColDetails( mDecalType == VisibleMesh, &mDecalDetails, 0 );
mDecalDetailsPtr = &mDecalDetails;
}
/* ORIGINAL CODE
if ( mCollisionType == CollisionMesh || mCollisionType == VisibleMesh )
mShape->findColDetails( mCollisionType == VisibleMesh, &mCollisionDetails, &mLOSDetails );
*/
// AFX CODE BLOCK (polysoup-zodiacs) >>

_updatePhysics();
}
@@ -620,6 +685,11 @@ void TSStatic::prepRenderImage( SceneRenderState* state )
}
mShapeInstance->render( rdata );

// AFX CODE BLOCK (polysoup-zodiacs) <<
if (!mIgnoreZodiacs && mDecalDetailsPtr != 0)
afxZodiacMgr::renderPolysoupZodiacs(state, this);
// AFX CODE BLOCK (polysoup-zodiacs) >>

if ( mRenderNormalScalar > 0 )
{
ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
@@ -711,6 +781,15 @@ U32 TSStatic::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
stream->write(mAlphaFadeEnd);
stream->write(mInvertAlphaFade);
}
// AFX CODE BLOCK (polysoup-zodiacs) <<
stream->writeFlag(mIgnoreZodiacs);
if (stream->writeFlag(mHasGradients))
{
stream->writeFlag(mInvertGradientRange);
stream->write(mGradientRange.x);
stream->write(mGradientRange.y);
}
// AFX CODE BLOCK (polysoup-zodiacs) >>

if ( mLightPlugin )
retMask |= mLightPlugin->packUpdate(this, AdvancedStaticOptionsMask, con, mask, stream);
@@ -776,6 +855,16 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream)
stream->read(&mAlphaFadeEnd);
stream->read(&mInvertAlphaFade);
}
// AFX CODE BLOCK (polysoup-zodiacs) <<
mIgnoreZodiacs = stream->readFlag();
mHasGradients = stream->readFlag();
if (mHasGradients)
{
mInvertGradientRange = stream->readFlag();
stream->read(&mGradientRange.x);
stream->read(&mGradientRange.y);
}
// AFX CODE BLOCK (polysoup-zodiacs) >>

if ( mLightPlugin )
{
@@ -784,6 +873,10 @@ void TSStatic::unpackUpdate(NetConnection *con, BitStream *stream)

if ( isProperlyAdded() )
_updateShouldTick();

// AFX CODE BLOCK (special-types) <<
set_special_typing();
// AFX CODE BLOCK (special-types) >>
}

//----------------------------------------------------------------------------
@@ -894,6 +987,13 @@ bool TSStatic::buildPolyList(PolyListContext context, AbstractPolyList* polyList
polyList->addBox( mObjBox );
else if ( meshType == VisibleMesh )
mShapeInstance->buildPolyList( polyList, 0 );
// AFX CODE BLOCK (special-types) <<
else if (context == PLC_Decal && mDecalDetailsPtr != 0)
{
for ( U32 i = 0; i < mDecalDetailsPtr->size(); i++ )
mShapeInstance->buildPolyListOpcode( (*mDecalDetailsPtr)[i], polyList, box );
}
// AFX CODE BLOCK (special-types) >>
else
{
// Everything else is done from the collision meshes
@@ -1210,4 +1310,47 @@ DefineEngineMethod( TSStatic, getModelFile, const char *, (),,
)
{
return object->getShapeFileName();
}
}

// AFX CODE BLOCK (special-types) <<
void TSStatic::set_special_typing()
{
if (mCollisionType == VisibleMesh || mCollisionType == CollisionMesh)
mTypeMask |= InteriorLikeObjectType;
else
mTypeMask &= ~InteriorLikeObjectType;
}
// AFX CODE BLOCK (special-types) >>

// AFX CODE BLOCK (polysoup-zodiacs) (special-types) <<
void TSStatic::onStaticModified(const char* slotName, const char*newValue)
{
if (slotName == afxZodiacData::GradientRangeSlot)
{
afxZodiacData::convertGradientRangeFromDegrees(mGradientRange, mGradientRangeUser);
return;
}

set_special_typing();
}
// AFX CODE BLOCK (polysoup-zodiacs) (special-types) >>

// AFX CODE BLOCK (selection-highlight) <<
void TSStatic::setSelectionFlags(U8 flags)
{
Parent::setSelectionFlags(flags);

if (!mShapeInstance || !isClientObject())
return;

if (!mShapeInstance->ownMaterialList())
return;

TSMaterialList* pMatList = mShapeInstance->getMaterialList();
for (S32 j = 0; j < pMatList->size(); j++)
{
BaseMatInstance * bmi = pMatList->getMaterialInst(j);
bmi->setSelectionHighlighting(needsSelectionHighlighting());
}
}
// AFX CODE BLOCK (selection-highlight) >>
@@ -20,6 +20,14 @@
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------

//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
// Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
// Copyright (C) 2015 Faust Logic, Inc.
//
// Changes:
// polysoup-zodiacs -- zodiac rendering on polysoup enabled objects
//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//

#ifndef _TSSTATIC_H_
#define _TSSTATIC_H_

@@ -224,6 +232,28 @@ class TSStatic : public SceneObject

const Vector<S32>& getLOSDetails() const { return mLOSDetails; }

// AFX CODE BLOCK (polysoup-zodiacs) <<
private:
virtual void onStaticModified(const char* slotName, const char*newValue = NULL);
protected:
Vector<S32> mDecalDetails;
Vector<S32>* mDecalDetailsPtr;
public:
bool mIgnoreZodiacs;
bool mHasGradients;
bool mInvertGradientRange;
Point2F mGradientRangeUser;
Point2F mGradientRange;
// AFX CODE BLOCK (polysoup-zodiacs) >>

// AFX CODE BLOCK (special-types) <<
private:
void set_special_typing();
// AFX CODE BLOCK (special-types) >>

// AFX CODE BLOCK (selection-highlight) <<
virtual void setSelectionFlags(U8 flags);
// AFX CODE BLOCK (selection-highlight) >>
};

typedef TSStatic::MeshType TSMeshType;
@@ -151,16 +151,41 @@ class AITurretShapeData: public TurretShapeData {

//----------------------------------------------------------------------------

// AFX CODE BLOCK <<
// As shipped, AITurretShape plus the chain of classes it inherits from, consumes
// all 32 mask-bits. AFX uses one additional mask-bit in GameBase, which pushes
// AITurretShape over the mask-bit limit which will cause runtime crashes. As
// a workaround, AFX modifies AITurretShape so that it reuses the TurretUpdateMask
// defined by TurretShape rather than adding a unique TurretStateMask. This will
// make AITurretShape's network updates slightly less efficient, but should be
// acceptable for most uses of AITurretShape. If you plan to populate your levels
// with many AITurretShape objects, consider restoring it to use of a unique
// bit-mask, but if you do that, you will have to eliminate at use of at least one
// bit by one of it's parent classes. (FYI ShapeBase uses 20 bits.)
//
// Comment out this define if you want AITurretShape to define it's own bit-mask.
#define AFX_REUSE_TURRETSHAPE_MASKBITS
// AFX CODE BLOCK >>

class AITurretShape: public TurretShape
{
typedef TurretShape Parent;

protected:

// AFX CODE BLOCK (bug-fix) <<
#ifdef AFX_REUSE_TURRETSHAPE_MASKBITS
enum MaskBits {
TurretStateMask = Parent::TurretUpdateMask,
NextFreeMask = Parent::NextFreeMask
};
#else // ORIGINAL CODE
enum MaskBits {
TurretStateMask = Parent::NextFreeMask,
NextFreeMask = Parent::NextFreeMask << 1
};
#endif
// AFX CODE BLOCK >>

struct TargetInfo
{