
#ifndef FXPARTICLEEMITTER_H
#define FXPARTICLEEMITTER_H

class CFXParticleSystem;

// Emitter names defined in xml files
#define FXPEMITTER_BASIC		"basic emitter"
#define FXPEMITTER_RADIATE		"radiating"
#define FXPEMITTER_RING_RADIATE	"ring radiate"
#define FXPEMITTER_RISE			"rise"
#define FXPEMITTER_SCATTER		"scatter"

// Various parse strings
#define FXPARTICLEPARSE_NONE	"none"
#define FXPARTICLEPARSE_STOP	"stop"
#define FXPARTICLEPARSE_BOUNCE	"bounce"
#define FXPARTICLEPARSE_REND_NORM	"normal"
#define FXPARTICLEPARSE_REND_ADD	"additive"
#define FXPARTICLEPARSE_REND_SOLIDTRANS "solid trans"
#define FXPARTICLEPARSE_STYLE_NORM "normal"
#define FXPARTICLEPARSE_STYLE_ELONGATE "elongate"
#define FXPARTICLEPARSE_CULL_FRONT	"front"
#define FXPARTICLEPARSE_CULL_NONE	"none"
#define FXPARTICLEPARSE_VELT_NORM	"normal"
#define FXPARTICLEPARSE_VELT_OUT	"outward"
#define FXPARTICLEPARSE_EMIT_FLOW	"flow"
#define FXPARTICLEPARSE_EMIT_BURST	"burst"


// Collision types
enum
{	FXPCOLLISION_NONE=0,
	FXPCOLLISION_STOP,
	FXPCOLLISION_BOUNCE,
};

// Emit types
enum
{	FXEMITTYPE_FLOW=0,
	FXEMITTYPE_BURST,
};

// style types

// Emit types
enum
{	FXDRAWSTYLE_NORMAL=0,
	FXDRAWSTYLE_ELONGATE,
};


class CFXStorage;

/*
* Base particle emitter
*/
class CFXParticleEmitter
{
public:
	// Constructor
	CFXParticleEmitter();
	CFXParticleEmitter(CFXParticleSystem *pParticleSystem);

	// Reset
	virtual void Reset( void );

	// Parse Data
	virtual void parseData( CFXStorage *pData );
	
	// Get new particle
	virtual CFXParticle *getNewParticle( void ) { return new CFXParticle(); }

	// Get Range
	vec3_t getRange( vec3_t *range );
	int	getRange( int *range );
	float getRange( float *range );

	// Get random sprite from list
	virtual HSPRITE getRandSprite( void );

	// Get sprite count
	virtual int getSpriteNum( void );

	// Name of emitter
	static std::string getStaticName( void ) { return FXPEMITTER_BASIC; }

	// Name of emitter (used in non-static situations)
	virtual std::string getName( void ) { return CFXParticleEmitter::getStaticName(); }

	/*
	* Emit Particles
	*/

	// Cancel new particle
	// (remove it from the particle list and add it to the free list)
	virtual void cancelNewParticle( CFXParticle *pParticle );
	
	// Set Sprite
	virtual bool setParticleSprite( CFXParticle *pParticle );

	// Set Life
	virtual bool setParticleLife( CFXParticle *pParticle );

	// Set RGBA
	virtual void setParticleRGBA( CFXParticle *pParticle );

	// Set Size
	virtual void setParticleSize( CFXParticle *pParticle );

	// Set Origin and Velocity
	virtual void setParticleOriginVelocity( CFXParticle *pParticle );

	// Set Collision
	virtual void setParticleCollision( CFXParticle *pParticle );

	// Set resistance (bounce damp, gravity, air resistance)
	virtual void setParticleResistance( CFXParticle *pParticle );
	
	// Emit Particle
	virtual CFXParticle *emitParticle( CFXParticle *pParticle );

	// Get particles to emit this frame
	virtual int particlesToEmitThisFrame( void );

	// Emit Particles
	virtual void emitParticles( void );

	/*
	* Accessors
	*/
	CFXParticleSystem *getParticleSystem ( void ) { return m_pParticleSystem; }
	void setParticleSystem( CFXParticleSystem *pSys ) { m_pParticleSystem = pSys; }

	int getMaxParticles( void ) { return m_iMaxParticles; }
	void setMaxParticles( int iMaxParticles ) { m_iMaxParticles = iMaxParticles; }

	int getCollision( void ) { return m_iCollision; }
	void setCollision( int iCollision ) { m_iCollision = iCollision; }

	int getRenderType( void ) { return m_iRenderType; }
	void setRenderType( int iRender ) { m_iRenderType = iRender; }

	int getDrawStyle( void ) { return m_iDrawStyle; }
	void setDrawStyle( int iStyle ) { m_iDrawStyle = iStyle; }

