#ifdef ASURA_USE_AXON
//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_AnimTemplates.h
//
// Created by Tamir Ibrahim (28.09.06)
// Was the old <project>_AnimationTemplates made by Andrew Weinkove - 22/07/2005
// Animation template classes : Animation templates can be played by actors to perform
// preset sequences of animations similar to a cutscene.
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
//////////////////////////////////////////////////////////////////////////////

// B E G I N   F I L E   W R A P P E R ///////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
    #pragma once
#endif

#ifndef AXON_GAMESCENE_ANIMTEMPLATES_H___
#define AXON_GAMESCENE_ANIMTEMPLATES_H___ 1

// E N D   F I L E   W R A P P E R ///////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

// asura
#include "Core/Asura_Hash.h"
#include "Core/Asura_Maths.h"
#include "Core/Asura_String.h"

#ifdef ASURA_TOOLS
#include "Misc/list_tem.hpp"
#endif

// F O R W A R D   D E C L A R A T I O N S ///////////////////////////////////

class Asura_Chunk_Stream;
class Asura_String;
class Axon_Gamescene_AnimTemplate;

//////////////////////////////////////////////////////////////////////////////
//
// Template types enum.
//
//////////////////////////////////////////////////////////////////////////////

const u_int uAXON_ANIMATION_SEQUENCE_ID_NONE = 0xffffffffu;

enum AXON_ANIM_TEMPLATE_TYPE
{
	AXON_ATT_STATIC = 0,
	AXON_ATT_LOOPINGMOVEMENT,
	AXON_ATT_RIGIDMOVEMENT,
	AXON_ATT_FIDGETBEHAVIOUR,

	NUM_AXON_ANIM_TEMPLATE_TYPES
};

#ifdef ASURA_TOOLS
extern const char* s_pszAnimTemplateTypeStrings[ NUM_AXON_ANIM_TEMPLATE_TYPES ];
#endif

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_AnimTemplate_Entry
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_AnimTemplate_Entry
{
	friend class Axon_Gamescene_AnimTemplate;
	friend class Tools_AnimTemplates;

public:
	Axon_Gamescene_AnimTemplate_Entry();
	virtual ~Axon_Gamescene_AnimTemplate_Entry() {}

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream, const Axon_Gamescene_AnimTemplate& xParentTemplate );
#ifdef ASURA_TOOLS
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual void Copy( const Axon_Gamescene_AnimTemplate_Entry* pxTemplateEntry );
	virtual void LoadAnims() const;
	virtual void AddFilesToExportList( List< Asura_String >& xNameList ) const;
	virtual bool Verify( const Axon_Gamescene_AnimTemplate& xParentTemplate ) const;
	bool WillFinish() const;

	void SetAnim( Asura_Hash_ID uAnimHashID, Asura_Hash_ID uAnimFilenameHashID );
	void SetAnimPackage( u_int uUniqueID );
#endif

	// Not the duration of the entry anim, but the duration the user has set via tools.
	virtual float GetUserSetDuration() const { return 0.0f; }
	float GetAnimationDuration( const void* pMappingData = NULL ) const;

	// Use this if you want to take any package mappings into account.
	Asura_Hash_ID CalcAnimHashIDToPlay( const void* pMappingData = NULL, Asura_Hash_ID* puAnimFilenameHashID = NULL ) const;

	bool ShouldLoop() const { return m_bLoop; }
	bool ShouldTween() const { return m_bTween; }
	bool ShouldPlayBackwards() const { return m_bBackwards; }
	bool ShouldPlayMirrored() const { return m_bMirror; }
	float GetTweenTime() const { return m_fTweenTime; }
	Axon_Gamescene_AnimTemplate_Entry* GetNextEntry() const { return m_pxNextEntry; }

private:
	bool		  ContainsAnim() const { return m_bContainsAnim; }
	// Simply returns m_uAnimHashIDOrUniqueID without performing any necessary package mappings.
	Asura_Hash_ID GetAnimHashID()                     const;
	Asura_Hash_ID GetAnimFilenameHashID()             const { return m_uAnimFilenameHashID; }
	u_int		  GetAnimPackageUniqueID()			  const;

public: // for now
	// Flags we need for all types.
	union
	{
		struct
		{
			u_int	m_bLoop              : 1,
                    m_bTween             : 1,
                    m_bBackwards         : 1,
                    m_bLoopTimeInSeconds : 1,
                    m_xDeathType         : 1,
					m_bMirror            : 1,
				    // If we don't contain an anim we contain the unique ID of an anim package.
				    m_bContainsAnim		 : 1;
		};
		u_int m_uAnimTemplateFlags;
	};
