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

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

		Author:	Pierre-Sylvain
		Date:	7/7/2006

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

#ifndef __I3DExAttributesSetControler__
#define __I3DExAttributesSetControler__

#if CP_PRAGMA_ONCE
#pragma once
#endif

class  TParamHolder;


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

MCDEFINE_GUID_H(IID_I3DExAttributesSetControler);
MCDEFINE_GUID_H(IID_I3DExTreeAttributesSetControler);


struct IAttributeValueHelper
{
	// ****************************************************************************
	//								GetPreviousValue
	// 
	/// Gets the previous value of a parameter. It is the value of the parameter
	/// before applying the current controller or sub controller to it.
	///
	/// \param paramIndex		The parameter index.
	/// \param outValue			Returns value (can be NULL if the param is not supported)
	///
	/// \return True if the previous value does not exist (ie. the current value is the first
	/// value for the parameter).
	/// 
	virtual boolean				MCCOMAPI GetPreviousValue(int32 paramIndex, TParamHolder*& outValue) = 0;

	// ****************************************************************************
	//								GetCurrentValue
	// 
	/// Gets the value of a parameter. It is the value of the parameter
	/// after applying the current controller or sub controller to it.
	///
	/// \param paramIndex		The parameter index.
	/// \param outValue			Returns value (can be NULL if the param is not supported)
	/// 
	virtual void				MCCOMAPI GetCurrentValue(int32 paramIndex, TParamHolder*& outValue) = 0;

	// ****************************************************************************
	//								ApplyLocalControllerToInternalValue
	// 
	/// Apply the local controller to the internal values of a controller.
	///
	/// \param invert			If true apply the controllers in invert mode calling ComputeAttributeForWrite
	///							instead of ComputeAttributeForRead.
	/// \param inoutValue		The current internal value for the current parameter that will be
	///							modified by the local controllers.
	///
	/// \return true if the out value is valid.
	/// 
	virtual boolean				MCCOMAPI ApplyLocalControllersToInternalValue(boolean invert, TParamHolder& inoutValue) = 0;

	// ****************************************************************************
	//								CheckValueRange
	// 
	/// Check the range of the parameter value.
	///
	/// \param inoutValue		The current value for the current parameter.
	/// 
	virtual void				MCCOMAPI CheckValueRange(TParamHolder& inoutValue) = 0;
};

struct IAttributeCurrentValueHelper
{
	// ****************************************************************************
	//								ComputeInitialValue
	// 
	/// Compute the "initial" value of the parameter. This helper is used with
	/// attributes set controlers. An attributes set contains a stack of controlers.
	/// All the controlers can modify the value of a parameter and are called in the
	/// stack order. This helper is given when the function ComputeAttributeForWrite()
	/// is called on a controler. This function computes the value of the parameter
	/// but without taking all controlers into account, only those that are before the
	/// current controler. This function is need to compute offsets for instance.
	///
	/// \param value			The computed value.
	/// 
	virtual TParamHolder&		MCCOMAPI ComputeInitialValue() = 0;
};

enum EComputeAttributeForWriteRetValue
{
	kPropagateChanges,	// continue calling the other controllers and finally create a keyframe in the timeline
	kChangesRecorded,	// stop propagating changes as the controller has recorded the changes
	kChangesLost,		// stop propagating changes but the controller has not taken the change into account
						// which means that a call to ComputeAttributeForRead will modify the value
	kNoChanges,			// when nothing has been done on the value
};


/// \addtogroup ExternalInterface
/// \{

// ****************************************************************************
//								I3DExAttributesSetControler
// 
/// <P>There are two interfaces to access a component: The shell interface (I3DShAttributesSetControler) and
/// the external interface (I3DExAttributesSetControler). You can get one from the other using QueryInterface.</P>
///
/// WARNING: The animated parameters of this type of component are not validated inside the application. So
/// to get the correct value of one of your animated parameters, you need to call the CheckParamForRead()
/// in your code. Be carefull not to create stack overflow by creating circular dependencies. For instance
/// when your controller is called in ComputeAttributeForRead() for one of the paramater of your PMap and
/// you call the CheckParamForRead() on this parameter, you are creating a circular dependency as you ask for
/// the final value (after applying all controllers) when your are actually computing this final value. If
/// you do this, you will end up with a stack overflow.
///
/// \see I3DShAttributesSetControler
///
struct I3DExAttributesSetControler : public IMCUnknown
{
	// ****************************************************************************
	//								IsLocalController
	// 
	/// Returns true if the controller is a local controller and false if it is a
	/// global controller.
	//
	/// \see I3DShAttributesSet
	/// 
	virtual boolean	MCCOMAPI IsLocalController() const = 0;

	// ****************************************************************************
	//								ShowControllerOnObjects
	// 
	/// Returns true if the controller UI shall be visible on all objects part
	/// of the attributes set.
	//
	/// \see I3DShAttributesSet
	/// 
	virtual boolean	MCCOMAPI ShowControllerOnObjects() const = 0;

