/****************************************************************************************

		I3DShKeyFrame.h

		Copyright: (c) 2001 Eovia Corp. All rights reserved.

		Author:	Ray Dream (from I3DSHUTI.H)
		Date:	3/2/98

		Revision History

		when		who			what & why
		==========	==========	======================================================
		9/23/99		Greg		Added Get/SetLink
		11/5/98		Joshua		Changes for animate button

*****************************************************************************************/

#ifndef __I3DSHKEYFRAME__
#define __I3DSHKEYFRAME__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "COMTypes.h"
#include "MCArray.h"
#include "APITypes.h"


//****** Globally Unique Ids *************************************************

MCDEFINE_GUID(IID_I3DShKeyFrame, 0x7e533ac, 0x4c5, 0x11d3, 0x81, 0x26, 0x0, 0x60, 0x97, 0xb, 0xc5, 0x21);

//*****************************************************************************

class TMCiostream;
struct I3DShTweenerChainLink;


/// \addtogroup ShellInterface
/// \{


enum ETangentType
{
	kNoTangent,
	kLinkedTangent,
	kUnlinkedTangent,
};

enum ETangentFlag
{
	kFreeWeightTangent		= 0x0001,
	kLockedWeightTangent	= 0x0002,
};

enum ETangentSide
{
	kLeftTangent,
	kRightTangent,
};


/// <P>This is the interface to access key frames. Key frames store the value of a parameter
/// for a given frame. The key frame does not store the time which is stored in the tweener
/// chain link (see I3DShTweenerChainLink).</P>
///
/// <P>Each animated parameter (I3DShParamInfo) owns a time line (I3DShParamTimeLine) which
/// is a linked list of Tweener Chain Links (I3DShTweenerChainLink), each
/// of them pointing to a keyframe.</P>
///
/// <P>The default keyframe types are:</P>
///
///  - 'bool' : boolean
///  - 'long' : int32
///  - 'shrt' : int16
///  - 'RGBc' : TMCRGBColor
///  - 'colo' : TMCColorRGBA
///  - 'colI' : TMCColorRGBAIndex
///  - 'grad' : TMCGradient
///  - 'qfix' : real
///  - 'VEC3' : TVector3
///  - 'ROTA' : TMatrix33SymQuaternion
///  - 'RECT' : TMCRect
///  - 'QREC' : TMCRealRect
///  - 'dire' : UnitTVector3
///  - 'qfv2' : TVector2
///  - 'qfv3' : TVector3
/// 
/// <P>You can derive your own keyframe class from this interface and create your keyframe type
/// that you can register with the application (see I3DShUtilities::RegisterNewKeyFrameType)</P>
///
struct I3DShKeyFrame: public IMCUnknown 
{
	// ****************************************************************************
	//								GetParamSize
	// 
	/// Returns the size (in bytes) necessary to store the parameter.
	/// 
	virtual int32	 MCCOMAPI GetParamSize		() const = 0;
	
	// ****************************************************************************
	//								GetParam
	// 
	/// Returns the value stored in the keyframe.
	/// 
	/// \param buffer   A pointer to a buffer that can store the value.
	/// \param type     The type of the buffer (should be the same as the type of the keyframe usually
	///					although some limited conversions are possible).
	/// \param changed  Returns true if the value that is returned is different from the value that
	///					was originally pointed to by buffer.
	/// 
	virtual MCCOMErr MCCOMAPI GetParam			(void* buffer,int32 type,boolean &changed) const = 0; 
	
	// ****************************************************************************
	//								SetParam
	// 
	/// Sets the value that is stored in the keyframe.
	/// 
	/// \param param  A pointer to a buffer that stores the value.
	/// \param type   The type of the buffer (should be the same as the type of the keyframe usually
	///				  although some limited conversions are possible).
	/// 
	virtual MCCOMErr MCCOMAPI SetParam			(const void *param,int32 type) = 0;  

	// ****************************************************************************
	//								GetType
	// 
	/// Returns the type of the keyframe.
	///
	virtual int32    MCCOMAPI GetType			() const = 0;

	// ****************************************************************************
	//								Clone
	// 
	/// Creates a copy of the keyframe
	/// 
	/// \param keyframe  A pointer to the copy that is created.
	/// 
	virtual void     MCCOMAPI Clone				(I3DShKeyFrame** keyframe) const = 0;

	// ****************************************************************************
	//								Read
	// 
	/// Reads a keyframe value from a stream.
	/// 
	/// \param stream  
	/// 
	virtual MCCOMErr MCCOMAPI Read				(TMCiostream& stream) = 0; 
	
	// ****************************************************************************
	//								Write
	// 
	/// Write a key frame value into a stream.
	/// 
	/// \param stream  
	/// 
	virtual MCCOMErr MCCOMAPI Write				(TMCiostream& stream) const = 0; 

	// ****************************************************************************
	//								Copy
	// 
	/// Copy the value of another keyframe.
	/// 
	/// \param from  A pointer to the keyframe whose value is copie
	/// 
	virtual MCCOMErr MCCOMAPI Copy				(const I3DShKeyFrame *from) = 0;

	// ****************************************************************************
	//								LinearInterpolate
	// 
	/// Performs a linear interpolation between two keyframes of the same type and
	/// stored the result in this keyframe.
	/// 
	/// \param lamda  The parameter of the interpolation (usually between 0 and 1)
	/// \param kf1    The keyframe that is selected when lamda is equal to 0
	/// \param kf2    The keyframe that is selected when lamda is equal to 1
	/// 
	virtual MCCOMErr MCCOMAPI LinearInterpolate	(const real &lamda,const I3DShKeyFrame *kf1,const I3DShKeyFrame *kf2) = 0;

