//===========================================================================//
// File:	AnimationState.hpp											
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 02/23/999  JSE  Inital coding
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Microsoft Corp.										 //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//


#pragma once

#include "MW4AnimationSystem.hpp"

#include <Adept\State.hpp>
#include <Stuff\NameList.hpp>

namespace Adept
{
	class AttributeEntry;
}

namespace MechWarrior4 
{
	class MWObject;
	class AnimationStateEngine;
	class AnimationState;
	class TransitionState;
	class AnimationStateEngine;
	struct AnimCurve;

	struct AnimHolder;
	struct PoseHolder;
	struct FullHeightPoseHolder;
	struct CycleHolder;
	struct SpeedCycleHolder;
	struct LerpCycleHolder;
	struct SpeedBlenderCycleHolder;
	struct FullHeightBlenderCycleHolder;
	struct FullHeightSpeedBlenderCycleHolder;

}

namespace MechWarrior4 
{

	extern HGOSHEAP g_AnimScript;


	class AnimationStateEngine:
		public Adept::StateEngine
	{
		
	friend AnimationState;
	friend TransitionState;

	friend AnimHolder;
	friend PoseHolder;
	friend FullHeightPoseHolder;
	friend CycleHolder;
	friend SpeedCycleHolder;
	friend LerpCycleHolder;
	friend SpeedBlenderCycleHolder;
	friend FullHeightBlenderCycleHolder;
	friend FullHeightSpeedBlenderCycleHolder;
	
	


	public:
		static void
			InitializeClass();
		static void
			TerminateClass();
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Ever important vehicle who owns me
	//
	public:
		MWObject *vehicleParent;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Run-time Construction and Destruction Support
	//
	public:

		typedef AnimationStateEngine*
			(*Factory)(MWObject *vehicle, const FactoryRequest *request);

		static AnimationStateEngine*
			Make(MWObject *vehicle, const FactoryRequest *request);

		void
			Save(FactoryRequest *request);
		void
			Reuse(const FactoryRequest *request);

		~AnimationStateEngine();

	protected:
		AnimationStateEngine(
			MWObject *vehicle,
			ClassData *class_data,
			const FactoryRequest *request
		);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Shared Data support
	//
	public:
		ClassData*
			GetClassData();

		static ClassData
			*DefaultData;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// State entries
	//
	public:
		enum {
			NoAnimationState = StateEngine::StateCount,//1
			Test1State,
			Test2State,
			Test3State,
			Test4State,
			Test5State,
			Test6State,
			Test7State,
			Test8State,
			StateCount
		};

	
	protected:
		static const StateEntry
			StateEntries[];

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Utility Methods
	//
	public:
		int GetAnimHolderType(const char *type_name);
		size_t GetAnimHolderSize(int type);
		AnimHolder *MakeAnimHolder(int type);
		MW4Animation::AnimInstance *LoadOrMakeAnimInstance(const char *animation_name);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Load Animation State Methods
	//
		void LoadScript(const char *filename, bool run_minimal = true);
		//void LoadScript(Stuff::MemoryStream *stream){};

		bool alreadyLoaded;
		
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Save Animatoin State Methods
	
		//void SaveScript(const char *filename){};
		//void SaveScript(Stuff::MemoryStream *stream){};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Animation types
	//
	public:
		enum {
			AnimHolderType = 0,
			PoseType,
			FullHeightPoseHolderType,
			CycleType,
			SpeedCycleType,
			LerpCycleType,
			FullHeightSpeedBlenderCycleType,
			FullHeightBlenderCycleType,
			SpeedBlenderCycleType,
			AnimTypeCount
		};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// all the memory for the anims and scripts
	//
	protected:
		// flags
		bool
			transitionFlag;

		bool
			quedCurrentState,
			quedNewState,
			quedTransState;
		
		Stuff::Scalar 
			lastCurrentStatePosition;

		int 
			transitionTo;

		// curves and animholders and animInstances
		int			animHoldersCount;
		AnimHolder **animHolderArray;


		AnimCurve	*animCurves;
		int			animCurvesCount;
		

		// the terators that are playing are in here
		MW4Animation::AnimHierarchyIteratorManager *iteratorManager;

		// states that are playing
		Stuff::SlotOf<AnimationState*>
			statePlaying;

		Stuff::SlotOf<AnimationState*>
			newStatePlaying;

		Stuff::SlotOf<AnimationState*>
			transitionPlaying;

		Stuff::ChainOf<AnimationState*>
			expressionsPlaying;


		// all the instances loaded
		Stuff::ChainOf<MW4Animation::AnimInstance*> 
			animInstancesLoaded;

		// states that are loaded
		// this can be optimized to have a static list
		// of all possible states and transitions
		// that way it would be a cheaper look up
		// just more memory.

		// total size never to excede state count
		Stuff::ChainOf<AnimationState*>
			animStatesLoaded;

		// total size never to excede (state count * state count) + state count
		// all combos of states plus the default states
		Stuff::ChainOf<TransitionState*>
			transitionsLoaded;

		// total size never to excede expression count
		Stuff::ChainOf<AnimationState*>
			expressionsLoaded;

		

		Stuff::Scalar
			oldBlendValue,
			newBlendValue,
			transBlendValue;

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Find methods
	//

	AnimationState *
		FindAnimationState(int state_number);

	TransitionState *
		FindTransitionState(int state_number, int trans_state);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Animation state playing methods
	//
	public:

		bool IsTransitioning(){return transitionFlag;};
		int GetTransitionState();
			


		Stuff::Scalar GetCurrentStatePercentage();
		Stuff::Scalar GetTranistionStatePercentage();
		Stuff::Scalar GetNewStatePercentage();

		bool CurrentStateLoopedThisFrame();

		virtual int
			RequestState(
				int new_state,
				bool run_minimal = false,
				void* data = NULL
				);

		virtual void
			RunStates(Stuff::Scalar time_slice, bool run_minimal = false);
		

		void StopAllExpressions(Stuff::Scalar timeslice){};

		void Reset();

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Network Support
	//

		void
			GetStates(
				int &current_state, int &transition_state, 
				bool &cued_current, Stuff::Scalar &current_position, 
				bool &cued_transition, Stuff::Scalar &transition_position, 
				bool &cued_new, Stuff::Scalar &new_position);

		void
			SetStates(
				int current_state, int transition_state, 
				bool cued_current, Stuff::Scalar current_position, 
				bool cued_transition, Stuff::Scalar transition_position, 
				bool cued_new, Stuff::Scalar new_position,
				bool run_minimal = false);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	// Test Support
	//
	public:
		void
      		TestClass();
	};


