// Ryzom - MMORPG Framework
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
/////////////
// INCLUDE //
/////////////
#include "stdpch.h" // First include for pre-compiled headers.
// 3D
#include "nel/3d/u_particle_system_instance.h"
#include "nel/pacs/u_global_position.h"
// Client
#include "fx_manager.h"
#include "time_client.h"
#include "pacs_client.h"
H_AUTO_DECL(RZ_FXManager)
///////////
// USING //
///////////
using namespace NLMISC;
using namespace NL3D;
using namespace NLPACS;
using namespace std;
////////////
// EXTERN //
////////////
extern UScene *Scene;
/////////////
// GLOBALS //
/////////////
// FX manager.
CFXManager FXMngr;
/////////////
// MEMBERS //
/////////////
/////////////
// METHODS //
/////////////
//-----------------------------------------------
// CFXManager :
// Constructor.
//-----------------------------------------------
CFXManager::CFXManager()
{
H_AUTO_USE(RZ_FXManager)
_NumFXToRemove = 0;
}// CFXManager //
//-----------------------------------------------
// CFXManager :
// Destructor.
//-----------------------------------------------
CFXManager::~CFXManager()
{
H_AUTO_USE(RZ_FXManager)
reset();
}// CFXManager //
//-----------------------------------------------
// instantFX :
// create an FX that will be removed as soon as possible.
//-----------------------------------------------
NL3D::UParticleSystemInstance CFXManager::instantFX(const std::string &fxName, float timeOut /* = 0.f*/)
{
H_AUTO_USE(RZ_FXManager)
// Check FX Name.
if(fxName.empty())
return 0;
NL3D::UParticleSystemInstance fx;
fx.cast (Scene->createInstance(fxName));
if(!fx.empty())
{
_FX2RemoveList.push_back(CFX2Remove(fx, timeOut));
++_NumFXToRemove;
}
return fx;
}// instantFX //
//-----------------------------------------------
// addFX :
//-----------------------------------------------
void CFXManager::addFX(NL3D::UParticleSystemInstance fx, float timeOut, bool testNoMoreParticles /*= false*/)
{
H_AUTO_USE(RZ_FXManager)
if (fx.empty()) return;
_FX2RemoveList.push_back(CFX2Remove(fx, timeOut, testNoMoreParticles));
++_NumFXToRemove;
}// addFX //
//-----------------------------------------------
// fx2remove :
//-----------------------------------------------
void CFXManager::fx2remove(NL3D::UParticleSystemInstance fx, float timeOut)
{
H_AUTO_USE(RZ_FXManager)
if(!fx.empty())
{
_FX2RemoveList.push_back(CFX2Remove(fx, timeOut));
++_NumFXToRemove;
}
}// fx2remove //
//-----------------------------------------------
// update :
//-----------------------------------------------
void CFXManager::update()
{
H_AUTO_USE(RZ_FXManager)
// deferred fx
while (!_DeferredFXByDate.empty())
{
if (T1 < _DeferredFXByDate.begin()->first) break;
const CDeferredFX &fx = _DeferredFXByDate.begin()->second;
NL3D::UParticleSystemInstance fxInstance = instantFX(fx.FXName, fx.TimeOut);
if (!fxInstance.empty())
{
fxInstance.setTransformMode(UTransform::DirectMatrix);
fxInstance.setMatrix(fx.Matrix);
UGlobalPosition gPos;
GR->retrievePosition(fx.Matrix.getPos());
UInstanceGroup *clusterSystem = getCluster(gPos);
fxInstance.setClusterSystem(clusterSystem);
fxInstance.forceInstanciate(); // accurate timing wanted
}
_DeferredFXByDate.erase(_DeferredFXByDate.begin());
}
#ifdef NL_DEBUG
nlassert(_NumFXToRemove == _FX2RemoveList.size());
#endif
// Try to remove Animation FXs still not removed.
std::list::iterator itFx = _FX2RemoveList.begin();
while(itFx != _FX2RemoveList.end())
{
// Backup the old iterator
std::list::iterator itTmp = itFx;
// Iterator on the Next FX.
itFx++;
// If the FX is not present or valid -> remove the FX.
if(!itTmp->Instance.isSystemPresent() ||
!itTmp->Instance.isValid() ||
(itTmp->TestNoMoreParticles && !itTmp->Instance.hasParticles())
)
{
// Delete the FX.
Scene->deleteInstance(itTmp->Instance);
// Remove from the list.
_FX2RemoveList.erase(itTmp);
-- _NumFXToRemove;
}
else
if (itTmp->TimeOut != 0.f)
{
itTmp->TimeOut -= DT;
if (itTmp->TimeOut < 0.f)
{
// Delete the FX.
Scene->deleteInstance(itTmp->Instance);
// Remove from the list.
_FX2RemoveList.erase(itTmp);
-- _NumFXToRemove;
}
}
}
}// update //
//-----------------------------------------------
// reset :
//-----------------------------------------------
void CFXManager::reset()
{
H_AUTO_USE(RZ_FXManager)
// Remove Animation FXs still not removed.
std::list::iterator itFx = _FX2RemoveList.begin();
while(itFx != _FX2RemoveList.end())
{
// Delete the FX.
if(Scene)
Scene->deleteInstance(itFx->Instance);
// Next FX
itFx++;
}
// clear FX list
_FX2RemoveList.clear();
_DeferredFXByDate.clear();
_NumFXToRemove = 0;
}
//-----------------------------------------------
// deferedFX :
//-----------------------------------------------
void CFXManager::deferFX(const std::string &fxName, const NLMISC::CMatrix &matrix, float delayInSeconds, float timeOut /*=FX_MANAGER_DEFAULT_TIMEOUT*/)
{
CDeferredFX fx;
fx.FXName = fxName;
fx.Matrix = matrix;
fx.TimeOut = timeOut;
_DeferredFXByDate.insert(std::make_pair(T1 + sint64(1000.f * delayInSeconds), fx));
}