//////////////////////////////////////////////////////////////////////////////
//
// AVP_MoveData_Animation.h
//
// Copyright (C) 2007 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 __AVP_MOVEDATA_ANIMATION_H__
#define __AVP_MOVEDATA_ANIMATION_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 "Blueprint/Asura_Blueprint.h"
#include "Entity/PhysicalObject/Moves/Asura_MoveData_Animation.h"

// avp
#include "Actor/AVP_Actor_AnimationHandler.h"

#define AVP_MOVEDATA_MAX_BLEND_REGIONS 4
#define AVP_MOVEDATA_MAX_ANIMS_PER_REGION 10

//////////////////////////////////////////////////////////////////////////////
//
// AVP_MoveData_Animation
//
//////////////////////////////////////////////////////////////////////////////

class Asura_Blueprint;

class AVP_MoveData_Animation : public Asura_MoveData_Animation
{
public:
	AVP_MoveData_Animation( const Asura_Hash_ID uAnimHash, const u_int uFlags = 0, const u_int uPriority = AVP_AAPC_MOVE, const Asura_Hash_ID uControllerGroupHash = ASURA_HASH_ID_UNSET );

	bool	AlwaysReCalculateFinalMovementOffset() const { return m_bAlwaysReCalculateFinalMovementOffset; }

	bool GetDontCalculateVelocity() const { return m_bDontCalculateVelocity; }

protected:
	bool m_bAlwaysReCalculateFinalMovementOffset;

private:

	typedef Asura_MoveData_Animation PARENT;
};

class AVP_MoveData_BlendedAnimation : public AVP_MoveData_Animation
{
public:
	AVP_MoveData_BlendedAnimation( const Asura_Blueprint& xAnimBlendTemplateBlueprint, const u_int uFlags = 0, const u_int uPriority = AVP_AAPC_MOVE, const Asura_Hash_ID uControllerGroupHash = ASURA_HASH_ID_UNSET );

	void SetBlendAngle( float fBlend ) { m_fBlendAngle = fBlend; }

	// Overridden functions
	virtual void Reset(void);
	virtual bool Start(const bool bLoopAtEnd, Asura_Animation& xAnimation);
	virtual bool Update( const float fTimeStep );

	virtual void	StopLoopedAnims();

	virtual bool	CalculateMovementOffset(const float fParametricTimer, Asura_AVector3* pxPosition, Asura_Quat* pxOrientation) const;
	virtual bool	CalculateVelocity(const float fParametricTimer, Asura_AVector3& xVelocity) const;
	virtual bool	CalculateAngularVelocity(const float fParametricTimer, Asura_AVector3& xAxis, Asura_Angle& fAngle) const;

	// Invalid functions
	virtual Asura_Hash_ID	GetAnimationControllerHash(void) const { return m_auMoveAnimAACAHash[ 0 ]; }
	virtual const Asura_AnimationController_Animation*	GetAnimationController(void) const; // return the first anim controller for setting tween getting parametric timer etc.
	virtual Asura_AnimationController_Animation*		GetAnimationController(void); // return the first anim controller for setting tween getting parametric timer etc.

	virtual const Asura_Hierarchy_Anim*					GetHierarchyAnim(void) const; // return the first anim in the BP for purposes of calculating the duration etc.

	virtual void	SetAnimHash(const Asura_Hash_ID uHash) { Asura_Assert(false, "Not valid to call on this type of movedata, use AVP_Move::SetAnimBlendTemplateBlueprint to create the MoveData_Animation instead"); }
	virtual bool	HasValidAnimation(void) const { return m_uNumBlendRegions > 0 && m_auNumAnims[ 0 ] > 0 && m_aauAnimHash[ 0 ][ 0 ] != ASURA_HASH_ID_UNSET; } // do we have at least 1 valid anim.

private:
	typedef AVP_MoveData_Animation PARENT;

	void InitialiseFromBlueprint( const Asura_Blueprint& xAnimBlendTemplateBlueprint );

	void UpdateBlends();
	void TweenToNewDirectionalAnimGroup( const Asura_Hash_ID uAnimACW, const Asura_Hash_ID uAnimCW, const float fTweenTime );

