
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Actor_AnimationHandler.h
// Author : Andy Tate
// Date   : 18-Oct-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __AVP_ACTOR_ANIMATIONHANDLER_H__
#define __AVP_ACTOR_ANIMATIONHANDLER_H__


////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

// asura
#include "Core/Asura_Handle.h"
#include "Core/Asura_Hash.h"
#include "Network/Asura_Guid.h"
#include "Animation/Asura_AnimationController.h"

// axon
#include "AnimTemplates/AVP_GS2_AnimPackage.h"
#include "AnimTemplates/Axon_Gamescene_AnimSequenceData.h"

////////////////////////////////////////////////////////////////////////////////
// Defines
////////////////////////////////////////////////////////////////////////////////

#define MAX_MARKER_POINTS 2

enum AVP_ACTOR_ANIMATION_CONTROLLER_PRIORITIES
{
	AVP_AAPC_DEATH_ANIM					= 0x00000100,
	AVP_AAPC_FLINCH_ANIM_TP				= 0x00000180,
	AVP_AAPC_FACIALANIMATION			= 0x00000200,
	AVP_AAPC_GAMESCENE_FIDGET_ANIM		= 0x00000300,
	AVP_AAPC_GAMESCENE_ANIM				= 0x00000400,
	AVP_AAPC_BITE_ANIM					= 0x00001000,
	AVP_AAPC_STIM_ANIM					= 0x00002000,
	AVP_AAPC_LOOK_DU_GROUP_TP			= 0x00002800,
	AVP_AAPC_LOOK_RL_GROUP_TP			= 0x00004000,
	AVP_AAPC_LOOK_GROUP_HUD				= 0x00004000,
	AVP_AAPC_MINIGUN_SPIN_ANIM			= 0x00005000,
	AVP_AAPC_READYBITE_ANIM				= 0x00006000,
	AVP_AAPC_GENERAL_ANIM				= 0x00006000,
	AVP_AAPC_FLINCH_ANIM_HUD			= 0x00007000,
	AVP_AAPC_DEATH						= 0x00008000,
	AVP_AAPC_GENERAL_GROUP				= 0x00008000,
	AVP_AAPC_MOVE						= 0x00008000,
	AVP_AAPC_ATTACHMENT					= 0x00008000,
	AVP_AAPC_REQUEST_ANIM				= 0x0000C000,
	AVP_AAPC_TURN_ANIM_HUD				= 0x0000F000,
	AVP_AAPC_TURN_ANIM_TP				= 0x0000F000,
	AVP_AAPC_WEAPON_ANIM				= 0x00010000,
	AVP_AAPC_WEAPON_GROUP				= 0x00010000,
	AVP_AAPC_WEAPON_IDLE				= 0x00014000,
	AVP_AAPC_RL_DRAG_GROUP				= 0x00015000,
	AVP_AAPC_DU_DRAG_GROUP				= 0x00016000,
	AVP_AAPC_STRAFE_DRAG_GROUP			= 0x00017000,
	AVP_AAPC_FIDGET_ANIM_GROUP			= 0x00018000,
	AVP_AAPC_UPPER_BODY_GROUP			= 0x0001D000,
	AVP_AAPC_UPPER_BODY_MOVING_GROUP	= 0x0001D000,
	AVP_AAPC_UPPER_BODY_IDLE_ANIM		= 0x00020000,
	AVP_AAPC_STATES_GROUP				= 0x00020000,
	AVP_AAPC_LOWER_BODY_GROUP			= 0x00020000,
};

enum AVP_ANIM_POSTURE
{
	AVP_ANIM_POST_STAND,
	AVP_ANIM_POST_CROUCH,
	AVP_ANIM_POST_PRONE_FRONT,
	AVP_ANIM_POST_PRONE_BACK,

	NUM_AVP_ANIM_POSTURE
};

