#ifdef ASURA_USE_ANIMATION_IK_SOLVER

///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_Animation_IK_Chain_LOS.h
// Author : Will Plano
// Date   : 24/08/2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
#pragma once
#endif

#ifndef __ASURA_ANIMATION_IK_CHAIN_LOS_H__
#define __ASURA_ANIMATION_IK_CHAIN_LOS_H__

#include "Animation/IK/Asura_Animation_IK_Chain.h"

#include "Core/Asura_LOS.h"
#include "Network/Asura_Guid.h"

class Asura_Animation;
class Asura_Entity_Renderable;

////////////////////////////////////////////////////////////////////////////////
// Class  : Asura_Animation_IK_Chain_LOS
// Author : Will Plano
// Date   : 24/08/2007
//
// Description  : Line of sight implementation of IK chain
////////////////////////////////////////////////////////////////////////////////

class Asura_Animation_IK_Chain_LOS : public Asura_Animation_IK_Chain
{
public:
	Asura_Animation_IK_Chain_LOS( const u_int uNumBones = 0, const Asura_AVector3& xLocalLOSDirection = Asura_Maths::ZeroAVector3 );
	Asura_Animation_IK_Chain_LOS( const int* piBoneIDs, const int* piTwistBoneIDs = NULL, const Asura_AVector3& xLocalLOSDirection = Asura_Maths::ZeroAVector3 );
	~Asura_Animation_IK_Chain_LOS();

	void SetLocalLOSDirection( const Asura_AVector3& xLocalLOSDirection ) { m_xLOSDirection = xLocalLOSDirection; m_bLosDirectionInObjectSpace = true; }
	void SetWorldSpaceLOSDirection( const Asura_AVector3& xWorldSpaceLOSDirection ) { m_xLOSDirection = xWorldSpaceLOSDirection; m_bLosDirectionInObjectSpace = false; }
	void SetTestAgainstEverything( const Asura_Guid uEntityToIgnore ) { m_xLOSInputData.m_uEntityToIgnore = uEntityToIgnore; m_bTestAgainstEverything = true; }
	void SetExclusionLists( const u_int uNumClassificationExceptions = 0, const u_short* ausClassification = NULL, const u_int uNumGuidExceptions = 0, const Asura_Guid* auGuid = NULL ) { m_xExclusionFunctor.SetExclusionLists( uNumClassificationExceptions, ausClassification, uNumGuidExceptions, auGuid ); }
	void SetLOSFlags( const u_int uFlagsToIgnore = AsuraPolygonFlag_IgnoreForIK, const u_int uFlagsToTestFor = UINT_MAX ) { m_xLOSInputData.m_uPolyFlagsToIgnore; m_xLOSInputData.m_uPolyFlagsToTestFor = uFlagsToTestFor; }

	const Asura_LOS_InputData& GetLOSInputData() const { return m_xLOSInputData; }
	const Asura_LOS_OutputData& GetLOSOutputData() const { return m_xLOSOutputData; }
	u_int GetLOSDataFrameStamp() const { return m_uLOSDataFrameStamp; }

#if defined(ASURA_SUPPORT_COMMAND_CONSOLE) && defined(ASURA_DEBUG_VARIABLE_SYSTEM)
	static void AddConsoleVars();
#endif

protected:
	virtual bool CalculateTarget();

private:
	typedef Asura_Animation_IK_Chain PARENT;

	class ExceptionFunctor
	{
	public:
		ExceptionFunctor( Asura_LOS_OutputData& xOutputData ) : m_rxOutData( xOutputData ), m_uNumClassificationExceptions( 0 ), m_ausClassification( NULL ), m_uNumGuidExceptions( 0 ), m_auGuid( NULL ) {}
		void SetExclusionLists( const u_int uNumClassificationExceptions, const u_short* ausClassification, const u_int uNumGuidExceptions, const Asura_Guid* auGuid ) { m_uNumClassificationExceptions = uNumClassificationExceptions; m_ausClassification = ausClassification; m_uNumGuidExceptions = uNumGuidExceptions; m_auGuid = auGuid; }

		bool CheckEntity( Asura_Entity_Renderable* pxEntity, const Asura_LOS_InputData& xInputData );
		float GetInitialMaxDistance() { return m_rxOutData.m_fDistanceToIntersection; }
		float GetMaxDistance() { return m_rxOutData.m_fDistanceToIntersection; }
		bool ShouldStop() { return false; }

	private:
		Asura_LOS_OutputData&	m_rxOutData;
		u_int					m_uNumClassificationExceptions;
		const u_short*			m_ausClassification;
		u_int					m_uNumGuidExceptions;
		const Asura_Guid*		m_auGuid;
	} m_xExclusionFunctor;

	Asura_AVector3					m_xLOSDirection;
	bool							m_bTestAgainstEverything;
	bool							m_bLosDirectionInObjectSpace;

	Asura_LOS_InputData				m_xLOSInputData; // cached for external use in project code
	Asura_LOS_OutputData			m_xLOSOutputData;
	u_int							m_uLOSDataFrameStamp;

}; // end class Asura_Animation_IK_Chain_LOS

#endif   // ifndef __ASURA_ANIMATION_IK_CHAIN_LOS_H__

#endif // ASURA_USE_ANIMATION_IK_SOLVER

/// End of file. ///