	u_int			m_uNumBlendRegions;
	u_int			m_auNumAnims			[ AVP_MOVEDATA_MAX_BLEND_REGIONS ];
	float			m_afTweenAngleACW		[ AVP_MOVEDATA_MAX_BLEND_REGIONS ];
	float			m_afTweenAngleCW		[ AVP_MOVEDATA_MAX_BLEND_REGIONS ];
	u_int			m_aauTweenOnAnimFlags	[ AVP_MOVEDATA_MAX_BLEND_REGIONS ][ AVP_MOVEDATA_MAX_ANIMS_PER_REGION ];
	Asura_Hash_ID	m_aauAnimHash			[ AVP_MOVEDATA_MAX_BLEND_REGIONS ][ AVP_MOVEDATA_MAX_ANIMS_PER_REGION ];
	float			m_aafAngle				[ AVP_MOVEDATA_MAX_BLEND_REGIONS ][ AVP_MOVEDATA_MAX_ANIMS_PER_REGION ];

	float			m_fBlendAngle;

	float			m_fCurrentBlendDir;

	u_int			m_uCurrentAnimBlendRegion;
	u_int			m_uCurrentACWAnimIndex;
	u_int			m_uLastAnimBlendRegion;

	bool			m_bLoopAtEnd;

	Asura_Hash_ID	m_auMoveAnimAACAHash[ 2 ];
};

class AVP_Blueprint_ParameterEnumerator_MoveData_BlendedAnimation_Region : public Asura_Blueprint_ParameterEnumerator
{
public:
	AVP_Blueprint_ParameterEnumerator_MoveData_BlendedAnimation_Region( const Asura_Blueprint& xBP, float* pfTweenAngleACW, float* pfTweenAngleCW ) : m_xBP( xBP ), m_pfTweenAngleACW( pfTweenAngleACW ), m_pfTweenAngleCW( pfTweenAngleCW ) {}
	virtual ~AVP_Blueprint_ParameterEnumerator_MoveData_BlendedAnimation_Region() {}

	virtual void BeginEnumeration() {}
	virtual bool Enumerate( const u_int uIndex, char const* const szName, const Asura_Value& xValue);
	virtual void EndEnumeration( const bool bSuccess ) {}

	virtual const char* GetParameterFormat() const { return "%s%0*d.Anim.01"; }

private:
	typedef Asura_Blueprint_ParameterEnumerator PARENT;

	const Asura_Blueprint& 	m_xBP;
	float*					m_pfTweenAngleACW;
	float*					m_pfTweenAngleCW;
};

class AVP_Blueprint_ParameterEnumerator_MoveData_BlendedAnimation_Anim : public Asura_Blueprint_ParameterEnumerator
{
public:
	AVP_Blueprint_ParameterEnumerator_MoveData_BlendedAnimation_Anim( const Asura_Blueprint& xBP, u_int uRegionIndex, u_int* puTweenOnAnimFlags, Asura_Hash_ID* puAnimHash, float* pfAngle ) : m_xBP( xBP ), m_uRegionIndex( uRegionIndex ), m_puTweenOnAnimFlags( puTweenOnAnimFlags ), m_puAnimHash( puAnimHash ), m_pfAngle( pfAngle ) {}
	virtual ~AVP_Blueprint_ParameterEnumerator_MoveData_BlendedAnimation_Anim() {}

	virtual void BeginEnumeration() {}
	virtual bool Enumerate( const u_int uIndex, char const* const szName, const Asura_Value& xValue);
	virtual void EndEnumeration( const bool bSuccess ) {}

	virtual const char* GetParameterFormat() const;

private:
	typedef Asura_Blueprint_ParameterEnumerator PARENT;

	const Asura_Blueprint&	m_xBP;
	u_int					m_uRegionIndex;
	u_int*					m_puTweenOnAnimFlags;
	Asura_Hash_ID*			m_puAnimHash;
	float*					m_pfAngle;

	mutable char			m_szParameterFormat[20];
};

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

#endif //__AVP_MOVEDATA_ANIMATION_H__
