/**
* Timeline
* @version: 01-29-2005
* @author Joseph 'Pcjoe' Florencio
*/
#ifndef FXTIMELINE_H
#define FXTIMELINE_H

// timeline ID enum
typedef enum
{	TLID_ROTATION=1,
	TLID_SIZE,
	TLID_ALPHA,
	TLID_COLOR,
	TLID_SOUND,
	TLID_POSITION,
	TLID_SEQUENCE,
	TLID_FRAMEMULTI,
	TLID_BODYPART,
	TLID_MDLBLUR,
	TLID_RADIALBLUR,
	TLID_SCREENSHAKE,
	TLID_SNDSTREAM1,
	TLID_SNDSTREAM2,
	TLID_SNDVOL1,
	TLID_SNDVOL2
}tlid;

// timed event ID enum
typedef enum
{
	TEID_ROTATION=1,
	TEID_ROTATION_ADD,
	TEID_SIZE,
	TEID_ALPHA,
	TEID_COLOR,
	TEID_SOUND,
	TEID_POSITION,
	TEID_VELOCITY,
	TEID_SEQUENCE,
	TEID_FRAMEMULTI,
	TEID_BODYPART,
	TEID_MDLBLUR,
	TEID_RADIALBLUR,
	TEID_SCREENSHAKE,
	TEID_SNDSTREAM,
	TEID_SNDVOL
}teid;

/*
* Timed Event
*/
class CTimedEvent
{
public:
	CTimedEvent() { setInterpTo(true); }
	
	// Get ID
	virtual int getID( void ) { return 0; }

	// Get Copy
	virtual CTimedEvent *getCopy( void ) { return NULL; }

	/*
	* XML
	*/
	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// xmlCreate
	TiXmlElement *xmlCreateFloat( string strName, float flValue );
	TiXmlElement *xmlCreateInt( string strName, int iValue );
	TiXmlElement *xmlCreateBool( string strName, bool bValue );
	TiXmlElement *xmlCreateString( string strName, std::string strString );
	TiXmlElement *xmlCreateVector( string strName, vec3_t vecValue );

	// xmlFind
	float xmlFindFloat( TiXmlElement *pTE, string strName );
	int xmlFindInt( TiXmlElement *pTE, string strName );
	bool xmlFindBool( TiXmlElement *pTE, string strName );
	std::string xmlFindString( TiXmlElement *pTE, string strName );
	vec3_t xmlFindVector( TiXmlElement *pTE, string strName );

	// Accessors
	bool canInterpTo( void ) { return m_bInterpTo; }
	void setInterpTo( bool interp ) { m_bInterpTo = interp; }
protected:
	// Interpolate to this event
	bool m_bInterpTo;
};

class CTimedEventTrigger : public CTimedEvent
{
public:

	bool getTriggerStatus( void ) { return m_bTriggered; }
	void setTrigger( void ) { m_bTriggered = true; }
	void releaseTrigger( void ) { m_bTriggered = false; }
protected:
	bool m_bTriggered;
};

/*
* Timeline Base
*/
class CTimeline
{
public:
	// Constructor
	CTimeline();
	// Destructor
	~CTimeline();

	// Trigger / Interpolate
	virtual bool isTrigger( void ) { return false; }
	virtual bool isInterpolate( void ) { return false; }

	// Update Data
	virtual void updateData( float flTime ) { };

	// Get Name
	virtual const char *getName() { return ""; }

	// Get ID
	virtual const int getID( void ) { return 0; }

	// Get FX Object
	CFXObject *getFXObject( void );

	// Read XML
	virtual void readXML( TiXmlElement *pElement );

	// Write XML
	virtual TiXmlElement *writeXML( void );

	// Get FX Object 3D
	CFXObject3D *getFXObject3D( void ) { return (CFXObject3D*)getFXObject(); }

	// Get FX Object Render
	CFXObjectRender *getFXObjectRender( void ) { return (CFXObjectRender*)getFXObject(); }

	// Get FX Object MDL
	CFXObjectMDL	*getFXObjectMDL( void ) { return (CFXObjectMDL*)getFXObject(); }

	// Get Timed Event Previous
	std::map<float,CTimedEvent*>::iterator getTimedEventPrev( float flTime );

