//===========================================================================//
// File:	AnimationHolder.cpp											
//---------------------------------------------------------------------------//
//   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               //
//===========================================================================//


#include "MW4Headers.hpp"

#include "Vehicle.hpp"
#include "AnimationState.hpp"

using namespace MW4Animation;





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

void PoseHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);

	page = param_list->FindEntry("Position");
	Check_Object(page);
	targetPosition = page->GetAtof();
	Verify(targetPosition >= 0.0f);
	Verify(targetPosition <= 1.0f);

	page = param_list->FindEntry("Anim");
	Check_Object(page);

	// god i hate mstrings...
	MString string;
	string = page->GetChar();
	string += ".MW4ANIM";

	animInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(animInstance);

}


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

bool PoseHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{
	Verify(animIterator != NULL);

	// work thru the delay if there is one...
	currentTime += time_slice;

	if (currentTime >= startDelay)
	{
		animIterator->SetVelocityScale(0.0f);
		
		anim_state_engine->iteratorManager->AddAnimToCurrentLayer(animIterator);



		if (startDelay == 0.0f)
		{
			carryOver = 0.0f;
		}
		else
		{
			carryOver = currentTime - startDelay;
		}
		return true;
	}

	return false;

}

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


void PoseHolder::Que(Stuff::Scalar position, bool run_minimal)
{
	Verify(animIterator != NULL);
	
	
	animIterator->SetPosition(targetPosition);
	
	
	
	currentTime = 0.0f;
}

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

void PoseHolder::LoadIterators(bool run_minimal)
{
	Verify(animIterator == NULL);
	animIterator = new MW4Animation::AnimIterator(animInstance);
	Register_Pointer(animIterator);
}

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

void PoseHolder::UnloadIterators(void)
{
	Verify(animIterator != NULL);
	Unregister_Pointer(animIterator);
	delete animIterator;
	animIterator = NULL;
	currentTime = -1.0f;
}

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


Stuff::Scalar PoseHolder::GetCurrentPercentage()
{
	Verify(animInstance != NULL);
	
	if (startDelay == 0.0f)
	{
		return startPercentage;
	}

	Scalar percent = currentTime / startDelay;

	percent *= percentageOfChain;
	percent += startPercentage;

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return percent;

}


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


Stuff::Scalar PoseHolder::GetTimeTotal()
{
	Verify(animInstance != NULL);
	return 
		0.0f + startDelay;
}


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

void CycleHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);

	page = param_list->FindEntry("Position");
	Check_Object(page);
		
	if (!_stricmp(page->GetChar(), "old"))
	{
		startPosition = -1;
	}
	else
	{
		startPosition = page->GetAtof();
	}
	
	//cycle_holder->targetPosition = page->GetAtof();

	page = param_list->FindEntry("Anim");
	Check_Object(page);

	// god i hate mstrings...
	MString string;
	string = page->GetChar();
	string += ".MW4ANIM";

	animInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(animInstance);
}

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

bool CycleHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{
	Verify(animIterator != NULL);

	currentTime += time_slice;

	if (currentTime >= startDelay)
	{
		if (animIterator->IncrementTime(time_slice))
		{
			carryOver = animIterator->GetCarryOverTime();
			return true;
		}
		
		anim_state_engine->iteratorManager->AddAnimToCurrentLayer(animIterator);

		// add the curve
		if (curveCount)
		{
			// we don't support multiple curves now
			Verify(curveCount == 1);
			animIterator->SetBlendValue(anim_state_engine->animCurves[firstCurve].Play(animIterator->GetPosition()));
		}
	}
	

	return false;
}

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

void CycleHolder::Que(Stuff::Scalar position, bool run_minimal)
{
	Verify(animIterator != NULL);
	

	if (position != -1.0f)
	{
		animIterator->SetPosition(position);
		Verify(startDelay == 0.0f);

		currentTime = GetTimeTotal() * position;
	}
	else
	{
		animIterator->SetPosition(startPosition);
		currentTime = 0.0f;
	}

	
}


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

void CycleHolder::LoadIterators(bool run_minimal)
{
	Verify(animIterator == NULL);
	animIterator = new MW4Animation::AnimIterator(animInstance);
	Register_Pointer(animIterator);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
		
void CycleHolder::UnloadIterators(void)
{
	Verify(animIterator != NULL);
	Unregister_Pointer(animIterator);
	delete animIterator;
	animIterator = NULL;
	currentTime = -1.0f;
}

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

Stuff::Scalar CycleHolder::GetCurrentPercentage()
{
	Verify(animInstance != NULL);
	
	Scalar percent = currentTime / GetTimeTotal();

	percent *= percentageOfChain;
	percent += startPercentage;

	//SPEW(("jerryeds", "GetTime %f", animIterator->GetTime()));

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return 
		percent;
}

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

Stuff::Scalar CycleHolder::GetTimeTotal()
{
	Verify(animInstance != NULL);

	// don't forget the start offset and the start delay..
	Scalar anim_time = animInstance->animData->animHeaderBlock->endTime - 
		animInstance->animData->animHeaderBlock->startTime;

	if (startPosition == -1.0f)
	{
		return (anim_time + startDelay);
	}

	return
		anim_time + startDelay - (anim_time * startPosition);
}

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

void SpeedCycleHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);
				
	page = param_list->FindEntry("Position");
	Check_Object(page);
	
	if (!_stricmp(page->GetChar(), "old"))
	{
		STOP(("NO LONGER SUPPORTED"));
		startPosition = -1;
	}
	else
	{
		startPosition = page->GetAtof();
	}
	
	//targetPosition = page->GetAtof();

	page = param_list->FindEntry("Anim");
	Check_Object(page);

	// god i hate mstrings...
	MString string;
	string = page->GetChar();
	string += ".MW4ANIM";

	animInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(animInstance);

	page = param_list->FindEntry("SpeedAttrib");
	Check_Object(page);

	speedAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(speedAttrib);

	// get the speed
	animSpeed = 0.0f;

	MW4Animation::AnimIterator *anim_iterator = new MW4Animation::AnimIterator(animInstance);
	Register_Pointer(anim_iterator);

	for (int i = 0; i < animInstance->animData->GetChannelCount(); ++i)
	{
		if (animInstance->animData->animChannelBlock[i].channelType ==
						MW4Animation::ChannelAnimData::VelocityChannelType )
		{
			MW4Animation::BaseKeyframe *keyframe = NULL;
			MW4Animation::BaseKeyframeTime *keyframetime = NULL;
			keyframe = anim_iterator->GetLastKeyFrame(i);
			keyframetime = anim_iterator->GetLastKeyFrameTime(i);

			animSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z);

			keyframe = anim_iterator->GetFirstKeyFrame(i);
			keyframetime = anim_iterator->GetFirstKeyFrameTime(i);

			if (animSpeed < Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime,  0.0f).z))
			{
				animSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime,  0.0f).z);
			}
		}
	}

	Unregister_Pointer(anim_iterator);
	delete anim_iterator;

	
}

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

bool SpeedCycleHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{
	Verify(animIterator != NULL);

	// frig with the time slice
	Stuff::Scalar current_speed;
	speedAttrib->GetValue(anim_state_engine->vehicleParent, &current_speed);
	current_speed = Abs(current_speed);

	Stuff::Scalar time_slow_down = 0.0f;

	if (!Small_Enough(animSpeed, 0.0f))
	{
		time_slow_down = current_speed/animSpeed;	
	}
	else
	{
		// if the animspeed is 0 then we just play full speed with no speed effect
		time_slow_down = 1.0f;
	}
	
	currentTime += (time_slice * time_slow_down);


	if (currentTime >= startDelay)
	{
		animIterator->SetVelocityScale(time_slow_down);
		if(time_slow_down > 0.0f)
		{
			if (animIterator->IncrementTime(time_slice * time_slow_down))
			{
				// ok, this isn't as easy as this.
				// we actually have to scale the carryover back up!
				carryOver = animIterator->GetCarryOverTime()/time_slow_down;
				//SPEW(("jerryeds", "ts:%f tsd:%f tsco:%f co:%f", time_slice, time_slow_down, animIterator->GetCarryOverTime(), carryOver));

				return true;
			}
		}

		anim_state_engine->iteratorManager->AddAnimToCurrentLayer(animIterator);

		// add the curve
		if (curveCount)
		{
			// we don't support multiple curves now
			Verify(curveCount == 1);
			animIterator->SetBlendValue(anim_state_engine->animCurves[firstCurve].Play(animIterator->GetPosition()));
		}
	}
	

	return false;
}

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

void SpeedCycleHolder::Que(Stuff::Scalar position, bool run_minimal)
{
	Verify(animIterator != NULL);
	

	if (position != -1.0f)
	{
		animIterator->SetPosition(position);
		Verify(startDelay == 0.0f);

		currentTime = GetTimeTotal() * position;
	}
	else
	{
		animIterator->SetPosition(startPosition);
		currentTime = 0.0f;
	}

		

}

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