#ifdef ASURA_TOOLS
extern const char* s_aszAVPPostureStrings[ NUM_AVP_ANIM_POSTURE ];
#endif

enum AVP_ANIM_POSE
{
	AVP_ANIM_POSE_RELAXED,
	AVP_ANIM_POSE_NEUTRAL,
	AVP_ANIM_POSE_ALERT,
	AVP_ANIM_POSE_AIM,

	NUM_AVP_ANIM_POSE
};

#ifdef ASURA_TOOLS
extern const char* s_aszAVPPoseStrings[ NUM_AVP_ANIM_POSE ];
#endif

////////////////////////////////////////////////////////////////////////////////
// Forward class declarations...
////////////////////////////////////////////////////////////////////////////////

class Asura_Animation;
class Asura_AnimationBlend;
class Asura_AnimationController_Group;
class Asura_Animation_IK_Chain_LOS;
class Asura_Hierarchy_Skin;
class Asura_Physics_Ragdoll_Description;
class Asura_Shape_Instance;

class Axon_Gamescene_AnimTemplate_Entry;

class AVP_EntityDamage_ApplyToEntity;
struct AVP_Message_Actor_RequestAnimation;
class Asura_AnimationController_Animation;

class AVP_Actor_AnimStateData;
class AVP_Animation_BodyRig;
class AVP_ClientEntity_Actor;
class AVP_Inventory_Item;
class AVP_Actor_FidgetAnimHandler;

////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Actor_AnimationHandler
// Author       : Andy Tate
// Date         : 18-Oct-2006
//
// Description  : Class to handle the animation of an actor.
////////////////////////////////////////////////////////////////////////////////

class AVP_Actor_AnimationHandler
{
public:

	// Public functions...
	AVP_Actor_AnimationHandler          (AVP_ClientEntity_Actor& xOwner);
	virtual ~AVP_Actor_AnimationHandler ();

	virtual void	Initialise( void ); // CALL THIS STRAIGHT AFTER CONSTRUCTION OR ELSE.
	virtual void	Shutdown( void );

	bool PlayDeathAnimation(Asura_Hash_ID uDeathAnimID);

	Asura_Hash_ID GetCurrentGamesceneAnimControllerHash (void) { return m_uCurrentGamesceneAnimControllerHash; }
	void SetCurrentGamesceneAnimControllerHash( const Asura_Hash_ID uCurrentGamesceneAnimControllerHash ) { m_uCurrentGamesceneAnimControllerHash = uCurrentGamesceneAnimControllerHash; }
	void HandleGamesceneAnimSequenceData	(const Axon_Gamescene_AnimSequenceData& xAnimSequenceData);
    void UpdateGamesceneAnimSequence();

	Asura_Hash_ID GetCurrentRequestedAnimControllerHash (void) { return m_uCurrentRequestedAnimControllerHash; }
    virtual void HandleAnimationRequest					( const AVP_Message_Actor_RequestAnimation& xAnimRequestData ) {}
    bool RequestedAnimationHasFinished();

	virtual bool IsRagdoll(void) const { return false; }

	virtual void	UpdateSkin(void);

	virtual	void Reset(void);
    virtual void Update(void);
	virtual void Render(void) const;

	// Camera accessor function...
	virtual bool	GetCameraData(Asura_Vector_3& xPosition, Asura_Matrix_3x3& xOrientation) const;

	// Accessor functions...
	Asura_Animation*		GetAnimation(void)			{ return(m_pxAnimation); }
	const Asura_Animation*	GetAnimation(void) const	{ return(m_pxAnimation); }

	int						GetTargetMarkerCount(void)	const		{ return m_uNumTargetMarkerPoints; }
	static Asura_Hash_ID	GetTargetMarkerPointHash(const int iIndex)	{ return s_auTargetMarkerPointHashes[iIndex]; }