	// Get Timed Event After
	std::map<float,CTimedEvent*>::iterator getTimedEventAfter( float flTime );

	// Update time ( delete updated iterator, return new iterator with same data, but new time )
	std::map<float,CTimedEvent*>::iterator updateTime( std::map<float,CTimedEvent*>::iterator iterUpdate, float flTime );

	// Add timed event
	void addTimedEvent( float flTime, CTimedEvent *pNewEvent ) { m_TimedEvents[flTime] = pNewEvent; }

	// Accessors
	CTimelineManager *getTimelineManager( void ) { return m_pTimelineManager; }
	void setTimelineManager( CTimelineManager *manager ) { m_pTimelineManager = manager; }

	std::map<float,CTimedEvent*> *getTimedEvents( void ) { return &m_TimedEvents; }
	
protected:
	// Link to Timeline Manager
	CTimelineManager *m_pTimelineManager;

	// Timed events for timeline <time,event>
	std::map<float,CTimedEvent*> m_TimedEvents;
};

/*
* Timeline Base Interpolate
*/
class CTimeInterpolate : public CTimeline
{
public:
	// Interpolate
	virtual bool isInterpolate( void ) { return true; }

	// Update Data
	virtual void updateData( float flTime );

	// Calculate no occured event
	virtual void calcTimedEventNone( float flTime ) {}

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime ) {}

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime ) {}

	// Get percent between both events
	float getPercentBetween( std::map<float,CTimedEvent*>::iterator iterStart, std::map<float,CTimedEvent*>::iterator iterEnd, float flTime );

	// Can Interpolate Two Events (will make use of prev and after events)
	virtual bool canInterpolTwoEvents( float flTime );

	// No event has occured at this time
	virtual bool noOccuredEvent( float flTime );

	// Only use previous event (no after event, or no interpolation used on after event)
	virtual bool usePreviousEventOnly( float flTime );
};


/*
* Timeline Rotation
*/
class CTimedEventRotation : public CTimedEvent
{
public:
	// Constructors
	CTimedEventRotation() { }
	CTimedEventRotation(CQuaternion qRot) { getRotation()->setQuaternion(qRot); }
	CTimedEventRotation(const float *angles) { getRotation()->EulerToQuaternion(angles); }

	// Get ID
	virtual int getID( void ) { return TEID_ROTATION; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventRotation;
		memcpy(pCopy,this,sizeof(CTimedEventRotation));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML( pElement );
		getRotation()->EulerToQuaternion(xmlFindVector(pElement,"rotation"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateVector("rotation", getRotation()->QuaternionToEuler()));
		return pTE;
	}

	// Timed Event Add Rotation
	virtual bool isTimedAddRotation( void ) { return false; }

	// Accessors
	CQuaternion *getRotation( void ) { return &m_qRotation; }
protected:
	CQuaternion	m_qRotation;
};

// Used for adding a constant rotation to an object
class CTimedEventAddRotation : public CTimedEventRotation
{
public:
	// Constructors
	CTimedEventAddRotation() { setInterpTo(false); setInitialRotation(false); }

	// No interpolation, once time is hit set off with velocity
	CTimedEventAddRotation(vec3_t addRot)
	{	CTimedEventAddRotation(); setAddedRotation(addRot);
		setInterpTo(false);
	}
	CTimedEventAddRotation(CQuaternion qAddRot)
	{	CTimedEventAddRotation(qAddRot.QuaternionToEuler());
	}

	// Interpolate to distance, then apply velocity
	CTimedEventAddRotation(vec3_t rotTo, vec3_t addRot)
	{	CTimedEventAddRotation(); setInterpTo(true);
		getRotation()->EulerToQuaternion(rotTo);
		setAddedRotation(addRot); setInitialRotation(true);
	}
	CTimedEventAddRotation(CQuaternion qRotTo, CQuaternion qAddRot)
	{	CTimedEventAddRotation(); setInterpTo(true);
		getRotation()->setQuaternion(qRotTo);
		setAddedRotation(qAddRot.QuaternionToEuler());
		setInitialRotation(true);
	}