	//#############################################################################
	//##########################    CurveHolders           ########################
	//#############################################################################


	struct HermiteSpline1D
	{
	public:
		void Init(
			Stuff::Scalar start_point, 
			Stuff::Scalar out_tan, 
			Stuff::Scalar in_tan, 
			Stuff::Scalar stop_point);

		Stuff::Scalar Evaluate(Stuff::Scalar time_of_curve);

		Stuff::Scalar point1;
		Stuff::Scalar tangent1;
		Stuff::Scalar tangent2;
		Stuff::Scalar point2;
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//

	struct AnimCurve
	{
	public:

		enum {
			NULLAnimType = -1,
			LinearUpCurveType,
			CubedCurveType,
			EaseUpCurveType,
			EdgeCurveType,
			BumpCurveType,
			EaseUpSplineCurveType,
			CurveUpCurveType,
			SpikeUpCurveType,
			BellCurveType,
			SpikeCurveType,
			LongBumpCurveType,
			BumpSpikeCurveType,
			SpikeBellCurveType,
			CurveTypeCount
		};

		//double 
		//	curveMasks; // limit 64 total flags. must be first due to 4 byte packing

		int curveType;
		Stuff::Scalar
			curveMin,
			curveMax,
			timeStart,
			timeEnd;

		bool
			invertTime,
			invertScale;
		
		static void
			InitializeClass();

