//===========================================================================//
// File:	AnimInstance.cpp                                                 
// Project: MechWarrior 4
// Contents: 
//			
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 07/01/98  JSE  Initial coding, 
//---------------------------------------------------------------------------//
// Copyright (C) 1998, Fasa Interactive, Inc.
// All Rights reserved worldwide
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL
//===========================================================================//


#include <MW4\MW4AnimationSystem.hpp>


using namespace MW4Animation;

AnimInstanceManager *
	AnimInstanceManager::Anim_Instance_Manager = NULL;


HGOSHEAP
	g_AnimParentHeap = NULL;
HGOSHEAP
	g_AnimDataHeap = NULL;
HGOSHEAP
	g_AnimIteratorHeap = NULL;
HGOSHEAP
	g_AnimGeneral = NULL;

//#############################################################################
//#######################       AnimInstance         #########################
//#############################################################################

void AnimInstanceManager::InitializeClass()
{

	Verify(!g_AnimParentHeap);
	g_AnimParentHeap = gos_CreateMemoryHeap("Animation");
	Check_Pointer(g_AnimParentHeap);

	Verify(!g_AnimDataHeap);
	g_AnimDataHeap = gos_CreateMemoryHeap("RawData", 0, g_AnimParentHeap);
	Check_Pointer(g_AnimDataHeap);

	Verify(!g_AnimIteratorHeap);
	g_AnimIteratorHeap = gos_CreateMemoryHeap("Iterators", 0, g_AnimParentHeap);
	Check_Pointer(g_AnimIteratorHeap);

	Verify(!g_AnimGeneral);
	g_AnimGeneral = gos_CreateMemoryHeap("General", 0, g_AnimParentHeap);
	Check_Pointer(g_AnimGeneral);


	gos_PushCurrentHeap(g_AnimGeneral);

	Anim_Instance_Manager = new AnimInstanceManager;
	Register_Object(Anim_Instance_Manager);

	gos_PopCurrentHeap();
}

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

void AnimInstanceManager::TerminateClass()
{
	Unregister_Object(Anim_Instance_Manager);
	delete Anim_Instance_Manager;
	
	
	Check_Pointer(g_AnimDataHeap);
	gos_DestroyMemoryHeap(g_AnimDataHeap);
	g_AnimDataHeap = NULL;

	Check_Pointer(g_AnimIteratorHeap);
	gos_DestroyMemoryHeap(g_AnimIteratorHeap);
	g_AnimIteratorHeap = NULL;

	Check_Pointer(g_AnimGeneral);
	gos_DestroyMemoryHeap(g_AnimGeneral);
	g_AnimGeneral = NULL;

	Check_Pointer(g_AnimParentHeap);
	gos_DestroyMemoryHeap(g_AnimParentHeap);
	g_AnimParentHeap = NULL;
}

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

AnimInstanceManager::AnimInstanceManager():
	Plug(DefaultData),
	animDataChains(NULL)
{
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void AnimInstanceManager::DeleteAnimations(void)
{
	
	Stuff::ChainIteratorOf<Stuff::PlugOf<AnimData*>*> iterator(&animDataChains);
	Stuff::PlugOf<AnimData*> *anim_plug;

	while ((anim_plug = iterator.GetCurrent()) != NULL)
	{


		AnimData* anim = anim_plug->GetItem();

		//SPEW(("jerryeds","DELETING : %x : %s ", anim, anim->animHeaderBlock->animationName));

		
		Unregister_Pointer(anim);
		delete anim;

		iterator.Remove();
		Unregister_Object(anim_plug);
		delete anim_plug;
	}

}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
AnimInstanceManager::~AnimInstanceManager()
{
	
	Stuff::ChainIteratorOf<Stuff::PlugOf<AnimData*>*> iterator(&animDataChains);
	Stuff::PlugOf<AnimData*> *anim_plug;

	while ((anim_plug = iterator.GetCurrent()) != NULL)
	{


		AnimData* anim = anim_plug->GetItem();

		//SPEW(("jerryeds","DELETING : %x : %s ", anim, anim->animHeaderBlock->animationName));

		
		Unregister_Pointer(anim);
		delete anim;

		iterator.Remove();
		Unregister_Object(anim_plug);
		delete anim_plug;
	}

}

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

AnimData *
	AnimInstanceManager::LoadAnim(const char *animation_name)
{
	Stuff::ChainIteratorOf<Stuff::PlugOf<AnimData*>*> iterator(&animDataChains);
	Stuff::PlugOf<AnimData*> *anim_plug;

	Stuff::MString new_anim_name = animation_name;
	new_anim_name.StripDirectory().StripExtension();



	//SPEW(("jerryeds","SEARCHING FOR : '%s'",  (const char *)new_anim_name));


	while ((anim_plug = iterator.ReadAndNext()) != NULL)
	{
		if (
			!_stricmp(anim_plug->GetItem()->animHeaderBlock->animationName, (const char *)new_anim_name)
		)
		{
			//SPEW(("jerryeds","FOUND : %x : '%s'", anim_plug, anim_plug->GetItem()->animHeaderBlock->animationName));

			// we found it
			return anim_plug->GetItem();
		}
	}

	// we didn't find it so load it.

	gos_PushCurrentHeap(g_AnimDataHeap);

	AnimData *anim = new AnimData;
	Register_Pointer(anim);
	
	gos_PopCurrentHeap();


	gos_PushCurrentHeap(g_AnimGeneral);

	Stuff::PlugOf<AnimData*> *plug = new Stuff::PlugOf<AnimData*>(anim);
	Register_Object(plug);
	animDataChains.Add(plug);

	gos_PopCurrentHeap();


	Adept::Resource anim_res(animation_name);

	if (!anim_res.DoesResourceExist())
	{
		STOP(("Animation does not exist in resources, please add to props : %s", animation_name));
	}

	anim->Load(&anim_res);

	//SPEW(("jerryeds","Adding : %x : '%s'", anim, anim->animHeaderBlock->animationName));

	return anim;

}

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

AnimInstance 
	*AnimInstanceManager::MakeAnimInstance(
			const char *animation_name, 
			UserDefinedSearchFunction search_func,
			void *user_data
		)
{
	
	AnimData *anim = LoadAnim(animation_name);

	gos_PushCurrentHeap(g_AnimIteratorHeap);

	AnimInstance *anim_inst = new AnimInstance(anim);
	
	gos_PopCurrentHeap();


	for (int i = 0; i < anim->GetJointCount(); ++i)
	{
		anim_inst->jointToIndex[i] = 
			(*search_func)( anim->animJointBlock[i].GetName(anim->animNameBlock), user_data);
	}

	return anim_inst;
}


//#############################################################################
//#######################       AnimInstance         #########################
//#############################################################################

AnimInstance::AnimInstance(AnimData *anim):
	Plug(DefaultData)
{
	
	animData = anim;
	jointToIndex = NULL;

	if (anim->GetJointCount())
	{
		jointToIndex = new int [anim->GetJointCount()];
		Register_Pointer(jointToIndex);
	}
}

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

AnimInstance::~AnimInstance()
{
	if (jointToIndex != NULL)
	{
		Unregister_Pointer(jointToIndex);
		delete[] jointToIndex;
	}
}
