Browse Source

RibbonNode class.
Simple RibbonNode class for an implementation similar to that of
ParticleEmitterNodes. Datablock currently has no static fields.

Lukas Joergensen 11 years ago
parent
commit
a8a141e73c
2 changed files with 432 additions and 0 deletions
  1. 324 0
      Engine/source/T3D/fx/ribbonNode.cpp
  2. 108 0
      Engine/source/T3D/fx/ribbonNode.h

+ 324 - 0
Engine/source/T3D/fx/ribbonNode.cpp

@@ -0,0 +1,324 @@
+//-----------------------------------------------------------------------------
+// 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 "ribbonNode.h"
+#include "console/consoleTypes.h"
+#include "core/stream/bitStream.h"
+#include "T3D/fx/ribbon.h"
+#include "math/mathIO.h"
+#include "sim/netConnection.h"
+#include "console/engineAPI.h"
+
+IMPLEMENT_CO_DATABLOCK_V1(RibbonNodeData);
+IMPLEMENT_CO_NETOBJECT_V1(RibbonNode);
+
+ConsoleDocClass( RibbonNodeData,
+   "@brief Contains additional data to be associated with a RibbonNode."
+   "@ingroup FX\n"
+   );
+
+ConsoleDocClass( RibbonNode, ""
+   );
+
+
+//-----------------------------------------------------------------------------
+// RibbonNodeData
+//-----------------------------------------------------------------------------
+RibbonNodeData::RibbonNodeData()
+{
+}
+
+RibbonNodeData::~RibbonNodeData()
+{
+
+}
+
+//-----------------------------------------------------------------------------
+// initPersistFields
+//-----------------------------------------------------------------------------
+void RibbonNodeData::initPersistFields()
+{
+   Parent::initPersistFields();
+}
+
+
+//-----------------------------------------------------------------------------
+// RibbonNode
+//-----------------------------------------------------------------------------
+RibbonNode::RibbonNode()
+{
+   // Todo: ScopeAlways?
+   mNetFlags.set(Ghostable);
+   mTypeMask |= EnvironmentObjectType;
+
+   mActive = true;
+
+   mDataBlock          = NULL;
+   mRibbonDatablock   = NULL;
+   mRibbonDatablockId = 0;
+   mRibbon            = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Destructor
+//-----------------------------------------------------------------------------
+RibbonNode::~RibbonNode()
+{
+   //
+}
+
+//-----------------------------------------------------------------------------
+// initPersistFields
+//-----------------------------------------------------------------------------
+void RibbonNode::initPersistFields()
+{
+   addField( "active", TYPEID< bool >(), Offset(mActive,RibbonNode),
+      "Controls whether ribbon is emitted from this node." );
+   addField( "ribbon",  TYPEID< RibbonData >(), Offset(mRibbonDatablock, RibbonNode),
+      "Datablock to use for the ribbon." );
+
+   Parent::initPersistFields();
+}
+
+//-----------------------------------------------------------------------------
+// onAdd
+//-----------------------------------------------------------------------------
+bool RibbonNode::onAdd()
+{
+   if( !Parent::onAdd() )
+      return false;
+
+   if( !mRibbonDatablock && mRibbonDatablockId != 0 )
+   {
+      if( Sim::findObject(mRibbonDatablockId, mRibbonDatablock) == false )
+         Con::errorf(ConsoleLogEntry::General, "RibbonNode::onAdd: Invalid packet, bad datablockId(mRibbonDatablock): %d", mRibbonDatablockId);
+   }
+
+   if( isClientObject() )
+   {
+      setRibbonDatablock( mRibbonDatablock );
+   }
+   else
+   {
+      setMaskBits( StateMask | EmitterDBMask );
+   }
+
+   mObjBox.minExtents.set(-0.5, -0.5, -0.5);
+   mObjBox.maxExtents.set( 0.5,  0.5,  0.5);
+   resetWorldBox();
+   addToScene();
+
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+// onRemove
+//-----------------------------------------------------------------------------
+void RibbonNode::onRemove()
+{
+   removeFromScene();
+   if( isClientObject() )
+   {
+      if( mRibbon )
+      {
+         mRibbon->deleteOnEnd();
+         mRibbon = NULL;
+      }
+   }
+
+   Parent::onRemove();
+}
+
+//-----------------------------------------------------------------------------
+// onNewDataBlock
+//-----------------------------------------------------------------------------
+bool RibbonNode::onNewDataBlock( GameBaseData *dptr, bool reload )
+{
+   mDataBlock = dynamic_cast<RibbonNodeData*>( dptr );
+   if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
+      return false;
+
+   // Todo: Uncomment if this is a "leaf" class
+   scriptOnNewDataBlock();
+   return true;
+}
+
+//-----------------------------------------------------------------------------
+void RibbonNode::inspectPostApply()
+{
+   Parent::inspectPostApply();
+   setMaskBits(StateMask | EmitterDBMask);
+}
+
+//-----------------------------------------------------------------------------
+// processTick
+//-----------------------------------------------------------------------------
+void RibbonNode::processTick(const Move* move)
+{
+   Parent::processTick(move);
+
+   if ( isMounted() )
+   {
+      MatrixF mat;
+      mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );
+      setTransform( mat );
+   }
+}
+
+//-----------------------------------------------------------------------------
+// advanceTime
+//-----------------------------------------------------------------------------
+void RibbonNode::advanceTime(F32 dt)
+{
+   Parent::advanceTime(dt);
+
+   if(!mActive || mRibbon.isNull() || !mDataBlock)
+      return;
+
+   MatrixF trans(getTransform());
+   Point3F pos = getPosition();
+   mRibbon->addSegmentPoint(pos, trans);
+}
+
+//-----------------------------------------------------------------------------
+// packUpdate
+//-----------------------------------------------------------------------------
+U32 RibbonNode::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
+{
+   U32 retMask = Parent::packUpdate(con, mask, stream);
+
+   if ( stream->writeFlag( mask & InitialUpdateMask ) )
+   {
+      mathWrite(*stream, getTransform());
+      mathWrite(*stream, getScale());
+   }
+
+   if ( stream->writeFlag( mask & EmitterDBMask ) )
+   {
+      if( stream->writeFlag(mRibbonDatablock != NULL) )
+      {
+         stream->writeRangedU32(mRibbonDatablock->getId(), DataBlockObjectIdFirst,
+            DataBlockObjectIdLast);
+      }
+   }
+
+   if ( stream->writeFlag( mask & StateMask ) )
+   {
+      stream->writeFlag( mActive );
+   }
+
+   return retMask;
+}
+
+//-----------------------------------------------------------------------------
+// unpackUpdate
+//-----------------------------------------------------------------------------
+void RibbonNode::unpackUpdate(NetConnection* con, BitStream* stream)
+{
+   Parent::unpackUpdate(con, stream);
+
+   if ( stream->readFlag() )
+   {
+      MatrixF temp;
+      Point3F tempScale;
+      mathRead(*stream, &temp);
+      mathRead(*stream, &tempScale);
+
+      setScale(tempScale);
+      setTransform(temp);
+   }
+
+   if ( stream->readFlag() )
+   {
+      mRibbonDatablockId = stream->readFlag() ?
+         stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast) : 0;
+
+      RibbonData *emitterDB = NULL;
+      Sim::findObject( mRibbonDatablockId, emitterDB );
+      if ( isProperlyAdded() )
+         setRibbonDatablock( emitterDB );
+   }
+
+   if ( stream->readFlag() )
+   {
+      mActive = stream->readFlag();
+   }
+}
+
+//-----------------------------------------------------------------------------
+// setRibbonDatablock
+//-----------------------------------------------------------------------------
+void RibbonNode::setRibbonDatablock(RibbonData* data)
+{
+   if ( isServerObject() )
+   {
+      setMaskBits( EmitterDBMask );
+   }
+   else
+   {
+      Ribbon* pRibbon = NULL;
+      if ( data )
+      {
+         // Create emitter with new datablock
+         pRibbon = new Ribbon;
+         pRibbon->onNewDataBlock( data, false );
+         if( pRibbon->registerObject() == false )
+         {
+            Con::warnf(ConsoleLogEntry::General, "Could not register base ribbon of class: %s", data->getName() ? data->getName() : data->getIdString() );
+            delete pRibbon;
+            return;
+         }
+      }
+
+      // Replace emitter
+      if ( mRibbon )
+         mRibbon->deleteOnEnd();
+
+      mRibbon = pRibbon;
+   }
+
+   mRibbonDatablock = data;
+}
+
+DefineEngineMethod(RibbonNode, setRibbonDatablock, void, (RibbonData* ribbonDatablock), (0),
+   "Assigns the datablock for this ribbon node.\n"
+   "@param ribbonDatablock RibbonData datablock to assign\n"
+   "@tsexample\n"
+   "// Assign a new emitter datablock\n"
+   "%emitter.setRibbonDatablock( %ribbonDatablock );\n"
+   "@endtsexample\n" )
+{
+   if ( !ribbonDatablock )
+   {
+      Con::errorf("RibbonData datablock could not be found when calling setRibbonDataBlock in ribbonNode.");
+      return;
+   }
+
+   object->setRibbonDatablock(ribbonDatablock);
+}
+
+DefineEngineMethod(RibbonNode, setActive, void, (bool active),,
+   "Turns the ribbon on or off.\n"
+   "@param active New ribbon state\n" )
+{
+   object->setActive( active );
+}