		static 
			HermiteSpline1D 
				BumpCurveMat,
				EaseUpSplineCurveMat,
				CurveUpCurveMat,
				SpikeUpCurveMat,  
				//start the doubles
				BellCurveMat,
				SpikeCurveMat,
				LongBumpCurveMat,
				BumpSpikeCurveMat,
				SpikeBellCurveMat;


		AnimCurve();
		void LoadCurve(const char *curve_text);
		void LoadMasks(const char *mask_text);
		Stuff::Scalar Play(Stuff::Scalar percent_of_curve);
		
		

	};


	//#############################################################################
	//##########################    AnimationState    ########################
	//#############################################################################


	class AnimationState:
		public Stuff::Plug
	{
	public:
		AnimationStateEngine
			*animStateEngine;

		int 
			myState;
		
		Stuff::Scalar
			startTime;

		Stuff::Scalar
			elapsedTime;

		int 
			animCount,
			firstAnim;

		bool
			justLooped;

		bool
			carryOver;

		Stuff::Scalar
			statePercentage;

	public:
		AnimationState(AnimationStateEngine *anim_state_engine);
		~AnimationState(){	Check_Object(this); };


		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// loading methods
		//
		virtual 
			void PreLoad(Stuff::Page *page);
		
		virtual 
			void LoadScriptEntry(
				Stuff::Page *page,
				int &current_holder,
				int &curve_count,
				bool run_minimal
		);

		void 
			LoadAnimHolder(
				Stuff::NameList *param_list, 
				int anim_holder_count,
				int &current_curve,
				bool run_minimal
		);

		//virtual void LoadScript(Stuff::MemoryStream *stream){};
		//virtual void SaveScript(Stuff::Page *page){};
		//virtual void SaveScript(Stuff::MemoryStream *stream){};

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// Count, size and time methods
		//

		size_t GetAnimHolderCount(Stuff::Page *page);
		virtual int GetCurveCount(Stuff::Page *page);
		

		void CalculateChainTimes();
		void RecurseAndCalculateChainTime(
			Stuff::Scalar &total_time,
			int current_anim
		);


		Stuff::Scalar GetStatePercentage() {return statePercentage;};
		void CalculateStatePercentage();

	public:

		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		// playing methods
		//

		virtual void LoadIterators(bool run_minimal);
		virtual void UnloadIterators(void);

		virtual void Que(Stuff::Scalar old_state_position, Stuff::Scalar over_ride_position, bool run_minimal);
		virtual void Advance(Stuff::Scalar time_slice,int depth_count, bool run_minimal);
		virtual void NoAdvance(Stuff::Scalar time_slice, int depth_count, bool run_minimal);


		bool LoopedThisFrame(void) { return justLooped; };
		

	};


	//#############################################################################
	//##########################    TransitionState    ########################
	//#############################################################################


	class TransitionState:
		public AnimationState
	{
	public:
		Stuff::Scalar
			transitionStart,
			playOldStateTill,
			startNewState,
			overrideNewStatePosition;


		int startOverlapCurve;
		int endOverlapCurve;
		
		enum {
			StartAnyWhereToken = -1
		};
	
		TransitionState(AnimationStateEngine *anim_state_engine);
		~TransitionState(){	Check_Object(this); };

		int
			transitionToState;

		void PreLoad(Stuff::Page *page);

		int GetCurveCount(Stuff::Page *page);
		
		void LoadScriptEntry(
				Stuff::Page *page,
				int &current_holder,
				int &curve_count,
				bool run_minimal
		);

		void Advance(Stuff::Scalar time_slice,int depth_count, bool run_minimal);


	};
	//#############################################################################
	//##########################    AnimationHolders       ########################
	//#############################################################################

	struct AnimHolder
	{
	public:

		enum
		{
			NoStartAfterToken = -1
		};

		enum
		{
			BeforePlaying,
			NowPlaying,
			DonePlaying
		};

		AnimHolder()
			{
				currentTime = -1.0f;
				currentStateFlag = BeforePlaying;
				carryOver = 0.0f;
				inAnimIteratorManager = false;
			};