	Asura_Hash_ID			PlayAnimation( const u_int uAnimFlags,
										   const u_int uPriority,
										   Asura_Hash_ID uAnimHashID,
										   Asura_AnimationBlend* pxBlend,
										   Asura_AnimationController_Group* pxParentGroup = NULL,
										   const float fParametricStartTime = 0.0f ) const;

	virtual void	UpdateAnimStateData( const AVP_Actor_AnimStateData* pxAnimDataLBSlow, const AVP_Actor_AnimStateData* pxAnimDataLBFast, const AVP_Actor_AnimStateData* pxAnimDataUBSlow, const AVP_Actor_AnimStateData* pxAnimDataUBFast, const bool bLoop, const float fBlendLBSpeed, const float fBlendUBSpeed, const float fOSMoveDirAngle, const float fTweenTime, const bool bSynch ) = 0;
	virtual void	PauseCurrentAnimState() = 0;
	virtual void	PlayCurrentAnimState() = 0;
	// these are only needed by the AI but should work for players too should the need arise
	virtual bool	IsCurrentAnimStateFinished() const = 0;
	virtual void	SetCurrentAnimStateLooped( const bool bSet ) = 0;

	void	SetFirstPerson(void);
	void	SetThirdPerson(void);
	void	SetFirstPerson(const bool bSet)	{ if(bSet) SetFirstPerson(); else SetThirdPerson(); }
	bool	IsFirstPerson(void) const		{ return(m_bFirstPerson); }
	bool	IsThirdPerson(void) const		{ return(!m_bFirstPerson); }

	void	SetDamaged(const bool bSet)	{ m_bDamaged = bSet; }
	bool	IsDamaged(void) const		{ return(m_bDamaged); }

	// weapon stuff
	bool			IsWeaponGroupTweenFinished(void) const;

	Asura_Hash_ID	PlayWeaponAnimation( const Asura_Hash_ID uAnimHash, const float fTweenTime, const bool bLooped, u_int uFlags = AAC_FLAG_ACTIVE | AAC_FLAG_ENSURE_UNIQUE_HASH | AAC_FLAG_DESTROY_WHEN_FINISHED);
	void			StopWeaponAnimation( const Asura_Hash_ID uAnimControllerHash, const bool bDestroy );
	bool			IsWeaponAnimationPlaying( const Asura_Hash_ID uAnimControllerHash ) const;

	bool	IsActivateAnimPlaying() const;
	bool	IsDeactivateAnimPlaying() const;

	// This unpauses the extend weapon anim and destroys the old retract anim.
	bool	OnWeaponExtending(void);

	// This plays the extend weapon anim and pauses it on the first frame so we can tween to it from the last weapon.
	virtual bool	OnWeaponTweening(const Asura_Hash_ID uAnimHash, const bool bInstant, const bool bCalculateMovement);

	// This function plays the retract weapon anim and leaves it paused once it is finished so we can tween to the new weapon. It also destroys the permanent anim if there is one
	bool	OnWeaponRetracting(const Asura_Hash_ID uAnimHash, const bool bCalculateMovement);

	// This function plays the permanent weapon anim.
	bool	OnWeaponExtended(const Asura_Hash_ID uAnimHash);

	// Attach/detach weapons from vertebrate. Called when hit a certain point in the extend/retract animation.
	virtual void AttachItem( AVP_Inventory_Item* pxItem );
	virtual void DetachItem( AVP_Inventory_Item* pxItem );

	bool	IsItemAttached( const AVP_Inventory_Item* pxItem ) const;

	virtual const Asura_Animation_IK_Chain_LOS* GetLimbIKChainLOS( u_int uLimbItr ) const { return NULL; }

#ifdef ASURA_USE_DEBUG_TEXT
	void RenderDebugInfo();
#endif	//ASURA_USE_DEBUG_TEXT

	virtual const AVP_Actor_AnimStateData* GetCurrentAnimStateData() const = 0;

