
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_ControlMapping_TapKey.cpp
// Author : Andy Tate
// Date   : 6-Jan-2006
//
// Copyright (C) 2006 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#include "Core/Asura.h"

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

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


////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_ControlMapping_TapKey::Asura_ControlMapping_TapKey
// Author       : Andy Tate
// Date         : 6-Jan-2006
//
// Description  : Constructor function for the tap-key control mapping.
//
// Parameters   : The ID of the key to use and the maximum duration allowed
//				  to detect the tap over.
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_ControlMapping_TapKey::Asura_ControlMapping_TapKey (const int iKeyID,
														  const float fMaxPressDuration,
														  const float fScale) :
	Asura_ControlMapping(fScale),
	m_iKeyID(iKeyID),
	m_uNumTaps(1),
	m_eHoldType(ON_DEBOUNCED_RELEASE),
	m_fMaxPressDuration(fMaxPressDuration),
	m_fMaxReleaseDuration(0.0f),

	m_eState(INACTIVE),
	m_uCurrentNumTaps(0),
	m_fCurrentDuration(0.0f)
{
	// Nothing more to initialise...
	Asura_Assert(iKeyID < MAX_NUMBER_OF_ASURA_KEYIDS, "invalid key ID");
}

/// End of function 'Asura_ControlMapping_TapKey::Asura_ControlMapping_TapKey'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_ControlMapping_TapKey::Asura_ControlMapping_TapKey
// Author       : Andy Tate
// Date         : 6-Jan-2006
//
// Description  : Constructor function for the tap-key control mapping.
//
// Parameters   : The ID of the key to use and the maximum duration allowed
//				  to detect the tap over.
//
// Return value : N/A.
////////////////////////////////////////////////////////////////////////////////

Asura_ControlMapping_TapKey::Asura_ControlMapping_TapKey (const int iKeyID,
														  const u_int uNumTaps,
														  const KeyHoldType eHoldType,
														  const float fMaxPressDuration,
														  const float fMaxReleaseDuration,
														  const float fScale) :
	Asura_ControlMapping(fScale),
	m_iKeyID(iKeyID),
	m_uNumTaps(uNumTaps),
	m_eHoldType(eHoldType),
	m_fMaxPressDuration(fMaxPressDuration),
	m_fMaxReleaseDuration(fMaxReleaseDuration),

	m_eState(INACTIVE),
	m_uCurrentNumTaps(0),
	m_fCurrentDuration(0.0f)
{
	// Nothing more to initialise...
	Asura_Assert(iKeyID < MAX_NUMBER_OF_ASURA_KEYIDS, "invalid key ID");
}

/// End of function 'Asura_ControlMapping_TapKey::Asura_ControlMapping_TapKey'. ///



////////////////////////////////////////////////////////////////////////////////
// Function     : Asura_ControlMapping_TapKey::UpdateValue
// Author       : Andy Tate
// Date         : 6-Jan-2006
////////////////////////////////////////////////////////////////////////////////

