
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_ControlMapping_Motion.h
// Author : Simon Watson
// Date   : 27-Aug-2008
//
//	For now this is wii-only, but it should be fairly easy to turn it into
//  a cross-playform solution.
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#ifndef __ASURA_CONTROLMAPPING_MOTION_H__
#define __ASURA_CONTROLMAPPING_MOTION_H__

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

#include "Input/Asura_ControlMapping.h"
#include "Core/Asura_Maths.h" // for Asura_Vector_3

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


////////////////////////////////////////////////////////////////////////////////
// Useful Enum declarations...
////////////////////////////////////////////////////////////////////////////////

enum ASURA_WII_MOTION_ID
{
	// KOR - do not re-order the flicks, as assumptions about the order
	// are made in the platform update
	ASURA_WII_MOTION_REMOTE_FLICK_LEFT_X,
	ASURA_WII_MOTION_REMOTE_FLICK_RIGHT_X,
	ASURA_WII_MOTION_REMOTE_FLICK_UP_Y,
	ASURA_WII_MOTION_REMOTE_FLICK_DOWN_Y,
	ASURA_WII_MOTION_REMOTE_FLICK_IN_Z,
	ASURA_WII_MOTION_REMOTE_FLICK_OUT_Z,
	ASURA_WII_MOTION_NUNCHUCK_FLICK_LEFT_X,
	ASURA_WII_MOTION_NUNCHUCK_FLICK_RIGHT_X,
	ASURA_WII_MOTION_NUNCHUCK_FLICK_UP_Y,
	ASURA_WII_MOTION_NUNCHUCK_FLICK_DOWN_Y,
	ASURA_WII_MOTION_NUNCHUCK_FLICK_IN_Z,
	ASURA_WII_MOTION_NUNCHUCK_FLICK_OUT_Z,
	ASURA_WII_MOTION_REMOTE_FLICK,			// remote flick in any direction
	ASURA_WII_MOTION_NUNCHUCK_FLICK,			// nunchuck flick in any direction
	ASURA_WII_MOTION_REMOTE_SHAKE,			// remote shake in any direction
	ASURA_WII_MOTION_NUNCHUCK_SHAKE,			// nunchuck shake in any direction

	ASURA_WII_MOTION_REMOTE_IN_OUT,			// inwards and outwards movement with the remote
	ASURA_WII_MOTION_NUNCHUCK_IN_OUT,		// inwards and outwards movement with the nunchuck
	ASURA_WII_MOTION_REMOTE_UP_DOWN,			// up and down movement with the remote
	ASURA_WII_MOTION_NUNCHUCK_UP_DOWN,		// up and down movement with the nunchuck
	ASURA_WII_MOTION_REMOTE_LEFT_RIGHT,		// left and right movement with the remote
	ASURA_WII_MOTION_NUNCHUCK_LEFT_RIGHT,	// left and right movement with the nunchuck
	ASURA_WII_MOTION_REMOTE_CLOCKWISE_CIRCLE,	    // clockwise circle motion with the remote
	ASURA_WII_MOTION_REMOTE_ANTI_CLOCKWISE_CIRCLE,   // anti-clockwise circle motion with the remote
	ASURA_WII_MOTION_NUNCHUCK_CLOCKWISE_CIRCLE,	    // clockwise circle motion with the nunchuck
	ASURA_WII_MOTION_NUNCHUCK_ANTI_CLOCKWISE_CIRCLE, // anti-clockwise circle motion with the nunchuck

	ASURA_WII_NUM_MOTIONS,
};

enum ASURA_WII_SPIKES
{
	ASURA_WII_SPIKE_X_POS = 0,
	ASURA_WII_SPIKE_X_NEG,
	ASURA_WII_SPIKE_Y_POS,
	ASURA_WII_SPIKE_Y_NEG,
	ASURA_WII_SPIKE_Z_POS,
	ASURA_WII_SPIKE_Z_NEG,
	ASURA_WII_NUM_SPIKES,
};

enum ASURA_WII_MOTION_SOURCE
{
	ASURA_WII_MOTION_SOURCE_REMOTE = 0,
	ASURA_WII_MOTION_SOURCE_NUNCHUCK,
	ASURA_WII_NUM_MOTION_SOURCE,
};

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