	// Get ID
	virtual int getID( void ) { return TEID_ROTATION_ADD; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventAddRotation;
		memcpy(pCopy,this,sizeof(CTimedEventAddRotation));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEventRotation::readXML(pElement);
		setAddedRotation(xmlFindVector(pElement, "added rotation"));
		setInitialRotation(xmlFindBool(pElement, "init rotation"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateVector("added rotation", getAddedRotation()));
		pTE->LinkEndChild(xmlCreateBool("init rotation", hasInitialRotation()));
		return pTE;
	}

	// Timed Event Add Rotation
	bool isTimedAddRotation( void ) { return true; }

	// Get Start Rotation
/*	vec3_t getStartRotation( float flDurration, std::map<float,CTimedEvent*>::iterator iterFirst, std::map<float,CTimedEvent*>::iterator iterThis )
	{	// This one isn't relitive to the previous rotation, use start rotation
		if(hasInitialRotation())
		{	return getRotation()->QuaternionToEuler();
		}
		else
		{	// First link, start rotation must be 0,0,0
			if(iterFirst == iterThis)
			{	return vec3_t(0,0,0);
			}
			vec3_t vecRot = vec3_t(0,0,0);
			if(flDurration > 0)
			{	vecRot = 
				vec3_t vecRot = iterFirst->second->getRotation()->QuaternionToEuler();
				vecRot = vecRot + pTimedAddRot->getAddedRotation() * (flTime-iterTimedRot->first);

			// Get previous iterator
			std::map<float,CTimedEvent*>::iterator iterPrev = iterThis;
			iterPrev--;
			// Another timed add rotation, call function recursivly
			if(((CTimedEventRotation*)iterPrev->second)->isTimedAddRotation())
			{
				flDurration = iterThis->first - iterPrev->first;
				return (vecRot+getStartRotation(flDurration, iterFirst, iterPrev));
			}
			// Regular rotation, grab pos
			else
			{
			}
		}
		return vec3_t(0,0,0);
	}*/
	
	// Accessors
	vec3_t getAddedRotation( void ) { return m_vecAddRotation; }
	void setAddedRotation( vec3_t vecRot ) { m_vecAddRotation = vecRot; }

	bool hasInitialRotation( void ) { return m_bInitialRotation; }
	void setInitialRotation( bool bRot ) { m_bInitialRotation = bRot; }
protected:
	vec3_t	m_vecAddRotation;
	bool	m_bInitialRotation;
};

class CTimeRotation : public CTimeInterpolate
{
public:
//	CTimeRotation();
	
	// Account for regular rotation and additive rotational
	virtual bool usePreviousEventOnly( float flTime );

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Rotation"; }

	// Get ID
	virtual const int getID( void ) { return TLID_ROTATION; }
};


/*
* Timeline Size
*/
class CTimedEventSize : public CTimedEvent
{
public:
	// Constructors
	CTimedEventSize() { setSize(0); }
	CTimedEventSize(float flSize) { setSize(flSize); }

	// Get ID
	virtual int getID( void ) { return TEID_SIZE; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventSize;
		memcpy(pCopy,this,sizeof(CTimedEventSize));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setSize(xmlFindFloat(pElement, "size"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateFloat("size", getSize()));
		return pTE;
	}

	// Accessors
	float getSize( void ) { return m_flSize; }
	void setSize( float flSize ) { m_flSize = flSize; }
protected:
	float m_flSize;
};


class CTimeSize : public CTimeInterpolate
{
public:
//	CTimeSize();

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Size"; }

	// Get ID
	virtual const int getID( void ) { return TLID_SIZE; }
};

/*
* Timeline Alpha
*/
class CTimedEventAlpha : public CTimedEvent
{
public:
	// Constructors
	CTimedEventAlpha() { setAlpha(0); }
	CTimedEventAlpha(float flAlpha) { setAlpha(flAlpha); }

	// Get ID
	virtual int getID( void ) { return TEID_ALPHA; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventAlpha;
		memcpy(pCopy,this,sizeof(CTimedEventAlpha));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setAlpha(xmlFindFloat(pElement, "alpha"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateFloat("alpha", getAlpha()));
		return pTE;
	}

	// Accessors
	float getAlpha( void ) { return m_flAlpha; }
	void setAlpha( float flAlpha ) { m_flAlpha = flAlpha; }
protected:
	float m_flAlpha;
};

class CTimeAlpha : public CTimeInterpolate
{
public:
//	CTimeAlpha();

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Alpha"; }

