ribbonNode.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2014 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "ribbonNode.h"
  23. #include "console/consoleTypes.h"
  24. #include "core/stream/bitStream.h"
  25. #include "T3D/fx/ribbon.h"
  26. #include "math/mathIO.h"
  27. #include "sim/netConnection.h"
  28. #include "console/engineAPI.h"
  29. IMPLEMENT_CO_DATABLOCK_V1(RibbonNodeData);
  30. IMPLEMENT_CO_NETOBJECT_V1(RibbonNode);
  31. ConsoleDocClass( RibbonNodeData,
  32. "@brief Contains additional data to be associated with a RibbonNode."
  33. "@ingroup FX\n"
  34. );
  35. ConsoleDocClass( RibbonNode, ""
  36. );
  37. //-----------------------------------------------------------------------------
  38. // RibbonNodeData
  39. //-----------------------------------------------------------------------------
  40. RibbonNodeData::RibbonNodeData()
  41. {
  42. }
  43. RibbonNodeData::~RibbonNodeData()
  44. {
  45. }
  46. //-----------------------------------------------------------------------------
  47. // initPersistFields
  48. //-----------------------------------------------------------------------------
  49. void RibbonNodeData::initPersistFields()
  50. {
  51. Parent::initPersistFields();
  52. }
  53. //-----------------------------------------------------------------------------
  54. // RibbonNode
  55. //-----------------------------------------------------------------------------
  56. RibbonNode::RibbonNode()
  57. {
  58. // Todo: ScopeAlways?
  59. mNetFlags.set(Ghostable);
  60. mTypeMask |= EnvironmentObjectType;
  61. mActive = true;
  62. mDataBlock = NULL;
  63. mRibbonDatablock = NULL;
  64. mRibbonDatablockId = 0;
  65. mRibbon = NULL;
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Destructor
  69. //-----------------------------------------------------------------------------
  70. RibbonNode::~RibbonNode()
  71. {
  72. //
  73. }
  74. //-----------------------------------------------------------------------------
  75. // initPersistFields
  76. //-----------------------------------------------------------------------------
  77. void RibbonNode::initPersistFields()
  78. {
  79. addField( "active", TYPEID< bool >(), Offset(mActive,RibbonNode),
  80. "Controls whether ribbon is emitted from this node." );
  81. addField( "ribbon", TYPEID< RibbonData >(), Offset(mRibbonDatablock, RibbonNode),
  82. "Datablock to use for the ribbon." );
  83. Parent::initPersistFields();
  84. }
  85. //-----------------------------------------------------------------------------
  86. // onAdd
  87. //-----------------------------------------------------------------------------
  88. bool RibbonNode::onAdd()
  89. {
  90. if( !Parent::onAdd() )
  91. return false;
  92. if( !mRibbonDatablock && mRibbonDatablockId != 0 )
  93. {
  94. if( Sim::findObject(mRibbonDatablockId, mRibbonDatablock) == false )
  95. Con::errorf(ConsoleLogEntry::General, "RibbonNode::onAdd: Invalid packet, bad datablockId(mRibbonDatablock): %d", mRibbonDatablockId);
  96. }
  97. if( isClientObject() )
  98. {
  99. setRibbonDatablock( mRibbonDatablock );
  100. }
  101. else
  102. {
  103. setMaskBits( StateMask | EmitterDBMask );
  104. }
  105. mObjBox.minExtents.set(-0.5, -0.5, -0.5);
  106. mObjBox.maxExtents.set( 0.5, 0.5, 0.5);
  107. resetWorldBox();
  108. addToScene();
  109. return true;
  110. }
  111. //-----------------------------------------------------------------------------
  112. // onRemove
  113. //-----------------------------------------------------------------------------
  114. void RibbonNode::onRemove()
  115. {
  116. removeFromScene();
  117. if( isClientObject() )
  118. {
  119. if( mRibbon )
  120. {
  121. mRibbon->deleteOnEnd();
  122. mRibbon = NULL;
  123. }
  124. }
  125. Parent::onRemove();
  126. }
  127. //-----------------------------------------------------------------------------
  128. // onNewDataBlock
  129. //-----------------------------------------------------------------------------
  130. bool RibbonNode::onNewDataBlock( GameBaseData *dptr, bool reload )
  131. {
  132. mDataBlock = dynamic_cast<RibbonNodeData*>( dptr );
  133. if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
  134. return false;
  135. // Todo: Uncomment if this is a "leaf" class
  136. scriptOnNewDataBlock();
  137. return true;
  138. }
  139. //-----------------------------------------------------------------------------
  140. void RibbonNode::inspectPostApply()
  141. {
  142. Parent::inspectPostApply();
  143. setMaskBits(StateMask | EmitterDBMask);
  144. }
  145. //-----------------------------------------------------------------------------
  146. // processTick
  147. //-----------------------------------------------------------------------------
  148. void RibbonNode::processTick(const Move* move)
  149. {
  150. Parent::processTick(move);
  151. if ( isMounted() )
  152. {
  153. MatrixF mat;
  154. mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );
  155. setTransform( mat );
  156. }
  157. }
  158. //-----------------------------------------------------------------------------
  159. // advanceTime
  160. //-----------------------------------------------------------------------------
  161. void RibbonNode::advanceTime(F32 dt)
  162. {
  163. Parent::advanceTime(dt);
  164. if(!mActive || mRibbon.isNull() || !mDataBlock)
  165. return;
  166. MatrixF trans(getTransform());
  167. Point3F pos = getPosition();
  168. mRibbon->addSegmentPoint(pos, trans);
  169. }
  170. //-----------------------------------------------------------------------------
  171. // packUpdate
  172. //-----------------------------------------------------------------------------
  173. U32 RibbonNode::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
  174. {
  175. U32 retMask = Parent::packUpdate(con, mask, stream);
  176. if ( stream->writeFlag( mask & InitialUpdateMask ) )
  177. {
  178. mathWrite(*stream, getTransform());
  179. mathWrite(*stream, getScale());
  180. }
  181. if ( stream->writeFlag( mask & EmitterDBMask ) )
  182. {
  183. if( stream->writeFlag(mRibbonDatablock != NULL) )
  184. {
  185. stream->writeRangedU32(mRibbonDatablock->getId(), DataBlockObjectIdFirst,
  186. DataBlockObjectIdLast);
  187. }
  188. }
  189. if ( stream->writeFlag( mask & StateMask ) )
  190. {
  191. stream->writeFlag( mActive );
  192. }
  193. return retMask;
  194. }
  195. //-----------------------------------------------------------------------------
  196. // unpackUpdate
  197. //-----------------------------------------------------------------------------
  198. void RibbonNode::unpackUpdate(NetConnection* con, BitStream* stream)
  199. {
  200. Parent::unpackUpdate(con, stream);
  201. if ( stream->readFlag() )
  202. {
  203. MatrixF temp;
  204. Point3F tempScale;
  205. mathRead(*stream, &temp);
  206. mathRead(*stream, &tempScale);
  207. setScale(tempScale);
  208. setTransform(temp);
  209. }
  210. if ( stream->readFlag() )
  211. {
  212. mRibbonDatablockId = stream->readFlag() ?
  213. stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast) : 0;
  214. RibbonData *emitterDB = NULL;
  215. Sim::findObject( mRibbonDatablockId, emitterDB );
  216. if ( isProperlyAdded() )
  217. setRibbonDatablock( emitterDB );
  218. }
  219. if ( stream->readFlag() )
  220. {
  221. mActive = stream->readFlag();
  222. }
  223. }
  224. //-----------------------------------------------------------------------------
  225. // setRibbonDatablock
  226. //-----------------------------------------------------------------------------
  227. void RibbonNode::setRibbonDatablock(RibbonData* data)
  228. {
  229. if ( isServerObject() )
  230. {
  231. setMaskBits( EmitterDBMask );
  232. }
  233. else
  234. {
  235. Ribbon* pRibbon = NULL;
  236. if ( data )
  237. {
  238. // Create emitter with new datablock
  239. pRibbon = new Ribbon;
  240. pRibbon->onNewDataBlock( data, false );
  241. if( pRibbon->registerObject() == false )
  242. {
  243. Con::warnf(ConsoleLogEntry::General, "Could not register base ribbon of class: %s", data->getName() ? data->getName() : data->getIdString() );
  244. delete pRibbon;
  245. return;
  246. }
  247. }
  248. // Replace emitter
  249. if ( mRibbon )
  250. mRibbon->deleteOnEnd();
  251. mRibbon = pRibbon;
  252. }
  253. mRibbonDatablock = data;
  254. }
  255. DefineEngineMethod(RibbonNode, setRibbonDatablock, void, (RibbonData* ribbonDatablock), (nullAsType<RibbonData*>()),
  256. "Assigns the datablock for this ribbon node.\n"
  257. "@param ribbonDatablock RibbonData datablock to assign\n"
  258. "@tsexample\n"
  259. "// Assign a new emitter datablock\n"
  260. "%emitter.setRibbonDatablock( %ribbonDatablock );\n"
  261. "@endtsexample\n" )
  262. {
  263. if ( !ribbonDatablock )
  264. {
  265. Con::errorf("RibbonData datablock could not be found when calling setRibbonDataBlock in ribbonNode.");
  266. return;
  267. }
  268. object->setRibbonDatablock(ribbonDatablock);
  269. }
  270. DefineEngineMethod(RibbonNode, setActive, void, (bool active),,
  271. "Turns the ribbon on or off.\n"
  272. "@param active New ribbon state\n" )
  273. {
  274. object->setActive( active );
  275. }