#include "munga.h"
#pragma hdrstop

#include "tool.h"
#include "fileutil.h"
#include "joint.h"
#include "namelist.h"

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
	ApplicationTool::WriteAnimationCycle(
		NotationFile *animation_file,
		StreamableResourceFile *file,
		const char *animation_name
	)
{
	int frame_count;
	int joint_count;
	int i;

	if (!animation_file->GetEntry("HEADER", "framecount", &frame_count))
	{
		std::cout << "No framecount in HEADER for animation " << animation_name << std::endl;
		return False;
	}

	if (!animation_file->GetEntry("HEADER", "jointcount", &joint_count))
	{
		std::cout << "No jointcount in HEADER for animation " << animation_name << std::endl;
		return False;
	}

	char **joint_indices = new char *[joint_count];
	int *joint_indices_numbers = new int[joint_count];
	Register_Pointer(joint_indices_numbers);
	Register_Pointer(joint_indices);

	NameList *joint_list = animation_file->MakeEntryList("JointIndices");
	Register_Object(joint_list);
	NameList::Entry *entry = joint_list->GetFirstEntry();

	i = 0;
	while (entry != NULL)
	{
		if (entry->GetData())
		{
			joint_indices_numbers[i] = entry->GetAtoi();
			//Dump(entry->GetName());
			joint_indices[i] = new char[strlen(entry->GetName()) +2 ];
			Register_Pointer(joint_indices[i]);
			strcpy(joint_indices[i], entry->GetName());
			++i;
		}
		entry = entry->GetNextEntry();
	}


	Unregister_Object(joint_list);
	delete joint_list;


	Scalar *frame_time = new Scalar[frame_count];
	Register_Pointer(frame_time);

	NameList *frame_list = animation_file->MakeEntryList("Time", "frame");
	Register_Object(frame_list);
	entry = frame_list->GetFirstEntry();

	i = 0;


	while (entry != NULL)
	{
		if (entry->GetData())
		{
			frame_time[i] = entry->GetAtof();
			++i;
		}
		entry = entry->GetNextEntry();
	}



	Unregister_Object(frame_list);
	delete frame_list;



	char temp[100];
	const char *euler_txt;
	char page_name[100];

	NameList *page_list = animation_file->MakePageList("frame");
	Register_Object(page_list);
	entry = page_list->GetFirstEntry();

	EulerAngles *keyframe = new EulerAngles[joint_count*frame_count];
	Register_Pointer(keyframe);

	int keycounter = 0;


	while (entry != NULL)
	{
		if (entry->GetData())
		{
			strcpy(page_name, entry->GetName());

			for (int j = 0; j < joint_count; ++j)
			{
				if (!animation_file->GetEntry(page_name, joint_indices[j], &euler_txt))
				{
					std::cout << "No page for joint " << j << "in page " << page_name
						<< " - joint " << joint_indices[j] << std::endl;
					Unregister_Object(page_list);
					delete page_list;

					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
				}

				strcpy(temp, euler_txt);
				strtok(temp,White_Space);


				keyframe[keycounter].pitch = atof(temp);
				keyframe[keycounter].yaw = atof(NextToken()) ;
				keyframe[keycounter].roll = atof(NextToken());
				++keycounter;
			}
		}
		entry = entry->GetNextEntry();

	 }
	Unregister_Object(page_list);
	delete page_list;


	NameList *root_list = animation_file->MakeEntryList("RootTranslation", "frame");
	Register_Object(root_list);
	entry = root_list->GetFirstEntry();

	Vector3D *root_trans = new Vector3D[frame_count];
	Register_Pointer(root_trans);

	i = 0;

	while (entry != NULL)
	{
		if (entry->GetData())
		{
			char *root_txt = entry->GetChar();

			strcpy(temp, root_txt);
			strtok(temp,White_Space);

			root_trans[i].x = atof(temp);
			root_trans[i].y = atof(NextToken());
			root_trans[i].z = atof(NextToken());

			++i;
		}
		entry = entry->GetNextEntry();
	}

	Unregister_Object(root_list);
	delete root_list;


	NameList *keyjoint_list = animation_file->MakeEntryList("KeyJointPos", "frame");
	Vector3D *keyjoint_trans;

	Logical key_used = False;

	if (keyjoint_list)
	{
		key_used = True;
		Register_Object(keyjoint_list);
		entry = keyjoint_list->GetFirstEntry();

		keyjoint_trans = new Vector3D[frame_count];
		Register_Pointer(keyjoint_trans);

		i = 0;


		while (entry != NULL)
		{
			if (entry->GetData())
			{
				char *keyjoint_txt = entry->GetChar();

				strcpy(temp, keyjoint_txt);
				strtok(temp,White_Space);

				keyjoint_trans[i].x = atof(temp);
				keyjoint_trans[i].y = atof(NextToken());
				keyjoint_trans[i].z = atof(NextToken());

				++i;
			}
			entry = entry->GetNextEntry();
		}

		Unregister_Object(keyjoint_list);
		delete keyjoint_list;

	}

	//
	// Take bottom 5% of scaling for foot_step
	//

	float foot_step = 0.0f;

	if (key_used)
	{
		float min_step = keyjoint_trans[0].y;
		float max_step = keyjoint_trans[0].y;

		for (i = 0; i < frame_count; ++i)
		{
			if (keyjoint_trans[i].y < min_step)
			{
				min_step = keyjoint_trans[i].y;
			}
			if (keyjoint_trans[i].y > max_step)
			{
				max_step = keyjoint_trans[i].y;
			}
		}

		if (min_step == max_step)
		{
			foot_step = min_step;
		}
		else
		{
			float diffrence = (float)max_step - (float)min_step;
			float percent = (float)diffrence * 0.20f;
			foot_step = (float)min_step + (float)percent;
		}
	}

	NameList *jointtype_list = animation_file->MakeEntryList("JointType");
	Register_Object(jointtype_list);
	entry = jointtype_list->GetFirstEntry();

	Joint::JointType *joint_type = new Joint::JointType[joint_count];
	Register_Pointer(joint_type);

	i = 0;


	while (entry != NULL)
	{
		if (entry->GetData())
		{
			char *keyjoint_txt = entry->GetChar();

			if (!stricmp(keyjoint_txt, "ball"))
			{
				joint_type[i] = Joint::BallJointType;
			}
			else if (!stricmp(keyjoint_txt, "hingex"))
			{
				joint_type[i] = Joint::HingeXJointType;
			}
			else if (!stricmp(keyjoint_txt, "hingey"))
			{
				joint_type[i] = Joint::HingeYJointType;
			}
			else if (!stricmp(keyjoint_txt, "hingez"))
			{
				joint_type[i] = Joint::HingeZJointType;
			}
			else if (!stricmp(keyjoint_txt, "balltranslate"))
			{
				joint_type[i] = Joint::BallTranslationJointType;
			}
			else if (!stricmp(keyjoint_txt, "static"))
			{
				std::cout << "No static joints allowed!" << std::endl;
					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
			}
			else
			{
					Dump(keyjoint_txt);
					std::cout << "Unrecognized Joint Type" << std::endl;
					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
			}

			++i;
		}
		entry = entry->GetNextEntry();
	}

	Unregister_Object(jointtype_list);
	delete(jointtype_list);


	//############################################################
	// Write Resource
	//############################################################


	int huge_honkin_array_size = sizeof(frame_count) + sizeof(joint_count);
	huge_honkin_array_size += sizeof(float);
	huge_honkin_array_size += (joint_count * sizeof(int));
	huge_honkin_array_size += (frame_count * sizeof(Scalar));

	// Change size for ball or hinge
	// or for ball translation


	//huge_honkin_array_size += joint_count * frame_count * sizeof(EulerAngles);


	for (i = 0; i < joint_count; ++i)
	{
//			Dump(i);
			if (joint_type[i] == Joint::BallJointType)
			{
				huge_honkin_array_size += (sizeof(EulerAngles) * frame_count);
			}
			else if (joint_type[i] == Joint::HingeXJointType)
			{
				huge_honkin_array_size += (sizeof(Hinge) * frame_count);
			}
			else if (joint_type[i] == Joint::HingeYJointType)
			{
				huge_honkin_array_size += (sizeof(Hinge) * frame_count);
			}
			else if (joint_type[i] == Joint::HingeZJointType)
			{
				 huge_honkin_array_size += (sizeof(Hinge) * frame_count);
			}
			else if (joint_type[i] == Joint::BallTranslationJointType)
			{
				 huge_honkin_array_size += (sizeof(EulerAngles) * frame_count);
				 huge_honkin_array_size += (sizeof(Vector3D) * frame_count);
			}
			else
			{
					Dump(joint_type[i]);
					std::cout << "Unknown Joint type" << std::endl;
					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
			}
	}

	huge_honkin_array_size += (frame_count * sizeof(Vector3D));

	// adjust for long's instead of chars

	huge_honkin_array_size += 3;
	size_t long_array_size = huge_honkin_array_size >> 2;

	long *huge_honkin_array = new long[long_array_size];
	Register_Pointer(huge_honkin_array);
	#if DEBUG_LEVEL>0
		long *end_of_array = huge_honkin_array + long_array_size;
	#endif
	EulerAngles *p = (EulerAngles *)huge_honkin_array;




	*(int*)p = frame_count;
	p = (EulerAngles *)((char *)p+sizeof(frame_count));

	*(int*)p = joint_count;
	p = (EulerAngles *)((char *)p+sizeof(joint_count));

	*(float*)p = foot_step;
	p = (EulerAngles *)((char *)p+sizeof(foot_step));

	for (i = 0; i < joint_count; ++i)
	{
		*(int*)p = joint_indices_numbers[i];
		p = (EulerAngles *)((char *)p+sizeof(joint_indices_numbers[i]));
	}

	for (i = 0; i < frame_count; ++i)
	{
		*(Scalar*)p = frame_time[i];
		p = (EulerAngles *)((char *)p+sizeof(frame_time[i]));
	}

//########################################################################
// THIS MUST CHANGE TO USE DIFFRENT JOINT TYPES
//


	keycounter = 0;
	for (i = 0; i < frame_count; ++i)
	{
		for (int j = 0; j < joint_count; ++j)
		{
			if (joint_type[j] == Joint::BallJointType)
			{
				*(EulerAngles*)p = keyframe[keycounter];
				p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter]));
			}
			else if (joint_type[j] == Joint::HingeXJointType)
			{
				Hinge hinge(X_Axis, keyframe[keycounter].pitch);
				*(Hinge*)p = hinge;
				p = (EulerAngles *)((char *)p+sizeof(hinge));
			}
			else if (joint_type[j] == Joint::HingeYJointType)
			{
				Hinge hinge(Y_Axis, keyframe[keycounter].yaw);
				*(Hinge*)p = hinge;
				p = (EulerAngles *)((char *)p+sizeof(hinge));
			}
			else if (joint_type[j] == Joint::HingeZJointType)
			{
				Hinge hinge(Z_Axis, keyframe[keycounter].roll);
				*(Hinge*)p = hinge;
				p = (EulerAngles *)((char *)p+sizeof(hinge));
			}
			else if (joint_type[j] == Joint::BallTranslationJointType)
			{
				*(EulerAngles*)p = keyframe[keycounter];
				p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter]));
				*(Vector3D*)p = keyjoint_trans[i];
				p = (EulerAngles *)((char *)p+sizeof(keyjoint_trans[i]));
			}

			++keycounter;
		}
	}