	// Get ID
	virtual const int getID( void ) { return TLID_ALPHA; }
};

/*
* Timeline Color
*/
class CTimedEventColor : public CTimedEvent
{
public:
	// Constructors
	CTimedEventColor() { }
	CTimedEventColor(float r, float g, float b) { getColor()->setColor(r,g,b); }

	// Get ID
	virtual int getID( void ) { return TEID_COLOR; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventColor;
		memcpy(pCopy,this,sizeof(CTimedEventColor));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		getColor()->setColor((xmlFindVector(pElement, "color")));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateVector("color", getColor()->getColor()));
		return pTE;
	}

	// Accessors
	CFXColor *getColor( void ) { return (&m_Color); }

protected:
	CFXColor m_Color;
};

class CTimeColor : public CTimeInterpolate
{
public:
//	CTimeColor();

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Color"; }

	// Get ID
	virtual const int getID( void ) { return TLID_COLOR; }
};

/*
* Timeline Sound
*/
class CTimedEventSound : public CTimedEventTrigger
{
public:
	// Constructor
	CTimedEventSound() { releaseTrigger(); setChannelIndex(0); }

	// Get ID
	virtual int getID( void ) { return TEID_SOUND; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventSound;
		memcpy(pCopy,this,sizeof(CTimedEventSound));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setSound(xmlFindString(pElement, "sound"));
		setChannelIndex(xmlFindInt(pElement, "channel"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateString("sound", getSound()));
		pTE->LinkEndChild(xmlCreateInt("channel", getChannelIndex()));
		return pTE;
	}

	// Accessors
	// Sound string
	std::string getSound( void ) { return m_strSound; }
	void setSound( std::string sound ) { m_strSound = sound; }

	// Channel Index
	int getChannelIndex( void ) { return m_iChannelIndex; }
	void setChannelIndex( int channel ) { m_iChannelIndex = channel; }
protected:
	std::string	m_strSound;
	int			m_iChannelIndex;
};

class CTimeSound : public CTimeline
{
public:
//	CTimeSound();

	// Reset triggers
	virtual void resetTriggers( float flReleaseAfterTime );

	// Update Data
	virtual void updateData( float flTime );

	// Get Name
	virtual const char *getName() { return "Sound"; }

	// Get ID
	virtual const int getID( void ) { return TLID_SOUND; }
};



/*
* Timeline Sound Stream
*/
class CTimedEventSoundStream : public CTimedEventTrigger
{
public:
	// Get ID
	virtual int getID( void ) { return TEID_SNDSTREAM; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventSoundStream;
		memcpy(pCopy,this,sizeof(CTimedEventSoundStream));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setStreamFile(xmlFindString(pElement, "stream file"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateString("stream file", getStreamFile()));
		return pTE;
	}

	// Accessors
	// Stream
	std::string getStreamFile( void ) { return m_strStream; }
	void setStreamFile( std::string stream ) { m_strStream = stream; }
protected:
	std::string	m_strStream;
};

class CTimeSoundStream : public CTimeline
{
public:
	// Reset triggers
	virtual void resetTriggers( void );

	// Update Data
	virtual void updateData( float flTime );

	// Get Name
	virtual const char *getName() { return "Sound Stream"; }

	// Get ID
	virtual const int getID( void ) { return TLID_SNDSTREAM1; }

	// Stream
	virtual FSOUND_STREAM *getStream( CFXObjectSound *pObj ) { return NULL; }
	virtual void setStream( CFXObjectSound *pObj, FSOUND_STREAM *pStream ) { }

	// Channel
	virtual int getChannel( CFXObjectSound *pObj ) { return 0; }
	virtual void setChannel( CFXObjectSound *pObj, int iChan ) { }
};

class CTimeSoundStream1 : public CTimeSoundStream
{
public:
	// Get Name
	virtual const char *getName() { return "Sound Stream 1"; }
	// Get ID
	virtual const int getID( void ) { return TLID_SNDSTREAM1; }

	// Stream
	virtual FSOUND_STREAM *getStream( CFXObjectSound *pObj );
	virtual void setStream( CFXObjectSound *pObj, FSOUND_STREAM *pStream );
	
