Files
scummvm-cursorfix/engines/hpl1/engine/graphics/ParticleSystem3D.cpp
2026-02-02 04:50:13 +01:00

380 lines
11 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
/*
* Copyright (C) 2006-2010 - Frictional Games
*
* This file is part of HPL1 Engine.
*/
#include "hpl1/engine/graphics/ParticleSystem3D.h"
#include "hpl1/engine/impl/tinyXML/tinyxml.h"
#include "hpl1/engine/graphics/ParticleEmitter3D_UserData.h"
#include "hpl1/engine/resources/ParticleManager.h"
#include "hpl1/engine/game/Game.h"
#include "hpl1/engine/scene/Scene.h"
#include "hpl1/engine/scene/World3D.h"
namespace hpl {
//////////////////////////////////////////////////////////////////////////
// CREATOR
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cParticleSystemData3D::cParticleSystemData3D(const tString &asName,
cResources *apResources, cGraphics *apGraphics)
: iResourceBase(asName, 0) {
mpResources = apResources;
mpGraphics = apGraphics;
}
//-----------------------------------------------------------------------
cParticleSystemData3D::~cParticleSystemData3D() {
STLDeleteAll(mvEmitterData);
}
//-----------------------------------------------------------------------
void cParticleSystemData3D::AddEmitterData(iParticleEmitterData *apData) {
mvEmitterData.push_back(apData);
}
//-----------------------------------------------------------------------
cParticleSystem3D *cParticleSystemData3D::Create(tString asName, cVector3f avSize,
const cMatrixf &a_mtxTransform) {
if (mvEmitterData.empty()) {
Warning("Particle system '%s' has no emitters.\n", msName.c_str());
return NULL;
}
cParticleSystem3D *pPS = hplNew(cParticleSystem3D, (asName, this, mpResources, mpGraphics));
pPS->SetMatrix(a_mtxTransform);
for (size_t i = 0; i < mvEmitterData.size(); ++i) {
///////////////////////////
// Create and add
iParticleEmitter3D *pPE = static_cast<iParticleEmitter3D *>(mvEmitterData[i]->Create(asName, avSize));
pPS->AddEmitter(pPE);
pPE->SetSystem(pPS);
}
return pPS;
}
//-----------------------------------------------------------------------
bool cParticleSystemData3D::LoadFromFile(const tString &asFile) {
TiXmlDocument *pXmlDoc = hplNew(TiXmlDocument, (asFile.c_str()));
if (pXmlDoc->LoadFile() == false) {
Warning("Couldn't open XML file %s\n", asFile.c_str());
hplDelete(pXmlDoc);
return false;
}
TiXmlElement *pRootElem = pXmlDoc->RootElement();
TiXmlElement *pEmitterElem = pRootElem->FirstChildElement("ParticleEmitter");
for (; pEmitterElem != NULL; pEmitterElem = pEmitterElem->NextSiblingElement("ParticleEmitter")) {
cParticleEmitterData3D_UserData *pPE = hplNew(cParticleEmitterData3D_UserData, ("",
mpResources, mpGraphics));
pPE->LoadFromElement(pEmitterElem);
mvEmitterData.push_back(pPE);
}
hplDelete(pXmlDoc);
return true;
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
cParticleSystem3D::cParticleSystem3D(const tString asName,
cParticleSystemData3D *apData,
cResources *apResources, cGraphics *apGraphics)
: iEntity3D(asName) {
mpResources = apResources;
mpGraphics = apGraphics;
mpParticleManager = NULL;
mpData = apData;
mbFirstUpdate = true;
}
//-----------------------------------------------------------------------
cParticleSystem3D::~cParticleSystem3D() {
for (size_t i = 0; i < mvEmitters.size(); ++i) {
hplDelete(mvEmitters[i]);
}
if (mpParticleManager)
mpParticleManager->Destroy(mpData);
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
void cParticleSystem3D::SetVisible(bool abVisible) {
if (mbIsVisible == abVisible)
return;
mbIsVisible = abVisible;
for (size_t i = 0; i < mvEmitters.size(); ++i) {
mvEmitters[i]->SetVisible(mbIsVisible);
}
}
//-----------------------------------------------------------------------
bool cParticleSystem3D::IsDead() {
size_t lCount = 0;
for (size_t i = 0; i < mvEmitters.size(); ++i) {
iParticleEmitter3D *pPE = mvEmitters[i];
if (pPE->IsDead())
lCount++;
}
if (lCount == mvEmitters.size())
return true;
return false;
}
bool cParticleSystem3D::IsDying() {
size_t lCount = 0;
for (size_t i = 0; i < mvEmitters.size(); ++i) {
iParticleEmitter3D *pPE = mvEmitters[i];
if (pPE->IsDying())
lCount++;
}
if (lCount == mvEmitters.size())
return true;
return false;
}
//-----------------------------------------------------------------------
void cParticleSystem3D::Kill() {
SetIsSaved(false);
for (size_t i = 0; i < mvEmitters.size(); ++i) {
iParticleEmitter3D *pPE = mvEmitters[i];
pPE->Kill();
}
}
//-----------------------------------------------------------------------
void cParticleSystem3D::KillInstantly() {
SetIsSaved(false);
for (size_t i = 0; i < mvEmitters.size(); ++i) {
iParticleEmitter3D *pPE = mvEmitters[i];
pPE->KillInstantly();
}
}
//-----------------------------------------------------------------------
void cParticleSystem3D::UpdateLogic(float afTimeStep) {
if (IsActive() == false)
return;
for (size_t i = 0; i < mvEmitters.size(); ++i) {
iParticleEmitter3D *pPE = mvEmitters[i];
//////////////////////////
// Warm Up
if (mbFirstUpdate) {
iParticleEmitterData *pData = mpData->GetEmitterData((int)i);
if (pData->GetWarmUpTime() > 0) {
float fTime = pData->GetWarmUpTime();
float fStepSize = 1.0f / pData->GetWarmUpStepsPerSec();
while (fTime > 0) {
pPE->UpdateLogic(fStepSize);
fTime -= fStepSize;
}
}
mbFirstUpdate = false;
}
//////////////////////////
// Update
pPE->UpdateLogic(afTimeStep);
}
}
//-----------------------------------------------------------------------
void cParticleSystem3D::AddEmitter(iParticleEmitter3D *apEmitter) {
mvEmitters.push_back(apEmitter);
AddChild(apEmitter);
}
//-----------------------------------------------------------------------
iParticleEmitter3D *cParticleSystem3D::GetEmitter(int alIdx) {
return mvEmitters[alIdx];
}
//-----------------------------------------------------------------------
int cParticleSystem3D::GetEmitterNum() {
return (int)mvEmitters.size();
}
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// PRIVATE METHODS
//////////////////////////////////////////////////////////////////////////
//-----------------------------------------------------------------------
//-----------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////
// SAVE OBJECT STUFF
//////////////////////////////////////////////////////////////////////////
kBeginSerializeBase(cSaveData_ParticleEmitter3D)
kSerializeVar(mbActive, eSerializeType_Bool)
kSerializeVar(mbDying, eSerializeType_Bool)
kEndSerialize()
//-----------------------------------------------------------------------
kBeginSerialize(cSaveData_cParticleSystem3D, cSaveData_iEntity3D)
kSerializeVar(msDataName, eSerializeType_String)
kSerializeVar(mvDataSize, eSerializeType_Vector3f)
kSerializeClassContainer(mvEmitters, cSaveData_ParticleEmitter3D, eSerializeType_Class)
kEndSerialize()
//-----------------------------------------------------------------------
iSaveObject *cSaveData_cParticleSystem3D::CreateSaveObject(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
cWorld3D *pWorld = apGame->GetScene()->GetWorld3D();
cParticleSystem3D *pPS = pWorld->CreateParticleSystem(msName, msDataName, mvDataSize,
m_mtxLocalTransform);
return pPS;
}
//-----------------------------------------------------------------------
int cSaveData_cParticleSystem3D::GetSaveCreatePrio() {
return 3;
}
//-----------------------------------------------------------------------
iSaveData *cParticleSystem3D::CreateSaveData() {
return hplNew(cSaveData_cParticleSystem3D, ());
}
//-----------------------------------------------------------------------
void cParticleSystem3D::SaveToSaveData(iSaveData *apSaveData) {
kSaveData_SaveToBegin(cParticleSystem3D);
kSaveData_SaveTo(msDataName);
kSaveData_SaveTo(mvDataSize);
pData->mvEmitters.Resize(GetEmitterNum());
for (int i = 0; i < GetEmitterNum(); ++i) {
iParticleEmitter3D *pPE = GetEmitter(i);
pData->mvEmitters[i].mbDying = pPE->IsDying();
pData->mvEmitters[i].mbActive = pPE->IsActive();
}
}
//-----------------------------------------------------------------------
void cParticleSystem3D::LoadFromSaveData(iSaveData *apSaveData) {
kSaveData_LoadFromBegin(cParticleSystem3D);
kSaveData_LoadFrom(msDataName);
kSaveData_LoadFrom(mvDataSize);
if (GetEmitterNum() != (int)pData->mvEmitters.Size()) {
Error("Saved emitter number in %s/%d does not match loaded, killing system!\n",
GetName().c_str(),
GetSaveObjectId());
for (int i = 0; i < GetEmitterNum(); ++i) {
iParticleEmitter3D *pPE = GetEmitter(i);
pPE->KillInstantly();
return;
}
}
for (int i = 0; i < GetEmitterNum(); ++i) {
iParticleEmitter3D *pPE = GetEmitter(i);
pPE->SetActive(pData->mvEmitters[i].mbActive);
if (pData->mvEmitters[i].mbDying)
pPE->KillInstantly();
}
}
//-----------------------------------------------------------------------
void cParticleSystem3D::SaveDataSetup(cSaveObjectHandler *apSaveObjectHandler, cGame *apGame) {
kSaveData_SetupBegin(cParticleSystem3D);
}
//-----------------------------------------------------------------------
} // namespace hpl