
///////////////////////////////////////////////////////////////////////////////
//
// File   : Asura_MoveData_PositionInterpolation.h
// Author : Andy Tate
// Date   : 10-Sep-2007
//
// Copyright (C) 2007 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#ifndef __ASURA_MOVEDATA_POSITIONINTERPOLATION_H__
#define __ASURA_MOVEDATA_POSITIONINTERPOLATION_H__

#if defined(ASURA_USE_MOVEMENT_SYSTEM)

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

#include "Core/Asura_Maths.h"
#include "Entity/PhysicalObject/Moves/Asura_MoveData.h"


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


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

////////////////////////////////////////////////////////////////////////////////
// Class        : Asura_MoveData_PositionInterpolation
// Author       : Andy Tate
// Date         : 10-Sep-2007
//
// Description  : Class to handle the positional interpolation during a 
//				  particular move.
////////////////////////////////////////////////////////////////////////////////

class Asura_MoveData_PositionInterpolation : public Asura_MoveData
{
public:
	// Public typedefs...
	enum MovementOffsetOperation
	{
		IGNORE_MOVEMENT_OFFSET,
		ADD_MOVEMENT_OFFSET,
		SUBTRACT_MOVEMENT_OFFSET,
		STRETCH_MOVEMENT_OFFSET,

		MAX_MOVEMENT_OFFSET_OPERATIONS
	};

	enum VelocityOperation
	{
		IGNORE_VELOCITY,
		ADD_VELOCITY,

		MAX_VELOCITY_OPERATIONS,
	};

	// Public functions...
	Asura_MoveData_PositionInterpolation(void);
//	~Asura_MoveData_PositionInterpolation();

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

	bool	Start(Asura_AVector3_InParam xInitial);
	bool	Update(const float fTimeStep);
	bool	Update(const float fTimeStep, Asura_AVector3_InParam xLSMOCurrentPosition, Asura_AVector3_InParam xLSMOFinalPosition, const Asura_Quat& xWSCurrentOrientation, const Asura_Quat& xWSFinalOrientation);
	bool	UpdateUsingVelocity(const float fTimeStep, Asura_AVector3_InParam xVelocity);
	void	Finish(void);

	// Query functions...
	bool	HasReachedFinal(Asura_AVector3_InParam xCurrent) const	{ return(xCurrent.ApproximatelyEquals(m_xFinal, m_fReachedFinalEpsilon)); }
	bool	HasExceededDuration(void) const							{ return(m_bDurationBased && (m_fTimer >= m_fDuration));  }

	// Accessor functions...
	void	SetInitial(Asura_AVector3_InParam xInitial)	{ m_bInitialSet = true; m_xInitial = xInitial; m_xCurrent = m_xInitial; m_xActual = m_xInitial; }
	void	SetInitial(const Asura_Vector_3& xInitial)	{ m_bInitialSet = true; m_xInitial = xInitial; m_xCurrent = m_xInitial; m_xActual = m_xInitial; }
	void	SetFinal(Asura_AVector3_InParam xFinal)		{ m_bFinalSet = true; m_xFinal = xFinal; }
	void	SetFinal(const Asura_Vector_3& xFinal)		{ m_bFinalSet = true; m_xFinal = xFinal; }

	void	SetDuration(const float fDuration)		{ m_bDurationBased = true; m_fDuration = fDuration; }
	void	SetSpeed(const float fSpeed)			{ m_bSpeedBased = true; m_fSpeed = fSpeed; }

	bool	IsDurationBased(void) const		{ return(m_bDurationBased); }
	bool	IsSpeedBased(void) const		{ return(m_bSpeedBased); }

	void					SetMovementOffsetOperation(const MovementOffsetOperation eOperation)	{ m_eMovementOffsetOperation = eOperation; }
	MovementOffsetOperation	GetMovementOffsetOperation(void) const									{ return(static_cast<MovementOffsetOperation>(m_eMovementOffsetOperation)); }