class Asura_ControlMapping_Motion : public Asura_ControlMapping
{
public:
	// Public functions...
	Asura_ControlMapping_Motion(	const int iController,							// Which controller are we bound to?
									const ASURA_WII_MOTION_ID eMotionId,			// What type of motion are we looking for?
									const float fScale = 1.0f
							   );

	// Overridden virtual functions...
	virtual void	ResetValue	( void );
	virtual	void	UpdateValues( const bool bActive, float& fValue, float& fHUDValue);
	virtual int		GetControlID( void ) const	{ return m_iController; } 
	virtual Asura_Hash_ID	GetInstanceMappingType(void) const	{ return s_uMappingType; } 

protected:
	// Protected variables...

	// Protected functions...

private:
	// Private variables...

	// The details of the motion we detect.  
	// Making these const allows us to make some simplifying assumptions in other places
	const int						m_iController;		// Which controller are we bound to?
	const ASURA_WII_MOTION_ID		m_eMotionId;		// What type of motion are we looking for?

	Asura_Vector_3	m_xIndividualFlickSpikeDetection;
	Asura_Vector_3	m_xFlickSpikeDetection;
	Asura_Vector_3	m_xShakeSpikeDetection;
	Asura_Vector_3	m_xInOutSpikeDetection;
	Asura_Vector_3	m_xUpDownSpikeDetection;
	Asura_Vector_3	m_xLeftRightSpikeDetection;
	Asura_Vector_3	m_xClockwiseCircleSpikeDetection;
	Asura_Vector_3	m_xAntiClockwiseCircleSpikeDetection;

	u_int	m_uNumberOfSpikes;
	u_int	m_uCurrentInOutSpike;
	u_int	m_uNumInOutSpikes;
	u_int	m_uCurrentUpDownSpike;
	u_int	m_uNumUpDownSpikes;
	u_int	m_uCurrentLeftRightSpike;
	u_int	m_uNumLeftRightSpikes;
	u_int	m_uCurrentClockwiseCircleSpike;
	u_int	m_uNumClockwiseCircleSpikes;
	u_int	m_uCurrentAntiClockwiseCircleSpike;
	u_int	m_uNumAntiClockwiseCircleSpikes;

	float	m_fShakeTimer;
	float	m_fToggleTimer;
	float	m_fLastInOutSpikeTime;
	float	m_fLastUpDownSpikeTime;
	float	m_fLastLeftRightSpikeTime;
	float	m_fLastClockwiseCircleSpikeTime;
	float	m_fLastAntiClockwiseCircleSpikeTime;

	bool	m_bClockwiseCircleAllowedToSkip;		// Not quite sure what these do.
	bool	m_bAntiClockwiseCircleAllowedToSkip;	// The flag which turns them on is off by default, and I haven't messed with it. SW

	// Private functions...

	// Helper functions
	const float				DetectRemoteSpikes(const Asura_Vector_3& xCurrentGradient);
	const float				DetectNunchuckSpikes(const Asura_Vector_3& xCurrentGradient);

	const int				DetectSpike(Asura_Vector_3& xSpikeDetection, const Asura_Vector_3& xGradient, 
										u_int uAxis, float fPosSpikeThreshold, float fNegSpikeThreshold);
	const Asura_Vector_3	GetCurrentAccSample(void);
	const Asura_Vector_3	GetPrevAccSample(void);
	const ASURA_WII_MOTION_SOURCE GetMotionSource(void) const;

	// Default operations not allowed
	Asura_ControlMapping_Motion					( void);
	Asura_ControlMapping_Motion					( const Asura_ControlMapping_Motion& xOther );
	Asura_ControlMapping_Motion&	operator=	( const Asura_ControlMapping_Motion& xOther );
	
	static const Asura_Hash_ID s_uMappingType = 0xC052BFB6;	//Asura_GetHashId( "MOTION" )
	

};   // End of class 'Asura_ControlMapping_Motion'.


#endif   // ifndef __ASURA_CONTROLMAPPING_MOTION_H__


/// End of file. ///
