
///////////////////////////////////////////////////////////////////////////////
//
// File   : AVP_Actor_InputHandler.h
// Author : Andy Tate
// Date   : 4-Oct-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_PRAGMA_ONCE
	#pragma once
#endif   // ifdef ASURA_USE_PRAGMA_ONCE

#ifndef __AVP_ACTOR_INPUTHANDLER_H__
#define __AVP_ACTOR_INPUTHANDLER_H__


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

#include "Blueprint/Asura_Blueprint.h"
#include "Blueprint/Asura_Blueprint_System.h"
#include "Core/Asura_Maths.h"
#include "Core/Asura_UserInput.h"
#include "Input/Asura_ControlMap.h"
#include "Network/Asura_Guid.h"

#define AVP_DEBUG_INPUT

////////////////////////////////////////////////////////////////////////////////
// Forward class declarations...
////////////////////////////////////////////////////////////////////////////////

class Asura_Message;
class AVP_ClientEntity_Actor;

////////////////////////////////////////////////////////////////////////////////
// Class declaration...
////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////
// Class        : AVP_Actor_InputHandler
// Author       : Andy Tate
// Date         : 4-Oct-2006
//
// Description  : Abstract class to handle input from a player which controls 
//				  a particular type of actor.
////////////////////////////////////////////////////////////////////////////////

class AVP_Actor_InputHandler
{
public:
	// Public enumerated types...
	enum ActorMappings
	{
		// Look mappings...
		LOOK_LEFT_RIGHT,
		LOOK_UP_DOWN,

		LOOK_MOUSE_LEFT_RIGHT,
		LOOK_MOUSE_UP_DOWN,

		// Movement mappings...
		FORWARDS_BACKWARDS,
		STRAFE_LEFT_RIGHT,

		END_OF_MOVE_AND_LOOK_KEYS,

		// Zoom mappings...
		ZOOM_IN = END_OF_MOVE_AND_LOOK_KEYS,
		ZOOM_OUT,
		ZOOM_HOLD,

		// Miscellaneous mappings...
		INTERACT,
		MENU_TOGGLE,
		OBJECTIVES_TOGGLE,
		FREEZE_TIME_TOGGLE,
#if defined(ASURA_DEBUG_VARIABLE_SYSTEM)
		DVS_TOGGLE,
#else
		SCOREBOARD,
#endif	// defined(ASURA_DEBUG_VARIABLE_SYSTEM)

		// Menu mappings...
		MENU_UP,
		MENU_DOWN,
		MENU_SELECT,
		SKIP_CUTSCENE,

		// Weapon mappings...
		SELECT_LAST_WEAPON,
		SELECT_NEXT_WEAPON,
		SELECT_PREVIOUS_WEAPON,

		// Vision Mode...
		VISION_SELECTOR_HOLD,
		VISION_SELECTOR_NEXT,
		VISION_SELECTOR_PREV,
		VISION_SELECTOR_SLOT_UP,
		VISION_SELECTOR_SLOT_DOWN,
		VISION_SELECTOR_SLOT_LEFT,
		VISION_SELECTOR_SLOT_RIGHT,
		
		//Selector
		WEAPON_SELECTOR_BEGIN,
		WEAPON_SELECTOR_END,
		WEAPON_SELECTOR_PREV,
		WEAPON_SELECTOR_NEXT,
		WEAPON_SELECTOR_HOLD,
		WEAPON_SELECTOR_SLOT_UP,
		WEAPON_SELECTOR_SLOT_UP_RIGHT,
		WEAPON_SELECTOR_SLOT_RIGHT,
		WEAPON_SELECTOR_SLOT_DOWN_RIGHT,
		WEAPON_SELECTOR_SLOT_DOWN,
		WEAPON_SELECTOR_SLOT_DOWN_LEFT,
		WEAPON_SELECTOR_SLOT_LEFT,
		WEAPON_SELECTOR_SLOT_UP_LEFT,

		// NB any new additions should be added above this line
		// KEEP BELOW THE LAST TWO ENTRIES

#if defined(ASURA_USE_TEXTURE_STREAMING)
		// Test/demoing commands, not to be used in the final game.
		STREAMINGTEXTURES_TOGGLEDELAY,
		STREAMINGTEXTURES_UNLOADALL,
#endif	//defined(ASURA_USE_TEXTURE_STREAMING)

		// Total...
		MAX_ACTOR_MAPPINGS
	};

#if defined(AVP_ALLOW_DEBUG_MOVEMENT)
	enum MovementType
	{
		MT_PLAYER_THIRD_PERSON,
		MT_PLAYER_FIRST_PERSON,
		MT_FLYING_PLAYER_COLLISIONS,
		MT_FLYING_PLAYER_NO_COLLISIONS,
		MT_FLYING_CAMERA,