	void				SetVelocityOperation(const VelocityOperation eOperation)	{ m_eVelocityOperation = eOperation; }
	VelocityOperation	GetVelocityOperation(void) const							{ return(static_cast<VelocityOperation>(m_eVelocityOperation)); }

	const Asura_AVector3&	GetInitial(void) const	{ return(m_xInitial); }
	const Asura_AVector3&	GetCurrent(void) const	{ return(m_xCurrent); }
	const Asura_AVector3&	GetFinal(void) const	{ return(m_xFinal); }

	const Asura_AVector3&	GetMovementOffsetCurrent(void) const	{ return(m_xMovementOffsetCurrent); }
	const Asura_AVector3&	GetMovementOffsetFinal(void) const		{ return(m_xMovementOffsetFinal); }

	const Asura_AVector3&	GetActual(void) const	{ return(m_xActual); }

	float	GetTimer(void) const			{ return(m_fTimer); }
	float	GetDuration(void) const			{ return(m_fDuration); }
	float	GetParametricTimer(void) const	{ return(m_fTimer / m_fDuration); }

	float	GetSpeed(void) const			{ return(m_fSpeed); }


protected:
	// Protected variables...

	// Protected functions...
	bool	UpdateDurationBased(void);
	bool	UpdateDurationBased(const float fParametricTimer, Asura_AVector3_InParam xLSMOCurrentPosition, Asura_AVector3_InParam xLSMOFinalPosition, const Asura_Quat& xWSCurrentOrientation, const Asura_Quat& xWSFinalOrientation);
	bool	UpdateDurationBased(Asura_AVector3_InParam xLSMOCurrentPosition, Asura_AVector3_InParam xLSMOFinalPosition, const Asura_Quat& xWSCurrentOrientation, const Asura_Quat& xWSFinalOrientation);

	bool	UpdateSpeedBased(const float fTimeStep);


private:
	// Private typedefs...
	typedef Asura_MoveData PARENT;

	// Private variables...
	Asura_AVector3	m_xInitial;		// The initial position used for the interpolation.
	Asura_AVector3	m_xCurrent;		// The current position used for the interpolation.
	Asura_AVector3	m_xFinal;		// The final position used for the interpolation.

	Asura_AVector3	m_xMovementOffsetCurrent;	// The current position used for the interpolation.
	Asura_AVector3	m_xMovementOffsetFinal;		// The final position used for the interpolation.

	Asura_AVector3	m_xActual;	// The actual position used by the move.

	float	m_fReachedFinalEpsilon;	// The epsilon value used when checking whether our current orientation is the final orientation.
	float	m_fTimer;				// The timer used when interpolating position.

	float	m_fDuration;	// The duration over which to interpolate position.
	float	m_fSpeed;		// The speed at which we're to move to our position.

	union
	{
		u_int		m_uFlags;							// Single access point for the flags.

		struct
		{
			u_int	m_bInitialSet				: 1,	// Flag to say that we have set an initial value.
					m_bFinalSet					: 1,	// Flag to say that we have set a final value.
					m_bSnapToFinal				: 1,	// Flag to say that we need to snap our current value to the final one.
					m_bDurationBased			: 1,	// Flag to say whether this move is duration-based.
					m_bSpeedBased				: 1,	// Flag to say whether this move is speed-based.
					m_eMovementOffsetOperation	: 4,	// Flags to say whether we need to take the movement-offset into account.
					m_eVelocityOperation		: 2,	// Flags to say whether we need to take the animation velocity into account. Only relevant if the movement offset is ignored.
												: 0;	// 26 spare-bits.
		};
	};

	// Private functions...
	Asura_MoveData_PositionInterpolation(const Asura_MoveData_PositionInterpolation& xOther);

	Asura_MoveData_PositionInterpolation&	operator=(const Asura_MoveData_PositionInterpolation& xOther);

};   // End of class 'Asura_MoveData_PositionInterpolation'.

#endif	// defined(ASURA_USE_MOVEMENT_SYSTEM)

#endif   // ifndef __ASURA_MOVEDATA_POSITIONINTERPOLATION_H__


/// End of file. ///
