
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Alien_PlayerAnimStateData.cpp
// Author : Will Plano
// Date   : 27/09/2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Include files...
////////////////////////////////////////////////////////////////////////////////

#include "Core/Asura.h"

// This file's header...
#include "Actor/Vertebrates/Alien/AVP_Alien_PlayerAnimStateData.h"

// Asura
#include "Blueprint/Asura_Blueprint_System.h"
#include "Core/Asura_Hash.h"
#include "Dynamics/Asura_Collision_Object.h"

// AVP
#include "Actor/AVP_Actor_AnimStateData.h"
#include "Blueprint/AVP_Blueprint_HashIDs.h"
#include "Core/AVP_Settings.h"
#include "Physics/AVP_Collision_Descriptor.h"

#ifdef ASURA_TOOLS
#include "Blueprint/ToolsAVP_Blueprint_AnimSpreadsheetExporter.h"
#endif

AVP_Alien_PlayerAnimStateData AVP_Alien_PlayerAnimStateData::s_xSingleton; 

#ifdef ASURA_TOOLS
static const char* g_aszFloor[ 2 ] =
{
	"_OnFloor",
	"_NonFloor",
};
#endif

static const char* const g_aszState[AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_END_NOAIM] =
{
	"",
	"Stand",
	"Jump",
	"Fall",
};

static const char* const g_szMove = "Move";

static const char* const g_aszSpeed[AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_END] = 
{
	"Idle",
	"Slow",
	"Medium",
	"Fast"
};


const AVP_Actor_AnimStateData* AVP_Alien_PlayerAnimStateData::GetAnimStateData( const Asura_Hash_ID uAnimStateBlueprintType, const bool bFirstPerson, const bool bOnFloor, bool bStanding, const bool bJumping, const bool bFalling, AVP_Vertebrate_PlayerAnimStateHandler::MovementSpeed eMoveSpeed )
{
#ifdef ASURA_TOOLS
	if ( !m_bInitialised )
	{
		Initialise( uAnimStateBlueprintType, AVP_Settings::IsMultiPlayer() );
	}
#endif
	Asura_Assert( m_bInitialised, "Alien state data not initialised, do characters or common need re-exporting?" );
	if ( !m_bInitialised )
	{
		return NULL;
	}

	Asura_Assert( bOnFloor || !bStanding, "No standing on the wall" );
	Asura_Assert( !bStanding || eMoveSpeed < AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_FAST, "No sprinting while standing" );

	if ((bJumping || bFalling) && (eMoveSpeed != AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_IDLE))
	{
		eMoveSpeed = AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_SLOW;
	}

	u_int uState;
	if (!bOnFloor)
	{
		uState = AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_BEGIN;
	}
	else if (bJumping)
	{
		uState = AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_JUMPING;
	}
	else if (bFalling)
	{
		uState = AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_FALLING;
	}
	else
	{
		uState = bStanding ? AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_ALTPOSTURE : AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_NORMAL;
	}

	return m_aaaapxAnimStateData[ bFirstPerson ? 0 : 1 ][ bOnFloor ? 0 : 1 ][ uState ][ eMoveSpeed ];
}

void AVP_Alien_PlayerAnimStateData::ResetStorage()	
{
	if ( m_bInitialised )
	{
		m_bInitialised = false;
		for ( u_int uHudItr = 0; uHudItr < 2; ++uHudItr )
		{
			for ( u_int uFloorItr = 0; uFloorItr < 2; ++uFloorItr )
			{
				for ( u_int uStateItr = 0; uStateItr < AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_END_NOAIM; ++uStateItr )
				{
					for ( u_int uSpeedItr = 0; uSpeedItr < AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_END; ++uSpeedItr  )
					{
						delete m_aaaapxAnimStateData[ uHudItr ][ uFloorItr ][ uStateItr ][ uSpeedItr ];
					}
				}
			}
		}
	}
}

#ifdef ASURA_TOOLS

