
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_AnimationController_Group.h
// Author : Andy Tate
// Date   : 14-Sep-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#ifndef __ASURA_ANIMATIONCONTROLLER_GROUP_H__
#define __ASURA_ANIMATIONCONTROLLER_GROUP_H__

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

#include "Animation/Asura_AnimationController.h"
#include "Animation/Asura_Hierarchy_Tween.h"


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

////////////////////////////////////////////////////////////////////////////////
// Defines...
////////////////////////////////////////////////////////////////////////////////

#define AACG_FLAG_DONT_PASS_DESTROY_TO_CHILDREN	0x00010000
#define AACG_FLAG_PRESERVE_TWEEN_STORE			0x00020000
#define AACG_FLAG_INHERIT_PARENT_TWEEN_STORE	0x00040000

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

////////////////////////////////////////////////////////////////////////////////
// Class        : Asura_AnimationController_Group
// Author       : Andy Tate
// Date         : 14-Sep-2006
//
// Description  : This class allows "Asura_AnimationController" classes to be
//				  grouped together, we can then blend between these animations
//				  using any weights we deem appropriate. The groups doesn't just
//				  have to be instances of animations, there can be other groups
//				  hooked in too - this allows a hierarchy of animations to be
//				  created generating very powerful sequences of animation blends.
////////////////////////////////////////////////////////////////////////////////

class Asura_AnimationController_Group : public Asura_AnimationController
{
public:
	// Public functions...
	Asura_AnimationController_Group          (const Asura_Hash_ID uControllerHash, const u_int uInitialFlags, const u_int uPriority = 0x00004000, Asura_AnimationController_Group* pxParentGroup = NULL );
	virtual ~Asura_AnimationController_Group ();

	// Child controller functions...
	bool	AddChildController			(Asura_AnimationController& xController, Asura_AnimationBlend* pxBlend);
	bool	DestroyChildController		(Asura_AnimationController* pxController);
	bool    DestroyChildControllers		(bool(*pfnShouldDeleteCallback)(const Asura_AnimationController* pxChild));
	bool	DestroyAllChildControllers	(void);
	
	// Clone functions...
	void	CloneTweenStore	(const Asura_AnimationController_Group& xGroup);

	// Overridden activation functions...
//	virtual	void	Activate	(void);
	virtual	void	Deactivate	(void);

	// Overridden function to get the interval flags which were appropriate during the last frame...
	virtual int		GetFlagsForLastFrame	(void) const;

	// Overridden bone-update function...
	virtual	u_int	TweenBoneData	(const Asura_Hierarchy_Skin& xSkin, const u_int uFirstBone, const u_int uLastBone, const float fWeight, const bool bDeltasUseBlends, Asura_AnimationController_Group* pxParentGroup);

	// Overridden bounding-box function...
	virtual	u_int	TweenBoundingBox	(Asura_Bounding_Box& xBB, const Asura_Hierarchy_Skin& xSkin, const float fWeight, const bool bDeltasUseBlends, const bool bSlerpVelocity, Asura_AnimationController_Group* pxParentGroup);

	// Overridden message handling functions...
	virtual	bool	HandleMessage	(const u_int uType, void* pvUserData = NULL);

	// Overridden timer update functions...
	virtual	void	UpdateTimers	(const float fTimeStep, bool bIgnoreTimerFrameStamp);

	// Overridden accessor functions...
	virtual	bool	AreAllBonesUsingDeltas	(void) const	{ return(m_pxTweenStore->AreAllBonesUsingDeltas()); }
	virtual bool	IsUsingSubsetOfBones	(void) const	{ return(m_bIsUsingSubsetOfBones); }
	virtual bool	IsFinished				(void) const	{ return(m_pxFirstChildController == NULL); }
	virtual bool	IsReadyForDestruction	(void) const	{ return(((m_uControllerFlags & AAC_FLAG_DESTROY_WHEN_FINISHED) != 0) && IsFinished()); }
	virtual	float	GetTimeUntilFinished	(void) const	{ return(Asura_Maths::LargeFloat); }

	// Special functions to force the weights of the blends between child controllers...
	bool	SetBlendWeights			(const float* pfWeights, const u_int uNumWeights);
	bool	SetControllerWeights	(const float* pfWeights, const u_int uNumControllers);

	// Accessor functions...
	void	SetDeltasUseBlends(const bool bSet)	{ m_bDeltasUseBlends = bSet; }
	bool	GetDeltasUseBlends(void) const		{ return(m_bDeltasUseBlends); }

	bool	GetVelocity(Asura_Vector_3& xOutput) const;
	bool	GetAngularVelocity(Asura_Vector_3& xOutputAxis, Asura_Angle& fOutputAngle) const;
	bool	GetMovementOffset(Asura_Vector_3* pxOutputPos, Asura_Quat* pxOutputQuat = NULL) const;

	u_int	GetNumChildBlends		(void) const	{ return((m_uNumChildControllers == 0) ? 0 : (m_uNumChildControllers - 1)); }
	u_int	GetNumChildControllers	(void) const	{ return(m_uNumChildControllers); }

	Asura_Hierarchy_Tween&			GetTweenStore	(void)			{ return(*m_pxTweenStore); } // Because we'll always set up a valid tween store pointer in the constructor and this code will be called *a lot* we're not going to NULL check this, it'll never be NULL anyway
	const Asura_Hierarchy_Tween&	GetTweenStore	(void) const	{ return(*m_pxTweenStore); }

	virtual Asura_AnimationController* Duplicate(Asura_Animation* pxDestAnimation) const;

#if (defined ASURA_USE_DEBUG_TEXT || defined ASURA_LOGFILES_ENABLED)
	virtual void PrintDebugInfo(u_int& uRow, u_int& uCol, const Asura_AnimationController_Group* pxParentGroup = NULL, const char* szFilename = NULL) const;
#endif

protected:
	// Protected variables...
	union
	{
		u_int	m_uGroupFlags;						// Single access point for the group flags.

		struct
		{
			u_int	m_uNumChildControllers		: 16,	// The number of child controllers held by this group.
					m_bIsUsingSubsetOfBones		: 1,	// Flag to say that all of this groups children are using a sub-set of bones from the skin.
					m_bDeltasUseBlends			: 1,	// Flag to allow delta animations to be blended together rather than added together.
					m_bNeedsToDeleteTweenStore	: 1,	// Flag to say if we new'd the tween store in the constructor so should delete it on destruction
												: 0;	// 14 spare-bits.
		};
	};

	Asura_Hierarchy_Tween*		m_pxTweenStore;				// Contains the results of blending ALL of this controller's children.

	Asura_AnimationController*	m_pxFirstChildController;	// The first of the children to be blended together.
	Asura_AnimationController*	m_pxLastChildController;	// The last of the children to be blended together.

	// JEB - 09 February 2007 15:30:44 - The last frame the group was updated
	u_int						m_uFrameNumberStamp;


private:
	// Private variables...


	// Private functions...
	Asura_AnimationController_Group  (void);
	Asura_AnimationController_Group  (const Asura_AnimationController_Group& xOther);

	Asura_AnimationController_Group&	operator=	(const Asura_AnimationController_Group& xOther);

};   // End of class 'Asura_AnimationController_Group'.


#endif   // ifndef __ASURA_ANIMATIONCONTROLLER_GROUP_H__


/// End of file. ///
