فهرست منبع

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

Lukas Joergensen 11 سال پیش
والد
کامیت
a8a141e73c
2فایلهای تغییر یافته به همراه432 افزوده شده و 0 حذف شده
  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_
+