void AVP_Alien_PlayerAnimStateData::Initialise( const Asura_Hash_ID uAnimStateBlueprintType, const bool bMultiplayer )
{
	if ( m_bInitialised )
	{
		return;
	}

	m_bInitialised = true;

	for ( u_int uHudItr = 0; uHudItr < 2; ++uHudItr )
	{
		for ( u_int uFloorItr = 0; uFloorItr < 2; ++uFloorItr )
		{
			const bool bHUDValid = uHudItr == 0 || bMultiplayer;
			Asura_String xStateBPName( uHudItr == 0 ? "HUD" : "ThirdPersonPlayer" );
			xStateBPName += g_aszFloor[ uFloorItr ];
			if ( ToolsAVP_Blueprint_AnimSpreadsheetExporter::IsActive() )
			{
				ToolsAVP_Blueprint_AnimSpreadsheetExporter::CreateFile( ( Asura_String( "Alien_" ) + xStateBPName + ".csv" ).GetString() );
			}
			const u_int uNumStates = uFloorItr == 0 ? GetNumStates() : 1;
			for ( u_int uStateItr = 0; uStateItr < AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_END_NOAIM; ++uStateItr )
			{
				const bool bStateValid = ( uStateItr < uNumStates );
				const Asura_Blueprint* pxStateBP = NULL;
				if ( bHUDValid && bStateValid )
				{
					pxStateBP = Asura_Blueprint_System::GetBlueprintByHashID( uAnimStateBlueprintType, xStateBPName.GetHash() );
					Asura_Assertf( pxStateBP, ( "Couldn't get alien state BP with hash 0x%08x", xStateBPName.GetHash() ) );
				}
				const u_int uNumSpeed = GetNumSpeeds(uStateItr);
				for ( u_int uSpeedItr = 0; uSpeedItr < AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_END; ++uSpeedItr )
				{
					const bool bSpeedValid = ( uSpeedItr < uNumSpeed );
					if ( bHUDValid && bStateValid && bSpeedValid && pxStateBP )
					{
						if ( uSpeedItr == AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_IDLE )
						{
							m_aaaapxAnimStateData[ uHudItr ][ uFloorItr ][ uStateItr ][ uSpeedItr ] = new AVP_Actor_AnimStateData_NonDirectional();
							m_aaaapxAnimStateData[ uHudItr ][ uFloorItr ][ uStateItr ][ uSpeedItr ]->InitialiseFromBlueprint( uAnimStateBlueprintType, *pxStateBP, GetStateDescription( uStateItr, uSpeedItr ).GetString(), true );
						}
						else
						{
							m_aaaapxAnimStateData[ uHudItr ][ uFloorItr ][ uStateItr ][ uSpeedItr ] = new AVP_Actor_AnimStateData_Directional();
							m_aaaapxAnimStateData[ uHudItr ][ uFloorItr ][ uStateItr ][ uSpeedItr ]->InitialiseFromBlueprint( uAnimStateBlueprintType, *pxStateBP, GetStateDescription( uStateItr, uSpeedItr ).GetString(), true );
						}
						if ( ToolsAVP_Blueprint_AnimSpreadsheetExporter::IsActive() && pxStateBP )
						{
							ToolsAVP_Blueprint_AnimSpreadsheetExporter::WriteState( GetStateDescription( uStateItr, uSpeedItr ).GetString(), m_aaaapxAnimStateData[ uHudItr ][ uFloorItr ][ uStateItr ][ uSpeedItr ], pxStateBP, uAnimStateBlueprintType );
						}
					}
					else
					{
						m_aaaapxAnimStateData[ uHudItr ][ uFloorItr ][ uStateItr ][ uSpeedItr ] = NULL;
					}
				} // end speed loop
			} // end state loop
		} // end floor loop
	} // end hud loop
}

#endif

const Asura_String AVP_Alien_PlayerAnimStateData::GetStateDescription( u_int uState, u_int uSpeed )
{
	Asura_Assert(uState < AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_END, "Invalid player anim state.");
	Asura_Assert(uSpeed < AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_END, "Invalid player anim direction.");

	const u_int uMaxState = AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_END - 1;
	const u_int uMaxSpeed = GetNumSpeeds( uState ) - 1;
	uState = Asura_Maths::Min(uState, uMaxState);
	uSpeed = Asura_Maths::Min(uSpeed, uMaxSpeed);
	Asura_String xRet( g_aszState[ uState ] );
	if ( uSpeed > AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_IDLE )
	{
		if ( !xRet.IsBlank() )
		{
			xRet += '.';
		}
		xRet += g_szMove;
	}
	if ( uSpeed == AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_IDLE || uMaxSpeed > AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_SLOW )
	{
		if ( !xRet.IsBlank() )
		{
			xRet += '.';
		}
		xRet += g_aszSpeed[ uSpeed ];
	}
	return xRet;
}

u_int AVP_Alien_PlayerAnimStateData::GetNumSpeeds( const u_int uState )
{
	switch (uState)
	{
	case AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_NORMAL:
		return AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_END;

	case AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_ALTPOSTURE:
		// Standing prevents sprinting.
		return AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_MEDIUM + 1;

	case AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_JUMPING:
	case AVP_Vertebrate_PlayerAnimStateHandler::MOVESTATE_FALLING:
		// Falling can only go slowly.
		return AVP_Vertebrate_PlayerAnimStateHandler::MOVESPEED_SLOW + 1;

	default:
		Asura_Assert(false, "Unexpected anim state for player alien.");
		return 1;
	}
}

/// End of file. ///
