//-------------------------------------------------------------------------
//
// File:		GizmoI.h
// Desc:		Gizmo interface.
// 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_GIZMOI_H__
#define __DEMOPAJA_GIZMOI_H__

namespace Composition {
	class GizmoI;
};

#include "PajaTypes.h"
#include "DataBlockI.h"
#include "EditableI.h"
#include "ParamI.h"
#include "UndoC.h"
#include "TimeSegmentC.h"
#include "FileIO.h"
#include "EffectI.h"
#include <string>
#include <vector>

namespace Composition {

	//! Base classID.
	const PluginClass::SuperClassIdC		BASECLASS_GIZMO = PluginClass::SuperClassIdC( 1, 5 );

	//! Gizmo interface
	/*! Gizmo holds a set of parameters, which should form a logical group of
		information, such as geometric transformation of the effect.
		Gizmo interface also contains logic to respond the change of a
		parameter. This respond can be for example to get information
		from thru a file parameter and pass it to other parameters.

		The developer of the plugin is responsible to write a gizmo class
		for each different gizmo that is used by the plugin. If only simple
		gizmo is needed, use Composition::AutoGizmoC class instead.

		To create a new instace of the gizmo class a static member should be created,
		which takes care of the instantiating. The member could look like this:

		An ID is attached to each gizmo. When a parameter is changed on a gizmo,
		the parameter send a notify to the gizmo via the update_notify() method,
		the update notify is relayed to the effect via effects update_notify method.
		When handling a notify message each parameter and gizmo can be identified from
		the ID. 

		

		\code
		TestGizmoC*
		TestGizmoC::create_new( EffectI* pParent, uint32 ui32Id )
		{
			return new TestGizmoC( pParent, ui32Id );
		}
		\endcode
	*/
	class GizmoI : public Edit::EditableI
	{
	public:
		//! Deep copy from a data block, see Edit::DataBlockI::copy().
		/*!	When overriding this method the base class member should be called first.

			Example:
			\code
			void
			TestGizmoC::copy( EditableI* pEditable )
			{
				GizmoI::copy( pEditable );
				TestGizmoC*	pGizmo = (TestGizmoC*)pEditable;
				m_pParamPos->copy( pGizmo->m_pParamPos );
				m_pParamSize->copy( pGizmo->m_pParamSize );
				m_pParamFile->copy( pGizmo->m_pParamFile );
				m_pParamCamera->copy( pGizmo->m_pParamCamera );
			}
			\endcode
		*/
		virtual void				copy( Edit::EditableI* pEditable );
		//! Shallow copy from a editable, see Edit::EditableI::restore().
		/*!	When overriding this method the base class member should be called first.

			Example:
			\code
			void
			TestGizmoC::restore( EditableI* pEditable )
			{
				GizmoI::restore( pEditable );
				TestGizmoC*	pGizmo = (TestGizmoC*)pEditable;
				m_pParamPos = pGizmo->m_pParamPos;
				m_pParamSize = pGizmo->m_pParamSize;
				m_pParamFile = pGizmo->m_pParamFile;
				m_pParamCamera = pGizmo->m_pParamCamera;
			}
			\endcode
		*/
		virtual void				restore( Edit::EditableI* pEditable );
		//! Returns the base class ID.
		virtual PluginClass::SuperClassIdC		get_base_class_id() const;

