//-------------------------------------------------------------------------
//
// File:		KeyC.h
// Desc:		Keyframe class.
// Author:		memon <memon@inside.org>
//
//-------------------------------------------------------------------------
//	Copyright (c) 2000-2004 Moppi Productions. All Rights Reserved.
//  This file is part of Moppi Demopaja SDK. For conditions of 
//  distribution and use, see the accompanying license.txt file.
//  http://www.demopaja.org
//-------------------------------------------------------------------------

#ifndef __DEMOPAJA_KEYC_H__
#define __DEMOPAJA_KEYC_H__


#include "DataBlockI.h"
#include "EditableI.h"
#include "UndoC.h"
#include "PajaTypes.h"
#include <vector>
#include "FileIO.h"
#include "FileHandleC.h"

namespace Composition {

	//! Base classID.
	const PluginClass::SuperClassIdC		BASECLASS_KEY = PluginClass::SuperClassIdC( 1, 7 );

	//! Maximum number of channels in a key.
	/*!	This cosntant represent the maximum number of channels (values) the
		get_value() method may return. 
	*/
	const PajaTypes::uint32		KEY_MAXCHANNELS = 4;

	//! Key flags.
	enum KeyFlagsE {
		KEY_NOFLAGS =			0,
		KEY_SELECTED =			0x0001,		//!< Key is selected (used only in editor).
		KEY_LINEAR =			0x0002,		//!< Key uses linear interpolation.
		KEY_SMOOTH =			0x0004,		//!< Key uses smooth (TCB spline) interpolation.
		KEY_HOLD =				0x0008,		//!< Key uses hold interpolation.
		KEY_FILE =				0x0010,		//!< Key is file key
	};


	//! Keyframe class for controller.
	/*! Key class defines the keys used in controllers. There
		are two type of keys: Float keys and file keys. The KeyC
		class is used in cases where only the time value is used.

		Use key flags to indentity the different key types.

		This class is implemented by the system.
	*/
	class KeyC : public Edit::EditableI
	{
	public:
		//! Create new key with zero no channels.
		static KeyC*				create_new();
		//! Create new key with zero no channels.
		virtual Edit::DataBlockI*	create();
		//! Creates new file handle (used internally), see Edit::EditableI::create().
		virtual Edit::DataBlockI*	create( Edit::EditableI* pOriginal );
		//! Deep copy from a data block, see Edit::DataBlockI::copy().
		virtual void				copy( Edit::EditableI* pEditable );
		//! Shallow copy from a editable, see Edit::EditableI::restore().
		virtual void				restore( Edit::EditableI* pEditable );
		//! Returns the base class ID.
		virtual PluginClass::SuperClassIdC		get_base_class_id() const;

		//! Returns the time of the key.
		virtual PajaTypes::int32	get_time();
		//! Sets the time of the key.
		virtual void				set_time( PajaTypes::int32 i32Time );

		//! Sets the effect flags.
		/*! Be careful to use this method. There are some flags, which
			have to be in place to make the key work correctly.
			Use add, del or toggle flags methods instead.
		*/
		virtual void				set_flags( PajaTypes::int32 i32Flags );
		//! Sets only specified flags.
		virtual void				add_flags( PajaTypes::int32 i32Flags );
		//! Removes only specified flags.
		virtual void				del_flags( PajaTypes::int32 i32Flags );
		//! Toggles only specified flags.
		virtual void				toggle_flags( PajaTypes::int32 i32Flags );
		//! Returns key flags.
		virtual PajaTypes::int32	get_flags();

		//! Serialize the key to a Demopaja output stream.
		virtual PajaTypes::uint32	save( FileIO::SaveC* pSave );
		//! Serialize the key from a Demopaja input stream.
		virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad );

	protected:
		//! Default constructor.
		KeyC();
		//! Creates new key and assign it the specified time.
		KeyC( PajaTypes::int32 i32Time );
		//! Constructor with reference to the original.
		KeyC( Edit::EditableI* pOriginal );
		//! Default destructor.
		virtual ~KeyC();

