/*************************************/
/*                                   */
/*   SwooshMgr.h                     */
/*   big juju   10/18/02             */
/*   ned martin  avalanche software  */
/*   visual c++ 6.0                  */
/*   swooshes are dynamic trails     */
/*                                   */
/*************************************/

/* swooshes are dynamic trails that are generated by something that moves, sort of like a ribbon stretching out behind
a moving object. swooshes are fairly expensive to set up, so typically things that will need a swoosh create it at
level initialization time and activate it when needed */

#ifndef __SWOOSHMGR_H
#define __SWOOSHMGR_H

/******************* includes ****************************/

/* system includes */

/* engine includes */

/******************* forward declarations ****************/

class CTriStrip;
class CActor;
class CBallistic;

/******************* defines *****************************/

/* when we allocate vertices for the swoosh, we do it assuming we'll run at 30 hz-- that is, a new point will be added
to the swoosh 30 times a second. if the point lifetime is 1 second, then we'll need a total of 30 points for the swoosh--
after a second the first point will be gone and available for re-use. however, this assumes that there will be no
intermediate points needed. swooshes that are created by a fast-moving object may need quite a few intermediate points.
so we have an overridable default */

#define DEFAULT_POINT_COUNT_MULTIPLIER	1.0f
#define SWOOSH_DEFAULT_LOD_DISTANCE		12.0f

/******************* macros ******************************/

/******************* structures **************************/

/******************* global variables ********************/

/******************* global prototypes *******************/

/**************************** a swoosh emitter ****************************/

class CSwooshEmitter
{
public:

	/* Constructor/destructor-- cannot take parameters, templates don't know about parameters */

	CSwooshEmitter();
	~CSwooshEmitter();

	/* routines */

	void Initialize(
				ts_SwooshEmitterSource *pSource,
				int nDataIndex,		// which of possibly-multiply-loaded particle .dbl's this one comes from
				Vector3 *pvPos,		// pointer to bottom center of cylinder. if not stationary, must be persistent
				bool bStationary);	// if true, cylinder does not move and we copy input position
	bool Advance(const float fFrameSeconds);
	void Activate();
	void Deactivate();

protected:

	/* internal routines */

	void InitializeCylinder(ts_SwooshEmitterSource *pSource);
	void InitializePreview(ts_SwooshEmitterSource *pSource);
	void CreateSwooshes(ts_SwooshEmitterSource *pSource);
	bool AdvanceCylinder(const float fFrameSeconds);
	bool AdvancePreview(const float fFrameSeconds);
	void DeactivateAllSwooshes();

public:

	/* access */

	int GetDataIndex()	{ return(d_nDataIndex); }

	/* must have public prev and next pointers to support DoublyLinkedList template used by ManagedList */

	CSwooshEmitter		*prev;
	CSwooshEmitter		*next;

protected:

	/* flags, including emitter type */

	u32					d_u32Flags;

	/* which of possibly-multiply-loaded particle/swoosh .dbl's this one is from */

	int					d_nDataIndex;

	/* id for emitters that share a limited number of swoosh groups, so that emitter can look for */
	/* other emitters of same name if if needs to steal a swoosh group. really just an index into */
	/* swoosh manager's d_pSharedSwooshGroupEmitterSource array */
	
	int					d_nSharedSwooshGroupID;
	int					d_nDeactivatedID;	// emitter with lowest id was deactivated longest ago, best candidate for stealing from

	/* world position */

	Vector3				*d_pvPos;
	Vector3				d_vPos;	// a place to copy position if emitter is stationary

	/* lifetime. LOD distance. for swoosh emitter, the LOD distance determines when the emitter should deactivate */
	/* all its swooshes-- the swooshes themselves will fade out with distance according to their own LOD value */

	float					d_fLifetime;
	float					d_fLODSquared;

	/* timer, index into swoosh list */

	float					d_fTimer;
	int					d_nSwooshIndex;

	/* pointer to required number of swooshes */

	int					d_nSwooshCount;
	t_Handle				*d_pSwooshHandle;

	/* endpoints for swooshes-- swoosh emitters don't know anything about bones */

	Vector3Packed				*d_pvEndpoint0;
	Vector3Packed				*d_pvEndpoint1;

	/* for cylinder emitter */