		//! Update notify from a connected editable.
		/*!	The default implementation relays the message to the
			parent effect. The base class method should be called as
			shown in the example.

			Example:
			\code
			uint32
			TestGizmoC::update_notify( EditableI* pCaller )
			{
				ParamI*	pParam = 0;

				if( pCaller->get_base_class() == BASECLASS_PARAMETER )
					pParam = (ParamI*)pCaller;

				if( pParam->get_id() == ID_TEST_PARAMFILE ) {
					// The file has changed
					// Get undo object from the changed parameter.
					UndoC*			pUndo = m_pParamFile->get_undo();
					FileHandleC*	pHandle = 0;
					MASImportC*		pImp = 0;
					// Get importable.
					pHandle = m_pParamFile->get_file();
					if( pHandle )
						pImp = (MASImportC*)pHandle->get_importable();
					if( pImp ) {
						// Update labels
						// Begin undo block.
						UndoC*	pOldUndo = m_pParamCamera->begin_editing( pUndo );
						// Set labels in camera parameter to the names of the cameras in the file.
						m_pParamCamera->clear_labels();		// m_pParamCamera is integer parameter
						for( uint32 i = 0; i < pImp->get_camera_count(); i++ ) {
							CameraC*	pCam = pImp->get_camera( i );
							if( !pCam ) continue;
							m_pParamCamera->add_label( i, pCam->get_name() );
						}
						m_pParamCamera->set_min_max( 0, pImp->get_camera_count() );
						// Close undo block.
						m_pParamCamera->end_editing( pOldUndo );
					}
				}

				// Relay the message to the effect
				return GizmoI::update_notify( ui32Id, i32Time );
			}
			\endcode

			The return value determines the how the Demopaja system has to respond to the parameter change.
			For example id the return value is PARAM_NOTIFY_UI_CHANGE, the user interface is update after the
			parameter change. Only use the PARAM_NOTIFY_UI_CHANGE if the parameter/gizmos layout
			(such as number of parameter/gizmos) has changed.

			See also:
				\see Composition::ParamSetValNotifyE
		*/
		virtual PajaTypes::uint32							update_notify( EditableI* pCaller );

		//! Returns the name of the gizmo as NULL terminated string.
		/*! Implemented by the GizmoI class. */
		virtual const char*			get_name() const;

		//! Sets the name of the gizmo.
		/*! Implemented by the GizmoI class. */
		virtual void				set_name( const char* szName );

		//! Returns number of parameters in the gizmo.
		virtual PajaTypes::int32	get_parameter_count() = 0;

		//! Returns parameter at specified index.
		virtual ParamI*				get_parameter( PajaTypes::int32 i32Index ) = 0;

		//! Returns the ID of the gizmo.
		/*! Implemented by the GizmoI class. */
		virtual PajaTypes::uint32	get_id();
		//! Sets the ID of the gizmo.
		/*! Implemented by the GizmoI class. */
		virtual void				set_id( PajaTypes::uint32 ui32Id );

		//! Returns the parent effect.
		virtual EffectI*			get_parent() const;

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

		//! Serialize the gizmo to a Demopaja output stream.
		/*!	The base class implementation of this method has to
			be called in the overridden method.

			Example:
			\code
			uint32
			TestGizmoC::save( SaveC* pSave )
			{
				uint32	ui32Error = IO_OK;
				// GizmoI stuff
				pSave->begin_chunk( CHUNK_TESTGIZMO_GIZMOI, TESTGIZMO_VERSION );
					ui32Error = GizmoI::save( pSave );
				pSave->end_chunk();
				return ui32Error;
			}
			\endcode
		*/
		virtual PajaTypes::uint32	save( FileIO::SaveC* pSave );

		//! Serialize the gizmo from a Demopaja input stream.
		/*!	The base class implementation of this method has to
			be called in the overridden method.

			Example:
			\code
			uint32
			TestGizmoC::load( LoadC* pLoad )
			{
				uint32	ui32Error = IO_OK;
				while( (ui32Error = pLoad->open_chunk()) == IO_OK ) {
					switch( pLoad->get_chunk_id() ) {
					case CHUNK_TESTGIZMO_GIZMOI:
						if( pLoad->get_chunk_version() == TESTGIZMO_VERSION )
							ui32Error = GizmoI::load( pLoad );
						break;
					default:
						assert( 0 );
					}
					pLoad->close_chunk();
					if( ui32Error != IO_OK && ui32Error != IO_END )
						return ui32Error;
				}
				return ui32Error;
			}
			\endcode
		*/
		virtual PajaTypes::uint32	load( FileIO::LoadC* pLoad );

	protected:
		//! Default constructor.
		GizmoI();
		//! Constructor.
		/*!	\param pParent pointer to the effect which is holds this gizmo.
			\param ui32Id ID of the gizmo, this ID is passed to the update_notify() method.
		*/
		GizmoI( EffectI* pParent, PajaTypes::uint32 ui32Id );
		//! Constructor with reference to the original.
		GizmoI( Edit::EditableI* pOriginal );
		//! Default destructor.
		virtual ~GizmoI();

	private:
		std::string			m_sName;
		PajaTypes::int32	m_i32Flags;
		PajaTypes::int32	m_ui32Id;
		EffectI*			m_pParent;
	};

}; // namespace

#endif // __DEMOPAJA_GIZMOI_H__