	TRICULLSTYLE getCulling( void ) { return m_eCulling; }
	void setCulling( TRICULLSTYLE eCulling ) { m_eCulling = eCulling; }

	float getEmitRate( void ) { return m_flEmitRate; }
	void setEmitRate( float flRate ) { m_flEmitRate = flRate; }

	int getParticlesThisSecond( void ) { return m_iParticlesThisSecond; }
	void setParticlesThisSecond( int iParticles ) { m_iParticlesThisSecond = iParticles; }

	int getEmitType( void ) { return m_iEmitType; }
	void setEmitType( int iType ) { m_iEmitType = iType; }

	int getEmitAmount( void ) { return m_iEmitAmount; }
	void setEmitAmount( int iAmount ) { m_iEmitAmount = iAmount; }

	float getPPPClock( void ) { return m_flPPPClock; }
	void setPPPClock( float flTime ) { m_flPPPClock = flTime; }
	void incPPPClock( void ) { m_flPPPClock++; }
	
protected:
	CFXParticleSystem	*m_pParticleSystem;
	// Emitter settings
	int		m_iMaxParticles;
	int		m_iParticlesThisSecond;
	int		m_iCollision;
	int		m_iRenderType;
	int		m_iDrawStyle;
	int		m_iEmitType;
	int		m_iEmitAmount;
	float	m_flEmitRate;
	float	m_flPPPClock; // PPP = particles per second
	TRICULLSTYLE m_eCulling;
	// Particle specific settings
	std::vector<HSPRITE>	m_SpriteList;
	vec3_t	m_vecVelocity[2];
	float	m_flRGBAStart[2][4];
	float	m_flRGBAEnd[2][4];
	float	m_flLife[2];
	float	m_flGravity[2];
	float	m_flStartSize[2];
	float	m_flEndSize[2];
	float	m_flBounceDamp[2];
	float	m_flAirResistance[2];
};

/*
* Radiate particle system
*/
class CFXParticleEmitterRadiate : public CFXParticleEmitter
{
public:

	// Name of emitter
	static std::string getStaticName( void ) { return FXPEMITTER_RADIATE; }

	// Name of emitter (used in non-static situations)
	virtual std::string getName( void ) { return CFXParticleEmitterRadiate::getStaticName(); }
};

/*
* Ring Radiate particle system
*/
class CFXParticleEmitterRingRadiate : public CFXParticleEmitter
{
public:

	// Reset
	virtual void Reset( void );

	// Parse Data
	virtual void parseData( CFXStorage *pData );

	// Name of emitter
	static std::string getStaticName( void ) { return FXPEMITTER_RING_RADIATE; }

	// Name of emitter (used in non-static situations)
	virtual std::string getName( void ) { return CFXParticleEmitterRingRadiate::getStaticName(); }

	/*
	* Emit Particles
	*/
	// Set Origin and Velocity
	virtual void setParticleOriginVelocity( CFXParticle *pParticle );

	/*
	* Accessors
	*/
	int getVelocityType( void ) { return m_iVelocityType; }
	void setVelocityType( int iType ) { m_iVelocityType = iType; }

protected:
	int m_iVelocityType;
	float	m_flRadius[2];
	float	m_flVelSpeed[2];
	float	m_flVelSpeedZ[2];
};

/*
* Rise particle system
*/
class CFXParticleEmitterRise : public CFXParticleEmitter
{
public:

	// Reset
	virtual void Reset( void );

	// Parse Data
	virtual void parseData( CFXStorage *pData );

	// Name of emitter
	static std::string getStaticName( void ) { return FXPEMITTER_RISE; }

	// Name of emitter (used in non-static situations)
	virtual std::string getName( void ) { return CFXParticleEmitterRise::getStaticName(); }

	/*
	* Emit Particles
	*/
	// Set Origin and Velocity
	virtual void setParticleOriginVelocity( CFXParticle *pParticle );

	/*
	* Accessors
	*/
	float getRadius( void ) { return m_flRadius; }
	void setRadius( float flRadius ) { m_flRadius = flRadius; }

protected:
	float	m_flRadius;
};

/*
* Scatter particle system
*/
class CFXParticleEmitterScatter : public CFXParticleEmitter
{
public:

	// Reset
	virtual void Reset( void );

	// Parse Data
	virtual void parseData( CFXStorage *pData );

	// Name of emitter
	static std::string getStaticName( void ) { return FXPEMITTER_SCATTER; }

	// Name of emitter (used in non-static situations)
	virtual std::string getName( void ) { return CFXParticleEmitterScatter::getStaticName(); }

	/*
	* Emit Particles
	*/
	// Set Origin and Velocity
	virtual void setParticleOriginVelocity( CFXParticle *pParticle );

	/*
	* Accessors
	*/
	float getRadius( void ) { return m_flRadius; }
	void setRadius( float flRadius ) { m_flRadius = flRadius; }

protected:
	float	m_flRadius;
};



#endif