
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_ControlMapping_Axis.cpp
// Author : Andy Tate
// Date   : 1-Dec-2005
//
// Copyright (C) 2005 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

// This file's header...
#include "Input/Asura_ControlMapping_Axis.h"

// Asura independent header-files...
#include "Core/Asura_Maths.h"
#include "Core/Asura_Timers.h"
#ifdef ASURA_USE_NEW_INPUT
#include "Input/Asura_ControlMap.h"
#include "Input/Asura_Input.h"
#else
#include "Core/Asura_UserInput.h"
#endif


////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_ControlMapping_Axis::Asura_ControlMapping_Axis
// Author       : Andy Tate
// Date         : 1-Dec-2005
//
// Description  : Constructor function for the axis control-mapping.
//
// Parameters   : The ID of the axis to use and the scale to apply to the result
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_USE_NEW_INPUT
Asura_ControlMapping_Axis::Asura_ControlMapping_Axis (const u_int uPositiveID,
													  const u_int uNegativeID, 
#else
Asura_ControlMapping_Axis::Asura_ControlMapping_Axis (const int iAxisID, 
#endif
													  const float fScale,
													  const float fResponseTime,
													  const float fDecayTime,
													  const ASURA_CONTROLMAPPING_AXIS_MASK eSection,
													  const float fExponent)
: Asura_ControlMapping(fScale)
#ifdef ASURA_USE_NEW_INPUT
, m_uPositiveID(uPositiveID)
, m_uNegativeID(uNegativeID)
#else
, m_iAxisID(iAxisID)
#endif
, m_fValueToReport(0.0f)
, m_fResponseTime(fResponseTime)
, m_fDecayTime(fDecayTime)
, m_fExponent(fExponent)
, m_pfResponseTime(&m_fResponseTime)
, m_pfDecayTime(&m_fDecayTime)
, m_pfExponent(&m_fExponent)
, m_eSection(eSection)
{
#ifndef ASURA_USE_NEW_INPUT
	Asura_Assert(iAxisID < ASURA_MAX_NUMBER_OF_AXES, "invalid axis ID");
#endif // #ifndef ASURA_USE_NEW_INPUT
}

/// End of function 'Asura_ControlMapping_Axis::Asura_ControlMapping_Axis'. ///

#ifdef ASURA_USE_NEW_INPUT
Asura_ControlMapping_Axis::Asura_ControlMapping_Axis (const u_int uPositiveID,
													  const u_int uNegativeID, 
#else
Asura_ControlMapping_Axis::Asura_ControlMapping_Axis (const int iAxisID, 
#endif
													  const float fScale,
													  const float* const pfResponseTime,
													  const float* const pfDecayTime,
													  const ASURA_CONTROLMAPPING_AXIS_MASK eSection,
													  const float* const pfExponent)
: Asura_ControlMapping(fScale)
#ifdef ASURA_USE_NEW_INPUT
, m_uPositiveID(uPositiveID)
, m_uNegativeID(uNegativeID)
#else
, m_iAxisID(iAxisID)
#endif
, m_fValueToReport(0.0f)
, m_fResponseTime(0.0f)
, m_fDecayTime(0.0f)
, m_fExponent(0.0f)
, m_pfResponseTime(pfResponseTime)
, m_pfDecayTime(pfDecayTime)
, m_pfExponent(pfExponent)
, m_eSection(eSection)
{
#ifndef ASURA_USE_NEW_INPUT
	Asura_Assert(iAxisID < ASURA_MAX_NUMBER_OF_AXES, "invalid axis ID");
#endif // #ifndef ASURA_USE_NEW_INPUT
}

////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_ControlMapping_Axis::UpdateValue
// Author       : Andy Tate
// Date         : 1-Dec-2005
////////////////////////////////////////////////////////////////////////////////

void Asura_ControlMapping_Axis::UpdateValues(const bool bActive, float& fValue, float& fHUDValue)
{
	// Update the active flags...
	m_bActive	= bActive;

	if (!m_bActive && GetPauseWhileInactive())
	{
		fValue = m_fValueToReport;
		fHUDValue = 0.0f;
		return;
	}

	// Handle unspecified axis case...
#ifdef ASURA_USE_NEW_INPUT
	{
		const float fAxisValue = Asura_Input::GetAxisValue(m_pxOwner->GetControllerIndex(), m_uPositiveID, m_uNegativeID);
#else
	if(m_iAxisID == ASURA_AXIS_VOID)
	{
		fValue		= 0.0f;
		fHUDValue	= 0.0f;
	}
	else
	{
		float	fAxisValue	= Asura_UserInput::GetAxisValue(m_iAxisID);
		// SM - 12 April 2007 17:46:42 - Optional masking of positive and negative axis values
		if(m_eSection != ASURA_CONTROLMAPPING_AXIS_MASK_ALL)
		{
			if( (fAxisValue < 0.0f && m_eSection == ASURA_CONTROLMAPPING_AXIS_MASK_POSITIVE) || (fAxisValue > 0.0f && m_eSection == ASURA_CONTROLMAPPING_AXIS_MASK_NEGATIVE))
			{
				fValue		= 0.0f;
				fHUDValue	= 0.0f;
				return;
			}

			if(fAxisValue < 0.0f && m_eSection == ASURA_CONTROLMAPPING_AXIS_MASK_NEGATIVE)
			{	// Invert so negative only triggers return positive
				fAxisValue = -fAxisValue;
			}

		}
#endif

		// Do we have a response duration?
		// KJS : 27/10/2006 - Added a decay time which users can turn on.
		//						Otherwise code behaves as before.
		if ( ( m_pfResponseTime == NULL || *m_pfResponseTime <= 0.0f ) && ( m_pfDecayTime == NULL || *m_pfDecayTime <= 0.0f ) )
		{
			// No - simply use the axis value...
			m_fValueToReport	= fAxisValue;
		}
		else
		{
			const float	fTimeStep	= Asura_Timers::GetFrameTime();
			float		fTimeScale	= 1.0f;
			
			if ( fAxisValue > 0.0f && (fAxisValue - m_fValueToReport) > 0.0f ||
				 fAxisValue < 0.0f && (fAxisValue - m_fValueToReport) < 0.0f	) 
			{
				if ( m_pfResponseTime != NULL && *m_pfResponseTime > 0.0f )
				{
					fTimeScale	= Asura_Maths::Min( ( fTimeStep / *m_pfResponseTime ), 1.0f );
				}
			}
			else 
			{
				if ( m_pfDecayTime != NULL )
				{
					if ( *m_pfDecayTime > 0.0f )
					{
						fTimeScale	= Asura_Maths::Min( ( fTimeStep / *m_pfDecayTime ), 1.0f );
					}
					else if ( m_pfResponseTime != NULL && *m_pfDecayTime < 0.0f ) // if decay time < 0.0 then use response time instead.
					{
						fTimeScale	= Asura_Maths::Min( ( fTimeStep / *m_pfResponseTime), 1.0f );
					}
				}
			}

			// Calculate the new value...
			m_fValueToReport	+= (fAxisValue - m_fValueToReport) * fTimeScale;
		}
		
		if ( m_pfExponent != NULL && *m_pfExponent != 1.0f )
		{
			fValue	= Asura_Maths::Sign( m_fValueToReport ) * Asura_Maths::Power( Asura_Maths::Abs( m_fValueToReport ), *m_pfExponent );
		}
		else
		{
			fValue	= m_fValueToReport;
		}
		fHUDValue	= 0.0f;
	}
}

/// End of function 'Asura_ControlMapping_Axis::UpdateValue'. ///


// Clear the stored value.
void Asura_ControlMapping_Axis::ResetValue()
{
	m_bActive			= false;
	m_fValueToReport	= 0.0f;
}

/// End of file. ///
