Blob Blame Raw
//------------------------------------------------------------------
// Iwa_ParticlesManager for Marnie
// based on ParticlesManager by Digital Video
//------------------------------------------------------------------

#include "trenderer.h"

#include <QMutexLocker>

#include "iwa_particlesmanager.h"

/*
EXPLANATION:

ParticlesManager improves the old particles system as follows - the particles manager stores the
last particles configuration which had some particle rendered by a thread.
Under normal cicumstances, this means that every thread has the particles configuration that rendered
last. In case a trail was set, such frame is that beyond the trail.
This managemer works well on the assumption that each thread builds particle in an incremental timeline.
*/

//--------------------------------------------------------------------------------------------------

DEFINE_CLASS_CODE(Iwa_ParticlesManager::FxData, 170) /*- 注:ParticlesManager::FxDataは110 -*/

//--------------------------------------------------------------------------------------------------

typedef std::map<double, Iwa_ParticlesManager::FrameData> FramesMap;

//************************************************************************************************
//    Preliminaries
//************************************************************************************************

class Iwa_ParticlesManagerGenerator : public TRenderResourceManagerGenerator
{
public:
	Iwa_ParticlesManagerGenerator() : TRenderResourceManagerGenerator(true) {}

	TRenderResourceManager *operator()(void)
	{
		return new Iwa_ParticlesManager;
	}
};

MANAGER_FILESCOPE_DECLARATION(Iwa_ParticlesManager, Iwa_ParticlesManagerGenerator);

//************************************************************************************************
//    FrameData implementation
//************************************************************************************************

Iwa_ParticlesManager::FrameData::FrameData(FxData *fxData)
	: m_fxData(fxData), m_frame((std::numeric_limits<int>::min)()), m_calculated(false), m_maxTrail(-1), m_totalParticles(0)
{
	m_fxData->addRef();
}

//-------------------------------------------------------------------------

Iwa_ParticlesManager::FrameData::~FrameData()
{
	m_fxData->release();
}

//-------------------------------------------------------------------------

void Iwa_ParticlesManager::FrameData::buildMaxTrail()
{
	//Store the maximum trail of each particle
	std::list<Iwa_Particle>::iterator it;
	for (it = m_particles.begin(); it != m_particles.end(); ++it)
		m_maxTrail = tmax(m_maxTrail, it->trail);
}

//-------------------------------------------------------------------------

void Iwa_ParticlesManager::FrameData::clear()
{
	m_frame = (std::numeric_limits<int>::min)();
	m_particles.clear();
	m_random = TRandom();
	m_calculated = false;
	m_maxTrail = -1;
	m_totalParticles = 0;
}

//************************************************************************************************
//    FxData implementation
//************************************************************************************************

Iwa_ParticlesManager::FxData::FxData()
	: TSmartObject(m_classCode)
{
}

//************************************************************************************************
//    ParticlesContainer implementation
//************************************************************************************************

Iwa_ParticlesManager *Iwa_ParticlesManager::instance()
{
	return static_cast<Iwa_ParticlesManager *>(
		Iwa_ParticlesManager::gen()->getManager(TRenderer::renderId()));
}

//-------------------------------------------------------------------------

Iwa_ParticlesManager::Iwa_ParticlesManager()
	: m_renderStatus(-1)
{
}

//-------------------------------------------------------------------------

Iwa_ParticlesManager::~Iwa_ParticlesManager()
{
	//Release all fxDatas
	std::map<unsigned long, FxData *>::iterator it, end = m_fxs.end();
	for (it = m_fxs.begin(); it != end; ++it)
		it->second->release();
}

//-------------------------------------------------------------------------

void Iwa_ParticlesManager::onRenderStatusStart(int renderStatus)
{
	m_renderStatus = renderStatus;
}

//-------------------------------------------------------------------------

Iwa_ParticlesManager::FrameData *Iwa_ParticlesManager::data(unsigned long fxId)
{
	QMutexLocker locker(&m_mutex);

	std::map<unsigned long, FxData *>::iterator it = m_fxs.find(fxId);
	if (it == m_fxs.end()) {
		it = m_fxs.insert(std::make_pair(fxId, new FxData)).first;
		it->second->addRef();
	}

	FxData *fxData = it->second;
	FrameData *d = fxData->m_frames.localData();
	if (!d) {
		d = new FrameData(fxData);
		fxData->m_frames.setLocalData(d);
	}

	return d;
}

bool Iwa_ParticlesManager::isCached(unsigned long fxId)
{
	std::map<unsigned long, FxData *>::iterator it = m_fxs.find(fxId);
	return (it != m_fxs.end());
}