123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "T3D/fx/fxShapeReplicator.h"
- #include "gfx/gfxDevice.h"
- #include "gfx/primBuilder.h"
- #include "console/consoleTypes.h"
- #include "core/stream/bitStream.h"
- #include "math/mRandom.h"
- #include "math/mathIO.h"
- #include "T3D/gameBase/gameConnection.h"
- #include "scene/sceneManager.h"
- #include "scene/sceneRenderState.h"
- #include "renderInstance/renderPassManager.h"
- #include "console/engineAPI.h"
- //------------------------------------------------------------------------------
- //
- // Put this in /example/common/editor/editor.tscript in function [Editor::create()] (around line 66).
- //
- // // Ignore Replicated fxStatic Instances.
- // EWorldEditor.ignoreObjClass("fxShapeReplicatedStatic");
- //
- //------------------------------------------------------------------------------
- //
- // Put this in /example/common/editor/EditorGui.tscript 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.tscript 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);
- ConsoleDocClass( fxShapeReplicator,
- "@brief An emitter for objects to replicate across an area.\n"
- "@ingroup Foliage\n"
- );
- ConsoleDocClass( fxShapeReplicatedStatic,
- "@brief The object definition for shapes that will be replicated across an area using an fxShapeReplicator.\n"
- "@ingroup Foliage\n"
- );
- //------------------------------------------------------------------------------
- // Class: fxShapeReplicator
- //------------------------------------------------------------------------------
- fxShapeReplicator::fxShapeReplicator()
- {
- // Setup NetObject.
- mTypeMask |= StaticObjectType;
- mNetFlags.set(Ghostable | ScopeAlways);
- // Reset Shape Count.
- mCurrentShapeCount = 0;
- // Reset Creation Area Angle Animation.
- mCreationAreaAngle = 0;
- // Reset Last Render Time.
- mLastRenderTime = 0;
- mPlacementSB = NULL;
- }
- //------------------------------------------------------------------------------
- fxShapeReplicator::~fxShapeReplicator()
- {
- mPlacementSB = NULL;
- }
- //------------------------------------------------------------------------------
- void fxShapeReplicator::initPersistFields()
- {
- docsURL;
- // Add out own persistent fields.
- addGroup( "Debugging" ); // MM: Added Group Header.
- addField( "HideReplications", TypeBool, Offset( mFieldData.mHideReplications, fxShapeReplicator ), "Replicated shapes are hidden when set to true." );
- addField( "ShowPlacementArea", TypeBool, Offset( mFieldData.mShowPlacementArea, fxShapeReplicator ), "Draw placement rings when set to true." );
- addField( "PlacementAreaHeight", TypeS32, Offset( mFieldData.mPlacementBandHeight, fxShapeReplicator ), "Height of the placement ring in world units." );
- addField( "PlacementColour", TypeColorF, Offset( mFieldData.mPlaceAreaColour, fxShapeReplicator ), "Color of the placement ring." );
- endGroup( "Debugging" ); // MM: Added Group Footer.
- addGroup( "Media" ); // MM: Added Group Header.
- addField( "ShapeFile", TypeShapeFilename, Offset( mFieldData.mShapeFile, fxShapeReplicator ), "Filename of shape to replicate." );
- endGroup( "Media" ); // MM: Added Group Footer.
- addGroup( "Replications" ); // MM: Added Group Header.
- addField( "Seed", TypeS32, Offset( mFieldData.mSeed, fxShapeReplicator ), "Random seed for shape placement." );
- addField( "ShapeCount", TypeS32, Offset( mFieldData.mShapeCount, fxShapeReplicator ), "Maximum shape instance count." );
- addField( "ShapeRetries", TypeS32, Offset( mFieldData.mShapeRetries, fxShapeReplicator ), "Number of times to try placing a shape instance before giving up." );
- endGroup( "Replications" ); // MM: Added Group Footer.
- addGroup( "Placement Radius" ); // MM: Added Group Header.
- addField( "InnerRadiusX", TypeS32, Offset( mFieldData.mInnerRadiusX, fxShapeReplicator ), "Placement area inner radius on the X axis" );
- addField( "InnerRadiusY", TypeS32, Offset( mFieldData.mInnerRadiusY, fxShapeReplicator ), "Placement area inner radius on the Y axis" );
- addField( "OuterRadiusX", TypeS32, Offset( mFieldData.mOuterRadiusX, fxShapeReplicator ), "Placement area outer radius on the X axis" );
- addField( "OuterRadiusY", TypeS32, Offset( mFieldData.mOuterRadiusY, fxShapeReplicator ), "Placement area outer radius on the Y axis" );
- endGroup( "Placement Radius" ); // MM: Added Group Footer.
- addGroup( "Restraints" ); // MM: Added Group Header.
- addField( "AllowOnTerrain", TypeBool, Offset( mFieldData.mAllowOnTerrain, fxShapeReplicator ), "Shapes will be placed on terrain when set." );
- addField( "AllowOnStatics", TypeBool, Offset( mFieldData.mAllowStatics, fxShapeReplicator ), "Shapes will be placed on Static shapes when set." );
- addField( "AllowOnWater", TypeBool, Offset( mFieldData.mAllowOnWater, fxShapeReplicator ), "Shapes will be placed on/under water when set." );
- addField( "AllowWaterSurface", TypeBool, Offset( mFieldData.mAllowWaterSurface, fxShapeReplicator ), "Shapes will be placed on water when set. Requires AllowOnWater." );
- addField( "AlignToTerrain", TypeBool, Offset( mFieldData.mAlignToTerrain, fxShapeReplicator ), "Align shapes to surface normal when set." );
- addField( "Interactions", TypeBool, Offset( mFieldData.mInteractions, fxShapeReplicator ), "Allow physics interactions with shapes." );
- addField( "AllowedTerrainSlope", TypeS32, Offset( mFieldData.mAllowedTerrainSlope, fxShapeReplicator ), "Maximum surface angle allowed for shape instances." );
- addField( "TerrainAlignment", TypePoint3F, Offset( mFieldData.mTerrainAlignment, fxShapeReplicator ), "Surface normals will be multiplied by these values when AlignToTerrain is enabled." );
- endGroup( "Restraints" ); // MM: Added Group Footer.
- addGroup( "Object Transforms" ); // MM: Added Group Header.
- addField( "ShapeScaleMin", TypePoint3F, Offset( mFieldData.mShapeScaleMin, fxShapeReplicator ), "Minimum shape scale." );
- addField( "ShapeScaleMax", TypePoint3F, Offset( mFieldData.mShapeScaleMax, fxShapeReplicator ), "Maximum shape scale." );
- addField( "ShapeRotateMin", TypePoint3F, Offset( mFieldData.mShapeRotateMin, fxShapeReplicator ), "Minimum shape rotation angles.");
- addField( "ShapeRotateMax", TypePoint3F, Offset( mFieldData.mShapeRotateMax, fxShapeReplicator ), "Maximum shape rotation angles." );
- addField( "OffsetZ", TypeS32, Offset( mFieldData.mOffsetZ, fxShapeReplicator ), "Offset shapes by this amount vertically." );
- endGroup( "Object Transforms" ); // MM: Added Group Footer.
- // Initialise parents' persistent fields.
- Parent::initPersistFields();
- }
- //------------------------------------------------------------------------------
- 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;
- // Don't create shapes if we are hiding replications.
- if (mFieldData.mHideReplications) return;
- // Cannot continue without shapes!
- if (String::compare(mFieldData.mShapeFile, "") == 0) return;
- // Check that we can position somewhere!
- if (!( mFieldData.mAllowOnTerrain ||
- 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.clear();
- // 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
- {
- // Get the Replicator Position.
- ShapePosition = getPosition();
- // Calculate a random offset
- HypX = RandomGen.randF(mFieldData.mInnerRadiusX, mFieldData.mOuterRadiusX);
- HypY = RandomGen.randF(mFieldData.mInnerRadiusY, mFieldData.mOuterRadiusY);
- Angle = RandomGen.randF(0, (F32)M_2PI);
- // Calcualte the new position.
- ShapePosition.x += HypX * mCos(Angle);
- ShapePosition.y += HypY * mSin(Angle);
- // 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 & StaticShapeObjectType) && !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.
- ShapeScale.set( RandomGen.randF(mFieldData.mShapeScaleMin.x, mFieldData.mShapeScaleMax.x),
- RandomGen.randF(mFieldData.mShapeScaleMin.y, mFieldData.mShapeScaleMax.y),
- RandomGen.randF(mFieldData.mShapeScaleMin.z, mFieldData.mShapeScaleMax.z));
- // Set Shape Scale.
- fxStatic->setScale(ShapeScale);
- // Lock it.
- fxStatic->setLocked(true);
- // Store Shape in Replicated Shapes Vector.
- //mReplicatedShapes[mCurrentShapeCount++] = fxStatic;
- mReplicatedShapes.push_back(fxStatic);
- }
- mCurrentShapeCount = mReplicatedShapes.size();
- // Take first Timestamp.
- mLastRenderTime = Platform::getVirtualMilliseconds();
- }
- //------------------------------------------------------------------------------
- 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.clear();
- // 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)
- {
- 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.minExtents.set( -0.5, -0.5, -0.5 );
- mObjBox.maxExtents.set( 0.5, 0.5, 0.5 );
- resetWorldBox();
- // Add to Scene.
- setRenderTransform(mObjToWorld);
- addToScene();
- // Register for notification when GhostAlways objects are done loading
- NetConnection::smGhostAlwaysDone.notify( this, &fxShapeReplicator::onGhostAlwaysDone );
- return true;
- }
- //------------------------------------------------------------------------------
- void fxShapeReplicator::onRemove()
- {
- // Remove the Replicator from the Replicator Set.
- dynamic_cast<SimSet*>(Sim::findObject("fxReplicatorSet"))->removeObject(this);
- NetConnection::smGhostAlwaysDone.remove( this, &fxShapeReplicator::onGhostAlwaysDone );
- removeFromScene();
- // Destroy Shapes.
- DestroyShapes();
- // Do Parent.
- Parent::onRemove();
- }
- //------------------------------------------------------------------------------
- void fxShapeReplicator::onGhostAlwaysDone()
- {
- RenewShapes();
- }
- //------------------------------------------------------------------------------
- void fxShapeReplicator::inspectPostApply()
- {
- // Set Parent.
- Parent::inspectPostApply();
- // Renew Shapes.
- RenewShapes();
- // Set Replication Mask.
- setMaskBits(ReplicationMask);
- }
- //------------------------------------------------------------------------------
- DefineEngineFunction(StartClientReplication, void, (),, "Activates the shape replicator.\n"
- "@tsexample\n"
- "// Call the function\n"
- "StartClientReplication()\n"
- "@endtsexample\n"
- "@ingroup Foliage"
- )
- {
- // 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!");
- }
- //------------------------------------------------------------------------------
- void fxShapeReplicator::prepRenderImage( SceneRenderState* state )
- {
- ObjectRenderInst *ri = state->getRenderPass()->allocInst<ObjectRenderInst>();
- ri->renderDelegate.bind(this, &fxShapeReplicator::renderObject);
- // The fxShapeReplicator isn't technically foliage but our debug
- // effect seems to render best as a Foliage type (translucent,
- // renders itself, no sorting)
- ri->type = RenderPassManager::RIT_Foliage;
- state->getRenderPass()->addInst( ri );
- }
- //------------------------------------------------------------------------------
- // Renders a triangle stripped oval
- void fxShapeReplicator::renderArc(const F32 fRadiusX, const F32 fRadiusY)
- {
- PrimBuild::begin(GFXTriangleStrip, 720);
- for (U32 Angle = mCreationAreaAngle; Angle < (mCreationAreaAngle+360); Angle++)
- {
- F32 XPos, YPos;
- // Calculate Position.
- XPos = fRadiusX * mCos(mDegToRad(-(F32)Angle));
- YPos = fRadiusY * mSin(mDegToRad(-(F32)Angle));
- // Set Colour.
- PrimBuild::color4f(mFieldData.mPlaceAreaColour.red,
- mFieldData.mPlaceAreaColour.green,
- mFieldData.mPlaceAreaColour.blue,
- AREA_ANIMATION_ARC * (Angle-mCreationAreaAngle));
- PrimBuild::vertex3f(XPos, YPos, -(F32)mFieldData.mPlacementBandHeight/2.0f);
- PrimBuild::vertex3f(XPos, YPos, +(F32)mFieldData.mPlacementBandHeight/2.0f);
- }
- PrimBuild::end();
- }
- // This currently uses the primbuilder, could convert out, but why allocate the buffer if we
- // never edit the misison?
- void fxShapeReplicator::renderPlacementArea(const F32 ElapsedTime)
- {
- if (gEditingMission && mFieldData.mShowPlacementArea)
- {
- GFX->pushWorldMatrix();
- GFX->multWorld(getTransform());
- if (!mPlacementSB)
- {
- GFXStateBlockDesc transparent;
- transparent.setCullMode(GFXCullNone);
- transparent.alphaTestEnable = true;
- transparent.setZReadWrite(true);
- transparent.zWriteEnable = false;
- transparent.setBlend(true, GFXBlendSrcAlpha, GFXBlendInvSrcAlpha);
- mPlacementSB = GFX->createStateBlock( transparent );
- }
- GFX->setStateBlock(mPlacementSB);
- // Do we need to draw the Outer Radius?
- if (mFieldData.mOuterRadiusX || mFieldData.mOuterRadiusY)
- renderArc((F32) mFieldData.mOuterRadiusX, (F32) mFieldData.mOuterRadiusY);
- // Inner radius?
- if (mFieldData.mInnerRadiusX || mFieldData.mInnerRadiusY)
- renderArc((F32) mFieldData.mInnerRadiusX, (F32) mFieldData.mInnerRadiusY);
- GFX->popWorldMatrix();
- mCreationAreaAngle = (U32)(mCreationAreaAngle + (1000 * ElapsedTime));
- mCreationAreaAngle = mCreationAreaAngle % 360;
- }
- }
- //------------------------------------------------------------------------------
- void fxShapeReplicator::renderObject(ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance* overrideMat)
- {
- if (overrideMat)
- return;
- // Return if placement area not needed.
- if (!mFieldData.mShowPlacementArea)
- return;
- // Calculate Elapsed Time and take new Timestamp.
- S32 Time = Platform::getVirtualMilliseconds();
- F32 ElapsedTime = (Time - mLastRenderTime) * 0.001f;
- mLastRenderTime = Time;
- renderPlacementArea(ElapsedTime);
- }
- //------------------------------------------------------------------------------
- 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.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.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);
- RenewShapes();
- }
- }
|