void Asura_ControlMapping_TapKey::UpdateValues(const bool bActive, float& fValue, float& fHUDValue)
{
	const float	fTimeStep	= Asura_Timers::GetFrameTime();
#ifdef ASURA_USE_NEW_INPUT
	const float fKeyValue	= Asura_Input::GetKeyValue(m_pxOwner->GetControllerIndex(), m_iKeyID);
#else
	const int	iKeyValue	= Asura_UserInput::GetKeyValue(m_iKeyID);
	const float	fKeyValue	= static_cast<float>(iKeyValue) / 255.0f;
#endif

	// Update the active flags...
	if(bActive)
	{
		if(!m_bActive)
		{
			switch(m_eHoldType)
			{
			case ON_PRESS:
			case ON_DEBOUNCED_PRESS:
				{
					if(m_eState == INACTIVE)
					{
						m_bActive	= true;
					}
					break;
				}

			case ON_RELEASE:
			case ON_DEBOUNCED_RELEASE:
				{
					if( (m_eState == RELEASING) || (m_eState == INACTIVE))
					{
						m_bActive	= true;
					}
					break;
				}

			default:
				{
					Asura_Assert(false, "Unexpected state when attempting to activate tap-key control-mapping.");
					break;
				}
			}		// End of switch.
		}
	}
	else
	{
		m_bActive	= false;
	}

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

	// What state are we currently in?
	switch (m_eState)
	{
	case INACTIVE:
		{
			// Is the key held-down?
			if(fKeyValue > 0.5f)
			{
				// Yes - begin handling the pressing...
				m_eState			= PRESSING;
				m_uCurrentNumTaps	= 1;
				m_fCurrentDuration	= fTimeStep;

				// Have we reached the limit on number of taps?
				if( (m_uCurrentNumTaps >= m_uNumTaps) &&
					((m_eHoldType == ON_PRESS) || (m_eHoldType == ON_DEBOUNCED_PRESS)) )
				{
					fValue		= 1.0f;
					fHUDValue	= 0.0f;
					return;
				}
				else
				{
					fValue		= 0.0f;
					fHUDValue	= 0.0f;
					return;
				}
			}
			else
			{
				fValue		= 0.0f;
				fHUDValue	= 0.0f;
				return;
			}
		}

	case PRESSING:
		{
			// Is the key still held-down?
			if(fKeyValue > 0.5f)
			{
				// Yes - begin handling the pressing...
				m_fCurrentDuration	+= fTimeStep;

				if( (m_uCurrentNumTaps >= m_uNumTaps) && (m_eHoldType == ON_PRESS) )
				{
					fValue		= 1.0f;
					fHUDValue	= 0.0f;
					return;
				}
				else
				{
					fValue		= 0.0f;
					fHUDValue	= 0.0f;
					return;
				}
			}
			else
			{
				if(m_fCurrentDuration <= m_fMaxPressDuration)
				{
					// Released in time...
					m_eState			= RELEASING;
					m_fCurrentDuration	= fTimeStep;

					// Have we reached the limit on number of taps?
					if( (m_uCurrentNumTaps >= m_uNumTaps) && 
						((m_eHoldType == ON_RELEASE) || (m_eHoldType == ON_DEBOUNCED_RELEASE)) )
					{
						fValue		= 1.0f;
						fHUDValue	= 0.0f;
						return;
					}
					else
					{
						fValue		= 0.0f;
						fHUDValue	= 0.0f;
						return;
					}
				}
				else
				{
					// Held for too long - time to reset everything...
					m_eState	= INACTIVE;
					fValue		= 0.0f;
					fHUDValue	= 0.0f;
					return;
				}
			}
		}

	case RELEASING:
		{
			// Is the key being held-down again?
			if(fKeyValue > 0.5f)
			{
				// Yes - have we released it for too long?
				// AJG - 13/06/07 - Also reset the num taps if we've already reached the desired number, so we don't start returning success every tap after reaching the number intended (unless that number intended is 1).
				if((m_fCurrentDuration <= m_fMaxReleaseDuration) && (m_uCurrentNumTaps < m_uNumTaps))
				{
					// No - begin handling the pressing...
					m_eState			 = PRESSING;
					m_uCurrentNumTaps	+= 1;
					m_fCurrentDuration	 = fTimeStep;
				}
				else
				{
					// Yes - begin pressing again...
					m_eState			= PRESSING;
					m_uCurrentNumTaps	= 1;
					m_fCurrentDuration	= fTimeStep;
				}

				// Have we reached the limit on number of taps?
				if( (m_uCurrentNumTaps >= m_uNumTaps) &&
					((m_eHoldType == ON_PRESS) || (m_eHoldType == ON_DEBOUNCED_PRESS)) )
				{
					fValue		= 1.0f;
					fHUDValue	= 0.0f;
					return;
				}
				else
				{
					fValue		= 0.0f;
					fHUDValue	= 0.0f;
					return;
				}
			}
			else
			{
				// Yes - begin handling the pressing...
				m_fCurrentDuration	+= fTimeStep;

				if( (m_uCurrentNumTaps >= m_uNumTaps) && (m_eHoldType == ON_RELEASE) )
				{
					fValue		= 1.0f;
					fHUDValue	= 0.0f;
					return;
				}
				else
				{
					fValue		= 0.0f;
					fHUDValue	= 0.0f;
					return;
				}
			}
		}

	default:
		{
			Asura_Assert(false, "Unexpected state found.");
			fValue		= 0.0f;
			fHUDValue	= 0.0f;
			return;
		}
	}		// End of switch.
}


// Clear the stored value.
void Asura_ControlMapping_TapKey::ResetValue()
{
	m_bActive			= false;
	m_uCurrentNumTaps	= 0;
	m_fCurrentDuration	= 0.0f;
	m_eState			= INACTIVE;
}


/// End of file. ///
