//
// Asura_PFX_Source.h
//
// Created by KOR - 15/07/2004
//
// Copyright (C) 2004 Rebellion, All Rights Reserved.
//

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif

#ifndef __ASURA_PFX_SOURCE_H__
#define __ASURA_PFX_SOURCE_H__

#include "Core/Asura_Graph.h"
#include "Core/Asura_Hash.h"
#include "Core/Asura_Maths.h"
#include "SpecialFX/PFX/Asura_PFX_Volume.h"
#include "Rendering/Asura_Colour.h"

// Forward declares
class Asura_PFX_Particle;
class Asura_PFX_Particle_Template;
class Asura_PFX_Source_Template;
class Asura_PFX_Effect;
class Asura_PFX_Lighting;
template <typename T> class Asura_Spline;

/// Asura_PFX_Source //////////////////////////////////////////////////////////////////////////////
// A source instance
///////////////////////////////////////////////////////////////////////////////////////////////////

class Asura_PFX_Source
{
public:
	// Constructor
	Asura_PFX_Source(Asura_PFX_Effect* pxEffect, const Asura_Vector_3& xPosition, const Asura_Matrix_3x3& xDirection, Asura_Hash_ID uTemplateNameHash, const Asura_PFX_Volume& xVolume);
	// Destructor
	~Asura_PFX_Source();
	// Update particle position, velocity, etc.
	void Update(bool bLinkedIn, bool bInFrustum, const Asura_Spline<Asura_Vector_3>* pxSpline = NULL);
	void Render(bool bDontQueue = false);
	// Stop (bImmediate deletes all particles)
	void Stop(bool bImmediate);

	void SetVelocity(const Asura_Vector_3& xVelocity) { m_xVelocity = xVelocity; }

	//Expands culling bounding box to include box needed for this source
	void ExpandBoundingBox(Asura_Bounding_Box& xOutputBB) const;
	// Does this particle use the heat-haze translucency mode
	bool IsHeatHazeSource() const;
	// Generates pre-aged particles in the time range specified
	void Generate(float fStart, float fDuration);

	const Asura_PFX_Particle* GetRandomParticle() const;

	Asura_PFX_Effect*			m_pxEffect;
	Asura_Vector_3				m_xPosition;
	Asura_Matrix_3x3			m_xDirection; // direction to fire particles
	Asura_Vector_3				m_xVelocity; // only used if source dynamics are turned on
	Asura_PFX_Volume			m_xVolume; //Relative volume in which to spawn particles

	// Particle storage
	Asura_PFX_Particle*			m_pxParticles; // array of particles (MH - 18.08.2005, used to be array of pointers to particles)
	unsigned int				m_uMaxParticles;
	unsigned int				m_uNumParticles;
	
	Asura_Hash_ID				m_uTemplateNameHash;

	float						m_fParticleReleaseCounter;
	float						m_fAge;
	float						m_fRangeTimer;
	float						m_fReleaseRate;
	class Asura_PFX_Lighting* m_pxLighting;
	union
	{
		unsigned int			m_uFlags;
		struct
		{
			unsigned int		m_bInRange		:1,
								m_bHasDoneBurst :1;
		};
	};
#ifdef ASURA_SUPPORT_MULTITHREADED_JOB_QUEUE
	void*						m_pPlatformRenderData;
#endif

	void CreateParticle(float fReleaseTimer);//fReleaseTimer is the frame time to use for the new particle on the first frame

#ifdef ASURA_TOOLS
	void SetRNG(Asura_RandomGenerator* pxRNG) {m_pxRNG = pxRNG;}
	Asura_RandomGenerator* GetRNG() const {return m_pxRNG ? m_pxRNG : Asura_Random::GetSharedGenerator();}
#else
	Asura_RandomGenerator* GetRNG() const {return Asura_Random::GetSharedGenerator();}
#endif

private:
	void RemoveParticle(u_int uParticle);
	void RemoveAllParticles();
	// Helpers for ExpandBB
	void GetGraphMax(const Asura_Graph<float>& xGraph, float& fMax) const;
	void GetGraphMinAndMax(const Asura_Graph<float>& xGraph, float& fMin, float& fMax) const;
	void GetGraphMax(const Asura_Graph<Asura_Vector_3>& xGraph, float& fMaxX, float& fMaxY) const;
	void ApplyGravity(Asura_Bounding_Box& xBB, const Asura_Vector_3& xTravel) const;

#ifdef ASURA_SUPPORT_MULTITHREADED_JOB_QUEUE
	void UpdateRenderData();
#endif

#ifdef ASURA_TOOLS
	//Effect specific random generator for use while recording cutscenes. RAR 22/05/2006
	Asura_RandomGenerator* m_pxRNG;
#endif
};

#endif//__ASURA_PFX_SOURCE_H__