	// ****************************************************************************
	//								ComputeOffset
	// 
	/// Computes the different between 2 keyframes.
	/// 
	/// \param result    keyFrame - (*this)
	/// \param keyFrame  A keyframe.
	/// 
	virtual void	 MCCOMAPI ComputeOffset		(I3DShKeyFrame**result,I3DShKeyFrame* keyFrame)=0;
	
	// ****************************************************************************
	//								ApplyOffset
	// 
	/// Adds a value to the current keyframe
	/// 
	/// \param keyFrame  The keyframe that is added to this.
	/// 
	virtual MCCOMErr MCCOMAPI ApplyOffset		(I3DShKeyFrame* keyFrame)=0;

	// ****************************************************************************
	//								Subtract
	// 
	/// Subtract two keyframes and multiplies the result by a constant (res = (k1-k2) * lambda)
	/// The result is stored in (*this).
	/// 
	/// \param keyFrame1  First operand of the substraction
	/// \param keyFrame2  Second operand of the substraction
	/// \param lambda     The scaling factor.
	/// 
	virtual void	 MCCOMAPI Subtract			(I3DShKeyFrame* keyFrame1,I3DShKeyFrame* keyFrame2,real lambda)=0;
	
	// ****************************************************************************
	//								SetLink
	// 
	/// Sets a pointer to the tweener chain link that is pointing to this keyframe.
	/// 
	/// \param inLink  A pointer to the tweener chain link that is pointing to this keyframe.
	/// 
	virtual void					MCCOMAPI	SetLink			(I3DShTweenerChainLink* inLink) = 0;
	
	// ****************************************************************************
	//								GetLinkNoAddRef
	// 
	/// Returns a pointer to the tweener chain link that is pointing to this keyframe.
	/// 
	virtual I3DShTweenerChainLink* 	MCCOMAPI	GetLinkNoAddRef	() = 0;

	// ****************************************************************************
	//								SupportTangent
	// 
	/// Returns true if this keyframe support tangents.
	/// 
	virtual boolean					MCCOMAPI	SupportTangent() const = 0;

	
	// ****************************************************************************
	// The following functions are used mostly for the UI for the graph editor
	
	// ****************************************************************************
	//								GetDimensionCount
	// 
	/// Returns the dimension count for this keyframe (number of curve in the
	/// graph editor). Returns 0 if this keyframe cannot be displayed as curves.
	///
	virtual int32					MCCOMAPI	GetDimensionCount() const = 0;

	// ****************************************************************************
	//								GetDimensionValues
	// 
	/// Returns the values corresponding to the dimension of the keyframe (converted as real).
	/// 
	/// \param values		A pointer to an array that can store the values.
	/// 
	virtual void					MCCOMAPI	GetDimensionValues(TMCArray<real>& values) const = 0;

	// ****************************************************************************
	//								SetDimensionValues
	// 
	/// Sets the value corresponding to one of the dimension of this keyframe.
	/// 
	/// \param values		A pointer to an array that stores the values.
	/// 
	virtual void					MCCOMAPI	SetDimensionValues(const TMCArray<real>& values) = 0;

	// ****************************************************************************
	//								CreateTangents
	// 
	/// Creates tangents for this keyframe.
	/// 
	virtual void					MCCOMAPI	CreateTangents() = 0;

	// ****************************************************************************
	//								RemoveTangents
	// 
	/// Removes tangents for this keyframe.
	/// 
	virtual void					MCCOMAPI	RemoveTangents() = 0;

	// ****************************************************************************
	//								HaveTangents
	// 
	/// Returns true if this keyframe have keyframes.
	/// 
	virtual boolean					MCCOMAPI	HaveTangents() const = 0;

	// ****************************************************************************
	//								GetTangentType
	// 
	/// Returns the tangent type for a given dimension.
	/// 
	/// \param dimension		The dimension (must be < GetDimensionCount()).
	/// \param outTangentFlags	The flags for this tangent (see ETangentFlag).
	/// 
	virtual ETangentType			MCCOMAPI	GetTangentType(int32 dimension, int32& outTangentFlags) const = 0;

	// ****************************************************************************
	//								SetTangentType
	// 
	/// Sets the tangent type for a given dimension.
	/// 
	/// \param dimension		The dimension (must be < GetDimensionCount()).
	/// \param inTangentType	The tangent type (see ETangentFlag).
	/// \param inTangentFlags	The flags for this tangent (see ETangentFlag).
	/// 
	virtual void					MCCOMAPI	SetTangentType(int32 dimension, ETangentType inTangentType, int32 inTangentFlags) = 0;

	// ****************************************************************************
	//								GetTangent
	// 
	/// Gets the tangent for the given dimension at the given time
	/// 
	/// \param dimension	The dimension (must be < GetDimensionCount()).
	/// \param side			Which tangent left or right.
	/// \param value		The value of the tangent to be returned,
	/// \param time			The time of the tangent to get.
	/// \return true if the tangent exists or false otherwise.
	/// 
	virtual boolean					MCCOMAPI	GetTangent(int32 dimension, ETangentSide side, real& value, MicroTick& time) const = 0;

	// ****************************************************************************
	//								SetTangent
	// 
	/// Gets the left tangent for the given dimension
	/// 
	/// \param dimension	The dimension (must be < GetDimensionCount()).
	/// \param side			Which tangent left or right.
	/// \param value		The value of the tangent to be set,
	/// \param time			The time of the tangent to set.
	/// 
	virtual void					MCCOMAPI	SetTangent(int32 dimension, ETangentSide side, real value, MicroTick time) = 0;
};

/// \}

#endif