void SpeedCycleHolder::LoadIterators(bool run_minimal)
{
	Verify(animIterator == NULL);
	animIterator = new MW4Animation::AnimIterator(animInstance);
	Register_Pointer(animIterator);
	
}


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

void SpeedCycleHolder::UnloadIterators(void)
{
	Verify(animIterator != NULL);
	Unregister_Pointer(animIterator);
	delete animIterator;
	animIterator = NULL;
	currentTime = -1.0f;
}

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

Stuff::Scalar SpeedCycleHolder::GetCurrentPercentage()
{
	Verify(animInstance != NULL);
	 
	Scalar percent = currentTime / GetTimeTotal();

	percent *= percentageOfChain;
	percent += startPercentage;

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return 
		percent;
}

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

Stuff::Scalar SpeedCycleHolder::GetTimeTotal()
{
	Verify(animInstance != NULL);
	 
	Scalar anim_time = animInstance->animData->animHeaderBlock->endTime - 
		animInstance->animData->animHeaderBlock->startTime;

	if (startPosition == -1.0f)
	{
		return (anim_time + startDelay);
	}

	return
		anim_time + startDelay - (anim_time * startPosition);
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	
void SpeedBlenderCycleHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);
	
	page = param_list->FindEntry("Position");
	Check_Object(page);
	
	if (!_stricmp(page->GetChar(), "old"))
	{
		startPosition = -1;
	}
	else
	{
		startPosition = page->GetAtof();
	}
	
	//targetPosition = page->GetAtof();

	page = param_list->FindEntry("SlowAnim");
	Check_Object(page);

	// god i hate mstrings...
	MString string;
	string += page->GetChar();
	string += ".MW4ANIM";

	slowAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(slowAnimInstance);


	page = param_list->FindEntry("FastAnim");
	Check_Object(page);

	string = page->GetChar();
	string += ".MW4ANIM";

	fastAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(fastAnimInstance);


	page = param_list->FindEntry("SpeedAttrib");
	Check_Object(page);

	speedAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(speedAttrib);

	// get the speeds
	slowSpeed = -1.0f;

	MW4Animation::AnimIterator *anim_iterator = new MW4Animation::AnimIterator(slowAnimInstance);
	Register_Pointer(anim_iterator);

	for (int i = 0; i < slowAnimInstance->animData->GetChannelCount(); ++i)
	{
		if (slowAnimInstance->animData->animChannelBlock[i].channelType ==
						MW4Animation::ChannelAnimData::VelocityChannelType )
		{
			MW4Animation::BaseKeyframe *keyframe = NULL;
			keyframe = anim_iterator->GetLastKeyFrame(i);
			
			MW4Animation::BaseKeyframeTime *keyframetime = NULL;
			keyframetime = anim_iterator->GetLastKeyFrameTime(i);

			slowSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z);
		}
	}

	Unregister_Pointer(anim_iterator);
	delete anim_iterator;

	Verify(slowSpeed != -1.0f);

	fastSpeed = -1.0f;

	anim_iterator = new MW4Animation::AnimIterator(fastAnimInstance);
	Register_Pointer(anim_iterator);

	for (i = 0; i < fastAnimInstance->animData->GetChannelCount(); ++i)
	{
		if (fastAnimInstance->animData->animChannelBlock[i].channelType ==
						MW4Animation::ChannelAnimData::VelocityChannelType )
		{
			MW4Animation::BaseKeyframe *keyframe = NULL;
			keyframe = anim_iterator->GetLastKeyFrame(i);
			
			MW4Animation::BaseKeyframeTime *keyframetime = NULL;
			keyframetime = anim_iterator->GetLastKeyFrameTime(i);

			fastSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z);
		}
	}

	slowSpeedMultiplier = 1.0f;
	page = param_list->FindEntry("SlowSpeedMultiplier");
	if (page)
	{
		slowSpeedMultiplier = page->GetAtof();
	}



	Unregister_Pointer(anim_iterator);
	delete anim_iterator;

	Verify(fastSpeed != -1.0f);
}

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

bool SpeedBlenderCycleHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{
	Verify(slowAnimIterator != NULL);
	Verify(fastAnimIterator != NULL);

	// frig with the time slice
	Stuff::Scalar current_speed;
	speedAttrib->GetValue(anim_state_engine->vehicleParent, &current_speed);
	current_speed = Abs(current_speed);

	if (currentTime >= startDelay)
	{
		// we want to be absolutly sure that we mix the animations in their own layer
		AnimHierarchyNode *heir_node = NULL;
		heir_node = anim_state_engine->iteratorManager->PushLayer(1.0f);

		//{
			if (current_speed < (slowSpeed * slowSpeedMultiplier))
			{
				Stuff::Scalar position = slowAnimIterator->GetPosition();
				Stuff::Scalar time_slow_down = current_speed/slowSpeed;

				if(time_slow_down > 0.0f)
				{
					currentTime += (time_slice * time_slow_down);

					if(	slowAnimIterator->IncrementTime(time_slice * time_slow_down) )
					{
						carryOver = slowAnimIterator->GetCarryOverTime()/time_slow_down;;
						anim_state_engine->iteratorManager->UndoPush();
						return true;
					}
					else
					{
						position = slowAnimIterator->GetPosition() - position;
						if (position != 0.0f)
						{
							fastAnimIterator->IncrementPosition(position);
						}
					}
					slowAnimIterator->SetVelocityScale(time_slow_down);
					fastAnimIterator->SetVelocityScale(time_slow_down);
					slowAnimIterator->SetBlendValue(1.0f);
					fastAnimIterator->SetBlendValue(0.0f);

					//SPEW(("jerryeds", "w-- wp:%f rp:%f cs:%f ts:%f wb:%f rb:%f", slowAnimIterator->GetPosition(), fastAnimIterator->GetPosition(), current_speed, time_slow_down, 1.0f, 0.0f));

				}
				else
				{
					slowAnimIterator->SetVelocityScale(0.0f);
					fastAnimIterator->SetVelocityScale(0.0f);
				}

				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastAnimIterator);

			}
			else if (current_speed >= fastSpeed)
			{
				Stuff::Scalar position = fastAnimIterator->GetPosition();
				Stuff::Scalar time_slow_down = current_speed/fastSpeed;
				currentTime += (time_slice * time_slow_down);
				
				if(time_slow_down > 0.0f)
				{
					if(	fastAnimIterator->IncrementTime(time_slice * time_slow_down) )
					{
						carryOver = fastAnimIterator->GetCarryOverTime()/time_slow_down;;
						anim_state_engine->iteratorManager->UndoPush();
						return true;
					}
					else
					{
						position = fastAnimIterator->GetPosition() - position;
						if (position != 0.0f)
						{
							slowAnimIterator->IncrementPosition(position);
						}
					}
					slowAnimIterator->SetVelocityScale(time_slow_down);
					fastAnimIterator->SetVelocityScale(time_slow_down);
					slowAnimIterator->SetBlendValue(0.0f);
					fastAnimIterator->SetBlendValue(1.0f);

					//SPEW(("jerryeds", "r-- wp:%f rp:%f cs:%f ts:%f wb:%f rb:%f", slowAnimIterator->GetPosition(), fastAnimIterator->GetPosition(), current_speed, time_slow_down, 0.0f, 1.0f));
				}
				else
				{
					slowAnimIterator->SetVelocityScale(0.0f);
					fastAnimIterator->SetVelocityScale(0.0f);
				}
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastAnimIterator);
			}
			else
			{
				//we are in blending mode...
				Stuff::Scalar position = fastAnimIterator->GetPosition();
				
				//run is in control

				currentTime += time_slice;

				if(	fastAnimIterator->IncrementTime(time_slice) )
				{
					carryOver = fastAnimIterator->GetCarryOverTime();
					anim_state_engine->iteratorManager->UndoPush();
					return true;
				}
				else
				{
					position = fastAnimIterator->GetPosition() - position;
					if (position != 0.0f)
					{
						slowAnimIterator->IncrementPosition(position);
					}

				}
				fastAnimIterator->SetVelocityScale(1.0f);
				slowAnimIterator->SetVelocityScale(1.0f);

				Scalar speed_diff = fastSpeed - slowSpeed;
				Stuff::Scalar fast_blend_value = (current_speed - slowSpeed)/speed_diff;

				fastAnimIterator->SetBlendValue(fast_blend_value);
				slowAnimIterator->SetBlendValue(1.0f - fast_blend_value);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastAnimIterator);
			}

			
		//}

		anim_state_engine->iteratorManager->PopLayer();

		// add the curve
		if (curveCount)
		{
			// we don't support multiple curves now
			Check_Pointer(heir_node);
			Verify(curveCount == 1);
			heir_node->SetBlendValue(anim_state_engine->animCurves[firstCurve].Play(fastAnimIterator->GetPosition()));
		}
	}
	else
	{
		currentTime += time_slice;
	}

	return false;
}


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