//
//
//#########################################################################


	for (i = 0; i < frame_count; ++i)
	{
		*(Vector3D*)p = root_trans[i];
		p = (EulerAngles *)((char *)p+sizeof(root_trans[i]));
	}

	Verify((void*)p == (void*)end_of_array);

	file->AddResource(
		animation_name,
		ResourceDescription::AnimationResourceType,
		1,
		ResourceDescription::Preload,
		huge_honkin_array,
		long_array_size * sizeof(long)
	);

	//---------------------
	//  Delete everything
	//---------------------

	for (i = 0; i < joint_count; ++i)
	{
		Unregister_Pointer(joint_indices[i]);
		delete[] joint_indices[i];
	}

	Unregister_Pointer(joint_type);
	Unregister_Pointer(joint_indices_numbers);
	Unregister_Pointer(joint_indices);
	Unregister_Pointer(keyframe);
	Unregister_Pointer(frame_time);
	Unregister_Pointer(root_trans);
	Unregister_Pointer(huge_honkin_array);
	delete[] joint_type;
	delete[] huge_honkin_array;
	delete[] joint_indices;
	delete[] joint_indices_numbers;
	delete[] keyframe;
	delete[] frame_time;
	delete[] root_trans;

   if (key_used)
	{
		Unregister_Pointer(keyjoint_trans);
		delete[] keyjoint_trans;
	}
	return True;
}


