
//////////////////////////////////////////////////////////////////////////////
//
// Asura_Project_Skin_Elements.cpp
//
// Copyright (c) 2006 Rebellion. All rights reserved.
//
// Defines the list of supported sub-elements (chunks) for projects using
// ASURA_SUPPORT_SKIN_ELEMENTS
//
//////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

#include "Rendering/Asura_Project_Skin_Elements.h"

#include "Mesh/Asura_Mesh.h"
#include "Debugging/Asura_Assert.h"

#ifdef ASURA_SUPPORT_SKIN_ELEMENTS

const char* Asura_Project_Skin_Elements::s_aszElementNames[NUM_AVP_SKIN_ELEMENT_TYPES]=
{
	"Upper Right Leg",		//AVP_SET_RIGHT_LEG,
	"Lower Right Leg",		//AVP_SET_RIGHT_KNEE,
	"Upper Left Leg",		//AVP_SET_LEFT_LEG,
	"Lower Left Leg",		//AVP_SET_LEFT_KNEE,
	"Upper Right Arm",		//AVP_SET_RIGHT_ARM,
	"Lower Right Arm",		//AVP_SET_RIGHT_ELBOW,
	"Upper Left Arm",		//AVP_SET_LEFT_ARM,
	"Lower Left Arm",		//AVP_SET_LEFT_ELBOW,
	"Alien Pipes Left",		//AVP_SET_ALIEN_PIPES_TL,
	"Alien Pipes Right",	//AVP_SET_ALIEN_PIPES_TR,
	"Alien Tail Tip",		//AVP_SET_ALIEN_TAIL_TIP,
	"Alien Tail",			//AVP_SET_ALIEN_TAIL,
	"Alien Face",			//AVP_SET_ALIEN_FACE,
	"Head",					//AVP_SET_HEAD,
	"Pelvis",				//AVP_SET_BODY,
	"Head After Headbite",	//AVP_SET_HEAD_AFTER_HEADBITE,
	"Alien Inner Mouth",	//AVP_SET_ALIEN_INNER_MOUTH,
};

const char* Asura_Project_Skin_Elements::s_aszElementTypes[TOTAL_AVP_SKIN_ELEMENTS]=
{
	"default",

	"legstump_right",			//AVP_SET_RIGHT_LEG,
	"leg_right",				//AVP_SET_RIGHT_LEG,
	"kneestump_right",			//AVP_SET_RIGHT_KNEE,
	"knee_right",				//AVP_SET_RIGHT_KNEE,
	"legstump_left",			//AVP_SET_LEFT_LEG,
	"leg_left",					//AVP_SET_LEFT_LEG,
	"kneestump_left",			//AVP_SET_LEFT_KNEE,
	"knee_left",				//AVP_SET_LEFT_KNEE,
	"armstump_right",			//AVP_SET_RIGHT_ARM,
	"arm_right",				//AVP_SET_RIGHT_ARM,
	"elbowstump_right",			//AVP_SET_RIGHT_ELBOW,
	"elbow_right",				//AVP_SET_RIGHT_ELBOW,
	"armstump_left",			//AVP_SET_LEFT_ARM,
	"arm_left",					//AVP_SET_LEFT_ARM,
	"elbowstump_left",			//AVP_SET_LEFT_ELBOW,
	"elbow_left",				//AVP_SET_LEFT_ELBOW,
	"alien_pipe_stump_left",	//AVP_SET_ALIEN_PIPES_TL,
	"alien_pipe_left",			//AVP_SET_ALIEN_PIPES_TL,
	"alien_pipe_stump_right",	//AVP_SET_ALIEN_PIPES_TR,
	"alien_pipe_right",			//AVP_SET_ALIEN_PIPES_TR,
	"alien_tailtipstump",		//AVP_SET_ALIEN_TAIL_TIP,
	"alien_tailtip",			//AVP_SET_ALIEN_TAIL_TIP,
	"alien_tailstump",			//AVP_SET_ALIEN_TAIL,
	"alien_tail",				//AVP_SET_ALIEN_TAIL,
	"alien_facestump",			//AVP_SET_ALIEN_FACE,
	"alien_face",				//AVP_SET_ALIEN_FACE,
	"headstump",				//AVP_SET_HEAD,
	"head",						//AVP_SET_HEAD,
	"bodystump",				//AVP_SET_BODY,
	"body",						//AVP_SET_BODY,
	"head_after_headbite",		//AVP_SET_HEAD_AFTER_HEADBITE,
	"head_before_headbite",		//AVP_SET_HEAD_AFTER_HEADBITE,
	"alien_innermouthstump",	//AVP_SET_ALIEN_INNER_MOUTH,
	"alien_innermouth",			//AVP_SET_ALIEN_INNER_MOUTH,
};