	AVP_Animation_BodyRig* GetBodyRig() { return m_pxBodyRig; }
	const AVP_Animation_BodyRig* GetBodyRig() const { return m_pxBodyRig; }


	AVP_Actor_FidgetAnimHandler* GetFidgetAnimHandler()	{return m_pxFidgetAnimHandler;	}
	const AVP_Actor_FidgetAnimHandler* GetFidgetAnimHandler()	const {return m_pxFidgetAnimHandler;	}

	Asura_Hash_ID GetWeaponGroupHash() const { return m_uRootWeaponGroupHash; }

	AVP_GS2_AnimMappingData* GetAnimMappingData();

protected:
    // Protected functions...
	const Asura_Hierarchy_Skin*	CreateAnimation(void);
    bool PlayingGamesceneAnimSequence() const;

    // Protected variables...

	Axon_GS2_AnimSequenceData_Handler	m_xGS2SequenceHandler;

	Axon_Gamescene_AnimSequenceData		m_xPendingAnimSequenceData;
	Axon_Gamescene_AnimSequenceData		m_xCurrentAnimSequenceData;

	Asura_Animation*					m_pxAnimation;						// A pointer to the animation to go via.
	AVP_Animation_BodyRig*				m_pxBodyRig;
	AVP_Actor_FidgetAnimHandler*		m_pxFidgetAnimHandler;

	Axon_Gamescene_AnimTemplate_Entry*	m_pxCurrentAnimationTemplateEntry;

	Asura_Guid							m_uOwnerGuid;						// The GUID of the client-entity whose handler this is.
	AVP_ClientEntity_Actor&				m_xOwnerActor;						// A reference to the owenr actor.
	Asura_Hash_ID						m_uSkinHash;						// Hash-ID for the skin we're currently using.

	Asura_Hash_ID						m_uRootStatesGroupHash;				// Child of Asura root, contains all weapon specific state animation groups
	Asura_Hash_ID						m_uRootWeaponGroupHash;				// Child of Asura root, contains all weapon extend/retract/shoot/reload animations

	Asura_Hash_ID						m_uCurrentGamesceneAnimControllerHash;
	Asura_Hash_ID						m_uCurrentGamesceneFidgetAnimControllerHash;
	Asura_Hash_ID						m_uCurrentRequestedAnimControllerHash;

	Asura_Hash_ID						m_uCurrentExtendWeaponAnimHashID;
	Asura_Hash_ID						m_uCurrentRetractWeaponAnimHashID;
	Asura_Hash_ID						m_uCurrentPermanentWeaponAnimHashID;

	Asura_Hash_ID						m_uDeathAnimController;

	u_int								m_uNumTargetMarkerPoints;						// The number of target marker-points on this skin.

	union
	{
		u_int							m_uFlags;
		struct
		{
			u_int						m_bRequestedDefaultAnimation		: 1,
										m_bNotFirstUpdate					: 1,
										m_bFirstPerson						: 1,
										m_bDamaged							: 1,
																			: 0;
		};
	};

	static const Asura_Hash_ID			s_auTargetMarkerPointHashes[MAX_MARKER_POINTS];	// Static array of hashes for target marker-points.

	static AVP_GS2_AnimMappingData s_xAnimMappingData;

private:
	// Private variables...
#if defined(ASURA_DEBUG_VARIABLE_SYSTEM)
	static int s_iConsoleVarsCount;
#endif	// defined(ASURA_DEBUG_VARIABLE_SYSTEM)

	// Private functions...
	AVP_Actor_AnimationHandler				(void);
	AVP_Actor_AnimationHandler				(const AVP_Actor_AnimationHandler& xOther);
	AVP_Actor_AnimationHandler&	operator=	(const AVP_Actor_AnimationHandler& xOther);

};   // End of class 'AVP_Actor_AnimationHandler'.


#endif   // ifndef __AVP_ACTOR_ANIMATIONHANDLER_H__


/// End of file. ///
