ribbonNode.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  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. docsURL;
  52. Parent::initPersistFields();
  53. }
  54. //-----------------------------------------------------------------------------
  55. // RibbonNode
  56. //-----------------------------------------------------------------------------
  57. RibbonNode::RibbonNode()
  58. {
  59. // Todo: ScopeAlways?
  60. mNetFlags.set(Ghostable);
  61. mTypeMask |= EnvironmentObjectType;
  62. mActive = true;
  63. mDataBlock = NULL;
  64. mRibbonDatablock = NULL;
  65. mRibbonDatablockId = 0;
  66. mRibbon = NULL;
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Destructor
  70. //-----------------------------------------------------------------------------
  71. RibbonNode::~RibbonNode()
  72. {
  73. //
  74. }
  75. //-----------------------------------------------------------------------------
  76. // initPersistFields
  77. //-----------------------------------------------------------------------------
  78. void RibbonNode::initPersistFields()
  79. {
  80. docsURL;
  81. addField( "active", TYPEID< bool >(), Offset(mActive,RibbonNode),
  82. "Controls whether ribbon is emitted from this node." );
  83. addField( "ribbon", TYPEID< RibbonData >(), Offset(mRibbonDatablock, RibbonNode),
  84. "Datablock to use for the ribbon." );
  85. Parent::initPersistFields();
  86. }
  87. //-----------------------------------------------------------------------------
  88. // onAdd
  89. //-----------------------------------------------------------------------------
  90. bool RibbonNode::onAdd()
  91. {
  92. if( !Parent::onAdd() )
  93. return false;
  94. if( !mRibbonDatablock && mRibbonDatablockId != 0 )
  95. {
  96. if( Sim::findObject(mRibbonDatablockId, mRibbonDatablock) == false )
  97. Con::errorf(ConsoleLogEntry::General, "RibbonNode::onAdd: Invalid packet, bad datablockId(mRibbonDatablock): %d", mRibbonDatablockId);
  98. }
  99. if( isClientObject() )
  100. {
  101. setRibbonDatablock( mRibbonDatablock );
  102. }
  103. else
  104. {
  105. setMaskBits( StateMask | EmitterDBMask );
  106. }
  107. mObjBox.minExtents.set(-0.5, -0.5, -0.5);
  108. mObjBox.maxExtents.set( 0.5, 0.5, 0.5);
  109. resetWorldBox();
  110. addToScene();
  111. return true;
  112. }
  113. //-----------------------------------------------------------------------------
  114. // onRemove
  115. //-----------------------------------------------------------------------------
  116. void RibbonNode::onRemove()
  117. {
  118. removeFromScene();
  119. if( isClientObject() )
  120. {
  121. if( mRibbon )
  122. {
  123. mRibbon->deleteOnEnd();
  124. mRibbon = NULL;
  125. }
  126. }
  127. Parent::onRemove();
  128. }
  129. //-----------------------------------------------------------------------------
  130. // onNewDataBlock
  131. //-----------------------------------------------------------------------------
  132. bool RibbonNode::onNewDataBlock( GameBaseData *dptr, bool reload )
  133. {
  134. mDataBlock = dynamic_cast<RibbonNodeData*>( dptr );
  135. if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
  136. return false;
  137. // Todo: Uncomment if this is a "leaf" class
  138. scriptOnNewDataBlock();
  139. return true;
  140. }
  141. //-----------------------------------------------------------------------------
  142. void RibbonNode::inspectPostApply()
  143. {
  144. Parent::inspectPostApply();
  145. setMaskBits(StateMask | EmitterDBMask);
  146. }
  147. //-----------------------------------------------------------------------------
  148. // processTick
  149. //-----------------------------------------------------------------------------
  150. void RibbonNode::processTick(const Move* move)
  151. {
  152. Parent::processTick(move);
  153. if ( isMounted() )
  154. {
  155. MatrixF mat;
  156. mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );
  157. setTransform( mat );
  158. }
  159. }
  160. //-----------------------------------------------------------------------------
  161. // advanceTime
  162. //-----------------------------------------------------------------------------
  163. void RibbonNode::advanceTime(F32 dt)
  164. {
  165. Parent::advanceTime(dt);
  166. if(!mActive || mRibbon.isNull() || !mDataBlock)
  167. return;
  168. MatrixF trans(getTransform());
  169. Point3F pos = getPosition();
  170. mRibbon->addSegmentPoint(pos, trans);
  171. }
  172. //-----------------------------------------------------------------------------
  173. // packUpdate
  174. //-----------------------------------------------------------------------------
  175. U32 RibbonNode::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
  176. {
  177. U32 retMask = Parent::packUpdate(con, mask, stream);
  178. if ( stream->writeFlag( mask & InitialUpdateMask ) )
  179. {
  180. mathWrite(*stream, getTransform());
  181. mathWrite(*stream, getScale());
  182. }
  183. if ( stream->writeFlag( mask & EmitterDBMask ) )
  184. {
  185. if( stream->writeFlag(mRibbonDatablock != NULL) )
  186. {
  187. stream->writeRangedU32(mRibbonDatablock->getId(), DataBlockObjectIdFirst,
  188. DataBlockObjectIdLast);
  189. }
  190. }
  191. if ( stream->writeFlag( mask & StateMask ) )
  192. {
  193. stream->writeFlag( mActive );
  194. }
  195. return retMask;
  196. }
  197. //-----------------------------------------------------------------------------
  198. // unpackUpdate
  199. //-----------------------------------------------------------------------------
  200. void RibbonNode::unpackUpdate(NetConnection* con, BitStream* stream)
  201. {
  202. Parent::unpackUpdate(con, stream);
  203. if ( stream->readFlag() )
  204. {
  205. MatrixF temp;
  206. Point3F tempScale;
  207. mathRead(*stream, &temp);
  208. mathRead(*stream, &tempScale);
  209. setScale(tempScale);
  210. setTransform(temp);
  211. }
  212. if ( stream->readFlag() )
  213. {
  214. mRibbonDatablockId = stream->readFlag() ?
  215. stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast) : 0;
  216. RibbonData *emitterDB = NULL;
  217. Sim::findObject( mRibbonDatablockId, emitterDB );
  218. if ( isProperlyAdded() )
  219. setRibbonDatablock( emitterDB );
  220. }
  221. if ( stream->readFlag() )
  222. {
  223. mActive = stream->readFlag();
  224. }
  225. }
  226. //-----------------------------------------------------------------------------
  227. // setRibbonDatablock
  228. //-----------------------------------------------------------------------------
  229. void RibbonNode::setRibbonDatablock(RibbonData* data)
  230. {
  231. if ( isServerObject() )
  232. {
  233. setMaskBits( EmitterDBMask );
  234. }
  235. else
  236. {
  237. Ribbon* pRibbon = NULL;
  238. if ( data )
  239. {
  240. // Create emitter with new datablock
  241. pRibbon = new Ribbon;
  242. pRibbon->onNewDataBlock( data, false );
  243. if( pRibbon->registerObject() == false )
  244. {
  245. Con::warnf(ConsoleLogEntry::General, "Could not register base ribbon of class: %s", data->getName() ? data->getName() : data->getIdString() );
  246. delete pRibbon;
  247. return;
  248. }
  249. }
  250. // Replace emitter
  251. if ( mRibbon )
  252. mRibbon->deleteOnEnd();
  253. mRibbon = pRibbon;
  254. }
  255. mRibbonDatablock = data;
  256. }
  257. DefineEngineMethod(RibbonNode, setRibbonDatablock, void, (RibbonData* ribbonDatablock), (nullAsType<RibbonData*>()),
  258. "Assigns the datablock for this ribbon node.\n"
  259. "@param ribbonDatablock RibbonData datablock to assign\n"
  260. "@tsexample\n"
  261. "// Assign a new emitter datablock\n"
  262. "%emitter.setRibbonDatablock( %ribbonDatablock );\n"
  263. "@endtsexample\n" )
  264. {
  265. if ( !ribbonDatablock )
  266. {
  267. Con::errorf("RibbonData datablock could not be found when calling setRibbonDataBlock in ribbonNode.");
  268. return;
  269. }
  270. object->setRibbonDatablock(ribbonDatablock);
  271. }
  272. DefineEngineMethod(RibbonNode, setActive, void, (bool active),,
  273. "Turns the ribbon on or off.\n"
  274. "@param active New ribbon state\n" )
  275. {
  276. object->setActive( active );
  277. }