	// Channel
	virtual int getChannel( CFXObjectSound *pObj );
	virtual void setChannel( CFXObjectSound *pObj, int iChan );
};

class CTimeSoundStream2 : public CTimeSoundStream
{
public:
	// Get Name
	virtual const char *getName() { return "Sound Stream 2"; }
	// Get ID
	virtual const int getID( void ) { return TLID_SNDSTREAM2; }

	// Stream
	virtual FSOUND_STREAM *getStream( CFXObjectSound *pObj );
	virtual void setStream( CFXObjectSound *pObj, FSOUND_STREAM *pStream );
	
	// Channel
	virtual int getChannel( CFXObjectSound *pObj );
	virtual void setChannel( CFXObjectSound *pObj, int iChan );
};

/*
* Timeline Volume
*/
class CTimedEventVolume : public CTimedEvent
{
public:
	// Constructors
	CTimedEventVolume() { setVolume(0); }
	CTimedEventVolume(float flVolume) { setVolume(flVolume); }

	// Get ID
	virtual int getID( void ) { return TEID_SNDVOL; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventVolume;
		memcpy(pCopy,this,sizeof(CTimedEventVolume));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setVolume(xmlFindFloat(pElement, "volume"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateFloat("volume", getVolume()));
		return pTE;
	}

	// Accessors
	float getVolume( void ) { return m_flVolume; }
	void setVolume( float flVolume ) { m_flVolume = flVolume; }
protected:
	float m_flVolume;
};

class CTimeVolume : public CTimeInterpolate
{
public:
//	CTimeVolume();

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Volume"; }

	// Get ID
	virtual const int getID( void ) { return TLID_SNDVOL1; }

	// Channel
	virtual int getChannel( CFXObjectSound *pObj ) { return 0; }
	virtual void setChannel( CFXObjectSound *pObj, int iChan ) { }
};

class CTimeVolume1 : public CTimeVolume
{
public:

	// Get Name
	virtual const char *getName() { return "Volume 1"; }

	// Get ID
	virtual const int getID( void ) { return TLID_SNDVOL1; }

	// Channel
	virtual int getChannel( CFXObjectSound *pObj );
	virtual void setChannel( CFXObjectSound *pObj, int iChan );
};

class CTimeVolume2 : public CTimeVolume
{
public:

	// Get Name
	virtual const char *getName() { return "Volume 2"; }

	// Get ID
	virtual const int getID( void ) { return TLID_SNDVOL2; }

	// Channel
	virtual int getChannel( CFXObjectSound *pObj );
	virtual void setChannel( CFXObjectSound *pObj, int iChan );
};

/*
* Timeline Position
*/
class CTimedEventPosition : public CTimedEvent
{
public:
	// Constructors
	CTimedEventPosition() { setPathManager(0); setDistance(0); }
	CTimedEventPosition(int iPathManager, float flDistance) { setPathManager(iPathManager); setDistance(flDistance); }

	// Get ID
	virtual int getID( void ) { return TEID_POSITION; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventPosition;
		memcpy(pCopy,this,sizeof(CTimedEventPosition));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setDistance(xmlFindFloat(pElement, "distance"));
		setPathManager(xmlFindInt(pElement, "path manager"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateFloat("distance", getDistance()));
		pTE->LinkEndChild(xmlCreateInt("path manager", getPathManager()));
		return pTE;
	}

	// Timed Event Velocity
	virtual bool isTimedVelocity( void ) { return false; }

	// Accessors
	float getDistance( void ) { return m_flDistance; }
	void setDistance( float flDistance ) { m_flDistance = flDistance; }
	int getPathManager( void ) { return m_iPathManager; }
	void setPathManager( int iPathManager ) { m_iPathManager = iPathManager; }

protected:
	float m_flDistance;
	int m_iPathManager;
};

// Used for moving an object along a path at a velocity
class CTimedEventVelocity : public CTimedEventPosition
{
public:
	// Constructors
	CTimedEventVelocity() { setInterpTo(false); setLoopPath(false); }
	// No interpolation, once time is hit set off with velocity
	CTimedEventVelocity(int iPathManager, float flVelocity, bool bLoop)
	{	CTimedEventVelocity(); setPathManager(iPathManager);
		setVelocity(flVelocity); setLoopPath(bLoop);
		setInterpTo(false);
	}
	// Interpolate to distance, then apply velocity
	CTimedEventVelocity(int iPathManager, float flDistance, float flVelocity, bool bLoop)
	{	CTimedEventVelocity(); setInterpTo(true);
		setPathManager(iPathManager); setDistance(flDistance);
		setVelocity(flVelocity); setLoopPath(bLoop);
	}

