Torque3D Documentation / _generateds / particleEmitterNode.cpp

particleEmitterNode.cpp

Engine/source/T3D/fx/particleEmitterNode.cpp

More...

Public Functions

ConsoleDocClass(ParticleEmitterNode , "@brief A particle emitter object that can be positioned in the world and " "dynamically enabled or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "datablock <a href="/coding/class/classparticleemitternodedata/">ParticleEmitterNodeData</a>( SimpleEmitterNodeData )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   timeMultiple = 1.0;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "% emitter, use the setActive() method instead of changing the active field " "directly. When changing velocity, you need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> toggle setActive() on and off " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> force the state change <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be transmitted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> other <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ParticleEmitterNodeData\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ParticleEmitterData\n</a>" )
ConsoleDocClass(ParticleEmitterNodeData , "@brief Contains additional data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be associated with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ParticleEmitterNode." "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" )
DefineEngineMethod(ParticleEmitterNode , setActive , void , (bool active) , "Turns the emitter on or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">off.\n</a>" "@param active New emitter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" )
DefineEngineMethod(ParticleEmitterNode , setEmitterDataBlock , void , (ParticleEmitterData *emitterDatablock) , (nullAsType< ParticleEmitterData * >()) , "Assigns the datablock <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this emitter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param emitterDatablock <a href="/coding/class/classparticleemitterdata/">ParticleEmitterData</a> datablock <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">assign\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> emitter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablock\n</a>" "%emitter.setEmitterDatablock( %emitterDatablock );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" )

Detailed Description

Public Functions

ConsoleDocClass(ParticleEmitterNode , "@brief A particle emitter object that can be positioned in the world and " "dynamically enabled or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "datablock <a href="/coding/class/classparticleemitternodedata/">ParticleEmitterNodeData</a>( SimpleEmitterNodeData )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   timeMultiple = 1.0;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n\n</a>" "% emitter, use the setActive() method instead of changing the active field " "directly. When changing velocity, you need <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> toggle setActive() on and off " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> force the state change <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be transmitted <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> other <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">clients.\n\n</a>" " @ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ParticleEmitterNodeData\n</a>" " @see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">ParticleEmitterData\n</a>" )

ConsoleDocClass(ParticleEmitterNodeData , "@brief Contains additional data <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be associated with <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> ParticleEmitterNode." "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">FX\n</a>" )

DefineEngineMethod(ParticleEmitterNode , setActive , void , (bool active) , "Turns the emitter on or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">off.\n</a>" "@param active New emitter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">state\n</a>" )

DefineEngineMethod(ParticleEmitterNode , setEmitterDataBlock , void , (ParticleEmitterData *emitterDatablock) , (nullAsType< ParticleEmitterData * >()) , "Assigns the datablock <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> this emitter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">node.\n</a>" "@param emitterDatablock <a href="/coding/class/classparticleemitterdata/">ParticleEmitterData</a> datablock <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">assign\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "// Assign <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> emitter <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">datablock\n</a>" "%emitter.setEmitterDatablock( %emitterDatablock );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" )

IMPLEMENT_CO_DATABLOCK_V1(ParticleEmitterNodeData )

IMPLEMENT_CO_NETOBJECT_V1(ParticleEmitterNode )

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  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 "particleEmitterNode.h"
 25#include "console/consoleTypes.h"
 26#include "core/stream/bitStream.h"
 27#include "T3D/fx/particleEmitter.h"
 28#include "math/mathIO.h"
 29#include "sim/netConnection.h"
 30#include "console/engineAPI.h"
 31
 32IMPLEMENT_CO_DATABLOCK_V1(ParticleEmitterNodeData);
 33IMPLEMENT_CO_NETOBJECT_V1(ParticleEmitterNode);
 34
 35ConsoleDocClass( ParticleEmitterNodeData,
 36   "@brief Contains additional data to be associated with a ParticleEmitterNode."
 37   "@ingroup FX\n"
 38);
 39
 40ConsoleDocClass( ParticleEmitterNode,
 41   "@brief A particle emitter object that can be positioned in the world and "
 42   "dynamically enabled or disabled.\n\n"
 43
 44   "@tsexample\n"
 45   "datablock ParticleEmitterNodeData( SimpleEmitterNodeData )\n"
 46   "{\n"
 47   "   timeMultiple = 1.0;\n"
 48   "};\n\n"
 49
 50   "%emitter = new ParticleEmitterNode()\n"
 51   "{\n"
 52   "   datablock = SimpleEmitterNodeData;\n"
 53   "   active = true;\n"
 54   "   emitter = FireEmitterData;\n"
 55   "   velocity = 3.5;\n"
 56   "};\n\n"
 57
 58   "// Dynamically change emitter datablock\n"
 59   "%emitter.setEmitterDataBlock( DustEmitterData );\n"
 60   "@endtsexample\n"
 61
 62   "@note To change the emitter field dynamically (after the ParticleEmitterNode "
 63   "object has been created) you must use the setEmitterDataBlock() method or the "
 64   "change will not be replicated to other clients in the game.\n"
 65   "Similarly, use the setActive() method instead of changing the active field "
 66   "directly. When changing velocity, you need to toggle setActive() on and off "
 67   "to force the state change to be transmitted to other clients.\n\n"
 68
 69   "@ingroup FX\n"
 70   "@see ParticleEmitterNodeData\n"
 71   "@see ParticleEmitterData\n"
 72);
 73
 74
 75//-----------------------------------------------------------------------------
 76// ParticleEmitterNodeData
 77//-----------------------------------------------------------------------------
 78ParticleEmitterNodeData::ParticleEmitterNodeData()
 79{
 80   timeMultiple = 1.0;
 81}
 82
 83ParticleEmitterNodeData::~ParticleEmitterNodeData()
 84{
 85
 86}
 87
 88//-----------------------------------------------------------------------------
 89// initPersistFields
 90//-----------------------------------------------------------------------------
 91void ParticleEmitterNodeData::initPersistFields()
 92{
 93   addField( "timeMultiple", TYPEID< F32 >(), Offset(timeMultiple, ParticleEmitterNodeData),
 94      "@brief Time multiplier for particle emitter nodes.\n\n"
 95      "Increasing timeMultiple is like running the emitter at a faster rate - single-shot "
 96      "emitters will complete in a shorter time, and continuous emitters will generate "
 97      "particles more quickly.\n\n"
 98      "Valid range is 0.01 - 100." );
 99
100   Parent::initPersistFields();
101}
102
103//-----------------------------------------------------------------------------
104// onAdd
105//-----------------------------------------------------------------------------
106bool ParticleEmitterNodeData::onAdd()
107{
108   if( !Parent::onAdd() )
109      return false;
110
111   if( timeMultiple < 0.01 || timeMultiple > 100 )
112   {
113      Con::warnf("ParticleEmitterNodeData::onAdd(%s): timeMultiple must be between 0.01 and 100", getName());
114      timeMultiple = timeMultiple < 0.01 ? 0.01 : 100;
115   }
116
117   return true;
118}
119
120
121//-----------------------------------------------------------------------------
122// preload
123//-----------------------------------------------------------------------------
124bool ParticleEmitterNodeData::preload(bool server, String &errorStr)
125{
126   if( Parent::preload(server, errorStr) == false )
127      return false;
128
129   return true;
130}
131
132
133//-----------------------------------------------------------------------------
134// packData
135//-----------------------------------------------------------------------------
136void ParticleEmitterNodeData::packData(BitStream* stream)
137{
138   Parent::packData(stream);
139
140   stream->write(timeMultiple);
141}
142
143//-----------------------------------------------------------------------------
144// unpackData
145//-----------------------------------------------------------------------------
146void ParticleEmitterNodeData::unpackData(BitStream* stream)
147{
148   Parent::unpackData(stream);
149
150   stream->read(&timeMultiple);
151}
152
153
154//-----------------------------------------------------------------------------
155// ParticleEmitterNode
156//-----------------------------------------------------------------------------
157ParticleEmitterNode::ParticleEmitterNode()
158{
159   // Todo: ScopeAlways?
160   mNetFlags.set(Ghostable);
161   mTypeMask |= EnvironmentObjectType;
162
163   mActive = true;
164
165   mDataBlock          = NULL;
166   mEmitterDatablock   = NULL;
167   mEmitterDatablockId = 0;
168   mEmitter            = NULL;
169   mVelocity           = 1.0;
170}
171
172//-----------------------------------------------------------------------------
173// Destructor
174//-----------------------------------------------------------------------------
175ParticleEmitterNode::~ParticleEmitterNode()
176{
177   //
178}
179
180//-----------------------------------------------------------------------------
181// initPersistFields
182//-----------------------------------------------------------------------------
183void ParticleEmitterNode::initPersistFields()
184{
185   addField( "active", TYPEID< bool >(), Offset(mActive,ParticleEmitterNode),
186      "Controls whether particles are emitted from this node." );
187   addField( "emitter",  TYPEID< ParticleEmitterData >(), Offset(mEmitterDatablock, ParticleEmitterNode),
188      "Datablock to use when emitting particles." );
189   addField( "velocity", TYPEID< F32 >(), Offset(mVelocity, ParticleEmitterNode),
190      "Velocity to use when emitting particles (in the direction of the "
191      "ParticleEmitterNode object's up (Z) axis)." );
192
193   Parent::initPersistFields();
194}
195
196//-----------------------------------------------------------------------------
197// onAdd
198//-----------------------------------------------------------------------------
199bool ParticleEmitterNode::onAdd()
200{
201   if( !Parent::onAdd() )
202      return false;
203
204   if( !mEmitterDatablock && mEmitterDatablockId != 0 )
205   {
206      if( Sim::findObject(mEmitterDatablockId, mEmitterDatablock) == false )
207         Con::errorf(ConsoleLogEntry::General, "ParticleEmitterNode::onAdd: Invalid packet, bad datablockId(mEmitterDatablock): %d", mEmitterDatablockId);
208   }
209
210   if( isClientObject() )
211   {
212      setEmitterDataBlock( mEmitterDatablock );
213   }
214   else
215   {
216      setMaskBits( StateMask | EmitterDBMask );
217   }
218
219   mObjBox.minExtents.set(-0.5, -0.5, -0.5);
220   mObjBox.maxExtents.set( 0.5,  0.5,  0.5);
221   resetWorldBox();
222   addToScene();
223
224   return true;
225}
226
227//-----------------------------------------------------------------------------
228// onRemove
229//-----------------------------------------------------------------------------
230void ParticleEmitterNode::onRemove()
231{
232   removeFromScene();
233   if( isClientObject() )
234   {
235      if( mEmitter )
236      {
237         mEmitter->deleteWhenEmpty();
238         mEmitter = NULL;
239      }
240   }
241
242   Parent::onRemove();
243}
244
245//-----------------------------------------------------------------------------
246// onNewDataBlock
247//-----------------------------------------------------------------------------
248bool ParticleEmitterNode::onNewDataBlock( GameBaseData *dptr, bool reload )
249{
250   mDataBlock = dynamic_cast<ParticleEmitterNodeData*>( dptr );
251   if ( !mDataBlock || !Parent::onNewDataBlock( dptr, reload ) )
252      return false;
253
254   // Todo: Uncomment if this is a "leaf" class
255   scriptOnNewDataBlock();
256   return true;
257}
258
259//-----------------------------------------------------------------------------
260void ParticleEmitterNode::inspectPostApply()
261{
262   Parent::inspectPostApply();
263   setMaskBits(StateMask | EmitterDBMask);
264}
265
266//-----------------------------------------------------------------------------
267// advanceTime
268//-----------------------------------------------------------------------------
269void ParticleEmitterNode::processTick(const Move* move)
270{
271   Parent::processTick(move);
272
273   if ( isMounted() )
274   {
275      MatrixF mat;
276      mMount.object->getMountTransform( mMount.node, mMount.xfm, &mat );
277      setTransform( mat );
278   }
279}
280
281void ParticleEmitterNode::advanceTime(F32 dt)
282{
283   Parent::advanceTime(dt);
284   
285   if(!mActive || mEmitter.isNull() || !mDataBlock)
286      return;
287
288   Point3F emitPoint, emitVelocity;
289   Point3F emitAxis(0, 0, 1);
290   getTransform().mulV(emitAxis);
291   getTransform().getColumn(3, &emitPoint);
292   emitVelocity = emitAxis * mVelocity;
293
294   mEmitter->emitParticles(emitPoint, emitPoint,
295                           emitAxis,
296                           emitVelocity, (U32)(dt * mDataBlock->timeMultiple * 1000.0f));
297}
298
299//-----------------------------------------------------------------------------
300// packUpdate
301//-----------------------------------------------------------------------------
302U32 ParticleEmitterNode::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
303{
304   U32 retMask = Parent::packUpdate(con, mask, stream);
305
306   if ( stream->writeFlag( mask & InitialUpdateMask ) )
307   {
308      mathWrite(*stream, getTransform());
309      mathWrite(*stream, getScale());
310   }
311
312   if ( stream->writeFlag( mask & EmitterDBMask ) )
313   {
314      if( stream->writeFlag(mEmitterDatablock != NULL) )
315      {
316         stream->writeRangedU32(mEmitterDatablock->getId(), DataBlockObjectIdFirst,
317            DataBlockObjectIdLast);
318      }
319   }
320
321   if ( stream->writeFlag( mask & StateMask ) )
322   {
323      stream->writeFlag( mActive );
324      stream->write( mVelocity );
325   }
326
327   return retMask;
328}
329
330//-----------------------------------------------------------------------------
331// unpackUpdate
332//-----------------------------------------------------------------------------
333void ParticleEmitterNode::unpackUpdate(NetConnection* con, BitStream* stream)
334{
335   Parent::unpackUpdate(con, stream);
336
337   if ( stream->readFlag() )
338   {
339      MatrixF temp;
340      Point3F tempScale;
341      mathRead(*stream, &temp);
342      mathRead(*stream, &tempScale);
343
344      setScale(tempScale);
345      setTransform(temp);
346   }
347
348   if ( stream->readFlag() )
349   {
350      mEmitterDatablockId = stream->readFlag() ?
351         stream->readRangedU32(DataBlockObjectIdFirst, DataBlockObjectIdLast) : 0;
352
353      ParticleEmitterData *emitterDB = NULL;
354      Sim::findObject( mEmitterDatablockId, emitterDB );
355      if ( isProperlyAdded() )
356         setEmitterDataBlock( emitterDB );
357   }
358
359   if ( stream->readFlag() )
360   {
361      mActive = stream->readFlag();
362      stream->read( &mVelocity );
363   }
364}
365
366void ParticleEmitterNode::setEmitterDataBlock(ParticleEmitterData* data)
367{
368   if ( isServerObject() )
369   {
370      setMaskBits( EmitterDBMask );
371   }
372   else
373   {
374      ParticleEmitter* pEmitter = NULL;
375      if ( data )
376      {
377         // Create emitter with new datablock
378         pEmitter = new ParticleEmitter;
379         pEmitter->onNewDataBlock( data, false );
380         if( pEmitter->registerObject() == false )
381         {
382            Con::warnf(ConsoleLogEntry::General, "Could not register base emitter for particle of class: %s", data->getName() ? data->getName() : data->getIdString() );
383            delete pEmitter;
384            return;
385         }
386      }
387
388      // Replace emitter
389      if ( mEmitter )
390         mEmitter->deleteWhenEmpty();
391
392      mEmitter = pEmitter;
393   }
394
395   mEmitterDatablock = data;
396}
397
398
399DefineEngineMethod(ParticleEmitterNode, setEmitterDataBlock, void, (ParticleEmitterData* emitterDatablock), (nullAsType<ParticleEmitterData*>()),
400   "Assigns the datablock for this emitter node.\n"
401   "@param emitterDatablock ParticleEmitterData datablock to assign\n"
402   "@tsexample\n"
403   "// Assign a new emitter datablock\n"
404   "%emitter.setEmitterDatablock( %emitterDatablock );\n"
405   "@endtsexample\n" )
406{
407   if ( !emitterDatablock )
408   {
409      Con::errorf("ParticleEmitterData datablock could not be found when calling setEmitterDataBlock in particleEmitterNode.");
410      return;
411   }
412
413   object->setEmitterDataBlock(emitterDatablock);
414}
415
416DefineEngineMethod(ParticleEmitterNode, setActive, void, (bool active),,
417   "Turns the emitter on or off.\n"
418   "@param active New emitter state\n" )
419{
420   object->setActive( active );
421}
422