/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/include/sgx/graphics/sgxtexture_animation.hpp

*/

#ifndef SGX_GRAPHICS_TEXTURE_ANIMATION_HPP
#define SGX_GRAPHICS_TEXTURE_ANIMATION_HPP	1



class CSGXTextureAnimationFrame {
public:
	tUINT32		m_Region;
	tREAL32		m_Duration;
	tINT32		m_dx, m_dy;

	CSGXTextureAnimationFrame() :
		m_Region(0),
		m_Duration(0.1f),
		m_dx(0), m_dy(0) {
		}

	CSGXTextureAnimationFrame(const tUINT32 region, const tREAL32 duration, const tINT32 dx=0, const tINT32 dy=0) :
		m_Region(region),
		m_Duration(duration),
		m_dx(dx), m_dy(dy) {
		}
};

class CSGXTextureAnimationData;
class CSGXTextureAnimationSequence;
class CSGXTextureAnimationState;


/**
The @CSGXTextureAnimationManager provides a mechanism whereby the individual
regions of a texture can be animated in any fashion.
*/
class CSGXTextureAnimationManager  : public CSGXEngine {
public:
		
	static CSGXTextureAnimationManager *get();

	CSGXTextureAnimationData *		registerScenarioAnimation(const sgxString &filename);
	CSGXTextureAnimationData *		registerGlobalAnimation(const sgxString &filename);

	CSGXTextureAnimationData *		loadData(const sgxString &filename);

	CSGXTextureAnimationData *		createData();

	// Animation state - this is apply to the texture during render/update to 
	// determine which animation frame should be displayed.
	CSGXTextureAnimationState *		createState(const CSGXTextureAnimationSequence *pSequence=NULL, const tUINT32 iStartFrame=0);

protected:
	static CSGXTextureAnimationManager *	m_pSingleton;

};

 
class CSGXTextureAnimationSequence {
public:
	typedef enum {
		eForwards = 0,
		eForwardsAndStop = eForwards,
		eBackwards,
		eBackwardsAndStop = eBackwards,

		eForwardsAndLoop,
		eBackwardsAndLoop,

		ePingPongForwards,
		ePingPongBackwards,

	} tAnimationIterator;

	tUINT32												m_ID;
	tAnimationIterator									m_RunAs;
	sgxVector<CSGXTextureAnimationFrame *>				m_Frames;

	CSGXTextureAnimationSequence(tAnimationIterator runas = eForwards) : 
	m_RunAs(runas) {
	}
	~CSGXTextureAnimationSequence();

	tUINT32	addFrame(CSGXTextureAnimationFrame *pFrame);
	tUINT32	addFrame(const CSGXTextureAnimationFrame &pFrame);

	SGX_INLINE tUINT32 getFrameCount() {
		return m_Frames.size();
	}
};

class CSGXTextureAnimationData : public CGameHandler {
public:
	typedef enum {
		eForwards,
		eBackwards,
	} tRunDirection;

	virtual ~CSGXTextureAnimationData();

	sgxVector<CSGXTextureAnimationSequence *>	m_Sequences;
	// We could include the CSGXTexture backptr here, but its
	// functionality would not be supported everywhere, so we've
	// missed it out for now
	CSGXTextureAnimationSequence *	addSequence(CSGXTextureAnimationSequence::tAnimationIterator runsas = CSGXTextureAnimationSequence::eForwards);

	CSGXTextureAnimationSequence *	getSequenceFromIndex(const tUINT32 sequenceIndex) const;
	CSGXTextureAnimationSequence *	getSequence(const sgxString &sequenceID) const;
	CSGXTextureAnimationSequence *	getSequence(const tUINT32 sequenceID) const;

	CSGXTextureAnimationSequence *	getSequenceFromIndex(const tUINT32 seqIndex);

};


class CSGXTextureAnimationState {
public:

	CSGXTextureAnimationData *			m_pAnimationData;
	const CSGXTextureAnimationSequence *m_pCurrentSequence;
	tUINT32								m_CurrentFrame;
	tUINT32								m_CurrentDirection;
	tUINT32								m_iCurrentStaticCell;
	tBOOL								m_bIsRunning;
	tBOOL								m_bStaticCell;
	tBOOL								m_bExtent;
	tREAL32								m_fTimeCum;

public:
	void setAnimationDataSet(CSGXTextureAnimationData *pData);
	void startSequence(const sgxString &name, const tUINT32 iStartFrame=0);
	void startSequence(const CSGXTextureAnimationSequence *pSequence=NULL, const tUINT32 iStartFrame=0);
	void playStaticCell(tUINT32 cell);

	tBOOL startAnimation(tBOOL running) ;
	tBOOL stopAnimation();

	tUINT32 getCurrentFrame() const;
	tUINT32 getCurrentCell() const;

	void update(const tREAL32 telaps);

private:
	CSGXTextureAnimationState(const CSGXTextureAnimationSequence *pSequence=NULL, const tUINT32 iStartFrame=0);

	friend class CSGXTextureAnimationManager;
};


#endif /* SGX_GRAPHICS_TEXTURE_ANIMATION_HPP */
