Torque3D Documentation / _generateds / afxEA_ParticleEmitter.cpp

afxEA_ParticleEmitter.cpp

Engine/source/afx/ea/afxEA_ParticleEmitter.cpp

More...

Classes:

Detailed Description

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