//#####################################################################

//
// This doesn't have the last frame...
//

Logical
	ApplicationTool::WriteAnimationTransition(
		NotationFile *animation_file,
		StreamableResourceFile *file,
		const char *animation_name
	)
{

	int frame_count;
	int joint_count;
	int i;

	if (!animation_file->GetEntry("HEADER", "framecount", &frame_count))
	{
		std::cout << "No framecount in HEADER for animation " << animation_name << std::endl;
		return False;
	}

	//animation_file->GetEntry("HEADER", "framerate", &frame_rate);

	if (!animation_file->GetEntry("HEADER", "jointcount", &joint_count))
	{
		std::cout << "No jointcount in HEADER for animation " << animation_name << std::endl;
		return False;
	}



	//animation_file->GetEntry("HEADER", "skeletonfile", &skeleton_file_name);




	char **joint_indices = new char *[joint_count];
	int *joint_indices_numbers = new int[joint_count];
   Register_Pointer(joint_indices_numbers);
	Register_Pointer(joint_indices);



	NameList *joint_list = animation_file->MakeEntryList("JointIndices");
	Register_Object(joint_list);
	NameList::Entry *entry = joint_list->GetFirstEntry();

	i = 0;
	while (entry != NULL)
	{
		if (entry->GetData())
		{
			joint_indices_numbers[i] = entry->GetAtoi();
			//Dump(entry->GetName());
			joint_indices[i] = new char[strlen(entry->GetName()) +2 ];
			Register_Pointer(joint_indices[i]);
			strcpy(joint_indices[i], entry->GetName());
			++i;
		}
		entry = entry->GetNextEntry();
	}


	Unregister_Object(joint_list);
	delete joint_list;


	Scalar *frame_time = new Scalar[frame_count];
	Register_Pointer(frame_time);

	NameList *frame_list = animation_file->MakeEntryList("Time", "frame");
	Register_Object(frame_list);
	entry = frame_list->GetFirstEntry();

	i = 0;

	while (entry != NULL)
	{
		if (entry->GetData())
		{
			frame_time[i] = entry->GetAtof();
			++i;
		}
		entry = entry->GetNextEntry();
	}



	Unregister_Object(frame_list);
	delete frame_list;



	char temp[100];
	const char *euler_txt;
	char page_name[100];

	NameList *page_list = animation_file->MakePageList("frame");
	Register_Object(page_list);
	entry = page_list->GetFirstEntry();

	EulerAngles *keyframe = new EulerAngles[joint_count*frame_count];
	Register_Pointer(keyframe);

	int keycounter = 0;

	while (entry != NULL)
	{
		if (entry->GetData())
		{
			strcpy(page_name, entry->GetName());

			for (int j = 0; j < joint_count; ++j)
			{
				if (!animation_file->GetEntry(page_name, joint_indices[j], &euler_txt))
				{
					std::cout << "No page for joint " << j << "in page " << page_name
					<< " - joint " << joint_indices[j] << std::endl;
					Unregister_Object(page_list);
					delete page_list;

					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
				}

				Verify(keycounter < joint_count*frame_count);

				strcpy(temp, euler_txt);
				strtok(temp,White_Space);


				keyframe[keycounter].pitch = atof(temp);
				keyframe[keycounter].yaw = atof(NextToken()) ;
				keyframe[keycounter].roll = atof(NextToken());
				++keycounter;
			}
		}
		entry = entry->GetNextEntry();

	 }
	Unregister_Object(page_list);
	delete page_list;


	NameList *root_list = animation_file->MakeEntryList("RootTranslation", "frame");
	Register_Object(root_list);
	entry = root_list->GetFirstEntry();

	Vector3D *root_trans = new Vector3D[frame_count];
	Register_Pointer(root_trans);

	i = 0;

	while (entry != NULL)
	{
		if (entry->GetData())
		{
			char *root_txt = entry->GetChar();

			strcpy(temp, root_txt);
			strtok(temp,White_Space);

			root_trans[i].x = atof(temp);
			root_trans[i].y = atof(NextToken());
			root_trans[i].z = atof(NextToken());

			++i;
		}
		entry = entry->GetNextEntry();
	}

	Unregister_Object(root_list);
	delete root_list;




	NameList *keyjoint_list = animation_file->MakeEntryList("KeyJointPos", "frame");
	Vector3D *keyjoint_trans;
	Logical key_used = False;

	if (keyjoint_list)
	{
		key_used = True;
		Register_Object(keyjoint_list);
		entry = keyjoint_list->GetFirstEntry();

		keyjoint_trans = new Vector3D[frame_count];
		Register_Pointer(keyjoint_trans);

		i = 0;

		while (entry != NULL)
		{
			if (entry->GetData())
			{
				char *keyjoint_txt = entry->GetChar();

				strcpy(temp, keyjoint_txt);
				strtok(temp,White_Space);

				keyjoint_trans[i].x = atof(temp);
				keyjoint_trans[i].y = atof(NextToken());
				keyjoint_trans[i].z = atof(NextToken());

				++i;
			}
			entry = entry->GetNextEntry();
		}

		Unregister_Object(keyjoint_list);
		delete keyjoint_list;
	}

	//
	// Take bottom 5% of scaling for foot_step
	//

	float foot_step = 0.0f;

	if (key_used)
	{
		float min_step = keyjoint_trans[0].y;
		float max_step = keyjoint_trans[0].y;

		for (i = 0; i < frame_count; ++i)
		{
			if (keyjoint_trans[i].y < min_step)
			{
				min_step = keyjoint_trans[i].y;
			}
			if (keyjoint_trans[i].y > max_step)
			{
				max_step = keyjoint_trans[i].y;
			}
		}

		if (min_step == max_step)
		{
			foot_step = min_step;
		}
		else
		{
			float diffrence = (float)max_step - (float)min_step;
			float percent = (float)diffrence * 0.20f;
			foot_step = (float)min_step + (float)percent;
		}
	}

	NameList *jointtype_list = animation_file->MakeEntryList("JointType");
	Register_Object(jointtype_list);
	entry = jointtype_list->GetFirstEntry();

	Joint::JointType *joint_type = new Joint::JointType[joint_count];
	Register_Pointer(joint_type);

	i = 0;


	while (entry != NULL)
	{
		if (entry->GetData())
		{
			char *keyjoint_txt = entry->GetChar();

			if (!stricmp(keyjoint_txt, "ball"))
			{
				joint_type[i] = Joint::BallJointType;
			}
			else if (!stricmp(keyjoint_txt, "hingex"))
			{
				joint_type[i] = Joint::HingeXJointType;
			}
			else if (!stricmp(keyjoint_txt, "hingey"))
			{
				joint_type[i] = Joint::HingeYJointType;
			}
			else if (!stricmp(keyjoint_txt, "hingez"))
			{
				joint_type[i] = Joint::HingeZJointType;
			}
			else if (!stricmp(keyjoint_txt, "balltranslate"))
			{
				joint_type[i] = Joint::BallTranslationJointType;
			}
			else if (!stricmp(keyjoint_txt, "static"))
			{
					std::cout << "No static joints allowed!" << std::endl;
					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
			}
			else
			{
					Dump(keyjoint_txt);
					std::cout << "Unrecognized Joint Type" << std::endl;
					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
			}

			++i;
		}
		entry = entry->GetNextEntry();
	}

	Unregister_Object(jointtype_list);
	delete(jointtype_list);


	//
	//  Adjust the frame_count down 1 so it won't write..
	//

	frame_count -= 1;


	int huge_honkin_array_size = sizeof(frame_count) + sizeof(joint_count);
	huge_honkin_array_size += sizeof(foot_step);
	huge_honkin_array_size += joint_count * sizeof(int);
	huge_honkin_array_size += frame_count * sizeof(Scalar);

		// Change size for ball or hinge
	// Don't need to change for ball translation since that
	// is already done

	//huge_honkin_array_size += joint_count * frame_count * sizeof(EulerAngles);

	for (i = 0; i < joint_count; ++i)
	{
//   	   Dump(i);
			if (joint_type[i] == Joint::BallJointType)
			{
				huge_honkin_array_size += sizeof(EulerAngles) * frame_count;
			}
			else if (joint_type[i] == Joint::HingeXJointType)
			{
				huge_honkin_array_size += sizeof(Hinge) * frame_count;
			}
			else if (joint_type[i] == Joint::HingeYJointType)
			{
				huge_honkin_array_size += sizeof(Hinge) * frame_count;
			}
			else if (joint_type[i] == Joint::HingeZJointType)
			{
				 huge_honkin_array_size += sizeof(Hinge) * frame_count;
			}
			else if (joint_type[i] == Joint::BallTranslationJointType)
			{
				 huge_honkin_array_size += sizeof(EulerAngles) * frame_count;
				 huge_honkin_array_size += sizeof(Vector3D) * frame_count;
			}
			else
			{
					Dump(joint_type[i]);
					std::cout << "Unknown Joint type" << std::endl;
					for (i = 0; i < joint_count; ++i)
					{
						Unregister_Pointer(joint_indices[i]);
						delete[] joint_indices[i];
					}
					Unregister_Pointer(joint_indices_numbers);
					Unregister_Pointer(joint_indices);
					Unregister_Pointer(keyframe);
					Unregister_Pointer(frame_time);
					delete[] joint_indices;
					delete[] joint_indices_numbers;
					delete[] keyframe;
					delete[] frame_time;

					return False;
			}
	}

	huge_honkin_array_size += (frame_count+1) * sizeof(Vector3D);
	// the plus one is so this DOES have last frame

	// adjust for long's instead of chars

	huge_honkin_array_size += 3;
	size_t long_array_size = huge_honkin_array_size >> 2;

	long *huge_honkin_array = new long[long_array_size];
	Register_Pointer(huge_honkin_array);
	#if DEBUG_LEVEL>0
		long *end_of_array = huge_honkin_array + long_array_size;
	#endif
	EulerAngles *p = (EulerAngles *)huge_honkin_array;

	*(int*)p = frame_count;
	p = (EulerAngles *)((char *)p+sizeof(frame_count));

	*(int*)p = joint_count;
	p = (EulerAngles *)((char *)p+sizeof(joint_count));

	*(float*)p = foot_step;
	p = (EulerAngles *)((char *)p+sizeof(foot_step));

	for (i = 0; i < joint_count; ++i)
	{
		*(int*)p = joint_indices_numbers[i];
		p = (EulerAngles *)((char *)p+sizeof(joint_indices_numbers[i]));
	}

	for (i = 0; i < frame_count; ++i)
	{
		*(Scalar*)p = frame_time[i];
		p = (EulerAngles *)((char *)p+sizeof(frame_time[i]));
	}


	keycounter = 0;
	for (i = 0; i < frame_count; ++i)
	{
		for (int j = 0; j < joint_count; ++j)
		{
			if (joint_type[j] == Joint::BallJointType)
			{
				*(EulerAngles*)p = keyframe[keycounter];
				p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter]));
			}
			else if (joint_type[j] == Joint::HingeXJointType)
			{
				Hinge hinge(X_Axis, keyframe[keycounter].pitch);
				*(Hinge*)p = hinge;
				p = (EulerAngles *)((char *)p+sizeof(hinge));
			}
			else if (joint_type[j] == Joint::HingeYJointType)
			{
				Hinge hinge(Y_Axis, keyframe[keycounter].yaw);
				*(Hinge*)p = hinge;
				p = (EulerAngles *)((char *)p+sizeof(hinge));
			}
			else if (joint_type[j] == Joint::HingeZJointType)
			{
				Hinge hinge(Z_Axis, keyframe[keycounter].roll);
				*(Hinge*)p = hinge;
				p = (EulerAngles *)((char *)p+sizeof(hinge));
			}
			else if (joint_type[j] == Joint::BallTranslationJointType)
			{
				*(EulerAngles*)p = keyframe[keycounter];
				p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter]));
				*(Vector3D*)p = keyjoint_trans[i];
				p = (EulerAngles *)((char *)p+sizeof(keyjoint_trans[i]));
			}

			++keycounter;
		}
	}

	for (i = 0; i < (frame_count + 1); ++i)
	{
		*(Vector3D*)p = root_trans[i];
		p = (EulerAngles *)((char *)p+sizeof(root_trans[i]));
	}



	Verify((void*)p == (void*)end_of_array);


	file->AddResource(
		animation_name,
		ResourceDescription::AnimationResourceType,
		1,
		ResourceDescription::Preload,
		huge_honkin_array,
		long_array_size * sizeof(long)
	);

	//---------------------
	//  Delete everything
	//---------------------

	for (i = 0; i < joint_count; ++i)
	{
		Unregister_Pointer(joint_indices[i]);
		delete[] joint_indices[i];
	}
	Unregister_Pointer(joint_type);
	Unregister_Pointer(joint_indices_numbers);
	Unregister_Pointer(joint_indices);
	Unregister_Pointer(keyframe);
	Unregister_Pointer(frame_time);
	Unregister_Pointer(root_trans);
	Unregister_Pointer(huge_honkin_array);
	delete[] joint_type;
	delete[] huge_honkin_array;
	delete[] joint_indices;
	delete[] joint_indices_numbers;
	delete[] keyframe;
	delete[] frame_time;
	delete[] root_trans;

	if (key_used)
	{
		Unregister_Pointer(keyjoint_trans);
		delete[] keyjoint_trans;
	}

	return True;
}