void SpeedBlenderCycleHolder::Que(Stuff::Scalar position, bool run_minimal)
{			
	Verify(slowAnimIterator != NULL);
	Verify(fastAnimIterator != NULL);


	if (position != -1.0f)
	{
		slowAnimIterator->SetPosition(position);
		fastAnimIterator->SetPosition(position);

		Verify(startDelay == 0.0f);

		currentTime = GetTimeTotal() * position;
	}
	else
	{
		slowAnimIterator->SetPosition(startPosition);
		fastAnimIterator->SetPosition(startPosition);
		currentTime = 0.0f;
	}


		

}


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

void SpeedBlenderCycleHolder::LoadIterators(bool run_minimal)
{			
	Verify(slowAnimIterator == NULL);
	slowAnimIterator = new MW4Animation::AnimIterator(slowAnimInstance);
	Register_Pointer(slowAnimIterator);

	Verify(fastAnimIterator == NULL);
	fastAnimIterator = new MW4Animation::AnimIterator(fastAnimInstance);
	Register_Pointer(fastAnimIterator);
}

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

void SpeedBlenderCycleHolder::UnloadIterators(void)
{
	Verify(slowAnimIterator != NULL);
	Unregister_Pointer(slowAnimIterator);
	delete slowAnimIterator;
	slowAnimIterator = NULL;

	Verify(fastAnimIterator != NULL);
	Unregister_Pointer(fastAnimIterator);
	delete fastAnimIterator;
	fastAnimIterator = NULL;

	currentTime = -1.0f;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//

Stuff::Scalar SpeedBlenderCycleHolder::GetCurrentPercentage()
{
	Verify(slowAnimInstance != NULL);

	Scalar percent = currentTime / GetTimeTotal();

	percent *= percentageOfChain;
	percent += startPercentage;

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return 
		percent;
}

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

Stuff::Scalar SpeedBlenderCycleHolder::GetTimeTotal()
{
	Verify(slowAnimInstance != NULL);
	
	Scalar anim_time = slowAnimInstance->animData->animHeaderBlock->endTime - 
		slowAnimInstance->animData->animHeaderBlock->startTime;

	if (startPosition == -1.0f)
	{
		return (anim_time + startDelay);
	}

	return
		anim_time + startDelay - (anim_time * startPosition);
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
	
void LerpCycleHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);
				
	page = param_list->FindEntry("Position");
	Check_Object(page);
	targetPosition = page->GetAtof();


	page = param_list->FindEntry("LerpTime");
	Check_Object(page);
	lerpTime = page->GetAtof();


	page = param_list->FindEntry("Anim");
	Check_Object(page);

	// god i hate mstrings...
	MString string;
	string = page->GetChar();
	string += ".MW4ANIM";

	animInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(animInstance);
}


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

bool LerpCycleHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{

	currentTime += time_slice;

	if (currentTime >= startDelay)
	{
		
		if (currentTime > lerpTime + startDelay)
		{
			carryOver = currentTime - startDelay;
			return true;
		}
		animIterator->SetVelocityScale(0.0f);
		anim_state_engine->iteratorManager->AddAnimToCurrentLayer(animIterator);
	}
	

	return false;

}


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

void LerpCycleHolder::Que(Stuff::Scalar position, bool run_minimal)
{


	Verify(animIterator != NULL);
	animIterator->SetPosition(targetPosition);
	currentTime = 0.0f;


}


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


void LerpCycleHolder::LoadIterators(bool run_minimal)
{
	Verify(animIterator == NULL);
	animIterator = new MW4Animation::AnimIterator(animInstance);
	Register_Pointer(animIterator);
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
			
void LerpCycleHolder::UnloadIterators(void)
{
	Verify(animIterator != NULL);
	Unregister_Pointer(animIterator);
	delete animIterator;
	animIterator = NULL;
	currentTime = -1.0f;
}


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

Stuff::Scalar LerpCycleHolder::GetCurrentPercentage()
{
	Verify(animInstance != NULL);

	Scalar percent = currentTime / lerpTime + startDelay;

	percent *= percentageOfChain;
	percent += startPercentage;

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return percent;
}

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

Stuff::Scalar LerpCycleHolder::GetTimeTotal()
{
	Verify(animInstance != NULL);
	return 
		currentTime + startDelay;
}



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

void FullHeightBlenderCycleHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);

	page = param_list->FindEntry("Position");
	Check_Object(page);
	
	if (!_stricmp(page->GetChar(), "old"))
	{
		startPosition = -1;
	}
	else
	{
		startPosition = page->GetAtof();
	}

	

	MString string;
	page = param_list->FindEntry("EvenAnim");
	Check_Object(page);

	
	string = page->GetChar();
	string += ".MW4ANIM";

	evenAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(evenAnimInstance);


	if (!run_minimal)
	{
		page = param_list->FindEntry("UpAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		upAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(upAnimInstance);


		page = param_list->FindEntry("DownAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		downAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(downAnimInstance);


		page = param_list->FindEntry("LeftAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		leftAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(leftAnimInstance);

		page = param_list->FindEntry("RightAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		rightAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(rightAnimInstance);
	}




	page = param_list->FindEntry("RollAttrib");
	Check_Object(page);

	rollAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(rollAttrib);

	page = param_list->FindEntry("PitchAttrib");
	Check_Object(page);

	pitchAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(pitchAttrib);

	
	page = param_list->FindEntry("SpeedAttrib");
	Check_Object(page);

	speedAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(speedAttrib);


	// get the speed
	animSpeed = 0.0f;

	MW4Animation::AnimIterator *anim_iterator = new MW4Animation::AnimIterator(evenAnimInstance);
	Register_Pointer(anim_iterator);

	for (int i = 0; i < evenAnimInstance->animData->GetChannelCount(); ++i)
	{
		if (evenAnimInstance->animData->animChannelBlock[i].channelType ==
						MW4Animation::ChannelAnimData::VelocityChannelType )
		{
			MW4Animation::BaseKeyframe *keyframe = NULL;
			keyframe = anim_iterator->GetLastKeyFrame(i);

			MW4Animation::BaseKeyframeTime *keyframetime = NULL;
			keyframetime = anim_iterator->GetLastKeyFrameTime(i);

			animSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z);

			keyframe = anim_iterator->GetFirstKeyFrame(i);
			keyframetime = anim_iterator->GetFirstKeyFrameTime(i);


			if (animSpeed < Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z))
			{
				animSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z);
			}
		}
	}

	Unregister_Pointer(anim_iterator);
	delete anim_iterator;


}


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

bool FullHeightBlenderCycleHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{

#ifdef _ARMOR
	Verify(evenAnimIterator != NULL);

	if (!run_minimal)
	{
		Verify(upAnimIterator != NULL);
		Verify(downAnimIterator != NULL);
		Verify(leftAnimIterator != NULL);
		Verify(rightAnimIterator != NULL);
	}
#endif

	Stuff::Scalar current_speed;
	speedAttrib->GetValue(anim_state_engine->vehicleParent, &current_speed);
	current_speed = Abs(current_speed);

	Stuff::Scalar time_slow_down = 0.0f;

	if (!Small_Enough(animSpeed, 0.0f))
	{
		time_slow_down = current_speed/animSpeed;	
	}
	else
	{
		// if the animspeed is 0 then we just play full speed with no speed effect
		time_slow_down = 1.0f;
	}
	
	currentTime += (time_slice * time_slow_down);

	if (currentTime >= startDelay)
	{
		evenAnimIterator->SetVelocityScale(time_slow_down);
		
		if (!run_minimal)
		{
			downAnimIterator->SetVelocityScale(time_slow_down);
			upAnimIterator->SetVelocityScale(time_slow_down);
			leftAnimIterator->SetVelocityScale(time_slow_down);
			rightAnimIterator->SetVelocityScale(time_slow_down);
		}
	
		AnimHierarchyNode *heir_node = NULL;
		heir_node = anim_state_engine->iteratorManager->PushLayer(1.0f);


		Stuff::Scalar roll_slope;
		Stuff::Scalar pitch_slope;

		rollAttrib->GetValue(anim_state_engine->vehicleParent, &roll_slope);
		pitchAttrib->GetValue(anim_state_engine->vehicleParent, &pitch_slope);

		if(time_slow_down > 0.0f)
		{
			Stuff::Scalar position;
			position = evenAnimIterator->GetPosition();
			if (evenAnimIterator->IncrementTime(time_slice * time_slow_down))
			{
				carryOver = evenAnimIterator->GetCarryOverTime()/time_slow_down;;
				anim_state_engine->iteratorManager->UndoPush();
				return true;
			}
			
			position = evenAnimIterator->GetPosition() - position;
			if (position != 0.0f && !run_minimal)
			{
				downAnimIterator->IncrementPosition(position);
				upAnimIterator->IncrementPosition(position);
				leftAnimIterator->IncrementPosition(position);
				rightAnimIterator->IncrementPosition(position);
			}
		}
	
		// figure out blend value

		Stuff::Scalar up_blend = 0.0f;
		Stuff::Scalar down_blend = 0.0f;
		Stuff::Scalar even_blend = 0.0f;
		Stuff::Scalar left_blend = 0.0f;
		Stuff::Scalar right_blend = 0.0f;

		//SPEW(("jerryeds", "ps: %f", pitch_slope));

		if(pitch_slope > 0.0f)
		{
			down_blend = 0.0f;
			Max_Clamp(pitch_slope, Pi_Over_4);

			up_blend = pitch_slope/Pi_Over_4;
			//even_blend = 1.0f - up_blend;

			//SPEW(("jerryeds", "db: %f", up_blend));
		}
		else if(pitch_slope < 0.0f)
		{
			up_blend = 0.0f;
			pitch_slope = -pitch_slope;
			Max_Clamp(pitch_slope, Pi_Over_4);
		
			down_blend = pitch_slope/Pi_Over_4;
			//even_blend = 1.0f - down_blend;

			//SPEW(("jerryeds", "db: %f", down_blend));

		}
		else
		{
			down_blend = 0.0f;
			up_blend = 0.0f;
		}

		if(roll_slope > 0.0f)
		{
			right_blend = 0.0f;
			Max_Clamp(roll_slope, Pi_Over_4);

			left_blend = roll_slope/Pi_Over_4;
			//even_blend = 1.0f - right_blend;

			//SPEW(("jerryeds", "db: %f", up_blend));
		}
		else if(roll_slope < 0.0f)
		{
			left_blend = 0.0f;
			roll_slope = -roll_slope;
			Max_Clamp(roll_slope, Pi_Over_4);
		
			right_blend = roll_slope/Pi_Over_4;
			//even_blend = 1.0f - left_blend;

			//SPEW(("jerryeds", "db: %f", down_blend));

		}
		else
		{
			right_blend = 0.0f;
			left_blend = 0.0f;
		}


		if ((left_blend + right_blend + up_blend + down_blend) < 1.0f)
		{
			even_blend = 1.0f - (left_blend + right_blend + up_blend + down_blend);
		}
		else
		{
			even_blend = 0.015f;
		}

		//SPEW(("jerryeds", "%f - P<%f:%f>  R<%f:%f>", even_blend, left_blend, right_blend, up_blend, down_blend));

		evenAnimIterator->SetBlendValue(even_blend);
		
		if (!run_minimal)
		{
			downAnimIterator->SetBlendValue(down_blend);
			upAnimIterator->SetBlendValue(up_blend);
			leftAnimIterator->SetBlendValue(left_blend);
			rightAnimIterator->SetBlendValue(right_blend);
		}

		anim_state_engine->iteratorManager->AddAnimToCurrentLayer(evenAnimIterator);

		if (!run_minimal)
		{
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(upAnimIterator);
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(downAnimIterator);
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(leftAnimIterator);
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(rightAnimIterator);
		}

		// add the curve
		if (curveCount)
		{
			// we don't support multiple curves now
			Check_Pointer(heir_node);
			Verify(curveCount == 1);
			heir_node->SetBlendValue(anim_state_engine->animCurves[firstCurve].Play(evenAnimIterator->GetPosition()));
		}

		anim_state_engine->iteratorManager->PopLayer();
	}
	

	return false;
}


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

void FullHeightBlenderCycleHolder::Que(Stuff::Scalar position, bool run_minimal)
{
	
#ifdef _ARMOR
	Verify(evenAnimIterator != NULL);

	if (!run_minimal)
	{
		Verify(upAnimIterator != NULL);
		Verify(downAnimIterator != NULL);
		Verify(leftAnimIterator != NULL);
		Verify(rightAnimIterator != NULL);
	}
#endif


	if (position != -1.0f )
	{
		evenAnimIterator->SetPosition(position);

		if (!run_minimal)
		{
			upAnimIterator->SetPosition(position);
			downAnimIterator->SetPosition(position);
			leftAnimIterator->SetPosition(position);
			rightAnimIterator->SetPosition(position);
		}
		Verify(startDelay == 0.0f);

		currentTime = GetTimeTotal() * position;
	}
	else
	{

		evenAnimIterator->SetPosition(startPosition);
		
		if (!run_minimal)
		{
			upAnimIterator->SetPosition(startPosition);
			downAnimIterator->SetPosition(startPosition);
			leftAnimIterator->SetPosition(startPosition);
			rightAnimIterator->SetPosition(startPosition);
		}
		currentTime = 0.0f;
	}

}




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

void FullHeightBlenderCycleHolder::LoadIterators(bool run_minimal)
{
			
	Verify(evenAnimIterator == NULL);
	evenAnimIterator = new MW4Animation::AnimIterator(evenAnimInstance);
	Register_Pointer(evenAnimIterator);


	if (!run_minimal)
	{
		Verify(upAnimIterator == NULL);
		upAnimIterator = new MW4Animation::AnimIterator(upAnimInstance);
		Register_Pointer(upAnimIterator);

		Verify(downAnimIterator == NULL);
		downAnimIterator = new MW4Animation::AnimIterator(downAnimInstance);
		Register_Pointer(downAnimIterator);

		Verify(leftAnimIterator == NULL);
		leftAnimIterator = new MW4Animation::AnimIterator(leftAnimInstance);
		Register_Pointer(leftAnimIterator);

		Verify(rightAnimIterator == NULL);
		rightAnimIterator = new MW4Animation::AnimIterator(rightAnimInstance);
		Register_Pointer(rightAnimIterator);
	}
}


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

void FullHeightBlenderCycleHolder::UnloadIterators(void)
{

	Verify(evenAnimIterator != NULL);
	Unregister_Pointer(evenAnimIterator);
	delete evenAnimIterator;
	evenAnimIterator = NULL;


	// blends are loaded
	if(upAnimIterator != NULL)
	{
		Unregister_Pointer(upAnimIterator);
		delete upAnimIterator;
		upAnimIterator = NULL;

		Verify(downAnimIterator != NULL);
		Unregister_Pointer(downAnimIterator);
		delete downAnimIterator;
		downAnimIterator = NULL;

		Verify(leftAnimIterator != NULL);
		Unregister_Pointer(leftAnimIterator);
		delete leftAnimIterator;
		leftAnimIterator = NULL;

		Verify(rightAnimIterator != NULL);
		Unregister_Pointer(rightAnimIterator);
		delete rightAnimIterator;
		rightAnimIterator = NULL;
	}


	currentTime = -1.0f;
}


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

Stuff::Scalar FullHeightBlenderCycleHolder::GetCurrentPercentage()
{
	Verify(evenAnimInstance != NULL);

	Scalar percent = currentTime / GetTimeTotal();

	percent *= percentageOfChain;
	percent += startPercentage;

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return
		percent;

}


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

Stuff::Scalar FullHeightBlenderCycleHolder::GetTimeTotal()
{
	Verify(evenAnimInstance != NULL);

	Scalar anim_time = evenAnimInstance->animData->animHeaderBlock->endTime - 
		evenAnimInstance->animData->animHeaderBlock->startTime;

	if (startPosition == -1.0f)
	{
		return (anim_time + startDelay);
	}

	return
		anim_time + startDelay - (anim_time * startPosition);
}


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

void FullHeightSpeedBlenderCycleHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);

	page = param_list->FindEntry("Position");
	Check_Object(page);
	
	if (!_stricmp(page->GetChar(), "old"))
	{
		startPosition = -1;
	}
	else
	{
		startPosition = page->GetAtof();
	}
	
	page = param_list->FindEntry("SlowUpAnim");
	Check_Object(page);

	// god i hate mstrings...
	MString string;
	string = page->GetChar();
	string += ".MW4ANIM";

	slowUpAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(slowUpAnimInstance);

	page = param_list->FindEntry("SlowEvenAnim");
	Check_Object(page);

	string = page->GetChar();
	string += ".MW4ANIM";

	slowEvenAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(slowEvenAnimInstance);

	if (!run_minimal)
	{
		page = param_list->FindEntry("SlowDownAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		slowDownAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(slowDownAnimInstance);


		page = param_list->FindEntry("SlowLeftAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		slowLeftAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(slowLeftAnimInstance);

		page = param_list->FindEntry("SlowRightAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		slowRightAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(slowRightAnimInstance);
	}



	page = param_list->FindEntry("FastEvenAnim");
	Check_Object(page);

	string = page->GetChar();
	string += ".MW4ANIM";

	fastEvenAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(fastEvenAnimInstance);

	if (!run_minimal)
	{
		page = param_list->FindEntry("FastUpAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		fastUpAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(fastUpAnimInstance);

		page = param_list->FindEntry("FastDownAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		fastDownAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(fastDownAnimInstance);


		page = param_list->FindEntry("FastLeftAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		fastLeftAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(fastLeftAnimInstance);

		page = param_list->FindEntry("FastRightAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		fastRightAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(fastRightAnimInstance);
	}


	page = param_list->FindEntry("RollAttrib");
	Check_Object(page);

	rollAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(rollAttrib);

	page = param_list->FindEntry("PitchAttrib");
	Check_Object(page);

	pitchAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(pitchAttrib);

	
	page = param_list->FindEntry("SpeedAttrib");
	Check_Object(page);

	speedAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(speedAttrib);


	// get the speed
	slowSpeed = -1.0f;

	MW4Animation::AnimIterator *anim_iterator = new MW4Animation::AnimIterator(slowEvenAnimInstance);
	Register_Pointer(anim_iterator);

	for (int i = 0; i < slowEvenAnimInstance->animData->GetChannelCount(); ++i)
	{
		if (slowEvenAnimInstance->animData->animChannelBlock[i].channelType ==
						MW4Animation::ChannelAnimData::VelocityChannelType )
		{
			MW4Animation::BaseKeyframe *keyframe = NULL;
			keyframe = anim_iterator->GetLastKeyFrame(i);
			MW4Animation::BaseKeyframeTime *keyframetime = NULL;
			keyframetime = anim_iterator->GetLastKeyFrameTime(i);

			slowSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z);
		}
	}

	Unregister_Pointer(anim_iterator);
	delete anim_iterator;

	Verify(slowSpeed != -1.0f);

	fastSpeed = -1.0f;

	anim_iterator = new MW4Animation::AnimIterator(fastEvenAnimInstance);
	Register_Pointer(anim_iterator);

	for (i = 0; i < fastEvenAnimInstance->animData->GetChannelCount(); ++i)
	{
		if (fastEvenAnimInstance->animData->animChannelBlock[i].channelType ==
						MW4Animation::ChannelAnimData::VelocityChannelType )
		{
			MW4Animation::BaseKeyframe *keyframe = NULL;
			keyframe = anim_iterator->GetLastKeyFrame(i);
			
			MW4Animation::BaseKeyframeTime *keyframetime = NULL;
			keyframetime = anim_iterator->GetLastKeyFrameTime(i);

			fastSpeed = Abs(MW4Animation::Point3DVelPosSnapInterpolator(keyframe, keyframe, keyframetime, keyframetime, 0.0f).z);
		}
	}

	Unregister_Pointer(anim_iterator);
	delete anim_iterator;

	slowSpeedMultiplier = 1.0f;
	page = param_list->FindEntry("SlowSpeedMultiplier");
	if (page)
	{
		slowSpeedMultiplier = page->GetAtof();
	}

	Verify(fastSpeed != -1.0f);

}




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

bool FullHeightSpeedBlenderCycleHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{
#ifdef _ARMOR
	Verify(slowEvenAnimIterator != NULL);
	Verify(fastEvenAnimIterator != NULL);
	
	if (!run_minimal)
	{
		Verify(fastUpAnimIterator != NULL);
		Verify(fastDownAnimIterator != NULL);
		Verify(fastLeftAnimIterator != NULL);
		Verify(fastRightAnimIterator != NULL);
		Verify(slowUpAnimIterator != NULL);
		Verify(slowDownAnimIterator != NULL);
		Verify(slowLeftAnimIterator != NULL);
		Verify(slowRightAnimIterator != NULL);
	}
#endif
		// frig with the time slice
	Stuff::Scalar current_speed;
	speedAttrib->GetValue(anim_state_engine->vehicleParent, &current_speed);
	current_speed = Abs(current_speed);

	Stuff::Scalar slow_blend_value = 0.0f;
	Stuff::Scalar fast_blend_value = 0.0f;


	if (currentTime >= startDelay)
	{
		// we want to be absolutly sure that we mix the animations in their own layer
		AnimHierarchyNode *heir_node = NULL;
		heir_node = anim_state_engine->iteratorManager->PushLayer(1.0f);

		//{
			if (current_speed < (slowSpeed * slowSpeedMultiplier))
			{
				

				Stuff::Scalar position = slowEvenAnimIterator->GetPosition();
				Stuff::Scalar time_slow_down = current_speed/slowSpeed;

				//SPEWALWAYS(("jerryeds", "SLOW SPEED ts:%f slow:%f  speed:%f", time_slice, time_slow_down, current_speed));

				if(time_slow_down > 0.0f)
				{
					currentTime += (time_slice * time_slow_down);

					if(	slowEvenAnimIterator->IncrementTime(time_slice * time_slow_down) )
					{
						carryOver = slowEvenAnimIterator->GetCarryOverTime()/time_slow_down;;
						fastEvenAnimIterator->SetPosition(1.0f);
						anim_state_engine->iteratorManager->UndoPush();
						return true;
					}
					else
					{
						Scalar fast_position = slowEvenAnimIterator->GetPosition() - fastEvenAnimIterator->GetPosition();
						Scalar slow_position = slowEvenAnimIterator->GetPosition() - position;

					
						fastEvenAnimIterator->IncrementPosition(fast_position);

						if (!run_minimal)
						{
							fastUpAnimIterator->IncrementPosition(fast_position);
							fastDownAnimIterator->IncrementPosition(fast_position);
							fastLeftAnimIterator->IncrementPosition(fast_position);
							fastRightAnimIterator->IncrementPosition(fast_position);
							slowUpAnimIterator->IncrementPosition(slow_position);
							slowDownAnimIterator->IncrementPosition(slow_position);
							slowLeftAnimIterator->IncrementPosition(slow_position);
							slowRightAnimIterator->IncrementPosition(slow_position);
						}
						
					}
					
					

					fastEvenAnimIterator->SetVelocityScale(time_slow_down);
					slowEvenAnimIterator->SetVelocityScale(time_slow_down);
					
					if (!run_minimal)
					{
						fastUpAnimIterator->SetVelocityScale(time_slow_down);
						fastDownAnimIterator->SetVelocityScale(time_slow_down);
						fastLeftAnimIterator->SetVelocityScale(time_slow_down);
						fastRightAnimIterator->SetVelocityScale(time_slow_down);
						slowUpAnimIterator->SetVelocityScale(time_slow_down);
						slowDownAnimIterator->SetVelocityScale(time_slow_down);
						slowLeftAnimIterator->SetVelocityScale(time_slow_down);
						slowRightAnimIterator->SetVelocityScale(time_slow_down);
					}
				}
				else
				{
					slowEvenAnimIterator->SetVelocityScale(0.0f);
					fastEvenAnimIterator->SetVelocityScale(0.0f);
						
					if (!run_minimal)
					{
						fastUpAnimIterator->SetVelocityScale(0.0f);
						fastDownAnimIterator->SetVelocityScale(0.0f);
						fastLeftAnimIterator->SetVelocityScale(0.0f);
						fastRightAnimIterator->SetVelocityScale(0.0f);
						slowUpAnimIterator->SetVelocityScale(0.0f);
						slowDownAnimIterator->SetVelocityScale(0.0f);
						slowLeftAnimIterator->SetVelocityScale(0.0f);
						slowRightAnimIterator->SetVelocityScale(0.0f);
					}
				}
				
				slow_blend_value = 1.0f;
				fast_blend_value = 0.0f;

				//Start(anim_state_engine);
			}
			else if (current_speed >= fastSpeed)
			{
				Stuff::Scalar position = fastEvenAnimIterator->GetPosition();
				Stuff::Scalar time_slow_down = current_speed/fastSpeed;
				currentTime += (time_slice * time_slow_down);
				
				//SPEWALWAYS(("jerryeds", "FAST SPEED ts:%f speed:%f slow:%f ", time_slice, current_speed, time_slow_down));

				if(time_slow_down > 0.0f)
				{
					if(	fastEvenAnimIterator->IncrementTime(time_slice * time_slow_down) )
					{
						carryOver = fastEvenAnimIterator->GetCarryOverTime()/time_slow_down;;
						slowEvenAnimIterator->SetPosition(1.0f);
						anim_state_engine->iteratorManager->UndoPush();
						return true;
					}
					else
					{
						Scalar slow_position = fastEvenAnimIterator->GetPosition() - slowEvenAnimIterator->GetPosition();
						Scalar fast_position = fastEvenAnimIterator->GetPosition() - position;

						
						slowEvenAnimIterator->IncrementPosition(slow_position);
						if (!run_minimal)
						{
							fastUpAnimIterator->IncrementPosition(fast_position);
							fastDownAnimIterator->IncrementPosition(fast_position);
							fastLeftAnimIterator->IncrementPosition(fast_position);
							fastRightAnimIterator->IncrementPosition(fast_position);
							
							slowUpAnimIterator->IncrementPosition(slow_position);
							slowDownAnimIterator->IncrementPosition(slow_position);
							slowLeftAnimIterator->IncrementPosition(slow_position);
							slowRightAnimIterator->IncrementPosition(slow_position);
						}
						
					}

					fastEvenAnimIterator->SetVelocityScale(time_slow_down);
					slowEvenAnimIterator->SetVelocityScale(time_slow_down);
						
					if (!run_minimal)
					{
						fastUpAnimIterator->SetVelocityScale(time_slow_down);
						fastDownAnimIterator->SetVelocityScale(time_slow_down);
						fastLeftAnimIterator->SetVelocityScale(time_slow_down);
						fastRightAnimIterator->SetVelocityScale(time_slow_down);
						slowUpAnimIterator->SetVelocityScale(time_slow_down);
						slowDownAnimIterator->SetVelocityScale(time_slow_down);
						slowLeftAnimIterator->SetVelocityScale(time_slow_down);
						slowRightAnimIterator->SetVelocityScale(time_slow_down);
					}
				}
				else
				{
					fastEvenAnimIterator->SetVelocityScale(0.0f);
					slowEvenAnimIterator->SetVelocityScale(0.0f);
					if (!run_minimal)
					{
						fastUpAnimIterator->SetVelocityScale(0.0f);
						fastDownAnimIterator->SetVelocityScale(0.0f);
						fastLeftAnimIterator->SetVelocityScale(0.0f);
						fastRightAnimIterator->SetVelocityScale(0.0f);	
						slowUpAnimIterator->SetVelocityScale(0.0f);
						slowDownAnimIterator->SetVelocityScale(0.0f);
						slowLeftAnimIterator->SetVelocityScale(0.0f);
						slowRightAnimIterator->SetVelocityScale(0.0f);
					}
				}	
				slow_blend_value = 0.0f;
				fast_blend_value = 1.0f;
				
				
			}
			else
			{

				

				//we are in blending mode...
				Stuff::Scalar position = fastEvenAnimIterator->GetPosition();
				
				//run is in control

				currentTime += time_slice;

				if(	fastEvenAnimIterator->IncrementTime(time_slice) )
				{
					carryOver = fastEvenAnimIterator->GetCarryOverTime();
					slowEvenAnimIterator->SetPosition(1.0f);
					anim_state_engine->iteratorManager->UndoPush();
					//SPEWALWAYS(("jerryeds", "BLEND CO ts:%f speed:%f co:%f", time_slice, current_speed, carryOver));

					return true;
				}
				else
				{
					
					Scalar slow_position = fastEvenAnimIterator->GetPosition() - slowEvenAnimIterator->GetPosition();
					Scalar fast_position = fastEvenAnimIterator->GetPosition() - position;

					
					slowEvenAnimIterator->IncrementPosition(slow_position);

					if (!run_minimal)
					{
						fastUpAnimIterator->IncrementPosition(fast_position);
						fastDownAnimIterator->IncrementPosition(fast_position);
						fastLeftAnimIterator->IncrementPosition(fast_position);
						fastRightAnimIterator->IncrementPosition(fast_position);
						
						slowUpAnimIterator->IncrementPosition(slow_position);
						slowDownAnimIterator->IncrementPosition(slow_position);
						slowLeftAnimIterator->IncrementPosition(slow_position);
						slowRightAnimIterator->IncrementPosition(slow_position);
					}
					

				}
				
				slowEvenAnimIterator->SetVelocityScale(1.0f);
				fastEvenAnimIterator->SetVelocityScale(1.0f);
					
				if (!run_minimal)
				{
					fastUpAnimIterator->SetVelocityScale(1.0f);
					fastDownAnimIterator->SetVelocityScale(1.0f);
					fastLeftAnimIterator->SetVelocityScale(1.0f);
					fastRightAnimIterator->SetVelocityScale(1.0f);
					slowUpAnimIterator->SetVelocityScale(1.0f);
					slowDownAnimIterator->SetVelocityScale(1.0f);
					slowLeftAnimIterator->SetVelocityScale(1.0f);
					slowRightAnimIterator->SetVelocityScale(1.0f);
				}

				Scalar speed_diff = fastSpeed - slowSpeed;
				fast_blend_value = (current_speed - slowSpeed)/speed_diff;
				slow_blend_value = 1.0f - fast_blend_value;


				//SPEWALWAYS(("jerryeds", "BLEND ts:%f speed:%f sp:%f fp:%f", time_slice, current_speed, slowEvenAnimIterator->GetPosition(), fastEvenAnimIterator->GetPosition()));

			}

		// start

		CalculateAndSetHeightCurves(anim_state_engine, run_minimal);

		Verify(Close_Enough(fast_blend_value + slow_blend_value, 1.0f));
		
		anim_state_engine->iteratorManager->PushLayer(slow_blend_value);

			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowEvenAnimIterator);
			if (!run_minimal)
			{
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowUpAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowDownAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowLeftAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(slowRightAnimIterator);
			}

		anim_state_engine->iteratorManager->PopLayer();


		anim_state_engine->iteratorManager->PushLayer(fast_blend_value);

			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastEvenAnimIterator);
			if (!run_minimal)
			{
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastUpAnimIterator);	
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastDownAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastLeftAnimIterator);
				anim_state_engine->iteratorManager->AddAnimToCurrentLayer(fastRightAnimIterator);
			}
		anim_state_engine->iteratorManager->PopLayer();


		

		anim_state_engine->iteratorManager->PopLayer();

		// add the curve
		if (curveCount)
		{
			// we don't support multiple curves now
			Check_Pointer(heir_node);
			Verify(curveCount == 1);
			heir_node->SetBlendValue(anim_state_engine->animCurves[firstCurve].Play(fastEvenAnimIterator->GetPosition()));
		}
	}
	else
	{
		currentTime += time_slice;
	}

	return false;
}

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

void FullHeightSpeedBlenderCycleHolder::CalculateAndSetHeightCurves(AnimationStateEngine *anim_state_engine, bool run_minimal)
{

		Stuff::Scalar roll_slope;
		Stuff::Scalar pitch_slope;

		// figure out blend value
		rollAttrib->GetValue(anim_state_engine->vehicleParent, &roll_slope);
		pitchAttrib->GetValue(anim_state_engine->vehicleParent, &pitch_slope);

		Stuff::Scalar up_blend = 0.0f;
		Stuff::Scalar down_blend = 0.0f;
		Stuff::Scalar even_blend = 0.0f;
		Stuff::Scalar left_blend = 0.0f;
		Stuff::Scalar right_blend = 0.0f;

		//SPEW(("jerryeds", "ps: %f", pitch_slope));

		if(pitch_slope > 0.0f)
		{
			down_blend = 0.0f;
			Max_Clamp(pitch_slope, Pi_Over_4);

			up_blend = pitch_slope/Pi_Over_4;

		}
		else if(pitch_slope < 0.0f)
		{
			up_blend = 0.0f;
			pitch_slope = -pitch_slope;
			Max_Clamp(pitch_slope, Pi_Over_4);
		
			down_blend = pitch_slope/Pi_Over_4;
			

		}
		else
		{
			down_blend = 0.0f;
			up_blend = 0.0f;
		}

		if(roll_slope > 0.0f)
		{
			right_blend = 0.0f;
			Max_Clamp(roll_slope, Pi_Over_4);

			left_blend = roll_slope/Pi_Over_4;
			
		}
		else if(roll_slope < 0.0f)
		{
			left_blend = 0.0f;
			roll_slope = -roll_slope;
			Max_Clamp(roll_slope, Pi_Over_4);
		
			right_blend = roll_slope/Pi_Over_4;
			

		}
		else
		{
			right_blend = 0.0f;
			left_blend = 0.0f;
		}


		if ((left_blend + right_blend + up_blend + down_blend) < 1.0f)
		{
			even_blend = 1.0f - (left_blend + right_blend + up_blend + down_blend);
		}
		else
		{
			even_blend = 0.015f;
		}
		
		fastEvenAnimIterator->SetBlendValue(even_blend);
		slowEvenAnimIterator->SetBlendValue(even_blend);
		
		if (!run_minimal)
		{
			fastDownAnimIterator->SetBlendValue(down_blend);
			fastUpAnimIterator->SetBlendValue(up_blend);
			fastLeftAnimIterator->SetBlendValue(left_blend);
			fastRightAnimIterator->SetBlendValue(right_blend);
			slowDownAnimIterator->SetBlendValue(down_blend);
			slowUpAnimIterator->SetBlendValue(up_blend);
			slowLeftAnimIterator->SetBlendValue(left_blend);
			slowRightAnimIterator->SetBlendValue(right_blend);
		}
		//SPEW(("jerryeds", "%f %f %f %f %f", even_blend, up_blend, down_blend, left_blend, right_blend));

}

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

void FullHeightSpeedBlenderCycleHolder::Que(Stuff::Scalar position, bool run_minimal)
{


	//SPEWALWAYS(("jerryeds", "QUE - %f", position));
	
#ifdef _ARMOR
	Verify(slowEvenAnimIterator != NULL);
	Verify(fastEvenAnimIterator != NULL);
		

	if (!run_minimal)
	{
		Verify(fastUpAnimIterator != NULL);
		Verify(fastDownAnimIterator != NULL);
		Verify(fastLeftAnimIterator != NULL);
		Verify(fastRightAnimIterator != NULL);
		Verify(slowUpAnimIterator != NULL);	
		Verify(slowDownAnimIterator != NULL);
		Verify(slowLeftAnimIterator != NULL);
		Verify(slowRightAnimIterator != NULL);
	}
#endif



	if (position != -1.0f)
	{
		fastEvenAnimIterator->SetPosition(position);
		slowEvenAnimIterator->SetPosition(position);

		if (!run_minimal)
		{
			fastUpAnimIterator->SetPosition(position);
			fastDownAnimIterator->SetPosition(position);
			fastLeftAnimIterator->SetPosition(position);
			fastRightAnimIterator->SetPosition(position);
			slowUpAnimIterator->SetPosition(position);
			slowDownAnimIterator->SetPosition(position);
			slowLeftAnimIterator->SetPosition(position);
			slowRightAnimIterator->SetPosition(position);

			//SPEWALWAYS(("jerryeds", "R-FE-QUE - %f", fastEvenAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FU-QUE - %f", fastUpAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FD-QUE - %f", fastDownAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FL-QUE - %f", fastLeftAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FR-QUE - %f", fastRightAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SE-QUE - %f", slowEvenAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SU-QUE - %f", slowUpAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SD-QUE - %f", slowDownAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SL-QUE - %f", slowLeftAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SR-QUE - %f", slowRightAnimIterator->GetPosition()));

		}

		Verify(startDelay == 0.0f);

		currentTime = GetTimeTotal() * position;
	}
	else
	{
		fastEvenAnimIterator->SetPosition(startPosition);
		slowEvenAnimIterator->SetPosition(startPosition);

		if (!run_minimal)
		{
			fastUpAnimIterator->SetPosition(startPosition);
			fastDownAnimIterator->SetPosition(startPosition);
			fastLeftAnimIterator->SetPosition(startPosition);
			fastRightAnimIterator->SetPosition(startPosition);
			slowUpAnimIterator->SetPosition(startPosition);
			slowDownAnimIterator->SetPosition(startPosition);
			slowLeftAnimIterator->SetPosition(startPosition);
			slowRightAnimIterator->SetPosition(startPosition);

			//SPEWALWAYS(("jerryeds", "R-FE-QUE - %f", fastEvenAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FU-QUE - %f", fastUpAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FD-QUE - %f", fastDownAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FL-QUE - %f", fastLeftAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-FR-QUE - %f", fastRightAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SE-QUE - %f", slowEvenAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SU-QUE - %f", slowUpAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SD-QUE - %f", slowDownAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SL-QUE - %f", slowLeftAnimIterator->GetPosition()));
			//SPEWALWAYS(("jerryeds", "R-SR-QUE - %f", slowRightAnimIterator->GetPosition()));


		}
		currentTime = 0.0f;
	}

}

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

void FullHeightSpeedBlenderCycleHolder::LoadIterators(bool run_minimal)
{
	
	Verify(fastEvenAnimIterator == NULL);
	fastEvenAnimIterator = new MW4Animation::AnimIterator(fastEvenAnimInstance);
	Register_Pointer(fastEvenAnimIterator);

	if (!run_minimal)
	{
		Verify(fastUpAnimIterator == NULL);
		fastUpAnimIterator = new MW4Animation::AnimIterator(fastUpAnimInstance);
		Register_Pointer(fastUpAnimIterator);

		Verify(fastDownAnimIterator == NULL);
		fastDownAnimIterator = new MW4Animation::AnimIterator(fastDownAnimInstance);
		Register_Pointer(fastDownAnimIterator);

		Verify(fastLeftAnimIterator == NULL);
		fastLeftAnimIterator = new MW4Animation::AnimIterator(fastLeftAnimInstance);
		Register_Pointer(fastLeftAnimIterator);

		Verify(fastRightAnimIterator == NULL);
		fastRightAnimIterator = new MW4Animation::AnimIterator(fastRightAnimInstance);
		Register_Pointer(fastRightAnimIterator);
	}

	
	Verify(slowEvenAnimIterator == NULL);
	slowEvenAnimIterator = new MW4Animation::AnimIterator(slowEvenAnimInstance);
	Register_Pointer(slowEvenAnimIterator);

	if (!run_minimal)
	{
		Verify(slowUpAnimIterator == NULL);
		slowUpAnimIterator = new MW4Animation::AnimIterator(slowUpAnimInstance);
		Register_Pointer(slowUpAnimIterator);

		
		Verify(slowDownAnimIterator == NULL);
		slowDownAnimIterator = new MW4Animation::AnimIterator(slowDownAnimInstance);
		Register_Pointer(slowDownAnimIterator);

		Verify(slowLeftAnimIterator == NULL);
		slowLeftAnimIterator = new MW4Animation::AnimIterator(slowLeftAnimInstance);
		Register_Pointer(slowLeftAnimIterator);

		Verify(slowRightAnimIterator == NULL);
		slowRightAnimIterator = new MW4Animation::AnimIterator(slowRightAnimInstance);
		Register_Pointer(slowRightAnimIterator);
	}
}

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

void FullHeightSpeedBlenderCycleHolder::UnloadIterators(void)
{

	Verify(slowEvenAnimIterator != NULL);
	Unregister_Pointer(slowEvenAnimIterator);
	delete slowEvenAnimIterator;
	slowEvenAnimIterator = NULL;

	Verify(fastEvenAnimIterator != NULL);
	Unregister_Pointer(fastEvenAnimIterator);
	delete fastEvenAnimIterator;
	fastEvenAnimIterator = NULL;


	if (slowUpAnimIterator != NULL)
	{
		Unregister_Pointer(slowUpAnimIterator);
		delete slowUpAnimIterator;
		slowUpAnimIterator = NULL;

		Verify(slowDownAnimIterator != NULL);
		Unregister_Pointer(slowDownAnimIterator);
		delete slowDownAnimIterator;
		slowDownAnimIterator = NULL;

		Verify(slowLeftAnimIterator != NULL);
		Unregister_Pointer(slowLeftAnimIterator);
		delete slowLeftAnimIterator;
		slowLeftAnimIterator = NULL;

		Verify(slowRightAnimIterator != NULL);
		Unregister_Pointer(slowRightAnimIterator);
		delete slowRightAnimIterator;
		slowRightAnimIterator = NULL;

		Verify(fastUpAnimIterator != NULL);
		Unregister_Pointer(fastUpAnimIterator);
		delete fastUpAnimIterator;
		fastUpAnimIterator = NULL;

		Verify(fastDownAnimIterator != NULL);
		Unregister_Pointer(fastDownAnimIterator);
		delete fastDownAnimIterator;
		fastDownAnimIterator = NULL;

		Verify(fastLeftAnimIterator != NULL);
		Unregister_Pointer(fastLeftAnimIterator);
		delete fastLeftAnimIterator;
		fastLeftAnimIterator = NULL;

		Verify(fastRightAnimIterator != NULL);
		Unregister_Pointer(fastRightAnimIterator);
		delete fastRightAnimIterator;
		fastRightAnimIterator = NULL;
	}


	currentTime = -1.0f;
}

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

Stuff::Scalar FullHeightSpeedBlenderCycleHolder::GetCurrentPercentage()
{
	Verify(slowEvenAnimInstance != NULL);

	Verify(startDelay == 0.0f);

	//Scalar percent = currentTime / GetTimeTotal();
	Scalar percent = slowEvenAnimIterator->GetPosition();

	percent *= percentageOfChain;
	percent += startPercentage;

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return
		percent;

}

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

Stuff::Scalar FullHeightSpeedBlenderCycleHolder::GetTimeTotal()
{
	Verify(slowEvenAnimInstance != NULL);

	Scalar anim_time = slowEvenAnimInstance->animData->animHeaderBlock->endTime - 
		slowEvenAnimInstance->animData->animHeaderBlock->startTime;

	if (startPosition == -1.0f)
	{
		return (anim_time + startDelay);
	}

	return
		anim_time + startDelay - (anim_time * startPosition);
}



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

void FullHeightPoseHolder::Load(AnimationStateEngine *anim_state_engine, NameList *param_list, bool run_minimal)
{

	NameList::Entry *page = param_list->FindEntry("AnimType");
	Check_Object(page);

	page = param_list->FindEntry("Position");
	Check_Object(page);
	targetPosition = page->GetAtof();
	Verify(targetPosition >= 0.0f);
	Verify(targetPosition <= 1.0f);

	MString string;


	page = param_list->FindEntry("EvenAnim");
	Check_Object(page);

	
	string = page->GetChar();
	string += ".MW4ANIM";

	evenAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
	Check_Object(evenAnimInstance);

	if (!run_minimal)
	{

		page = param_list->FindEntry("UpAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		upAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(upAnimInstance);


		page = param_list->FindEntry("DownAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		downAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(downAnimInstance);


		page = param_list->FindEntry("LeftAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		leftAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(leftAnimInstance);

		page = param_list->FindEntry("RightAnim");
		Check_Object(page);

		string = page->GetChar();
		string += ".MW4ANIM";

		rightAnimInstance = anim_state_engine->LoadOrMakeAnimInstance((const char *)string);
		Check_Object(rightAnimInstance);

	}


	page = param_list->FindEntry("RollAttrib");
	Check_Object(page);

	rollAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(rollAttrib);

	page = param_list->FindEntry("PitchAttrib");
	Check_Object(page);

	pitchAttrib = anim_state_engine->vehicleParent->GetAttributeEntry(page->GetChar());
	Check_Object(pitchAttrib);


}


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

bool FullHeightPoseHolder::Advance(AnimationStateEngine *anim_state_engine, Stuff::Scalar time_slice, bool run_minimal)
{

#ifdef _ARMOR
	Verify(evenAnimIterator != NULL);

	if (!run_minimal)
	{
		Verify(upAnimIterator != NULL);
		Verify(downAnimIterator != NULL);
		Verify(leftAnimIterator != NULL);
		Verify(rightAnimIterator != NULL);
	}
#endif

	// work thru the delay if there is one...
	currentTime += time_slice;

	if (currentTime >= startDelay)
	{
		AnimHierarchyNode *heir_node = NULL;
		heir_node = anim_state_engine->iteratorManager->PushLayer(1.0f);

		evenAnimIterator->SetVelocityScale(0.0f);
		if (!run_minimal)
		{
			upAnimIterator->SetVelocityScale(0.0f);
			downAnimIterator->SetVelocityScale(0.0f);
			leftAnimIterator->SetVelocityScale(0.0f);
			rightAnimIterator->SetVelocityScale(0.0f);
		}

		Stuff::Scalar roll_slope;
		Stuff::Scalar pitch_slope;
		Stuff::Scalar up_blend = 0.0f;
		Stuff::Scalar down_blend = 0.0f;
		Stuff::Scalar even_blend = 0.0f;
		Stuff::Scalar left_blend = 0.0f;
		Stuff::Scalar right_blend = 0.0f;
		
		rollAttrib->GetValue(anim_state_engine->vehicleParent, &roll_slope);
		pitchAttrib->GetValue(anim_state_engine->vehicleParent, &pitch_slope);


		if(pitch_slope > 0.0f)
		{
			down_blend = 0.0f;
			Max_Clamp(pitch_slope, Pi_Over_4);

			up_blend = pitch_slope/Pi_Over_4;
			//even_blend = 1.0f - up_blend;

			
		}
		else if(pitch_slope < 0.0f)
		{
			up_blend = 0.0f;
			pitch_slope = -pitch_slope;
			Max_Clamp(pitch_slope, Pi_Over_4);
		
			down_blend = pitch_slope/Pi_Over_4;
			//even_blend = 1.0f - down_blend;
		}
		else
		{
			
			down_blend = 0.0f;
			up_blend = 0.0f;
		}

		if(roll_slope > 0.0f)
		{
			right_blend = 0.0f;
			Max_Clamp(roll_slope, Pi_Over_4);

			left_blend = roll_slope/Pi_Over_4;
			//even_blend = 1.0f - right_blend;

			
		}
		else if(roll_slope < 0.0f)
		{
			left_blend = 0.0f;
			roll_slope = -roll_slope;
			Max_Clamp(roll_slope, Pi_Over_4);
		
			right_blend = roll_slope/Pi_Over_4;
			//even_blend = 1.0f - left_blend;

		}
		else
		{
			
			right_blend = 0.0f;
			left_blend = 0.0f;
		}


		if ((left_blend + right_blend + up_blend + down_blend) < 1.0f)
		{
			even_blend = 1.0f - (left_blend + right_blend + up_blend + down_blend);
		}
		else
		{
			even_blend = 0.015f;
		}
		

		//SPEW(("jerryeds", "%f %f %f %f %f", up_blend, down_blend, even_blend, left_blend, right_blend));

		evenAnimIterator->SetBlendValue(even_blend);
		if (!run_minimal)
		{
			downAnimIterator->SetBlendValue(down_blend);
			upAnimIterator->SetBlendValue(up_blend);	
			leftAnimIterator->SetBlendValue(left_blend);
			rightAnimIterator->SetBlendValue(right_blend);
		}

		anim_state_engine->iteratorManager->AddAnimToCurrentLayer(evenAnimIterator);

		if (!run_minimal)
		{
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(upAnimIterator);
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(downAnimIterator);
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(leftAnimIterator);
			anim_state_engine->iteratorManager->AddAnimToCurrentLayer(rightAnimIterator);
		
		}
		anim_state_engine->iteratorManager->PopLayer();
		
		if (startDelay == 0.0f)
		{
			carryOver = 0.0f;
		}
		else
		{
			carryOver = currentTime - startDelay;
		}
		return true;
	}

	return false;

}

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


void FullHeightPoseHolder::Que(Stuff::Scalar position, bool run_minimal)
{
#ifdef _ARMOR
	Verify(evenAnimIterator != NULL);

	if (!run_minimal)
	{
		Verify(upAnimIterator != NULL);
		Verify(downAnimIterator != NULL);
		Verify(leftAnimIterator != NULL);
		Verify(rightAnimIterator != NULL);
	}
#endif

	
	evenAnimIterator->SetPosition(targetPosition);

	if (!run_minimal)
	{
		upAnimIterator->SetPosition(targetPosition);
		downAnimIterator->SetPosition(targetPosition);
		leftAnimIterator->SetPosition(targetPosition);
		rightAnimIterator->SetPosition(targetPosition);
	}


	currentTime = 0.0f;
}

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

void FullHeightPoseHolder::LoadIterators(bool run_minimal)
{

	Verify(evenAnimIterator == NULL);
	evenAnimIterator = new MW4Animation::AnimIterator(evenAnimInstance);
	Register_Pointer(evenAnimIterator);

	if (!run_minimal)
	{
		Verify(upAnimIterator == NULL);
		upAnimIterator = new MW4Animation::AnimIterator(upAnimInstance);
		Register_Pointer(upAnimIterator);

		Verify(downAnimIterator == NULL);
		downAnimIterator = new MW4Animation::AnimIterator(downAnimInstance);
		Register_Pointer(downAnimIterator);

		Verify(leftAnimIterator == NULL);
		leftAnimIterator = new MW4Animation::AnimIterator(leftAnimInstance);
		Register_Pointer(leftAnimIterator);

		Verify(rightAnimIterator == NULL);
		rightAnimIterator = new MW4Animation::AnimIterator(rightAnimInstance);
		Register_Pointer(rightAnimIterator);
	}
}

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

void FullHeightPoseHolder::UnloadIterators(void)
{
	Verify(evenAnimIterator != NULL);
	Unregister_Pointer(evenAnimIterator);
	delete evenAnimIterator;
	evenAnimIterator = NULL;

	if (upAnimIterator != NULL)
	{
		Unregister_Pointer(upAnimIterator);
		delete upAnimIterator;
		upAnimIterator = NULL;

		Verify(downAnimIterator != NULL);
		Unregister_Pointer(downAnimIterator);
		delete downAnimIterator;
		downAnimIterator = NULL;

		Verify(leftAnimIterator != NULL);
		Unregister_Pointer(leftAnimIterator);
		delete leftAnimIterator;
		leftAnimIterator = NULL;

		Verify(rightAnimIterator != NULL);
		Unregister_Pointer(rightAnimIterator);
		delete rightAnimIterator;
		rightAnimIterator = NULL;
	}

	currentTime = -1.0f;
}

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


Stuff::Scalar FullHeightPoseHolder::GetCurrentPercentage()
{
	Verify(evenAnimInstance != NULL);
	
	if (startDelay == 0.0f)
	{
		return startPercentage;
	}

	Scalar percent = currentTime / startDelay;

	percent *= percentageOfChain;
	percent += startPercentage;

	Verify(percent <= 1.0f);
	Verify(percent >= 0.0f);

	return percent;

}


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


Stuff::Scalar FullHeightPoseHolder::GetTimeTotal()
{
	//Verify(animInstance != NULL);
	return 
		0.0f + startDelay;
}