		int animType;

		int currentStateFlag;
		int waitForAnim;
		Stuff::Scalar startDelay;
		
		int curveCount;
		int firstCurve;

		bool inAnimIteratorManager;

		Stuff::Scalar
			currentTime,
			carryOver,
			startPercentage,
			percentageOfChain;

		Stuff::Scalar GetCarryOver()
			{return carryOver;}

		virtual void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal)
			{STOP(("AnimHolder::Load : PureVirtual Code ERROR"));};

		virtual void Que(Stuff::Scalar position, bool run_minimal)
			{STOP(("AnimHolder::Que : PureVirtual Code ERROR"));};

	
		virtual void LoadIterators(bool run_minimal)
			{STOP(("AnimHolder::LoadIterators : PureVirtual Code ERROR"));};

		virtual void UnloadIterators(void)
			{STOP(("AnimHolder::UnloadIterators : PureVirtual Code ERROR"));};


		virtual bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
			{STOP(("AnimHolder::Play : PureVirtual Code ERROR"));return false;};

		virtual Stuff::Scalar GetTimeTotal(void)
			{STOP(("AnimHolder::GetTimeTotal : PureVirtual Code ERROR"));return -1.0f;};

		virtual Stuff::Scalar GetCurrentPercentage(void)
			{STOP(("AnimHolder::GetCurrentPercentage : PureVirtual Code ERROR"));return -1.0f;};



	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


