Initial commit
This commit is contained in:
818
Torque/SDK/engine/game/fx/fxShapeReplicator.cc
Normal file
818
Torque/SDK/engine/game/fx/fxShapeReplicator.cc
Normal file
@@ -0,0 +1,818 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Written by Melvyn May, Started on 13th March 2002, finished 27th March 2002.
|
||||
//
|
||||
// "My code is written for the Torque community, so do your worst with it,
|
||||
// just don't rip-it-off and call it your own without even thanking me".
|
||||
//
|
||||
// - Melv (working hard to become an associate ... hint).
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dgl/dgl.h"
|
||||
#include "console/consoleTypes.h"
|
||||
#include "core/bitStream.h"
|
||||
#include "math/mRandom.h"
|
||||
#include "math/mathIO.h"
|
||||
#include "terrain/terrData.h"
|
||||
#include "game/gameConnection.h"
|
||||
#include "console/simBase.h"
|
||||
#include "sceneGraph/sceneGraph.h"
|
||||
#include "fxShapeReplicator.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Put this in /example/common/editor/editor.cs in function [Editor::create()] (around line 66).
|
||||
//
|
||||
// // Ignore Replicated fxStatic Instances.
|
||||
// EWorldEditor.ignoreObjClass("fxShapeReplicatedStatic");
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Put this in /example/common/editor/EditorGui.cs in [function Creator::init( %this )]
|
||||
//
|
||||
// %Environment_Item[8] = "fxShapeReplicator"; <-- ADD THIS.
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Put the function in /example/common/editor/ObjectBuilderGui.gui [around line 458] ...
|
||||
//
|
||||
// function ObjectBuilderGui::buildfxShapeReplicator(%this)
|
||||
// {
|
||||
// %this.className = "fxShapeReplicator";
|
||||
// %this.process();
|
||||
// }
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Put this in /example/common/client/missionDownload.cs in [function clientCmdMissionStartPhase3(%seq,%missionName)] (line 65)
|
||||
// after codeline 'onPhase2Complete();'.
|
||||
//
|
||||
// StartClientReplication();
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Put this in /engine/console/simBase.h (around line 509) in
|
||||
//
|
||||
// namespace Sim
|
||||
// {
|
||||
// DeclareNamedSet(fxReplicatorSet) <-- ADD THIS (Note no semi-colon).
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Put this in /engine/console/simBase.cc (around line 19) in
|
||||
//
|
||||
// ImplementNamedSet(fxReplicatorSet) <-- ADD THIS
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// Put this in /engine/console/simManager.cc [function void init()] (around line 269).
|
||||
//
|
||||
// namespace Sim
|
||||
// {
|
||||
// InstantiateNamedSet(fxReplicatorSet); <-- ADD THIS
|
||||
//
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern bool gEditingMission;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
IMPLEMENT_CO_NETOBJECT_V1(fxShapeReplicator);
|
||||
IMPLEMENT_CO_NETOBJECT_V1(fxShapeReplicatedStatic);
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Class: fxShapeReplicator
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
fxShapeReplicator::fxShapeReplicator()
|
||||
{
|
||||
// Setup NetObject.
|
||||
mTypeMask |= StaticObjectType | StaticTSObjectType | StaticRenderedObjectType;
|
||||
mAddedToScene = false;
|
||||
mNetFlags.set(Ghostable | ScopeAlways);
|
||||
|
||||
// Reset Client Replication Started.
|
||||
mClientReplicationStarted = false;
|
||||
|
||||
// Reset Shape Count.
|
||||
mCurrentShapeCount = 0;
|
||||
|
||||
// Reset Creation Area Angle Animation.
|
||||
mCreationAreaAngle = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
fxShapeReplicator::~fxShapeReplicator()
|
||||
{
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::initPersistFields()
|
||||
{
|
||||
// Initialise parents' persistent fields.
|
||||
Parent::initPersistFields();
|
||||
|
||||
// Add out own persistent fields.
|
||||
addGroup( "Debugging" );
|
||||
addField( "HideReplications", TypeBool, Offset( mFieldData.mHideReplications, fxShapeReplicator ) );
|
||||
addField( "ShowPlacementArea", TypeBool, Offset( mFieldData.mShowPlacementArea, fxShapeReplicator ) );
|
||||
addField( "PlacementAreaHeight",TypeS32, Offset( mFieldData.mPlacementBandHeight, fxShapeReplicator ) );
|
||||
addField( "PlacementColour", TypeColorF, Offset( mFieldData.mPlaceAreaColour, fxShapeReplicator ) );
|
||||
endGroup( "Debugging" );
|
||||
|
||||
addGroup( "Media" );
|
||||
addField( "ShapeFile", TypeFilename, Offset( mFieldData.mShapeFile, fxShapeReplicator ) );
|
||||
endGroup( "Media" );
|
||||
|
||||
addGroup( "Replications" );
|
||||
addField( "Seed", TypeS32, Offset( mFieldData.mSeed, fxShapeReplicator ) );
|
||||
addField( "ShapeCount", TypeS32, Offset( mFieldData.mShapeCount, fxShapeReplicator ) );
|
||||
addField( "ShapeRetries", TypeS32, Offset( mFieldData.mShapeRetries, fxShapeReplicator ) );
|
||||
endGroup( "Replications" );
|
||||
|
||||
addGroup( "Placement Radius" );
|
||||
addField( "InnerRadiusX", TypeS32, Offset( mFieldData.mInnerRadiusX, fxShapeReplicator ) );
|
||||
addField( "InnerRadiusY", TypeS32, Offset( mFieldData.mInnerRadiusY, fxShapeReplicator ) );
|
||||
addField( "OuterRadiusX", TypeS32, Offset( mFieldData.mOuterRadiusX, fxShapeReplicator ) );
|
||||
addField( "OuterRadiusY", TypeS32, Offset( mFieldData.mOuterRadiusY, fxShapeReplicator ) );
|
||||
endGroup( "Placement Radius" );
|
||||
|
||||
addGroup( "Restraints" );
|
||||
addField( "AllowOnTerrain", TypeBool, Offset( mFieldData.mAllowOnTerrain, fxShapeReplicator ) );
|
||||
addField( "AllowOnInteriors", TypeBool, Offset( mFieldData.mAllowOnInteriors, fxShapeReplicator ) );
|
||||
addField( "AllowOnStatics", TypeBool, Offset( mFieldData.mAllowStatics, fxShapeReplicator ) );
|
||||
addField( "AllowOnWater", TypeBool, Offset( mFieldData.mAllowOnWater, fxShapeReplicator ) );
|
||||
addField( "AllowWaterSurface", TypeBool, Offset( mFieldData.mAllowWaterSurface, fxShapeReplicator ) );
|
||||
addField( "AlignToTerrain", TypeBool, Offset( mFieldData.mAlignToTerrain, fxShapeReplicator ) );
|
||||
addField( "Interactions", TypeBool, Offset( mFieldData.mInteractions, fxShapeReplicator ) );
|
||||
addField( "AllowedTerrainSlope",TypeS32, Offset( mFieldData.mAllowedTerrainSlope, fxShapeReplicator ) );
|
||||
addField( "TerrainAlignment", TypePoint3F, Offset( mFieldData.mTerrainAlignment, fxShapeReplicator ) );
|
||||
endGroup( "Restraints" );
|
||||
|
||||
addGroup( "Object Transforms" );
|
||||
addField( "FixShapeAspect", TypeBool, Offset( mFieldData.mFixShapeAspect, fxShapeReplicator ) );
|
||||
addField( "ShapeScaleMin", TypePoint3F, Offset( mFieldData.mShapeScaleMin, fxShapeReplicator ) );
|
||||
addField( "ShapeScaleMax", TypePoint3F, Offset( mFieldData.mShapeScaleMax, fxShapeReplicator ) );
|
||||
addField( "ShapeRotateMin", TypePoint3F, Offset( mFieldData.mShapeRotateMin, fxShapeReplicator ) );
|
||||
addField( "ShapeRotateMax", TypePoint3F, Offset( mFieldData.mShapeRotateMax, fxShapeReplicator ) );
|
||||
addField( "OffsetZ", TypeS32, Offset( mFieldData.mOffsetZ, fxShapeReplicator ) );
|
||||
endGroup( "Object Transforms" );
|
||||
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::CreateShapes(void)
|
||||
{
|
||||
F32 HypX, HypY;
|
||||
F32 Angle;
|
||||
U32 RelocationRetry;
|
||||
Point3F ShapePosition;
|
||||
Point3F ShapeStart;
|
||||
Point3F ShapeEnd;
|
||||
Point3F ShapeScale;
|
||||
EulerF ShapeRotation;
|
||||
QuatF QRotation;
|
||||
bool CollisionResult;
|
||||
RayInfo RayEvent;
|
||||
TSShape* pShape;
|
||||
Container* pContainer;
|
||||
|
||||
|
||||
// Don't create shapes if we are hiding replications.
|
||||
if (mFieldData.mHideReplications) return;
|
||||
|
||||
// Cannot continue without shapes!
|
||||
if (mFieldData.mShapeFile == "") return;
|
||||
|
||||
// Check that we can position somewhere!
|
||||
if (!( mFieldData.mAllowOnTerrain ||
|
||||
mFieldData.mAllowOnInteriors ||
|
||||
mFieldData.mAllowStatics ||
|
||||
mFieldData.mAllowOnWater))
|
||||
{
|
||||
// Problem ...
|
||||
Con::warnf(ConsoleLogEntry::General, "[%s] - Could not place object, All alloweds are off!", getName());
|
||||
|
||||
// Return here.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check Shapes.
|
||||
AssertFatal(mCurrentShapeCount==0,"Shapes already present, this should not be possible!")
|
||||
|
||||
// Check that we have a shape...
|
||||
if (!mFieldData.mShapeFile) return;
|
||||
|
||||
// Set Seed.
|
||||
RandomGen.setSeed(mFieldData.mSeed);
|
||||
|
||||
// Set shape vector.
|
||||
mReplicatedShapes.reserve(mFieldData.mShapeCount);
|
||||
|
||||
// Add shapes.
|
||||
for (U32 idx = 0; idx < mFieldData.mShapeCount; idx++)
|
||||
{
|
||||
fxShapeReplicatedStatic* fxStatic;
|
||||
|
||||
// Create our static shape.
|
||||
fxStatic = new fxShapeReplicatedStatic();
|
||||
|
||||
// Set the 'shapeName' field.
|
||||
fxStatic->setField("shapeName", mFieldData.mShapeFile);
|
||||
|
||||
// Is this Replicator on the Server?
|
||||
if (isServerObject())
|
||||
// Yes, so stop it from Ghosting. (Hack, Hack, Hack!)
|
||||
fxStatic->touchNetFlags(Ghostable, false);
|
||||
else
|
||||
// No, so flag as ghost object. (Another damn Hack!)
|
||||
fxStatic->touchNetFlags(IsGhost, true);
|
||||
|
||||
// Register the Object.
|
||||
if (!fxStatic->registerObject())
|
||||
{
|
||||
// Problem ...
|
||||
Con::warnf(ConsoleLogEntry::General, "[%s] - Could not load shape file '%s'!", getName(), mFieldData.mShapeFile);
|
||||
|
||||
// Destroy Shape.
|
||||
delete fxStatic;
|
||||
|
||||
// Destroy existing hapes.
|
||||
DestroyShapes();
|
||||
|
||||
// Quit.
|
||||
return;
|
||||
}
|
||||
|
||||
// Get Allocated Shape.
|
||||
pShape = fxStatic->getShape();
|
||||
|
||||
// Reset Relocation Retry.
|
||||
RelocationRetry = mFieldData.mShapeRetries;
|
||||
|
||||
// Find it a home ...
|
||||
do
|
||||
{
|
||||
|
||||
// Calculate a random offset
|
||||
HypX = RandomGen.randF(mFieldData.mInnerRadiusX, mFieldData.mOuterRadiusX);
|
||||
HypY = RandomGen.randF(mFieldData.mInnerRadiusY, mFieldData.mOuterRadiusY);
|
||||
Angle = RandomGen.randF(0, M_2PI);
|
||||
|
||||
// Calculate the new random position (in local space).
|
||||
Point3F randomShapePosLocal;
|
||||
randomShapePosLocal.x = HypX * mCos(Angle);
|
||||
randomShapePosLocal.y = HypY * mSin(Angle);
|
||||
|
||||
// Transform into world space coordinates
|
||||
Point3F shapePosWorld;
|
||||
MatrixF objToWorld = getRenderTransform();
|
||||
objToWorld.mulP(randomShapePosLocal, &shapePosWorld);
|
||||
ShapePosition = shapePosWorld;
|
||||
|
||||
// Initialise RayCast Search Start/End Positions.
|
||||
ShapeStart = ShapeEnd = ShapePosition;
|
||||
ShapeStart.z = 2000.f;
|
||||
ShapeEnd.z= -2000.f;
|
||||
|
||||
// Is this the Server?
|
||||
if (isServerObject())
|
||||
// Perform Ray Cast Collision on Server Terrain.
|
||||
CollisionResult = gServerContainer.castRay(ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent);
|
||||
else
|
||||
// Perform Ray Cast Collision on Client Terrain.
|
||||
CollisionResult = gClientContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_COLLISION_MASK, &RayEvent);
|
||||
|
||||
// Did we hit anything?
|
||||
if (CollisionResult)
|
||||
{
|
||||
// For now, let's pretend we didn't get a collision.
|
||||
CollisionResult = false;
|
||||
|
||||
// Yes, so get it's type.
|
||||
U32 CollisionType = RayEvent.object->getTypeMask();
|
||||
|
||||
// Check Illegal Placements.
|
||||
if (((CollisionType & TerrainObjectType) && !mFieldData.mAllowOnTerrain) ||
|
||||
((CollisionType & InteriorObjectType) && !mFieldData.mAllowOnInteriors) ||
|
||||
((CollisionType & StaticTSObjectType) && !mFieldData.mAllowStatics) ||
|
||||
((CollisionType & WaterObjectType) && !mFieldData.mAllowOnWater) ) continue;
|
||||
|
||||
// If we collided with water and are not allowing on the water surface then let's find the
|
||||
// terrain underneath and pass this on as the original collision else fail.
|
||||
//
|
||||
// NOTE:- We need to do this on the server/client as appropriate.
|
||||
if ((CollisionType & WaterObjectType) && !mFieldData.mAllowWaterSurface)
|
||||
{
|
||||
// Is this the Server?
|
||||
if (isServerObject())
|
||||
{
|
||||
// Yes, so do it on the server container.
|
||||
if (!gServerContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, so do it on the client container.
|
||||
if (!gClientContainer.castRay( ShapeStart, ShapeEnd, FXREPLICATOR_NOWATER_COLLISION_MASK, &RayEvent)) continue;
|
||||
}
|
||||
}
|
||||
|
||||
// We passed with flying colours so carry on.
|
||||
CollisionResult = true;
|
||||
}
|
||||
|
||||
// Invalidate if we are below Allowed Terrain Angle.
|
||||
if (RayEvent.normal.z < mSin(mDegToRad(90.0f-mFieldData.mAllowedTerrainSlope))) CollisionResult = false;
|
||||
|
||||
// Wait until we get a collision.
|
||||
} while(!CollisionResult && --RelocationRetry);
|
||||
|
||||
// Check for Relocation Problem.
|
||||
if (RelocationRetry > 0)
|
||||
{
|
||||
// Adjust Impact point.
|
||||
RayEvent.point.z += mFieldData.mOffsetZ;
|
||||
|
||||
// Set New Position.
|
||||
ShapePosition = RayEvent.point;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Warning.
|
||||
Con::warnf(ConsoleLogEntry::General, "[%s] - Could not find satisfactory position for shape '%s' on %s!", getName(), mFieldData.mShapeFile,isServerObject()?"Server":"Client");
|
||||
|
||||
// Unregister Object.
|
||||
fxStatic->unregisterObject();
|
||||
|
||||
// Destroy Shape.
|
||||
delete fxStatic;
|
||||
|
||||
// Skip to next.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get Shape Transform.
|
||||
MatrixF XForm = fxStatic->getTransform();
|
||||
|
||||
// Are we aligning to Terrain?
|
||||
if (mFieldData.mAlignToTerrain)
|
||||
{
|
||||
// Yes, so set rotation to Terrain Impact Normal.
|
||||
ShapeRotation = RayEvent.normal * mFieldData.mTerrainAlignment;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, so choose a new Rotation (in Radians).
|
||||
ShapeRotation.set( mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.x, mFieldData.mShapeRotateMax.x)),
|
||||
mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.y, mFieldData.mShapeRotateMax.y)),
|
||||
mDegToRad(RandomGen.randF(mFieldData.mShapeRotateMin.z, mFieldData.mShapeRotateMax.z)));
|
||||
}
|
||||
|
||||
// Set Quaternion Roation.
|
||||
QRotation.set(ShapeRotation);
|
||||
|
||||
// Set Transform Rotation.
|
||||
QRotation.setMatrix(&XForm);
|
||||
|
||||
// Set Position.
|
||||
XForm.setColumn(3, ShapePosition);
|
||||
|
||||
// Set Shape Position / Rotation.
|
||||
fxStatic->setTransform(XForm);
|
||||
|
||||
// Choose a new Scale.
|
||||
F32 scaleX, scaleY, scaleZ;
|
||||
|
||||
// Choose a random X-Scale.
|
||||
scaleX = RandomGen.randF(mFieldData.mShapeScaleMin.x, mFieldData.mShapeScaleMax.x);
|
||||
|
||||
// Fix Shape Aspect?
|
||||
if ( mFieldData.mFixShapeAspect )
|
||||
{
|
||||
// Yes, so use Scale-X for all axis.
|
||||
scaleY = scaleZ = scaleX;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No, so choose Scale-Y/Z.
|
||||
scaleY = RandomGen.randF(mFieldData.mShapeScaleMin.y, mFieldData.mShapeScaleMax.y);
|
||||
scaleZ = RandomGen.randF(mFieldData.mShapeScaleMin.z, mFieldData.mShapeScaleMax.z);
|
||||
}
|
||||
|
||||
// Set Shape Scale.
|
||||
ShapeScale.set( scaleX, scaleY, scaleZ );
|
||||
|
||||
// Set Shape Scale.
|
||||
fxStatic->setScale(ShapeScale);
|
||||
|
||||
// Lock it.
|
||||
fxStatic->setLocked(true);
|
||||
|
||||
// Store Shape in Replicated Shapes Vector.
|
||||
mReplicatedShapes[mCurrentShapeCount++] = fxStatic;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::DestroyShapes(void)
|
||||
{
|
||||
// Finish if we didn't create any shapes.
|
||||
if (mCurrentShapeCount == 0) return;
|
||||
|
||||
// Remove shapes.
|
||||
for (U32 idx = 0; idx < mCurrentShapeCount; idx++)
|
||||
{
|
||||
fxShapeReplicatedStatic* fxStatic;
|
||||
|
||||
// Fetch the Shape Object.
|
||||
fxStatic = mReplicatedShapes[idx];
|
||||
|
||||
// Got a Shape?
|
||||
if (fxStatic)
|
||||
{
|
||||
// Unlock it.
|
||||
fxStatic->setLocked(false);
|
||||
|
||||
// Unregister the object.
|
||||
fxStatic->unregisterObject();
|
||||
|
||||
// Delete it.
|
||||
delete fxStatic;
|
||||
}
|
||||
}
|
||||
|
||||
// Empty the Replicated Shapes Vector.
|
||||
mReplicatedShapes.empty();
|
||||
|
||||
// Reset Shape Count.
|
||||
mCurrentShapeCount = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::RenewShapes(void)
|
||||
{
|
||||
// Destroy any shapes.
|
||||
DestroyShapes();
|
||||
|
||||
// Don't create shapes on the Server if we don't need interactions.
|
||||
if (isServerObject() && !mFieldData.mInteractions) return;
|
||||
|
||||
// Create Shapes.
|
||||
CreateShapes();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::StartUp(void)
|
||||
{
|
||||
// Flag, Client Replication Started.
|
||||
mClientReplicationStarted = true;
|
||||
|
||||
// Renew shapes.
|
||||
RenewShapes();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool fxShapeReplicator::onAdd()
|
||||
{
|
||||
if(!Parent::onAdd()) return(false);
|
||||
|
||||
// Add the Replicator to the Replicator Set.
|
||||
dynamic_cast<SimSet*>(Sim::findObject("fxReplicatorSet"))->addObject(this);
|
||||
|
||||
// Set Default Object Box.
|
||||
mObjBox.min.set( -0.5, -0.5, -0.5 );
|
||||
mObjBox.max.set( 0.5, 0.5, 0.5 );
|
||||
|
||||
// Reset the World Box.
|
||||
resetWorldBox();
|
||||
|
||||
// Are we editing the Mission?
|
||||
if(gEditingMission)
|
||||
{
|
||||
// Yes, so set the Render Transform.
|
||||
setRenderTransform(mObjToWorld);
|
||||
|
||||
// Add to Scene.
|
||||
addToScene();
|
||||
mAddedToScene = true;
|
||||
|
||||
// If we are in the editor and we are on the client then
|
||||
// we can manually startup replication.
|
||||
if (isClientObject()) mClientReplicationStarted = true;
|
||||
}
|
||||
|
||||
// Renew shapes on Server.
|
||||
if (isServerObject()) RenewShapes();
|
||||
|
||||
// Return OK.
|
||||
return(true);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::onRemove()
|
||||
{
|
||||
// Remove the Replicator from the Replicator Set.
|
||||
dynamic_cast<SimSet*>(Sim::findObject("fxReplicatorSet"))->removeObject(this);
|
||||
|
||||
// Are we editing the Mission?
|
||||
if(gEditingMission)
|
||||
{
|
||||
// Yes, so remove from Scene.
|
||||
removeFromScene();
|
||||
mAddedToScene = false;
|
||||
}
|
||||
|
||||
// Destroy Shapes.
|
||||
DestroyShapes();
|
||||
|
||||
// Do Parent.
|
||||
Parent::onRemove();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::inspectPostApply()
|
||||
{
|
||||
// Set Parent.
|
||||
Parent::inspectPostApply();
|
||||
|
||||
// Renew Shapes.
|
||||
RenewShapes();
|
||||
|
||||
// Set Replication Mask.
|
||||
setMaskBits(ReplicationMask);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::onEditorEnable()
|
||||
{
|
||||
// Are we in the Scene?
|
||||
if(!mAddedToScene)
|
||||
{
|
||||
// No, so add to scene.
|
||||
addToScene();
|
||||
mAddedToScene = true;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::onEditorDisable()
|
||||
{
|
||||
// Are we in the Scene?
|
||||
if(mAddedToScene)
|
||||
{
|
||||
// Yes, so remove from scene.
|
||||
removeFromScene();
|
||||
mAddedToScene = false;
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
ConsoleFunction(StartClientReplication, void, 1, 1, "StartClientReplication()")
|
||||
{
|
||||
// Find the Replicator Set.
|
||||
SimSet *fxReplicatorSet = dynamic_cast<SimSet*>(Sim::findObject("fxReplicatorSet"));
|
||||
|
||||
// Return if Error.
|
||||
if (!fxReplicatorSet) return;
|
||||
|
||||
// StartUp Replication Object.
|
||||
for (SimSetIterator itr(fxReplicatorSet); *itr; ++itr)
|
||||
{
|
||||
// Fetch the Replicator Object.
|
||||
fxShapeReplicator* Replicator = static_cast<fxShapeReplicator*>(*itr);
|
||||
// Start Client Objects Only.
|
||||
if (Replicator->isClientObject()) Replicator->StartUp();
|
||||
}
|
||||
// Info ...
|
||||
Con::printf("Client Replication Startup has Happened!");
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
bool fxShapeReplicator::prepRenderImage(SceneState* state, const U32 stateKey, const U32 startZone,
|
||||
const bool modifyBaseZoneState)
|
||||
{
|
||||
// Return if last state.
|
||||
if (isLastState(state, stateKey)) return false;
|
||||
// Set Last State.
|
||||
setLastState(state, stateKey);
|
||||
|
||||
// Is Object Rendered?
|
||||
if (state->isObjectRendered(this))
|
||||
{
|
||||
// Yes, so get a SceneRenderImage.
|
||||
SceneRenderImage* image = new SceneRenderImage;
|
||||
// Populate it.
|
||||
image->obj = this;
|
||||
image->sortType = SceneRenderImage::Normal;
|
||||
// Insert it into the scene images.
|
||||
state->insertRenderImage(image);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::renderObject(SceneState* state, SceneRenderImage*)
|
||||
{
|
||||
// Return if placement area not needed.
|
||||
if (!mFieldData.mShowPlacementArea) return;
|
||||
|
||||
// Check we are in Canonical State.
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on entry");
|
||||
|
||||
// Setup out the Projection Matrix/Viewport.
|
||||
RectI viewport;
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPushMatrix();
|
||||
dglGetViewport(&viewport);
|
||||
state->setupBaseProjection();
|
||||
|
||||
// Setup our rendering state.
|
||||
glPushMatrix();
|
||||
dglMultMatrix(&getTransform());
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
// Do we need to draw the Inner Radius?
|
||||
if (mFieldData.mInnerRadiusX || mFieldData.mInnerRadiusY)
|
||||
{
|
||||
// Yes, so draw Inner Radius.
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 Angle = mCreationAreaAngle; Angle < (mCreationAreaAngle+360); Angle++)
|
||||
{
|
||||
F32 XPos, YPos;
|
||||
|
||||
// Calculate Position.
|
||||
XPos = mFieldData.mInnerRadiusX * mCos(mDegToRad(-(F32)Angle));
|
||||
YPos = mFieldData.mInnerRadiusY * mSin(mDegToRad(-(F32)Angle));
|
||||
|
||||
// Set Colour.
|
||||
glColor4f( mFieldData.mPlaceAreaColour.red,
|
||||
mFieldData.mPlaceAreaColour.green,
|
||||
mFieldData.mPlaceAreaColour.blue,
|
||||
AREA_ANIMATION_ARC * (Angle-mCreationAreaAngle));
|
||||
|
||||
// Draw Arc Line.
|
||||
glVertex3f( XPos, YPos, -(F32)mFieldData.mPlacementBandHeight/2.0f);
|
||||
glVertex3f( XPos, YPos, +(F32)mFieldData.mPlacementBandHeight/2.0f);
|
||||
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Do we need to draw the Outer Radius?
|
||||
if (mFieldData.mOuterRadiusX || mFieldData.mOuterRadiusY)
|
||||
{
|
||||
// Yes, so draw Outer Radius.
|
||||
glBegin(GL_TRIANGLE_STRIP);
|
||||
for (U32 Angle = mCreationAreaAngle; Angle < (mCreationAreaAngle+360); Angle++)
|
||||
{
|
||||
F32 XPos, YPos;
|
||||
|
||||
// Calculate Position.
|
||||
XPos = mFieldData.mOuterRadiusX * mCos(mDegToRad(-(F32)Angle));
|
||||
YPos = mFieldData.mOuterRadiusY * mSin(mDegToRad(-(F32)Angle));
|
||||
|
||||
// Set Colour.
|
||||
glColor4f( mFieldData.mPlaceAreaColour.red,
|
||||
mFieldData.mPlaceAreaColour.green,
|
||||
mFieldData.mPlaceAreaColour.blue,
|
||||
AREA_ANIMATION_ARC * (Angle-mCreationAreaAngle));
|
||||
|
||||
// Draw Arc Line.
|
||||
glVertex3f( XPos, YPos, -(F32)mFieldData.mPlacementBandHeight/2.0f);
|
||||
glVertex3f( XPos, YPos, +(F32)mFieldData.mPlacementBandHeight/2.0f);
|
||||
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
// Restore rendering state.
|
||||
glDisable(GL_BLEND);
|
||||
glPopMatrix();
|
||||
|
||||
// Animate Area Selection.
|
||||
mCreationAreaAngle += 20;
|
||||
mCreationAreaAngle = mCreationAreaAngle % 360;
|
||||
|
||||
// Restore out nice and friendly canonical state.
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glPopMatrix();
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
dglSetViewport(viewport);
|
||||
|
||||
// Check we have restored Canonical State.
|
||||
AssertFatal(dglIsInCanonicalState(), "Error, GL not in canonical state on exit");
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
U32 fxShapeReplicator::packUpdate(NetConnection * con, U32 mask, BitStream * stream)
|
||||
{
|
||||
// Pack Parent.
|
||||
U32 retMask = Parent::packUpdate(con, mask, stream);
|
||||
|
||||
// Write Replication Flag.
|
||||
if (stream->writeFlag(mask & ReplicationMask))
|
||||
{
|
||||
stream->writeAffineTransform(mObjToWorld); // Replicator Position.
|
||||
|
||||
stream->writeInt(mFieldData.mSeed, 32); // Replicator Seed.
|
||||
stream->writeInt(mFieldData.mShapeCount, 32); // Shapes Count.
|
||||
stream->writeInt(mFieldData.mShapeRetries, 32); // Shapes Retries.
|
||||
stream->writeString(mFieldData.mShapeFile);
|
||||
stream->writeInt(mFieldData.mInnerRadiusX, 32); // Shapes Inner Radius X.
|
||||
stream->writeInt(mFieldData.mInnerRadiusY, 32); // Shapes Inner Radius Y.
|
||||
stream->writeInt(mFieldData.mOuterRadiusX, 32); // Shapes Outer Radius X.
|
||||
stream->writeInt(mFieldData.mOuterRadiusY, 32); // Shapes Outer Radius Y.
|
||||
mathWrite(*stream, mFieldData.mShapeScaleMin); // Shapes Scale Min.
|
||||
mathWrite(*stream, mFieldData.mShapeScaleMax); // Shapes Scale Max.
|
||||
mathWrite(*stream, mFieldData.mShapeRotateMin); // Shapes Rotate Min.
|
||||
mathWrite(*stream, mFieldData.mShapeRotateMax); // Shapes Rotate Max.
|
||||
stream->writeSignedInt(mFieldData.mOffsetZ, 32); // Shapes Offset Z.
|
||||
stream->writeFlag(mFieldData.mAllowOnTerrain); // Allow on Terrain.
|
||||
stream->writeFlag(mFieldData.mAllowOnInteriors); // Allow on Interiors.
|
||||
stream->writeFlag(mFieldData.mAllowStatics); // Allow on Statics.
|
||||
stream->writeFlag(mFieldData.mAllowOnWater); // Allow on Water.
|
||||
stream->writeFlag(mFieldData.mAllowWaterSurface); // Allow on Water Surface.
|
||||
stream->writeSignedInt(mFieldData.mAllowedTerrainSlope, 32); // Shapes Offset Z.
|
||||
stream->writeFlag(mFieldData.mAlignToTerrain); // Shapes AlignToTerrain.
|
||||
mathWrite(*stream, mFieldData.mTerrainAlignment); // Write Terrain Alignment.
|
||||
stream->writeFlag(mFieldData.mHideReplications); // Hide Replications.
|
||||
stream->writeFlag(mFieldData.mInteractions); // Shape Interactions.
|
||||
stream->writeFlag(mFieldData.mShowPlacementArea); // Show Placement Area Flag.
|
||||
stream->writeInt(mFieldData.mPlacementBandHeight, 32); // Placement Area Height.
|
||||
stream->write(mFieldData.mPlaceAreaColour);
|
||||
}
|
||||
|
||||
// Were done ...
|
||||
return(retMask);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
void fxShapeReplicator::unpackUpdate(NetConnection * con, BitStream * stream)
|
||||
{
|
||||
// Unpack Parent.
|
||||
Parent::unpackUpdate(con, stream);
|
||||
|
||||
// Read Replication Details.
|
||||
if(stream->readFlag())
|
||||
{
|
||||
MatrixF ReplicatorObjectMatrix;
|
||||
|
||||
stream->readAffineTransform(&ReplicatorObjectMatrix); // Replication Position.
|
||||
|
||||
mFieldData.mSeed = stream->readInt(32); // Replicator Seed.
|
||||
mFieldData.mShapeCount = stream->readInt(32); // Shapes Count.
|
||||
mFieldData.mShapeRetries = stream->readInt(32); // Shapes Retries.
|
||||
mFieldData.mShapeFile = stream->readSTString(); // Shape File.
|
||||
mFieldData.mInnerRadiusX = stream->readInt(32); // Shapes Inner Radius X.
|
||||
mFieldData.mInnerRadiusY = stream->readInt(32); // Shapes Inner Radius Y.
|
||||
mFieldData.mOuterRadiusX = stream->readInt(32); // Shapes Outer Radius X.
|
||||
mFieldData.mOuterRadiusY = stream->readInt(32); // Shapes Outer Radius Y.
|
||||
mathRead(*stream, &mFieldData.mShapeScaleMin); // Shapes Scale Min.
|
||||
mathRead(*stream, &mFieldData.mShapeScaleMax); // Shapes Scale Max.
|
||||
mathRead(*stream, &mFieldData.mShapeRotateMin); // Shapes Rotate Min.
|
||||
mathRead(*stream, &mFieldData.mShapeRotateMax); // Shapes Rotate Max.
|
||||
mFieldData.mOffsetZ = stream->readSignedInt(32); // Shapes Offset Z.
|
||||
mFieldData.mAllowOnTerrain = stream->readFlag(); // Allow on Terrain.
|
||||
mFieldData.mAllowOnInteriors = stream->readFlag(); // Allow on Interiors.
|
||||
mFieldData.mAllowStatics = stream->readFlag(); // Allow on Statics.
|
||||
mFieldData.mAllowOnWater = stream->readFlag(); // Allow on Water.
|
||||
mFieldData.mAllowWaterSurface = stream->readFlag(); // Allow on Water Surface.
|
||||
mFieldData.mAllowedTerrainSlope = stream->readSignedInt(32); // Allowed Terrain Slope.
|
||||
mFieldData.mAlignToTerrain = stream->readFlag(); // Read AlignToTerrain.
|
||||
mathRead(*stream, &mFieldData.mTerrainAlignment); // Read Terrain Alignment.
|
||||
mFieldData.mHideReplications = stream->readFlag(); // Hide Replications.
|
||||
mFieldData.mInteractions = stream->readFlag(); // Read Interactions.
|
||||
mFieldData.mShowPlacementArea = stream->readFlag(); // Show Placement Area Flag.
|
||||
mFieldData.mPlacementBandHeight = stream->readInt(32); // Placement Area Height.
|
||||
stream->read(&mFieldData.mPlaceAreaColour);
|
||||
|
||||
// Set Transform.
|
||||
setTransform(ReplicatorObjectMatrix);
|
||||
|
||||
// Renew Shapes (only if replication has started).
|
||||
if (mClientReplicationStarted) RenewShapes();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user