		MAX_MOVEMENT_TYPES
	};
#endif	// defined(AVP_ALLOW_DEBUG_MOVEMENT)

	// Public functions...
	virtual ~AVP_Actor_InputHandler ();

	// Virtual functions...
 	virtual	void			Reset			(void);

	virtual	Asura_Message*	Update			( AVP_ClientEntity_Actor& xClient );
#if defined(AVP_ALLOW_DEBUG_MOVEMENT)
	virtual	void			RenderDebugInfo	(void) const;
#endif	// defined(AVP_ALLOW_DEBUG_MOVEMENT)

	// Accessor functions...
	const Asura_Vector_3&	GetMovementInput() const { return m_xMovementInput; }

	float					GetControlMapValue	(const u_int uMapping, const bool bAllowConditions = true, const bool bConsumeKeypress = false) const;

//	void					SetGrappleControls(bool bSet);
	void					PushControls( Asura_ControlMap* pxControlMap );
	void 					PopControls();

	Asura_ControlMap&		GetMapFirstPerson(void)		{ return m_xMapFirstPerson; }
	Asura_ControlMap&		GetMapVisionSelector(void)	{ return m_xMapVisionSelector; }
	Asura_ControlMap&		GetMapCutscene(void)		{ return m_xMapCutscene; }

#if defined(AVP_ALLOW_DEBUG_MOVEMENT)
	static MovementType	GetMovementType	(void)					{ return(s_eMovementType); }

	static void			SetMovementType	(MovementType eType);

	static void			SetMovementType	(u_int uType)			{  SetMovementType(static_cast<MovementType>(uType)); }
	static void			SetMovementType	(int iType)				{  SetMovementType(static_cast<MovementType>(iType)); }

#endif	// defined(AVP_ALLOW_DEBUG_MOVEMENT)

	// Mapping creation functions...
	virtual void MapMovementAxes(Asura_ControlMap& xMap, const u_int uAxisForwardsBackwards, const u_int uAxisStrafeLeftRight, const u_int uKeySlow, const u_int uKeyFast, const u_int uKeyStanceToggle);
	virtual void MapMovementKeys(Asura_ControlMap& xMap, const u_int uKeyForwards, const u_int uKeyBackwards, const u_int uKeyStrafeLeft, const u_int uKeyStrafeRight, const u_int uKeySlow, const u_int uKeyFast, const u_int uKeyStanceToggle);
	virtual void MapWeaponSelect(Asura_ControlMap& xMap, const u_int uKeyUp, const u_int uKeyDown, const u_int uKeyLeft, const u_int uKeyRight);
	virtual void MapWeaponSelect(Asura_ControlMap& xMap, const u_int uKeyUp, const u_int uKeyUpRight, const u_int uKeyRight, const u_int uKeyDownRight, const u_int uKeyDown, const u_int uKeyDownLeft, const u_int uKeyLeft, const u_int uKeyUpLeft);

	virtual void MapVision(Asura_ControlMap& xMap, const u_int uKeyHold, const u_int uKeyNext, const u_int uKeyPrev);
	virtual void MapVisionSelect(Asura_ControlMap& xMap, const u_int uKeyUp, const u_int uKeyDown, const u_int uKeyLeft, const u_int uKeyRight );
	
	virtual void MapLookAxes(Asura_ControlMap& xMap, const u_int uAxisLeftRight, const u_int uAxisUpDown);
	virtual void MapLookKeys(Asura_ControlMap& xMap, const u_int uKeyUp, const u_int uKeyDown, const u_int uKeyLeft, const u_int uKeyRight);
	virtual void MapLookMouse(Asura_ControlMap& xMap);
	virtual void MapZoom(Asura_ControlMap& xMap, const u_int uKeyUp, const u_int uKeyDown, const u_int uKeyChange);
	virtual void MapInteract(Asura_ControlMap& xMap, const u_int uKeyInteract, float fDelayTime=0.0f );
	virtual void MapCutscene(Asura_ControlMap& xMap, const u_int uKey1, const u_int uKey2 = ASURA_KEYID_VOID, const u_int uKey3 = ASURA_KEYID_VOID, const u_int uKey4 = ASURA_KEYID_VOID, const u_int uKey5 = ASURA_KEYID_VOID);
	virtual void MapMenuToggle(Asura_ControlMap& xMap, const u_int uKey);
	virtual void MapObjectivesAndSelectToggle(Asura_ControlMap& xMap, const u_int uKey1, const u_int uKey2);
	virtual void MapFreezeTime(Asura_ControlMap& xMap, const u_int uKey);
	