bool Asura_Project_Skin_Elements::s_abCurrentToolsElementVisibility[TOTAL_AVP_SKIN_ELEMENTS]=
{
	// Show un-injured state by default
	true,		// "default",

	false,		//"legstump_right",		
	true,		//"leg_right",			
	false,		//"kneestump_right",		
	true,		//"knee_right",			
	false,		//"legstump_left",		
	true,		//"leg_left",				
	false,		//"kneestump_left",		
	true,		//"knee_left",			
	false,		//"armstump_right",		
	true,		//"arm_right",			
	false,		//"elbowstump_right",		
	true,		//"elbow_right",			
	false,		//"armstump_left",		
	true,		//"arm_left",				
	false,		//"elbowstump_left",		
	true,		//"elbow_left",			
	false,		//"alien_pipe_stump_left",		
	true,		//"alien_pipe_left",		
	false,		//"alien_pipe_stump_right",		
	true,		//"alien_pipe_right",	
	false,		//"alien_tailtipstump",	
	true,		//"alien_tailtip",		
	false,		//"alien_tailstump",		
	true,		//"alien_tail",			
	false,		//"alien_facestump",		
	true,		//"alien_face",			
	false,		//"headstump",			
	true,		//"head",					
	false,		//"bodystump",			
	true,		//"body",					
	false,		//"head_after_headbite",			
	true,		//"head_before_headbite",					
	false,		//"alien_innermouthstump",
	true,		//"alien_innermouth",	
};

bool Asura_Project_Skin_Elements::s_abDefaultElementVisibility[TOTAL_AVP_SKIN_ELEMENTS]=
{
	// Show un-injured state by default
	true,		// "default",

	false,		//"legstump_right",		
	true,		//"leg_right",			
	false,		//"kneestump_right",		
	true,		//"knee_right",			
	false,		//"legstump_left",		
	true,		//"leg_left",				
	false,		//"kneestump_right",		
	true,		//"knee_right",			
	false,		//"armstump_right",		
	true,		//"arm_right",			
	false,		//"elbowstump_right",		
	true,		//"elbow_right",			
	false,		//"armstump_left",		
	true,		//"arm_left",				
	false,		//"elbowstump_left",		
	true,		//"elbow_left",			
	false,		//"alien_pipe_stump_left",		
	true,		//"alien_pipe_left",		
	false,		//"alien_pipe_stump_right",		
	true,		//"alien_pipe_right",		
	false,		//"alien_tailtipstump",	
	true,		//"alien_tailtip",		
	false,		//"alien_tailstump",		
	true,		//"alien_tail",			
	false,		//"alien_facestump",		
	true,		//"alien_face",			
	false,		//"headstump",			
	true,		//"head",					
	false,		//"bodystump",			
	true,		//"body",		
	false,		//"head_after_headbite",			
	true,		//"head_before_headbite",					
	false,		//"alien_innermouthstump",
	true,		//"alien_innermouth",	
};

const Asura_Hash_ID Asura_Project_Skin_Elements::s_auElementBlueprintParameters[NUM_AVP_SKIN_ELEMENT_TYPES] =
{
	0xF92E6CAD,	//Asura_GetHashID("SkinElementLegRight")			//AVP_SET_RIGHT_LEG,
	0xBFC98EBA,	//Asura_GetHashID("SkinElementKneeRight")			//AVP_SET_RIGHT_KNEE,
	0x7BA3DF56,	//Asura_GetHashID("SkinElementLegLeft")				//AVP_SET_LEFT_LEG,
	0x6945C7A9,	//Asura_GetHashID("SkinElementKneeLeft")			//AVP_SET_LEFT_KNEE,
	0x3C6F951F,	//Asura_GetHashID("SkinElementArmRight")			//AVP_SET_RIGHT_ARM,
	0x39898058,	//Asura_GetHashID("SkinElementElbowRight")			//AVP_SET_RIGHT_ELBOW,
	0x4C42E0A4,	//Asura_GetHashID("SkinElementArmLeft")				//AVP_SET_LEFT_ARM,
	0xE9122A4B,	//Asura_GetHashID("SkinElementElbowLeft")			//AVP_SET_LEFT_ELBOW,
	0xE3ADD20D,	//Asura_GetHashID("SkinElementPipesLeft")			//AVP_SET_ALIEN_PIPES_LEFT,
	0x9262D0D6,	//Asura_GetHashID("SkinElementPipesRight")			//AVP_SET_ALIEN_PIPES_RIGHT,
	0x1C1EBE8C,	//Asura_GetHashID("SkinElementTailTip")				//AVP_SET_ALIEN_TAIL_TIP,
	0x8F7A9E53,	//Asura_GetHashID("SkinElementTailUpper")			//AVP_SET_ALIEN_TAIL,
	0x0F89D1BC,	//Asura_GetHashID("SkinElementFace")				//AVP_SET_ALIEN_FACE,
	0x0F8AC93F,	//Asura_GetHashID("SkinElementHead")				//AVP_SET_HEAD,
	0x0F883501,	//Asura_GetHashID("SkinElementBody")				//AVP_SET_BODY,
	0xC69EE1D5,	//Asura_GetHashID("SkinElementHeadAfterHeadbite")	//AVP_SET_HEAD_AFTER_HEADBITE,
	0xF7FC2C50,	//Asura_GetHashID("SkinElementInnerMouth")			//AVP_SET_ALIEN_INNER_MOUTH,
};

