tge/engine/game/fx/particleEmitter.cc
2017-04-17 06:17:10 -06:00

262 lines
7.1 KiB
C++
Executable File

//-----------------------------------------------------------------------------
// Torque Game Engine
// Copyright (C) GarageGames.com, Inc.
//-----------------------------------------------------------------------------
#include "console/consoleTypes.h"
#include "core/bitStream.h"
#include "game/fx/particleEmitter.h"
#include "game/fx/particleEngine.h"
#include "math/mathIO.h"
IMPLEMENT_CO_DATABLOCK_V1(ParticleEmitterNodeData);
IMPLEMENT_CO_NETOBJECT_V1(ParticleEmitterNode);
//--------------------------------------------------------------------------
//--------------------------------------
//
ParticleEmitterNodeData::ParticleEmitterNodeData()
{
timeMultiple = 1.0;
}
ParticleEmitterNodeData::~ParticleEmitterNodeData()
{
}
//--------------------------------------------------------------------------
void ParticleEmitterNodeData::initPersistFields()
{
Parent::initPersistFields();
addField("timeMultiple", TypeF32, Offset(timeMultiple, ParticleEmitterNodeData));
}
//--------------------------------------------------------------------------
bool ParticleEmitterNodeData::onAdd()
{
if(!Parent::onAdd())
return false;
if (timeMultiple < 0.01 || timeMultiple > 100) {
Con::warnf("ParticleEmitterNodeData::onAdd(%s): timeMultiple must be between 0.01 and 100", getName());
timeMultiple = timeMultiple < 0.01 ? 0.01 : 100;
}
return true;
}
bool ParticleEmitterNodeData::preload(bool server, char errorBuffer[256])
{
if (Parent::preload(server, errorBuffer) == false)
return false;
return true;
}
//--------------------------------------------------------------------------
void ParticleEmitterNodeData::packData(BitStream* stream)
{
Parent::packData(stream);
stream->write(timeMultiple);
}
void ParticleEmitterNodeData::unpackData(BitStream* stream)
{
Parent::unpackData(stream);
stream->read(&timeMultiple);
}
//--------------------------------------------------------------------------
//--------------------------------------
//
ParticleEmitterNode::ParticleEmitterNode()
{
// Todo: ScopeAlways?
mNetFlags.set(Ghostable);
mTypeMask |= EnvironmentObjectType;
mEmitterDatablock = NULL;
mEmitterDatablockId = 0;
mEmitter = NULL;
mVelocity = 1.0;
}
ParticleEmitterNode::~ParticleEmitterNode()
{
//
}
//--------------------------------------------------------------------------
void ParticleEmitterNode::initPersistFields()
{
Parent::initPersistFields();
addField("emitter", TypeParticleEmitterDataPtr, Offset(mEmitterDatablock, ParticleEmitterNode));
addField("velocity", TypeF32, Offset(mVelocity, ParticleEmitterNode));
}
//--------------------------------------------------------------------------
bool ParticleEmitterNode::onAdd()
{
if(!Parent::onAdd())
return false;
if (!mEmitterDatablock && mEmitterDatablockId != 0)
{
if (Sim::findObject(mEmitterDatablockId, mEmitterDatablock) == false)
Con::errorf(ConsoleLogEntry::General, "ParticleEmitterNode::onAdd: Invalid packet, bad datablockId(mEmitterDatablock): %d", mEmitterDatablockId);
}
if (mEmitterDatablock == NULL)
return false;
if (isClientObject())
{
ParticleEmitter* pEmitter = new ParticleEmitter;
pEmitter->onNewDataBlock(mEmitterDatablock);
if (pEmitter->registerObject() == false)
{
Con::warnf(ConsoleLogEntry::General, "Could not register base emitter for particle of class: %s", mDataBlock->getName());
delete pEmitter;
return false;
}
mEmitter = pEmitter;
}
mObjBox.min.set(-0.5, -0.5, -0.5);
mObjBox.max.set( 0.5, 0.5, 0.5);
resetWorldBox();
addToScene();
return true;
}
void ParticleEmitterNode::onRemove()
{
removeFromScene();
if (isClientObject())
{
mEmitter->deleteWhenEmpty();
mEmitter = NULL;
}
Parent::onRemove();
}
void ParticleEmitterNode::onGroupAdd()
{
Parent::onGroupAdd();
// To make sure that we don't orphan our emitter on mission end,
// let's add it to our parent group, so it will get cleaned up.
SimGroup* myGroup = getGroup();
if (myGroup && mEmitter)
myGroup->addObject(mEmitter);
}
bool ParticleEmitterNode::onNewDataBlock(GameBaseData* dptr)
{
mDataBlock = dynamic_cast<ParticleEmitterNodeData*>(dptr);
if (!mDataBlock || !Parent::onNewDataBlock(dptr))
return false;
// Todo: Uncomment if this is a "leaf" class
scriptOnNewDataBlock();
return true;
}
//--------------------------------------------------------------------------
void ParticleEmitterNode::advanceTime(F32 dt)
{
Parent::advanceTime(dt);
Point3F emitPoint, emitVelocity;
Point3F emitAxis(0, 0, 1);
getTransform().mulV(emitAxis);
getTransform().getColumn(3, &emitPoint);
emitVelocity = emitAxis * mVelocity;
mEmitter->emitParticles(emitPoint, emitPoint,
emitAxis,
emitVelocity, (U32)(dt * mDataBlock->timeMultiple * 1000.0f));
}
//--------------------------------------------------------------------------
U32 ParticleEmitterNode::packUpdate(NetConnection* con, U32 mask, BitStream* stream)
{
U32 retMask = Parent::packUpdate(con, mask, stream);
mathWrite(*stream, getTransform());
mathWrite(*stream, getScale());
if (stream->writeFlag(mEmitterDatablock != NULL)) {
stream->writeRangedU32(mEmitterDatablock->getId(), DataBlockObjectIdFirst,
DataBlockObjectIdLast);
}
return retMask;
}
void ParticleEmitterNode::unpackUpdate(NetConnection* con, BitStream* stream)
{
Parent::unpackUpdate(con, stream);
MatrixF temp;
Point3F tempScale;
mathRead(*stream, &temp);
mathRead(*stream, &tempScale);
if (stream->readFlag()) {
mEmitterDatablockId = stream->readRangedU32(DataBlockObjectIdFirst,
DataBlockObjectIdLast);
} else {
mEmitterDatablockId = 0;
}
setScale(tempScale);
setTransform(temp);
}
void ParticleEmitterNode::setEmitterDataBlock(ParticleEmitterData* data)
{
if (!data)
return;
if (mEmitter)
{
mEmitterDatablock = data;
ParticleEmitter* pEmitter = new ParticleEmitter;
pEmitter->onNewDataBlock(mEmitterDatablock);
if (pEmitter->registerObject() == false) {
Con::warnf(ConsoleLogEntry::General, "Could not register base emitter for particle of class: %s", mDataBlock->getName());
delete pEmitter;
pEmitter = NULL;
}
if (pEmitter)
{
mEmitter->deleteWhenEmpty();
mEmitter = pEmitter;
}
}
}
ConsoleMethod(ParticleEmitterNode, setEmitterDataBlock, void, 3, 3, "(data)")
{
ParticleEmitterData* data = dynamic_cast<ParticleEmitterData*>(Sim::findObject(dAtoi(argv[2])));
if (!data)
data = dynamic_cast<ParticleEmitterData*>(Sim::findObject(argv[2]));
if (data)
object->setEmitterDataBlock(data);
}