particleEmitterNode.cpp
Engine/source/T3D/fx/particleEmitterNode.cpp
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