	// ****************************************************************************
	//								GetSubControllerCount
	// 
	/// Returns the number of sub controllers. A controller can contains multiple
	/// sub controllers. In that case, the functions ComputeAttributeForRead and
	/// ComputeAttributeForWrite will be called multiple times.
	/// 
	virtual int32	MCCOMAPI GetSubControllerCount() = 0;

	// ****************************************************************************
	//								IsSubControllerActive
	// 
	/// Returns true if the given sub controller can modify some parameter value. If
	/// not the sub controller will not be called.
	///
	/// \param subControllerIndex	The index of the sub controller.
	/// 
	virtual boolean	MCCOMAPI IsSubControllerActive(int32 subControllerIndex) = 0;

	// ****************************************************************************
	//								InvalidateAttributesMapping
	// 
	/// This function is called when the mapping of the attributes changed. This
	/// function is not called everytime something change, but only when a validation
	/// is needed (before a call to ComputeAttributeForRead() for instance). You should
	/// validate the caches that you need to update during that function. This call
	/// is protected in SMP so it is safe to do so. Doing it in ComputeAttributeForRead
	/// is not protected.
	/// 
	virtual void	MCCOMAPI InvalidateAttributesMapping() = 0;

	// ****************************************************************************
	//								ComputeAttributeForRead
	// 
	/// Called to compute the value of one of the attribute for reading.
	/// WARNING: this function is called in SMP.
	///
	/// \param value				Current value of the attribute (this parameter can be modified).
	/// \param paramIndex			The index of the parameter in the attributes set.
	/// \param subControllerIndex	The index of the sub controller to apply.
	/// \param helper				A helper class that allows to get value of other parameters for local
	///								controllers or also allows a global controller to apply the local
	///								controllers to its internal values.
	/// \param internalValue		Allows the controller to fill this value with the internal value
	///								for the controller. This value is used when applying the local controllers
	///								to controllers internal values (only for global controllers).
	/// 
	virtual void	MCCOMAPI ComputeAttributeForRead(TParamHolder& value, int32 paramIndex, int32 subControllerIndex, IAttributeValueHelper* helper, TParamHolder* internalValue) = 0;

	// ****************************************************************************
	//								ComputeAttributeForWrite
	// 
	/// Called to compute the value of one of the attribute for writing.
	///
	/// \param value				Current value of the attribute (this parameter can be modified).
	/// \param paramIndex			The index of the parameter in the attributes set.
	/// \param subControllerIndex	The index of the sub controller to apply.
	/// \param record				If true the controller can modify its internal data to take the change
	///								into account (ie. for a keyframe clip in edition mode it should create
	///								a new keyframe in the parameters timeline in the clip) otherwise the controller
	///								should not be modified.
	/// \param valueHelper			This object is an helper that allows to get the value of the current
	///								parameter before applying the current controller or sub controller (only
	///								available for global parameter).
	/// \param helper				A helper class that allows to get value of other parameters for local
	///								controllers or also allows a global controller to apply the local
	///								controllers to its internal values.
	/// \param internalValue		Allows the controller to fill this value with the internal value
	///								for the controller. This value is used when applying the local controllers
	///								to controllers internal values (only for global controllers).
	/// \return the status of the parameters. \see EComputeAttributeForWriteRetValue
	/// 
	virtual EComputeAttributeForWriteRetValue	MCCOMAPI ComputeAttributeForWrite(TParamHolder& value, int32 paramIndex, int32 subControllerIndex, boolean record, IAttributeCurrentValueHelper* valueHelper, IAttributeValueHelper* helper, TParamHolder* internalValue) = 0;

	// ****************************************************************************
	//								AttributeModified
	// 
	/// Called when an attribute has been modified.
	///
	/// \param paramIndex		The index of the parameter in the clip.
	/// 
	virtual void	MCCOMAPI AttributeModified(int32 paramIndex) = 0;

	// ****************************************************************************
	//								AttributeInvalidated
	// 
	/// Called when an attribute has been invalidated (ie. its value will be check by
	/// the next CheckParamForRead().
	///
	/// \param paramIndex		The index of the parameter in the clip.
	/// 
	virtual void	MCCOMAPI AttributeInvalidated(int32 paramIndex) = 0;
};

/// \}


/// \addtogroup ExternalInterface
/// \{

// ****************************************************************************
//								I3DExTreeAttributesSetControler
//
/// This interface is an extention of I3DExAttributesSetControler for the 
/// tree attributes sets.
//
/// \see I3DShAttributesSetControler
///
struct I3DExTreeAttributesSetControler : public IMCUnknown
{
	// ****************************************************************************
	//								OffsetTransform
	// 
	/// Offset the local tree transform of the attributes set tree (this can be used
	/// to add offsets to the whole group in order to do some clip matching for
	/// instance).
	///
	/// \param localTransform		The transform to offset.
	/// 
	virtual void		MCCOMAPI OffsetTransform(TTreeTransform& localTransform) = 0;
};

/// \}

#endif