int Asura_Project_Skin_Elements::GetNumElementTypes()
{
	return TOTAL_AVP_SKIN_ELEMENTS;
}

int Asura_Project_Skin_Elements::GetNumElementNames()
{
	return NUM_AVP_SKIN_ELEMENT_TYPES;
}


const char **Asura_Project_Skin_Elements::GetElementTypeNames(void)
{
	return s_aszElementTypes;
}

const char **Asura_Project_Skin_Elements::GetElementNames(void)
{
	return s_aszElementNames;
}

bool Asura_Project_Skin_Elements::IsElementVisible(int iIndex, int iUserData)
{
	return s_abCurrentToolsElementVisibility[iIndex];
};

void Asura_Project_Skin_Elements::ToggleElementVisibility(int iIndex, int iUserData)
{
	s_abCurrentToolsElementVisibility[iIndex]=!s_abCurrentToolsElementVisibility[iIndex];
};

bool Asura_Project_Skin_Elements::GetDefaultElementVisibility(int iIndex)
{
	return s_abDefaultElementVisibility[iIndex];
};

u_int Asura_Project_Skin_Elements::GetParentElementType(u_int uElementType)
{
	switch( uElementType )
	{
		case AVP_SET_RIGHT_KNEE:
			return AVP_SET_RIGHT_LEG;

		case AVP_SET_LEFT_KNEE:
			return AVP_SET_LEFT_LEG;

		case AVP_SET_RIGHT_ELBOW:
			return AVP_SET_RIGHT_ARM;

		case AVP_SET_LEFT_ELBOW:
			return AVP_SET_LEFT_ARM;

		case AVP_SET_ALIEN_TAIL_TIP:
			return AVP_SET_ALIEN_TAIL;

		case AVP_SET_ALIEN_FACE:
		case AVP_SET_HEAD_AFTER_HEADBITE: // If the head gets destroyed, make sure we ditch the headbite hole polys too.
			return AVP_SET_HEAD;

		case AVP_SET_RIGHT_LEG:
		case AVP_SET_LEFT_LEG:
		case AVP_SET_ALIEN_PIPES_LEFT:
		case AVP_SET_ALIEN_PIPES_RIGHT:
		case AVP_SET_ALIEN_TAIL:
			return AVP_SET_BODY;

		case AVP_SET_ALIEN_INNER_MOUTH:
			return(AVP_SET_ALIEN_FACE);

		case AVP_SET_RIGHT_ARM:
		case AVP_SET_LEFT_ARM:
		case AVP_SET_HEAD:
		case AVP_SET_BODY:
		default:
			return NUM_AVP_SKIN_ELEMENT_TYPES;
	}
}

bool Asura_Project_Skin_Elements::IsChildOfElement(u_int uTestElement, u_int uParentElement, bool bRecursive)
{
	if (uTestElement == uParentElement) { return false; } // An element cannot be its own child.

	if (!bRecursive)
	{
		return GetParentElementType(uTestElement) == uParentElement;
	}
	else
	{
		u_int uCurrent = GetParentElementType(uTestElement);
		while (uCurrent != NUM_AVP_SKIN_ELEMENT_TYPES)
		{
			if (uCurrent == uParentElement) { return true; }

			uCurrent = GetParentElementType(uCurrent);
		}

		return false;
	}
}

void  Asura_Project_Skin_Elements::PackElementIDIntoPolyFlags(u_int *puFlags, int iElementIndex)
{
	// We're using the top 5 bits of the 8 project-specific bits, leaving 3 bits
	// free for project-specific flags
	if (iElementIndex>=0 && iElementIndex<=255)
	{	
		*puFlags = *puFlags & ~AsuraPolygonFlag_ProjectSpecificFlags;
		*puFlags += (iElementIndex << 8);
	}
	else
	{
		Asura_Assert(false, "Element index out of range!");
	}
}


int   Asura_Project_Skin_Elements::UnpackElementIDFromPolyFlags(u_int uFlags)
{
	// Extract the 5 bits that we're using.
	return ((uFlags & AsuraPolygonFlag_ProjectSpecificFlags) >> 8);
}


int  Asura_Project_Skin_Elements::AllocateDefaultVisibilityFlags(Asura_Animation *pxAnim, bool **ppbFlags)
{
	// (Todo: Use pxAnim to determine which type of skin this is)

	int iNumElements = GetNumElementTypes();
	*ppbFlags = new bool[iNumElements];

	if (*ppbFlags)
	{
		for(int i=0; i<iNumElements; i++)
		{		
			(*ppbFlags)[i]= GetDefaultElementVisibility(i);
		}
		return iNumElements;
	}
	else
	{
		// If mem allocation fails
		return 0;
	}
};	

#endif // ASURA_SUPPORT_SKIN_ELEMENTS


/// End of file. ///