	struct PoseHolder : 
		public AnimHolder
	{
	public:
		PoseHolder():AnimHolder()
		{
			animIterator = NULL; 
			animInstance = NULL;
		};

		MW4Animation::AnimInstance * 
			animInstance;
		MW4Animation::AnimIterator *
			animIterator;

		Stuff::Scalar 
			targetPosition;

		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators(bool run_minimal);
		void UnloadIterators(void);

		void Que(Stuff::Scalar position, bool run_minimal);
	
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);
		
		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);

	};


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


	struct FullHeightPoseHolder : 
		public AnimHolder
	{
	public:
		FullHeightPoseHolder():AnimHolder()
		{
			upAnimInstance	 = NULL;
			evenAnimInstance = NULL;
			downAnimInstance = NULL;
			leftAnimInstance = NULL;
			rightAnimInstance = NULL;

			upAnimIterator	 = NULL;
			evenAnimIterator = NULL;
			downAnimIterator = NULL;
			leftAnimIterator = NULL;
			rightAnimIterator = NULL;
		};

		Adept::AttributeEntry
			*rollAttrib,
			*pitchAttrib;
		
		MW4Animation::AnimInstance *
			upAnimInstance;
		MW4Animation::AnimInstance *
			evenAnimInstance;
		MW4Animation::AnimInstance *
			downAnimInstance;
		MW4Animation::AnimInstance *
			leftAnimInstance;
		MW4Animation::AnimInstance *
			rightAnimInstance;

		MW4Animation::AnimIterator *
			upAnimIterator;
		MW4Animation::AnimIterator *
			evenAnimIterator;
		MW4Animation::AnimIterator *
			downAnimIterator;
		MW4Animation::AnimIterator *
			leftAnimIterator;
		MW4Animation::AnimIterator *
			rightAnimIterator;

		Stuff::Scalar 
			targetPosition;

		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators(bool run_minimal);
		void UnloadIterators(void);

		void Que(Stuff::Scalar position, bool run_minimal);
		
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);
		
		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);

	};
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	struct CycleHolder : 
		public AnimHolder
	{
	public:
		CycleHolder():AnimHolder()
		{
			animIterator = NULL; 
			animInstance = NULL;
		};

		MW4Animation::AnimInstance * 
			animInstance;
		MW4Animation::AnimIterator * 
			animIterator;

		Stuff::Scalar 
			startPosition;

		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators( bool run_minimal);
		void UnloadIterators(void);

		void Que(Stuff::Scalar position, bool run_minimal);
		
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);

		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);
	};



	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	struct LerpCycleHolder : 
		public AnimHolder
	{
	public:
		LerpCycleHolder():AnimHolder()
		{
			animIterator = NULL; 
			animInstance = NULL;
		};

		MW4Animation::AnimInstance * 
			animInstance;
		MW4Animation::AnimIterator * 
			animIterator;

		Stuff::Scalar 
			targetPosition;
		Stuff::Scalar 
			lerpTime;
		

		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators(bool run_minimal);
		void UnloadIterators(void);

		void Que(Stuff::Scalar position, bool run_minimal);
		
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);

		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);

	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	struct SpeedCycleHolder : 
		public AnimHolder
	{
	public:
		SpeedCycleHolder():AnimHolder()
		{
			animIterator = NULL; 
			animInstance = NULL;
		};

		MW4Animation::AnimInstance * 
			animInstance;
		MW4Animation::AnimIterator * 
			animIterator;

		Stuff::Scalar 
			startPosition;
		Adept::AttributeEntry*
			speedAttrib;

		Stuff::Scalar
			animSpeed;

		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators(bool run_minimal);
		void UnloadIterators(void);

		void Que(Stuff::Scalar position, bool run_minimal);
		
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);

		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	struct SpeedBlenderCycleHolder : 
		public AnimHolder
	{
	public:
		SpeedBlenderCycleHolder():AnimHolder()
		{
			slowAnimInstance = NULL;
			fastAnimInstance = NULL;
			slowAnimIterator = NULL;
			fastAnimIterator = NULL;
		}

		Stuff::Scalar 
			startPosition;

		Adept::AttributeEntry*
			speedAttrib;

		Stuff::Scalar
			slowSpeed,
			fastSpeed,
			slowSpeedMultiplier;

		MW4Animation::AnimInstance * 
			slowAnimInstance;
		MW4Animation::AnimInstance *
			fastAnimInstance;

		MW4Animation::AnimIterator * 
			slowAnimIterator;
		MW4Animation::AnimIterator *
			fastAnimIterator;

		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators(bool run_minimal);
		void UnloadIterators(void);

		void Que(Stuff::Scalar position, bool run_minimal);
		
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);

		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);
	};


	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	struct FullHeightBlenderCycleHolder : 
		public AnimHolder
	{
	public:
		FullHeightBlenderCycleHolder():AnimHolder()
		{
			upAnimInstance	 = NULL;
			evenAnimInstance = NULL;
			downAnimInstance = NULL;
			leftAnimInstance = NULL;
			rightAnimInstance = NULL;

			upAnimIterator	 = NULL;
			evenAnimIterator = NULL;
			downAnimIterator = NULL;
			leftAnimIterator = NULL;
			rightAnimIterator = NULL;
		};

		Stuff::Scalar 
			startPosition;

		Adept::AttributeEntry*
			speedAttrib;
		
		Stuff::Scalar
			animSpeed;

		Adept::AttributeEntry
			*rollAttrib,
			*pitchAttrib;
		
		MW4Animation::AnimInstance *
			upAnimInstance;
		MW4Animation::AnimInstance *
			evenAnimInstance;
		MW4Animation::AnimInstance *
			downAnimInstance;
		MW4Animation::AnimInstance *
			leftAnimInstance;
		MW4Animation::AnimInstance *
			rightAnimInstance;

		MW4Animation::AnimIterator *
			upAnimIterator;
		MW4Animation::AnimIterator *
			evenAnimIterator;
		MW4Animation::AnimIterator *
			downAnimIterator;
		MW4Animation::AnimIterator *
			leftAnimIterator;
		MW4Animation::AnimIterator *
			rightAnimIterator;

		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators(bool run_minimal);
		void UnloadIterators(void);
		
		void Que(Stuff::Scalar position, bool run_minimal);
		
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);

		
		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);
	};

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

	struct FullHeightSpeedBlenderCycleHolder : 
		public AnimHolder
	{
	public:
		FullHeightSpeedBlenderCycleHolder():AnimHolder()
		{

			fastUpAnimInstance	 = NULL;
			fastEvenAnimInstance = NULL;
			fastDownAnimInstance = NULL;
			fastLeftAnimInstance = NULL;
			fastRightAnimInstance = NULL;

			fastUpAnimIterator	 = NULL;
			fastEvenAnimIterator = NULL;
			fastDownAnimIterator = NULL;
			fastLeftAnimIterator = NULL;
			fastRightAnimIterator = NULL;

			slowUpAnimInstance	 = NULL;
			slowEvenAnimInstance = NULL;
			slowDownAnimInstance = NULL;
			slowLeftAnimInstance = NULL;
			slowRightAnimInstance = NULL;

			slowUpAnimIterator	 = NULL;
			slowEvenAnimIterator = NULL;
			slowDownAnimIterator = NULL;
			slowLeftAnimIterator = NULL;
			slowRightAnimIterator = NULL;
		};

		Stuff::Scalar 
			startPosition;

		Adept::AttributeEntry*
			speedAttrib;
		
		Stuff::Scalar
			slowSpeed,
			fastSpeed,
			slowSpeedMultiplier;

		Adept::AttributeEntry
			*rollAttrib,
			*pitchAttrib;
		
		MW4Animation::AnimInstance *
			fastUpAnimInstance;
		MW4Animation::AnimInstance *
			fastEvenAnimInstance;
		MW4Animation::AnimInstance *
			fastDownAnimInstance;
		MW4Animation::AnimInstance *
			fastLeftAnimInstance;
		MW4Animation::AnimInstance *
			fastRightAnimInstance;

		MW4Animation::AnimIterator *
			fastUpAnimIterator;
		MW4Animation::AnimIterator *
			fastEvenAnimIterator;
		MW4Animation::AnimIterator *
			fastDownAnimIterator;
		MW4Animation::AnimIterator *
			fastLeftAnimIterator;
		MW4Animation::AnimIterator *
			fastRightAnimIterator;


		MW4Animation::AnimInstance *
			slowUpAnimInstance;
		MW4Animation::AnimInstance *
			slowEvenAnimInstance;
		MW4Animation::AnimInstance *
			slowDownAnimInstance;
		MW4Animation::AnimInstance *
			slowLeftAnimInstance;
		MW4Animation::AnimInstance *
			slowRightAnimInstance;

		MW4Animation::AnimIterator *
			slowUpAnimIterator;
		MW4Animation::AnimIterator *
			slowEvenAnimIterator;
		MW4Animation::AnimIterator *
			slowDownAnimIterator;
		MW4Animation::AnimIterator *
			slowLeftAnimIterator;
		MW4Animation::AnimIterator *
			slowRightAnimIterator;


		void Load(AnimationStateEngine *anim_state_engine, Stuff::NameList *param_list, bool run_minimal);
		void LoadIterators(bool run_minimal);
		void UnloadIterators(void);
		
		void Que(Stuff::Scalar position, bool run_minimal);
		
		bool Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal);

		void CalculateAndSetHeightCurves(AnimationStateEngine *anim_state_engine, bool run_minimal);

		Stuff::Scalar GetTimeTotal();
		Stuff::Scalar GetCurrentPercentage(void);
	};


		
		

	//#############################################################################
	//##########################			Inlines		   ########################
	//#############################################################################

	inline AnimationStateEngine::ClassData*
		AnimationStateEngine::GetClassData()
	{
		Check_Object(this);
		return Cast_Pointer(ClassData*, classData);
	}

	DECLARE_TIMER(extern, RunAnimStates);
	DECLARE_TIMER(extern, Iterate);
	DECLARE_TIMER(extern, Blend);
	DECLARE_TIMER(extern, Apply);
	DECLARE_TIMER(extern, BlendAlloc);
	DECLARE_TIMER(extern, blendDealloc);
	DECLARE_TIMER(extern, BlendAnimCombine);
	DECLARE_TIMER(extern, BlendCombine);
	DECLARE_TIMER(extern, BlendAndApply);


}

