
///////////////////////////////////////////////////////////////////////////////
//
// File   : Tools_FacialAnimation_FaceAnimation.h
// Author : Andy Tate
// Date   : 8-May-2008
//
// Copyright (C) 2008 Rebellion, All Rights Reserved.
//
///////////////////////////////////////////////////////////////////////////////

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

#ifndef __TOOLS_FACIALANIMATION_FACEANIMATION_H__
#define __TOOLS_FACIALANIMATION_FACEANIMATION_H__

#if defined(ASURA_USE_FACIAL_ANIMATION_SYSTEM)

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

#include "Core/Asura_String.h"
#include "Core/Asura_HashTree.h"

#include "FacialAnimation/Tools_FacialAnimation_FaceAnimation_FacePose.h"
#include "FacialAnimation/Tools_FacialAnimation_MuscleGroupAnimation.h"


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

class Asura_Chunk_Stream;
class Asura_FacialAnimation_FaceAnimation;
class Asura_FacialAnimation_EyeParamAnimation;
class Tools_FacialAnimation_FacePose;
class Tools_FacialAnimation_FaceType;

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

////////////////////////////////////////////////////////////////////////////////
// Class        : Tools_FacialAnimation_FaceAnimation
// Author       : Andy Tate
// Date         : 8-May-2008
//
// Description  : Tools-class used to point to a particular animation for a face.
////////////////////////////////////////////////////////////////////////////////

class Tools_FacialAnimation_FaceAnimation
{
public:
	// Public enumerated type...
	enum Status
	{
		CONVERTED_FROM_WAV,
		EXPORTED_FROM_MAX,

		MAX_STATUS_VALUES
	};

	// Public functions...
	Tools_FacialAnimation_FaceAnimation(void);
	Tools_FacialAnimation_FaceAnimation(const Asura_Hash_ID uHash, Asura_Chunk_Stream& xStream);
	~Tools_FacialAnimation_FaceAnimation();

	Asura_FacialAnimation_FaceAnimation*	CreateAsuraFaceAnimation(void) const;

	// Chunk-stream functions...
	void	ReadFromChunkStream(Asura_Chunk_Stream& xStream);
	void	WriteToChunkStream(Asura_Chunk_Stream& xStream) const;

	// Phoneme manipulation functions...
	void	AddPhoneme(const char* szPhoneme, const u_int uStartMS, const u_int uEndMS, const float fWeight);

	// Used by the max exporters for addins the keyframes
	void	AddMuscleGroupKeyFrame(const char* szMuscleGroup, float fTime, float fWeight, float fBalance);

	// Converts the face pose animation data created from the wav files into muscle group animation data
	bool ConvertToMuscleGroupAnimation();

	//returns true if the animation has yet to be converted from face pose to muscle group animation
	bool NeedsConversionToMuscleGroupAnimation();

	//Strips out and excess keyframes that can be generated by interpolating the frames either side
	void	RemoveRedundantKeyFrames();

	//Allocates the array of eye parameter animations , and allocates some empty keyframes in each
	void InitialiseEyeAnimation(u_int uNumKeyFrames);

	//Fills in one of the eye animation keyframes
	void SetEyeKeyFrame(u_int uParam, u_int uFrame, float fTime, float fValue);

	//Returns true if this animation contains eye animation
	bool HasEyeAnimation() const {return m_pxEyeParamAnimations != 0;}

	//Gets eye animation data for the specified eye parameter
	const Asura_FacialAnimation_EyeParamAnimation* GetEyeAnimation(u_int uParam) const;

	// Accessor functions...
	void				SetName(const char* szName)	{ m_xName = szName; }
	const Asura_String&	GetName(void) const			{ return(m_xName); }

	void				SetFaceTypeName(const char* szName)	{ m_xFaceTypeName = szName; }
	const Asura_String&	GetFaceTypeName(void) const			{ return(m_xFaceTypeName); }