	virtual void RefreshBlueprintData(void);

	virtual bool IsIdle() const;

	virtual void AddRecoilVelocity( Asura_Euler_3 xRecoilVel ) {}

protected:
	// Protected variables...
#if defined(AVP_ALLOW_DEBUG_MOVEMENT)
	static MovementType		s_eMovementType;		// The type of movement to be used for this actor.
#endif	// defined(AVP_ALLOW_DEBUG_MOVEMENT)

	Asura_Guid				m_uOwnerGuid;				// The Guid of the actor who owns this handler.
	Asura_Euler_3			m_xLookOrientationInput;	// The orientation input.
	Asura_Vector_3			m_xMovementInput;			// The direction of input.
	static float			s_fSavedTimeScale;
	float					m_fTurboTimer;

	Asura_ControlMap		m_xMapFirstPerson;		// Control map for first person input
	Asura_ControlMap		m_xMapVisionSelector;	// Control map for vision mode selector
	Asura_ControlMap		m_xMapCutscene;			// Control map for cutscene input

	Asura_ControlMap*		m_pxCurrentControlMap;	// A pointer to the current control-map.

	// Protected functions...
	AVP_Actor_InputHandler (const Asura_Guid uOwnerGuid, const u_int uMaxMappings);

	virtual void			UpdateLookInput		( AVP_ClientEntity_Actor& xClient, const float fTiltMaxSpeed, const float fTurnMaxSpeed, const float fInnerAimAssistMultiplier, const float fOuterAimAssistMultiplier, const float fTanLookAssistHalfAngle, const float fLookAssistHorizontalMaxSpeed, const float fLookAssistVerticalMaxSpeed ) = 0;
	virtual void			UpdateMovementInput	( AVP_ClientEntity_Actor& xClient ) = 0;

	// Abstract functions...
	virtual void			UpdateMovement						( AVP_ClientEntity_Actor& xClient )			= 0;
	virtual void			UpdateWeapons						( AVP_ClientEntity_Actor& xClient )			= 0;
	virtual void			UpdateVisionModes					( AVP_ClientEntity_Actor& xClient )			= 0;
	virtual	Asura_Message*	CreatePlayerCommandMessageToServer	( const AVP_ClientEntity_Actor& xClient ) const	= 0;

private:
	// Private variables...
	union
	{
		u_int	m_uFlags;					// Single accessor to cover all flags.

		struct
		{
			u_int	m_bInvertedLook	: 1,	// Flag to specify whether we invert the look.
									: 0;	// 31 spare-bits
		};
	};

#if defined(ASURA_SUPPORT_COMMAND_CONSOLE) && defined (AVP_DEBUG_INPUT)
		static u_int s_uConsoleVarReferenceCount;
#endif

	static bool s_bStreamingTextureDelayActive;

	// Private functions...
	AVP_Actor_InputHandler (void);
	AVP_Actor_InputHandler (const AVP_Actor_InputHandler& xOther);

	AVP_Actor_InputHandler&	operator=	(const AVP_Actor_InputHandler& xOther);

	void Platform_RefreshTurnAndTiltParams( const Asura_Blueprint* pxBlueprint );

	// console variables, used to be global, but now are needed cross platform so were moved into the class. 
	static float s_fInnerAimAssistMultiplier;
	static float s_fOuterAimAssistMultiplier;
	static float s_fLookAssistAngleInDegree;
	static float s_fLookAssistHorizontalMaxSpeedInDegree;
	static float s_fLookAssistVerticalMaxSpeedInDegree;
	static float s_fMouseVSensitivity;
	static float s_fMouseHSensitivity;

	static float s_fTiltMaxSpeedInDegree;
	static float s_fTiltRampUpTime;
	static float s_fTiltRampDownTime;
	static float s_fTiltExponent;

	static float s_fTurnDefaultMaxSpeedInDegree;
	static float s_fTurnTurboMaxSpeedInDegree;
	static float s_fTurnTurboDelay;
	static float s_fTurnTurboRampUpTime;
	static float s_fTurnRampUpTime;
	static float s_fTurnRampDownTime;
	static float s_fTurnExponent;

	static float s_fTanLookAssistHalfAngleInRadian;	// Radian Degree
	static float s_fLookAssistHorizontalMaxSpeedInRadian;
	static float s_fLookAssistVerticalMaxSpeedInRadian;
	static float s_fTiltMaxSpeedInRadian;
	static float s_fTurnDefaultMaxSpeedInRadian;
	static float s_fTurnTurboMaxSpeedInRadian;
};   // End of class 'AVP_Actor_InputHandler'.

#endif   // ifndef __AVP_ACTOR_INPUTHANDLER_H__

/// End of file. ///