private:
	float m_fTweenTime;
	Axon_Gamescene_AnimTemplate_Entry* m_pxNextEntry;

	// This is either the anim hash ID or the unique ID of an anim package, depending upon the value of m_bContainsAnim.
	Asura_Hash_ID m_uAnimHashIDOrUniqueID;
	Asura_Hash_ID m_uAnimFilenameHashID;

private:
	enum { CURRENT_CHUNK_VERSION = 2 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_StaticAnimTemplate_Entry
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_StaticAnimTemplate_Entry : public Axon_Gamescene_AnimTemplate_Entry
{
public:
	Axon_Gamescene_StaticAnimTemplate_Entry();

	u_int GetFidgetBehaviourID() const;

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream, const Axon_Gamescene_AnimTemplate& xParentTemplate );
#ifdef ASURA_TOOLS
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual void Copy( const Axon_Gamescene_AnimTemplate_Entry* pxTemplateEntry );
	virtual void LoadAnims() const;
	virtual bool Verify( const Axon_Gamescene_AnimTemplate& xParentTemplate ) const;
#endif

	virtual float GetUserSetDuration() const { return m_fUserSetDuration; }

private:
	float m_fUserSetDuration;
	u_int m_uFidgetBehaviourID;

	typedef Axon_Gamescene_AnimTemplate_Entry PARENT;

	friend class Axon_Gamescene_AnimTemplate;
	friend class Tools_AnimTemplates;

	enum { CURRENT_CHUNK_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_LoopingAnimTemplate_Entry
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_LoopingAnimTemplate_Entry : public Axon_Gamescene_AnimTemplate_Entry
{
public:
	Axon_Gamescene_LoopingAnimTemplate_Entry();

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream, const Axon_Gamescene_AnimTemplate& xParentTemplate );
#ifdef ASURA_TOOLS
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual void Copy( const Axon_Gamescene_LoopingAnimTemplate_Entry* pxTemplateEntry );
#endif

	virtual float GetUserSetDuration() const { return m_fUserSetDuration; }

private:
	float m_fUserSetDuration;

	typedef Axon_Gamescene_AnimTemplate_Entry PARENT;

	friend class Axon_Gamescene_AnimTemplate;
	friend class Tools_AnimTemplates;

	enum { CURRENT_CHUNK_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_RigidAnimTemplate_Entry
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_RigidAnimTemplate_Entry : public Axon_Gamescene_AnimTemplate_Entry
{
public:
	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream, const Axon_Gamescene_AnimTemplate& xParentTemplate );
#ifdef ASURA_TOOLS
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
#endif //ASURA_TOOLS

private:
	typedef Axon_Gamescene_AnimTemplate_Entry PARENT;

	enum { CURRENT_CHUNK_VERSION = 1 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_FidgetAnimTemplate_Entry
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_FidgetAnimTemplate_Entry : public Axon_Gamescene_AnimTemplate_Entry
{
public:
	Axon_Gamescene_FidgetAnimTemplate_Entry();

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream, const Axon_Gamescene_AnimTemplate& xParentTemplate );
#ifdef ASURA_TOOLS
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual void Copy( const Axon_Gamescene_AnimTemplate_Entry* pxTemplateEntry );
#endif //ASURA_TOOLS

	float GetFidgetWeight() const { return m_fFidgetWeight; }

private:
	float m_fFidgetWeight;

	typedef Axon_Gamescene_AnimTemplate_Entry PARENT;

	friend class Axon_Gamescene_AnimTemplate;
	friend class Tools_AnimTemplates;

	enum { CURRENT_CHUNK_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_AnimTemplate
//
// If mapping data is provided then any anim mappings can be correctly evaluated.
// If not then the default mapping will be applied.
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_AnimTemplate
{
public:
	Axon_Gamescene_AnimTemplate( const u_int uType );
	virtual ~Axon_Gamescene_AnimTemplate();

	u_int GetType() const { return m_uTemplateType; }
	u_int GetUniqueID() const { return m_uUniqueID; }

	void Empty();
	u_int GetNumEntries() const;
	Axon_Gamescene_AnimTemplate_Entry* GetFirstEntry() const { return m_pxFirstEntry; }
	// fTimeRemainder is the time we are already into the current anim template entry animation.
	Axon_Gamescene_AnimTemplate_Entry* GetCurrentEntry( float fTime, const void* pMappingData, float& fTimeRemainder ) const;
	float GetDuration( const void* pMappingData ) const;
	virtual void GetMovementOffset( float fTime, const void* pMappingData, Asura_Vector_3& xPosOffset, Asura_Matrix_3x3& xOriOffset ) const;
    void GetMovementVelocity( float fTime, const void* pMappingData, Asura_Vector_3& xVelocity ) const;

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );

#ifdef ASURA_TOOLS
	Axon_Gamescene_AnimTemplate( const Asura_String& xName, const u_int uType );

	bool WillFinish() const;
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual void Copy( const Axon_Gamescene_AnimTemplate* pxTemplate );
	// Add anims from this template to the list.
	virtual void AddFilesToExportList( List< Asura_String >& xNameList ) const;
	virtual bool Verify() const;

	void LoadAnims() const;

	static u_int CalculateUniqueID( const Asura_String& xName );

	const Asura_String& GetPath() const { return m_xPath; }
	void SetPath( const Asura_String& xPath ) { m_xPath = xPath; }
	const Asura_String& GetName() const { return m_xTemplateName; }
	void SetName( const Asura_String& xName ) { m_xTemplateName = xName; }
	bool IsLocalOnlyAndWritable() const { return m_bLocalOnlyAndWritable; }
	void SetLocalOnlyAndWritable( bool bVal ) { m_bLocalOnlyAndWritable = bVal; }
#endif

	// With values from AXON_ANIM_TEMPLATE_TYPE.
	u_int m_uTemplateType;
	// The unique ID is initially the hash of the name this was created with.
	// If there is a collision it is incremented until it no longer collides.
	// If the template name changes the hash remains the same, so references do not need to be fixed up.
	u_int m_uUniqueID;
	Axon_Gamescene_AnimTemplate_Entry* m_pxFirstEntry;

#ifdef ASURA_TOOLS
	Asura_String m_xPath;
	Asura_String m_xTemplateName;
	// Whether the file associated with this template is local only and writable.
	bool		 m_bLocalOnlyAndWritable;
#endif

private:
	enum { CURRENT_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_StaticAnimTemplate
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_StaticAnimTemplate : public Axon_Gamescene_AnimTemplate
{
private:
	typedef Axon_Gamescene_AnimTemplate PARENT;

public:
	Axon_Gamescene_StaticAnimTemplate();
	~Axon_Gamescene_StaticAnimTemplate();

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
#ifdef ASURA_TOOLS
	Axon_Gamescene_StaticAnimTemplate( const Asura_String& xName );
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
#endif

private:
	enum { CURRENT_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_LoopingAnimTemplate
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_LoopingAnimTemplate : public Axon_Gamescene_AnimTemplate
{
private:
	typedef Axon_Gamescene_AnimTemplate PARENT;

public:
	Axon_Gamescene_LoopingAnimTemplate();
	~Axon_Gamescene_LoopingAnimTemplate();

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
#ifdef ASURA_TOOLS
	Axon_Gamescene_LoopingAnimTemplate( const Asura_String& xName );
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual bool Verify() const;
#endif

private:
	enum { CURRENT_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_RigidAnimTemplate
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_RigidAnimTemplate : public Axon_Gamescene_AnimTemplate
{
private:
	typedef Axon_Gamescene_AnimTemplate PARENT;

public:
	Axon_Gamescene_RigidAnimTemplate();
	~Axon_Gamescene_RigidAnimTemplate();

	virtual void GetMovementOffset( float fTime, const void* pScoringData, Asura_Vector_3& xPosOffset, Asura_Matrix_3x3& xOriOffset ) const;

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
#ifdef ASURA_TOOLS
	Axon_Gamescene_RigidAnimTemplate( const Asura_String& xName );
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual bool Verify() const;
#endif

private:
	enum { CURRENT_VERSION = 0 };
};

//////////////////////////////////////////////////////////////////////////////
//
// Axon_Gamescene_FidgetAnimTemplate
//
//////////////////////////////////////////////////////////////////////////////

class Axon_Gamescene_FidgetAnimTemplate : public Axon_Gamescene_AnimTemplate
{
private:
	typedef Axon_Gamescene_AnimTemplate PARENT;

public:
	Axon_Gamescene_FidgetAnimTemplate();
	~Axon_Gamescene_FidgetAnimTemplate();

	u_int GetNumValidEntries() const;
	Axon_Gamescene_FidgetAnimTemplate_Entry* ChooseFidget();

	virtual void ReadFromChunkStream( Asura_Chunk_Stream& xStream );
#ifdef ASURA_TOOLS
	Axon_Gamescene_FidgetAnimTemplate( const Asura_String& xName );
	virtual void WriteToChunkStream( Asura_Chunk_Stream& xStream ) const;
	virtual bool Verify() const;
	void Copy( const Axon_Gamescene_AnimTemplate* pxTemplate );
#endif

	void CalculateTotalWeighting();

	float m_fMaxFidgetDelay;
	float m_fMinFidgetDelay;
	float m_fTotalWeighting;

private:
	static const u_int uCURRENT_CHUNK_VERSION = 1;
};

//////////////////////////////////////////////////////////////////////////////
//
// 
//
//////////////////////////////////////////////////////////////////////////////

#endif // #ifndef AXON_GAMESCENE_ANIMTEMPLATES_H___

#endif // ASURA_USE_AXON