	void				SetBaseFacePoseName(const char* szFacePose)	{ m_xBaseFacePoseName = szFacePose; }
	const Asura_String&	GetBaseFacePoseName(void) const				{ return(m_xBaseFacePoseName); }

	void				SetWAVFilename(const char* szName)	{ m_xWAVFilename = szName; }
	const Asura_String&	GetWAVFilename(void) const			{ return(m_xWAVFilename); }

	void				SetStatus(Status eStatus)			{m_eStatus = eStatus;}

	int GetNumMuscleGroupAnimation() const {return m_xMuscleGroupAnimationContainer.GetNumberOfNodes();}	
	const Tools_FacialAnimation_MuscleGroupAnimation* GetMuscleGroupAnimationByIndex(int iIndex) const {return m_xMuscleGroupAnimationContainer.GetDataByIndex(iIndex);}

	//Gets the duration by checking for the highest keyframe from the muscle animations
	float GetDuration() const;


protected:
	// Protected variables...

	// Protected functions...


private:
	// Private typedefs...
	typedef Asura_TemplateHashTree<Tools_FacialAnimation_FaceAnimation_FacePose> FacePoseAnimationContainer;
	typedef Asura_TemplateHashTree_Iterator<Tools_FacialAnimation_FaceAnimation_FacePose> FacePoseAnimationIterator;
	typedef Asura_TemplateHashTree_ConstIterator<Tools_FacialAnimation_FaceAnimation_FacePose> FacePoseAnimationConstIterator;

	typedef Asura_TemplateHashTree<Tools_FacialAnimation_MuscleGroupAnimation> MuscleGroupAnimationContainer;
	typedef Asura_TemplateHashTree_Iterator<Tools_FacialAnimation_MuscleGroupAnimation> MuscleGroupAnimationIterator;
	typedef Asura_TemplateHashTree_ConstIterator<Tools_FacialAnimation_MuscleGroupAnimation> MuscleGroupAnimationConstIterator;


	// Private variables...
	Asura_String				m_xName;						// The name of this animation.
	Asura_String				m_xFaceTypeName;				// The name of the face-type this animation is bound to.
	Asura_String				m_xBaseFacePoseName;			// The name of the base face pose this animation is bound to. LIKE "Scared" or "Sad"
	Asura_String				m_xWAVFilename;					// The name of the .WAV file we've converted this animation from (may be empty if its come directly from Max).
	Asura_String				m_xDefaultExpressionName;		// The name of the expression to be combined with the data we've converted from the .WAV to make our initial animation.
	Status						m_eStatus;						// The status of this animation.

	FacePoseAnimationContainer	m_xFacePoseAnimationContainer;	// Container class for each face-pose. This is used as an intermediate step while converting animations
	MuscleGroupAnimationContainer m_xMuscleGroupAnimationContainer; // Container class for each muscle group.
	Asura_FacialAnimation_EyeParamAnimation*	m_pxEyeParamAnimations;		// Array of animation data for the eye values. NULL if the animation doesn't control the eyes

	static const u_int			s_uChunkVersion;				// Current version used for reading/writing data.

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

	Tools_FacialAnimation_FaceAnimation&	operator=(const Tools_FacialAnimation_FaceAnimation& xOther);

	void AddMuscleGroupAnimationFromFacePoseAnimation(const Tools_FacialAnimation_FaceAnimation_FacePose& xToolsFacePoseAnimation, const Tools_FacialAnimation_FacePose& xToolsFacePose, const Tools_FacialAnimation_FaceType& xToolsFaceType);

	void OptimiseMuscleGroupAnimation();
	void CreateAndOptimiseEyesGroups();


};   // End of class 'Tools_FacialAnimation_FaceAnimation'.

#endif	//defined(ASURA_USE_FACIAL_ANIMATION_SYSTEM)

#endif   // ifndef __TOOLS_FACIALANIMATION_FACEANIMATION_H__


/// End of file. ///