	// Get ID
	virtual int getID( void ) { return TEID_VELOCITY; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventVelocity;
		memcpy(pCopy,this,sizeof(CTimedEventVelocity));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEventPosition::readXML(pElement);
		setVelocity(xmlFindFloat(pElement, "velocity"));
		setLoopPath(xmlFindBool(pElement, "loop path"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEventPosition::writeXML();
		pTE->LinkEndChild(xmlCreateFloat("velocity", getVelocity()));
		pTE->LinkEndChild(xmlCreateBool("loop path", canLoopPath()));
		return pTE;
	}

	// Timed Event Velocity
	bool isTimedVelocity( void ) { return true; }
	
	// Accessors
	float getVelocity( void ) { return m_flVelocity; }
	void setVelocity( float flVelocity ) { m_flVelocity = flVelocity; }
	bool canLoopPath( void ) { return m_bLoopPath; }
	void setLoopPath( bool bLoop ) { m_bLoopPath = bLoop; }
protected:
	float m_flVelocity;
	bool m_bLoopPath;
};

class CTimePosition : public CTimeInterpolate
{
public:
//	CTimePosition();
	
	// Overwrite to account for multiple timelines, only use previous event if after event is on another timeline
	// or if previous event is in the form of a constant velocity along the path
	virtual bool usePreviousEventOnly( float flTime );

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Position"; }

	// Get ID
	virtual const int getID( void ) { return TLID_POSITION; }
};

/*
* Timeline Sequence
*/
class CTimedEventSequence : public CTimedEvent
{
public:
	// Constructors
	CTimedEventSequence() { setSequence(""); setLoop(true); }
	CTimedEventSequence( string strSequence ) { setSequence(strSequence); setLoop(true); }
	CTimedEventSequence( string strSequence, bool loop ) { setSequence(strSequence); setLoop(loop); }

	// Get ID
	virtual int getID( void ) { return TEID_SEQUENCE; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventSequence;
		memcpy(pCopy,this,sizeof(CTimedEventSequence));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	
		CTimedEvent::readXML(pElement);	
		setSequence(xmlFindString(pElement, "sequence"));
		setLoop(xmlFindBool(pElement, "loop"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateString("sequence", getSequence()));
		pTE->LinkEndChild(xmlCreateBool("loop", canLoop()));
		return pTE;
	}

	// Accessors
	void setSequence( std::string strSequence ) { m_strSequence = strSequence; }
	string getSequence( void ) { return m_strSequence; }
	void setLoop( bool loop ) { m_bLoop = loop; }
	bool canLoop( void ) { return m_bLoop; }
protected:
	string m_strSequence;
	bool m_bLoop;
};

class CTimedSequence : public CTimeInterpolate
{
public:
	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Sequence"; }

	// Get ID
	virtual const int getID( void ) { return TLID_SEQUENCE; }
};

/*
* Timeline Framrate Multiply (sets model frame as well)
*/
class CTimedEventFrameMulti : public CTimedEvent
{
public:
	// Constructors
	CTimedEventFrameMulti() { setMulti(1); }
	CTimedEventFrameMulti(float flMulti) { setMulti(flMulti); }

	// Get ID
	virtual int getID( void ) { return TEID_FRAMEMULTI; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventFrameMulti;
		memcpy(pCopy,this,sizeof(CTimedEventFrameMulti));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setMulti(xmlFindFloat(pElement, "multi"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateFloat("multi", getMutli()));
		return pTE;
	}

	// Accessors
	void setMulti( float flMulti ) { m_flMulti = flMulti; }
	float getMutli( void ) { return m_flMulti; }
protected:
	float	m_flMulti;
};

class CTimedFrameMulti : public CTimeInterpolate
{
public:

	// Get Previous CTimedEventSequence
	std::map<float,CTimedEvent*>::iterator getPrevSeq( float flTime );

	// Calculate no occured event
	virtual void calcTimedEventNone( float flTime );

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Frame Multiplier"; }

	// Get ID
	virtual const int getID( void ) { return TLID_FRAMEMULTI; }
};

/*
* Timeline Body Part
*/
class CTimedEventBodyPart : public CTimedEvent
{
public:
	// Constructors
	CTimedEventBodyPart() { setBodyPart(0); }
	CTimedEventBodyPart( int iBody ) { setBodyPart(iBody); }

	// Get ID
	virtual int getID( void ) { return TEID_BODYPART; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventBodyPart;
		memcpy(pCopy,this,sizeof(CTimedEventBodyPart));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setBodyPart(xmlFindInt(pElement, "body part"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateInt("body part", getBodyPart()));
		return pTE;
	}

	// Accessors
	void setBodyPart( int iBody ) { m_iBodyPart = iBody; }
	int getBodyPart( void ) { return m_iBodyPart; }
protected:
	int	m_iBodyPart;
};

class CTimedBodyPart : public CTimeInterpolate
{
public:

	// Update Data
	virtual void updateData( float flTime );

	// Get Name
	virtual const char *getName() { return "Body Part"; }

	// Get ID
	virtual const int getID( void ) { return TLID_BODYPART; }
};

/*
* Timeline Model Blur
*/
class CTimedEventModelBlur : public CTimedEvent
{
public:
	// Constructors
	CTimedEventModelBlur() { setBlur(false); }
	CTimedEventModelBlur( bool blur ) { setBlur(blur); }

	// Get ID
	virtual int getID( void ) { return TEID_MDLBLUR; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventModelBlur;
		memcpy(pCopy,this,sizeof(CTimedEventModelBlur));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setBlur(xmlFindBool(pElement, "blur"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateBool("blur", getBlur()));
		return pTE;
	}

	// Accessors
	void setBlur( bool blur ) { m_bBlur = blur; }
	bool getBlur( void ) { return m_bBlur; }
protected:
	bool m_bBlur;
};

class CTimedModelBlur : public CTimeInterpolate
{
public:

	// Update Data
	virtual void updateData( float flTime );

	// Get Name
	virtual const char *getName() { return "Model Blur"; }

	// Get ID
	virtual const int getID( void ) { return TLID_MDLBLUR; }
};

/*
* Timeline Radial Blur
*/
class CTimedEventRadialBlur : public CTimedEvent
{
public:
	// Constructors
	CTimedEventRadialBlur() { setBlur(0); }
	CTimedEventRadialBlur(float flBlur) { setBlur(flBlur); }

	// Get ID
	virtual int getID( void ) { return TEID_RADIALBLUR; }

	// Get Copy
	virtual CTimedEvent *getCopy( void )
	{	CTimedEvent *pCopy=new CTimedEventRadialBlur;
		memcpy(pCopy,this,sizeof(CTimedEventRadialBlur));
		return pCopy;
	}

	// Read XML
	virtual void readXML( TiXmlElement *pElement )
	{	CTimedEvent::readXML(pElement);
		setBlur(xmlFindFloat(pElement, "radialamt"));
	}

	// Write XML
	virtual TiXmlElement *writeXML( void )
	{	TiXmlElement *pTE = CTimedEvent::writeXML();
		pTE->LinkEndChild(xmlCreateFloat("radialamt", getBlur()));
		return pTE;
	}

	// Accessors
	float getBlur( void ) { return m_flBlurAmt; }
	void setBlur( float flBlur ) { m_flBlurAmt = flBlur; }
protected:
	float m_flBlurAmt;
};

class CTimeRadialBlur : public CTimeInterpolate
{
public:
	~CTimeRadialBlur();

	// Set Blur
	void setBlur( float flAlpha );

	// Calculate previous event
	virtual void calcTimedEventPrev( float flTime );

	// Calculate interpol event
	virtual void calcTimedEventInterpol( float flTime );

	// Get Name
	virtual const char *getName() { return "Radial Blur"; }

	// Get ID
	virtual const int getID( void ) { return TLID_RADIALBLUR; }
};

#endif