		PajaTypes::int32	m_i32Flags;
		PajaTypes::int32	m_i32Time;
	};


	//! Float Keyframe class for controller.
	/*! One float key can have
		maximum of KEY_MAXCHANNELS channels. Currently the maximum number of
		channels is 4. All the channels in the key are floating point values.

		This class is implemented by the system.
	*/
	class FloatKeyC : public KeyC
	{
	public:
		//! Create new key with zero no channels.
		static FloatKeyC*			create_new();
		//! Create new key with specified number fo channels.
		static FloatKeyC*			create_new( PajaTypes::int32 i32NumChannels );
		//! Create new key with zero no channels.
		virtual Edit::DataBlockI*	create();
		//! Creates new file handle (used internally), see Edit::EditableI::create().
		virtual Edit::DataBlockI*	create( Edit::EditableI* pOriginal );
		//! Deep copy from a data block, see Edit::DataBlockI::copy().
		virtual void				copy( Edit::EditableI* pEditable );
		//! Shallow copy from a editable, see Edit::EditableI::restore().
		virtual void				restore( Edit::EditableI* pEditable );

		//! Returns ease in value.
		virtual PajaTypes::float32	get_ease_in();
		//! Returns ease out value.
		virtual PajaTypes::float32	get_ease_out();
		//! Returns tension value.
		virtual PajaTypes::float32	get_tens();
		//! Returns continuity value.
		virtual PajaTypes::float32	get_cont();
		//! Returns bias value.
		virtual PajaTypes::float32	get_bias();
		//! Sets ease in value.
		virtual void				set_ease_in( PajaTypes::float32 );
		//! Sets ease out value.
		virtual void				set_ease_out( PajaTypes::float32 );
		//! Sets tension value.
		virtual void				set_tens( PajaTypes::float32 );
		//! Sets continuity value.
		virtual void				set_cont( PajaTypes::float32 );
		//! Sets bias value.
		virtual void				set_bias( PajaTypes::float32 );

		//! Returns the value of the key.
		/*!	If the number of channels of the key isn't absolutely know
			the following method should be used to retrieve the value:

			\code
			float32	f32Values[KEY_MAXCHANNELS];
			pKey->get_value( f32Values );
			\endcode
		*/
		virtual void				get_value( PajaTypes::float32* pValues );
		//! Sets the value of the key.
		/*!	If the number of channels of the key isn't absolutely know
			the following method should be used to set the value:

			\code
			float32	f32Values[KEY_MAXCHANNELS];
			// Set values
			f32Values[0] = 10.0f;
			pKey->set_value( f32Values );
			\endcode
		*/
		virtual void				set_value( const PajaTypes::float32* pValues );

		//! Returns the value of in-coming tangent.
		//! \see get_value
		virtual void				get_in_tan( PajaTypes::float32* pValues );
		//! Sets in-coming tangent.
		//! \see set_value
		virtual void				set_in_tan( const PajaTypes::float32* pValues );

		//! Returns the value of out-going tangent.
		//! \see get_value
		virtual void				get_out_tan( PajaTypes::float32* pValues );
		//! Sets out-going tangent.
		//! \see set_value
		virtual void				set_out_tan( const PajaTypes::float32* pValues );

		//! Serialize the key to a Demopaja output stream.
		virtual PajaTypes::uint32	save( FileIO::SaveC* pSave );
		//! Serialize the key from a Demopaja input stream.
		virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad );

	protected:
		//! Default constructor.
		FloatKeyC();
		//! Creates new key and assign it the specified time.
		FloatKeyC( PajaTypes::int32 i32Time );
		//! Constructor with reference to the original.
		FloatKeyC( Edit::EditableI* pOriginal );
		//! Default destructor.
		virtual ~FloatKeyC();

		PajaTypes::float32*	m_pValues;
		PajaTypes::int32	m_i32NumChannels;
		PajaTypes::float32	m_f32EaseIn, m_f32EaseOut;
		PajaTypes::float32	m_f32Tens, m_f32Cont, m_f32Bias;
	};


	//! File Keyframe class for controller.
	/*! The file key frame class has three properties:
		the file handle, file time offset and file time scale.
		The time properties are used to calculate the actual
		time used to evaluate the importable the file handle
		points. The time is calculate as follows:

		Input:
			CurrentTime		timeline time
			KeyTime			time of the keyframe
			KeyTimeOffest	time offset of the keyframe
			KeyTimeScale	time scale of the keyframe
		Output:
			EvalTime		time used to evaluate the importable

		EvalTime = (CurrentTime - KeyTime + KeyOffsetTime) * KeyTimeScale

		This class is implemented by the system.
	*/
	class FileKeyC : public KeyC
	{
	public:
		//! Create new key with zero no channels.
		static FileKeyC*			create_new();
		//! Create new key with specified number fo channels.
		//! Create new key with zero no channels.
		virtual Edit::DataBlockI*	create();
		//! Creates new file handle (used internally), see Edit::EditableI::create().
		virtual Edit::DataBlockI*	create( Edit::EditableI* pOriginal );
		//! Deep copy from a data block, see Edit::DataBlockI::copy().
		virtual void				copy( Edit::EditableI* pEditable );
		//! Shallow copy from a editable, see Edit::EditableI::restore().
		virtual void				restore( Edit::EditableI* pEditable );

		//! Sets the file handle used.
		virtual void					set_file_handle( Import::FileHandleC* pHandle );
		//! Returns the file handle used.
		virtual Import::FileHandleC*	get_file_handle();
		
		//! Sets the time scale.
		virtual void				set_time_scale( PajaTypes::float32 f32Scale );
		//! Returns the time scale.
		virtual PajaTypes::float32	get_time_scale() const;

		//! Sets the time offset.
		virtual void				set_time_offset( PajaTypes::int32 i32Offset );
		//! Returns the time offset.
		virtual PajaTypes::int32	get_time_offset() const;


		//! Serialize the key to a Demopaja output stream.
		virtual PajaTypes::uint32	save( FileIO::SaveC* pSave );
		//! Serialize the key from a Demopaja input stream.
		virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad );

	protected:
		//! Default constructor.
		FileKeyC();
		//! Creates new key and assign it the specified time.
		FileKeyC( PajaTypes::int32 i32Time );
		//! Constructor with reference to the original.
		FileKeyC( Edit::EditableI* pOriginal );
		//! Default destructor.
		virtual ~FileKeyC();

		PajaTypes::int32		m_i32TimeOffset;
		PajaTypes::float32		m_f32TimeScale;
		Import::FileHandleC*	m_pFileHandle;
	};


};	// namespace Parameter

#endif // __KEYC_H__