+ 108 - 0
Engine/source/T3D/fx/ribbonNode.h

@@ -0,0 +1,108 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+
+#ifndef _RIBBON_NODE_H_
+#define _RIBBON_NODE_H_
+
+#ifndef _GAMEBASE_H_
+#include "T3D/gameBase/gameBase.h"
+#endif
+
+class RibbonData;
+class Ribbon;
+
+//*****************************************************************************
+// ParticleEmitterNodeData
+//*****************************************************************************
+class RibbonNodeData : public GameBaseData
+{
+   typedef GameBaseData Parent;
+
+   //-------------------------------------- Console set variables
+public:
+   F32 timeMultiple;
+
+   //-------------------------------------- load set variables
+
+public:
+   RibbonNodeData();
+   ~RibbonNodeData();
+
+   DECLARE_CONOBJECT(RibbonNodeData);
+   static void initPersistFields();
+};
+
+
+//*****************************************************************************
+// ParticleEmitterNode
+//*****************************************************************************
+class RibbonNode : public GameBase
+{
+   typedef GameBase Parent;
+
+   enum MaskBits
+   {
+      StateMask      = Parent::NextFreeMask << 0,
+      EmitterDBMask  = Parent::NextFreeMask << 1,
+      NextFreeMask   = Parent::NextFreeMask << 2,
+   };
+
+   RibbonNodeData* mDataBlock;
+
+protected:
+   bool onAdd();
+   void onRemove();
+   bool onNewDataBlock( GameBaseData *dptr, bool reload );
+   void inspectPostApply();
+
+   RibbonData* mRibbonDatablock;
+   S32 mRibbonDatablockId;
+
+   SimObjectPtr<Ribbon> mRibbon;
+
+   bool mActive;
+
+public:
+   RibbonNode();
+   ~RibbonNode();
+
+   Ribbon *getRibbonEmitter() {return mRibbon;}
+
+   // Time/Move Management
+
+   void processTick(const Move* move);
+   void advanceTime(F32 dt);
+
+   DECLARE_CONOBJECT(RibbonNode);
+   static void initPersistFields();
+
+   U32  packUpdate  (NetConnection *conn, U32 mask, BitStream* stream);
+   void unpackUpdate(NetConnection *conn,           BitStream* stream);
+
+   inline bool getActive( void )        { return mActive;                             };
+   inline void setActive( bool active ) { mActive = active; setMaskBits( StateMask ); };
+
+   void setRibbonDatablock(RibbonData* data);
+};
+
+#endif // _RIBBON_NODE_H_
+