afxEA_ParticleEmitter.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  2. // Arcane-FX for MIT Licensed Open Source version of Torque 3D from GarageGames
  3. // Copyright (C) 2015 Faust Logic, Inc.
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //
  23. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  24. #include <typeinfo>
  25. #include "afx/arcaneFX.h"
  26. #if defined(STOCK_TGE_PARTICLES)
  27. #include "game/fx/particleEngine.h"
  28. #else
  29. #include "afx/ce/afxParticleEmitter.h"
  30. #endif
  31. #include "afx/afxEffectDefs.h"
  32. #include "afx/afxEffectWrapper.h"
  33. #include "afx/afxChoreographer.h"
  34. #include "afx/ea/afxEA_ParticleEmitter.h"
  35. #include "afx/util/afxParticlePool.h"
  36. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  37. // afxEA_ParticleEmitter
  38. afxEA_ParticleEmitter::afxEA_ParticleEmitter()
  39. {
  40. emitter_data = 0;
  41. emitter = 0;
  42. do_bbox_update = false;
  43. }
  44. afxEA_ParticleEmitter::~afxEA_ParticleEmitter()
  45. {
  46. if (emitter)
  47. {
  48. clearNotify(emitter);
  49. emitter->deleteWhenEmpty();
  50. emitter = 0;
  51. }
  52. }
  53. void afxEA_ParticleEmitter::ea_set_datablock(SimDataBlock* db)
  54. {
  55. emitter_data = dynamic_cast<ParticleEmitterData*>(db);
  56. }
  57. bool afxEA_ParticleEmitter::ea_start()
  58. {
  59. if (!emitter_data)
  60. {
  61. Con::errorf("afxEA_ParticleEmitter::ea_start() -- missing or incompatible datablock.");
  62. return false;
  63. }
  64. do_runtime_substitutions();
  65. #if defined(STOCK_TGE_PARTICLES)
  66. emitter = new ParticleEmitter();
  67. emitter->onNewDataBlock(emitter_data);
  68. #else
  69. afxParticleEmitterData* afx_emitter_db = dynamic_cast<afxParticleEmitterData*>(emitter_data);
  70. if (afx_emitter_db)
  71. {
  72. if (dynamic_cast<afxParticleEmitterVectorData*>(emitter_data))
  73. {
  74. afxParticleEmitterVector* pe = new afxParticleEmitterVector();
  75. pe->onNewDataBlock(afx_emitter_db, false);
  76. pe->setAFXOwner(mChoreographer);
  77. emitter = pe;
  78. }
  79. else if (dynamic_cast<afxParticleEmitterConeData*>(emitter_data))
  80. {
  81. afxParticleEmitterCone* pe = new afxParticleEmitterCone();
  82. pe->onNewDataBlock(afx_emitter_db, false);
  83. pe->setAFXOwner(mChoreographer);
  84. emitter = pe;
  85. }
  86. else if (dynamic_cast<afxParticleEmitterPathData*>(emitter_data))
  87. {
  88. afxParticleEmitterPath* pe = new afxParticleEmitterPath();
  89. pe->onNewDataBlock(afx_emitter_db, false);
  90. pe->setAFXOwner(mChoreographer);
  91. emitter = pe;
  92. }
  93. else if (dynamic_cast<afxParticleEmitterDiscData*>(emitter_data))
  94. {
  95. afxParticleEmitterDisc* pe = new afxParticleEmitterDisc();
  96. pe->onNewDataBlock(afx_emitter_db, false);
  97. pe->setAFXOwner(mChoreographer);
  98. emitter = pe;
  99. }
  100. }
  101. else
  102. {
  103. emitter = new ParticleEmitter();
  104. emitter->onNewDataBlock(emitter_data, false);
  105. }
  106. #endif
  107. #if defined(AFX_CAP_PARTICLE_POOLS)
  108. // here we find or create any required particle-pools
  109. if (emitter_data->pool_datablock)
  110. {
  111. afxParticlePool* pool = mChoreographer->findParticlePool(emitter_data->pool_datablock, emitter_data->pool_index);
  112. if (!pool)
  113. {
  114. afxParticlePoolData* pool_data = emitter_data->pool_datablock;
  115. if (pool_data->getSubstitutionCount() > 0)
  116. {
  117. // clone the datablock and perform substitutions
  118. afxParticlePoolData* orig_db = pool_data;
  119. pool_data = new afxParticlePoolData(*orig_db, true);
  120. orig_db->performSubstitutions(pool_data, mChoreographer, mGroup_index);
  121. }
  122. pool = new afxParticlePool();
  123. pool->onNewDataBlock(pool_data, false);
  124. pool->setKeyBlock(emitter_data->pool_datablock, emitter_data->pool_index);
  125. if (!pool->registerObject())
  126. {
  127. Con::errorf("afxEA_ParticleEmitter::ea_start() -- Failed to register Particle Pool.");
  128. delete pool;
  129. pool = 0;
  130. }
  131. if (pool)
  132. {
  133. pool->setChoreographer(mChoreographer);
  134. mChoreographer->registerParticlePool(pool);
  135. }
  136. }
  137. if (pool)
  138. emitter->setPool(pool);
  139. }
  140. #endif
  141. if (!emitter->registerObject())
  142. {
  143. delete emitter;
  144. emitter = NULL;
  145. Con::errorf("afxEA_ParticleEmitter::ea_start() -- effect failed to register.");
  146. return false;
  147. }
  148. if (mDatablock->forced_bbox.isValidBox())
  149. {
  150. do_bbox_update = true;
  151. }
  152. emitter->setSortPriority(mDatablock->sort_priority);
  153. deleteNotify(emitter);
  154. return true;
  155. }
  156. bool afxEA_ParticleEmitter::ea_update(F32 dt)
  157. {
  158. if (emitter && mIn_scope)
  159. {
  160. if (do_bbox_update)
  161. {
  162. Box3F bbox = emitter->getObjBox();
  163. bbox.minExtents = mUpdated_pos + mDatablock->forced_bbox.minExtents;
  164. bbox.maxExtents = mUpdated_pos + mDatablock->forced_bbox.maxExtents;
  165. emitter->setForcedObjBox(bbox);
  166. emitter->setTransform(emitter->getTransform());
  167. if (!mDatablock->update_forced_bbox)
  168. do_bbox_update = false;
  169. }
  170. if (mDo_fades)
  171. emitter->setFadeAmount(mFade_value);
  172. emitter->emitParticlesExt(mUpdated_xfm, mUpdated_pos, Point3F(0.0,0.0,0.0), (U32)(dt*1000));
  173. }
  174. return true;
  175. }
  176. void afxEA_ParticleEmitter::ea_finish(bool was_stopped)
  177. {
  178. if (arcaneFX::isShutdown())
  179. return;
  180. if (emitter)
  181. {
  182. // make sure particles are fully faded.
  183. // note - fully faded particles are not always
  184. // invisible, so they are still kept alive and
  185. // deleted via deleteWhenEmpty().
  186. if (mEW_timing.fade_out_time > 0.0f)
  187. emitter->setFadeAmount(0.0f);
  188. if (dynamic_cast<afxParticleEmitter*>(emitter))
  189. ((afxParticleEmitter*)emitter)->setAFXOwner(0);
  190. clearNotify(emitter);
  191. emitter->deleteWhenEmpty();
  192. emitter = 0;
  193. }
  194. }
  195. void afxEA_ParticleEmitter::do_runtime_substitutions()
  196. {
  197. bool clone_particles = false;
  198. for (S32 i = 0; i < emitter_data->particleDataBlocks.size(); i++)
  199. {
  200. if (emitter_data->particleDataBlocks[i] && (emitter_data->particleDataBlocks[i]->getSubstitutionCount() > 0))
  201. {
  202. clone_particles = true;
  203. break;
  204. }
  205. }
  206. if (clone_particles || (emitter_data->getSubstitutionCount() > 0))
  207. {
  208. afxParticleEmitterData* afx_emitter_db = dynamic_cast<afxParticleEmitterData*>(emitter_data);
  209. if (afx_emitter_db)
  210. {
  211. if (dynamic_cast<afxParticleEmitterVectorData*>(emitter_data))
  212. {
  213. afxParticleEmitterVectorData* orig_db = (afxParticleEmitterVectorData*)emitter_data;
  214. emitter_data = new afxParticleEmitterVectorData(*orig_db, true);
  215. orig_db->performSubstitutions(emitter_data, mChoreographer, mGroup_index);
  216. }
  217. else if (dynamic_cast<afxParticleEmitterConeData*>(emitter_data))
  218. {
  219. afxParticleEmitterConeData* orig_db = (afxParticleEmitterConeData*)emitter_data;
  220. emitter_data = new afxParticleEmitterConeData(*orig_db, true);
  221. orig_db->performSubstitutions(emitter_data, mChoreographer, mGroup_index);
  222. }
  223. else if (dynamic_cast<afxParticleEmitterPathData*>(emitter_data))
  224. {
  225. afxParticleEmitterPathData* orig_db = (afxParticleEmitterPathData*)emitter_data;
  226. emitter_data = new afxParticleEmitterPathData(*orig_db, true);
  227. orig_db->performSubstitutions(emitter_data, mChoreographer, mGroup_index);
  228. }
  229. else if (dynamic_cast<afxParticleEmitterDiscData*>(emitter_data))
  230. {
  231. afxParticleEmitterDiscData* orig_db = (afxParticleEmitterDiscData*)emitter_data;
  232. emitter_data = new afxParticleEmitterDiscData(*orig_db, true);
  233. orig_db->performSubstitutions(emitter_data, mChoreographer, mGroup_index);
  234. }
  235. }
  236. else
  237. {
  238. ParticleEmitterData* orig_db = emitter_data;
  239. emitter_data = new ParticleEmitterData(*orig_db, true);
  240. orig_db->performSubstitutions(emitter_data, mChoreographer, mGroup_index);
  241. }
  242. if (clone_particles)
  243. {
  244. for (S32 i = 0; i < emitter_data->particleDataBlocks.size(); i++)
  245. {
  246. if (emitter_data->particleDataBlocks[i] && (emitter_data->particleDataBlocks[i]->getSubstitutionCount() > 0))
  247. {
  248. // clone the datablock and perform substitutions
  249. ParticleData* orig_db = emitter_data->particleDataBlocks[i];
  250. emitter_data->particleDataBlocks[i] = new ParticleData(*orig_db, true);
  251. orig_db->performSubstitutions(emitter_data->particleDataBlocks[i], mChoreographer, mGroup_index);
  252. }
  253. }
  254. }
  255. }
  256. }
  257. void afxEA_ParticleEmitter::onDeleteNotify(SimObject* obj)
  258. {
  259. if (emitter == dynamic_cast<ParticleEmitter*>(obj))
  260. emitter = 0;
  261. Parent::onDeleteNotify(obj);
  262. }
  263. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//
  264. class afxEA_ParticleEmitterDesc : public afxEffectAdapterDesc, public afxEffectDefs
  265. {
  266. static afxEA_ParticleEmitterDesc desc;
  267. public:
  268. virtual bool testEffectType(const SimDataBlock*) const;
  269. virtual bool requiresStop(const afxEffectWrapperData*, const afxEffectTimingData&) const;
  270. virtual bool runsOnServer(const afxEffectWrapperData*) const { return false; }
  271. virtual bool runsOnClient(const afxEffectWrapperData*) const { return true; }
  272. virtual afxEffectWrapper* create() const { return new afxEA_ParticleEmitter; }
  273. };
  274. afxEA_ParticleEmitterDesc afxEA_ParticleEmitterDesc::desc;
  275. bool afxEA_ParticleEmitterDesc::testEffectType(const SimDataBlock* db) const
  276. {
  277. #if defined(STOCK_TGE_PARTICLES)
  278. return (typeid(ParticleEmitterData) == typeid(*db));
  279. #else
  280. if (typeid(ParticleEmitterData) == typeid(*db))
  281. return true;
  282. if (typeid(afxParticleEmitterVectorData) == typeid(*db))
  283. return true;
  284. if (typeid(afxParticleEmitterConeData) == typeid(*db))
  285. return true;
  286. if (typeid(afxParticleEmitterPathData) == typeid(*db))
  287. return true;
  288. if (typeid(afxParticleEmitterDiscData) == typeid(*db))
  289. return true;
  290. return false;
  291. #endif
  292. }
  293. bool afxEA_ParticleEmitterDesc::requiresStop(const afxEffectWrapperData* ew, const afxEffectTimingData& timing) const
  294. {
  295. return (timing.lifetime < 0);
  296. }
  297. //~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~//