	float					d_fRadius;						// meters
	int					d_nRadiusRandomPct;			// +/-, 0..100
	float					d_fHeight;						// meters
	float					d_fSwooshYVel;					// meters/second
	int					d_nSwooshYVelRandomPct;		// +/-, 0..100
	float					d_fSwooshRotVel;				// radians/second
	float					d_fSwooshWidth;				// meters
	int					d_nSwooshWidthRandomPct;	// +/-, 0..100
	float					d_fSwooshLife;					// seconds, for sparse cylinder only
	int					d_nSwooshLifeRandomPct;		// +/-, 0..100
	int					d_nPointsOnCircle;
	float					d_fDeltaTime;
	float					d_fDeltaAngle;
	float					*d_pfSwooshHeight;
	float					*d_pfSwooshAngle;
	float					*d_pfSwooshRadius;
	float					*d_pfSwooshYVel;
	float					*d_pfSwooshXDelta;
	float					*d_pfSwooshYDelta;
	float					*d_pfSwooshLifetime;
	float					d_fAngle;

	/* for preview emitter-- pigpen only */

	/*** nothing needed ***/
};

int SwooshMgr__Init(int nMaxSwooshes, int nMaxSwooshEmitters);
void SwooshMgr__Reset();
void SwooshMgr__Shutdown();
void SwooshMgr__KillAllEmitters(t_Handle Handle = INVALID_HANDLE);
void SwooshMgr__KillAllSwooshes(t_Handle Handle = INVALID_HANDLE);
void SwooshMgr__Advance();
void SwooshMgr__Render();
void *SwooshMgr__GetSwooshSource(int nDataIndex, int nEntryIndex);
void *SwooshMgr__GetSwooshEmitterSource(int nDataIndex, int nEntryIndex);

/* create a new swoosh */
/*** NOTE: swooshes are inactive when created, and have to be activated by a call to Swoosh__Activate ***/

t_Handle SwooshMgr__CreateSwoosh(
				Vector3Packed *pEndpoint0,
				Vector3Packed *pEndpoint1,
				ts_bRGBA &Color,
				float fMaxAlpha,
				float fLifetime,
				bool bAdditiveRender,
				float fPointCountMultiplier = DEFAULT_POINT_COUNT_MULTIPLIER,
				float fLODDistance = SWOOSH_DEFAULT_LOD_DISTANCE);
t_Handle SwooshMgr__CreateSwoosh(
				CActor *pCActor,
				int nBoneID,
				ts_bRGBA &Color,
				float fMaxAlpha,
				float fLifetime,
				bool bAdditiveRender,
				float fPointCountMultiplier = DEFAULT_POINT_COUNT_MULTIPLIER,
				float fLODDistance = SWOOSH_DEFAULT_LOD_DISTANCE,
				float fBoneStart = 0.0f,
				float fBoneEnd = 1.0f);
t_Handle SwooshMgr__CreateSwoosh(
				CBallistic *pBallisticPath,
				float fPathWidth,							// meters
				float fPointInterval,					// seconds
				float fPathMaxTime,						// seconds
				ts_bRGBA &Color,
				float fMaxAlpha,
				float fLifetime,
				bool bAdditiveRender,
				float fLODDistance = SWOOSH_DEFAULT_LOD_DISTANCE);
t_Handle SwooshMgr__CreateSwooshFromRecord(
				const char *pSwooshName,
				Vector3Packed *pEndpoint0,
				Vector3Packed *pEndpoint1,
				float fPointCountMultiplier = DEFAULT_POINT_COUNT_MULTIPLIER);
t_Handle SwooshMgr__CreateSwooshFromRecord(
				const char *pSwooshName,
				CActor *pCActor,
				int nBoneID,
				float fBoneStart = 0.0f,
				float fBoneEnd = 1.0f,
				float fPointCountMultiplier = DEFAULT_POINT_COUNT_MULTIPLIER);
t_Handle SwooshMgr__CreateSwooshFromRecord(
				const char *pSwooshName,
				CBallistic *pBallisticPath,
				float fPathWidth,							// meters
				float fPointInterval,					// seconds
				float fPathMaxTime);						// seconds

/* manipulate individual swooshes */

void Swoosh__Activate(t_Handle SwooshHandle);
void Swoosh__Deactivate(t_Handle SwooshHandle, bool bHideImmediately = false);
void Swoosh__Kill(t_Handle SwooshHandle);
void Swoosh__SetColorMult(t_Handle SwooshHandle, float *pfColorMult);
void Swoosh__SetColorMultFloor(t_Handle SwooshHandle, float fColorMultFloor);
void Swoosh__SetConstantAlpha(t_Handle SwooshHandle, float *pfConstantAlpha);
void Swoosh__SetSharpTail(t_Handle SwooshHandle, bool bSharpTail);

/* create/kill a new swoosh emitter */

CSwooshEmitter *SwooshMgr__CreateEmitterFromRecord(const char *pName, Vector3 *pvPos, bool bStationary);
void SwooshMgr__KillEmitter(CSwooshEmitter *pSwooshEmitter);
bool SwooshMgr__SetEmitterMaxSwooshGroups(const char *pName, int nMaxSwooshGroups);



#endif // __SWOOSHMGR_H
