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

		AnimUtilities.h

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

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

		Revision History

		when		who			what & why
		==========	==========	======================================================
		4/27/99		Yann		Added ITimeBased::InvalidateCaches
		01/22/99	Charles		Inlined CheckParamForRead
		11/18/98	Joshua		Moved ECloneMode to APITypes.h from TTimeBased
		11/18/98	Eml			Animation engine cleanup
		11/3/98		Emil		TTimeBasedList (was TBList in TBList.cpp/h)
		3/6/98		Greg		Initial Conversion
		
*****************************************************************************************/

#ifndef __AnimUtilities__
#define __AnimUtilities__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "MCBasicTypes.h"
#include "MCBasicDefines.h"
#include "MCCountedPtr.h"
#include "MCCountedPtrArray.h"
#include "MCSMPCountedObject.h"
#include "MCPtrArray.h"

#include "I3DShAnimation.h"

#include "APITypes.h"

struct I3DShTimeManager;
struct I3DShTweener;
struct IShTokenStream;
struct I3DShAttributesSet;


/// \addtogroup ShellInterface
/// \{


//***************************************************************************************
/// Implementation of an animated object.
/// This class is meant to be derived. Do not instanciate as it doesn't define the memory operator.
/// (TCountedTimeBased gets them from TMCSMPCountedObject)
/// 
/// \see ITimeBased
class TTimeBased : public ITimeBased
{
	protected:
		TTimeBased();
		virtual ~TTimeBased();  
	public:

		virtual MCCOMErr			MCCOMAPI QueryInterface(const MCIID& riid, void** ppvObj);

		virtual boolean				MCCOMAPI IsAnimated() const;
		virtual void				MCCOMAPI SetAnimated(boolean animated);
		virtual I3DShTimeBasedData* MCCOMAPI GetTimeBasedDataNoAddRef();
		virtual void				MCCOMAPI SetLocalTime(MicroTick inTime);
		virtual MicroTick			MCCOMAPI GetCurrentTime() const;
		virtual boolean				MCCOMAPI CheckParameterRange(int32 itsIndex, void* value, IDType type) const { return false; }
		virtual I3DShAttributesSet*	MCCOMAPI GetOverrideAttributesSet(IDType subGroupParamID) { return NULL; }

		/// You should override this if your animated data generates cached data that needs to be invalidated
		virtual void     MCCOMAPI InvalidateCaches(int32 itsID, int32 itsIndex);

		void	 SetValidForCurrentTime();
	 	MCCOMErr MarkParamAsModified(int32 index);
		inline   void CheckParamForRead(int32 index) const;
		void	 SetApproximateParamCount(uint32 Count);
		int32    SetParam		(void *aParam, const int8 *itsName, int32 itsID, int32 itsType, int8 graphColorIndex = -1); 
		int32	 InsertParam	(int32 inIndex, void* aParam, const int8* itsName, int32 itsID, int32 itsType, int8 graphColorIndex= -1);
		int32    SetParamGroup	(TTimeBased *aGroup, const int8 *itsName, int32 itsID);
		int32    InsertParamGroup	(int32 inIndex, TTimeBased *aGroup, const int8 *itsName, int32 itsID);

		/// WARNING: when removing params, be aware that all the following indexes will shift. 
		MCCOMErr RemoveParams( const int32 index, const int32 count );
		MCCOMErr ClearParams();
		MCCOMErr EnableParam(int32 index, boolean enable);
		MCCOMErr ChangeParamGroup(TTimeBased *aGroup, int32 index);

		void 	 SetTimeManager(I3DShTimeManager *timeManager);
		void	 GetTimeManager(I3DShTimeManager **timeManager);
		void 	 SetType(int32 itsType, const int8* className=nil);       

 		void	 CopyTimeData(ECloneMode mode, TTimeBased *dest) const;

		// the valid flag should be set to true in the InvalidateCaches function when
		// the parameter is invalidated
		boolean SynchWithCurrentTime(int32 index, boolean& invalidFlag, void * privData = nil)
		{
			CheckParamForRead(index);

			if (invalidFlag)
			{
				SelfSynchWithCurrentTime(index, privData);
				invalidFlag = false;

				return true;
			}
			else
			{
				return false;
			}
		}

		I3DShTimeBasedData*		GetShTimeBasedNoAddRef() const {return fTimeBasedData;}
		I3DShAttributesSet*		GetAttributesSetControler() const;


	protected:
		boolean AreParamsRegistered() const {return fParamsRegistered;}
		virtual void RegisterParams();
		virtual void SelfSynchWithCurrentTime(int32 index, void * privData);

		TMCCountedPtr<I3DShTimeBasedData> fTimeBasedData;

	private:
		void SafeRegisterParams() {if (!fParamsRegistered) RegisterParams();}

		boolean			fParamsRegistered;
};


//***************************************************************************************
/// As TTimeBased but a counted object.
class TCountedTimeBased : public TTimeBased, public TMCSMPCountedObject
{
	public:

		virtual MCCOMErr MCCOMAPI QueryInterface(const MCIID& riid, void** ppvObj);
		virtual uint32   MCCOMAPI AddRef () { return TMCSMPCountedObject::AddRef(); }
		virtual uint32   MCCOMAPI Release() { return TMCSMPCountedObject::Release(); }
};


//***************************************************************************************
/// An array of TTimeBased objects.  
class TTimeBasedList : public TMCCountedPtrArray<TTimeBased>, 
public TCountedTimeBased
{
protected:
	TTimeBasedList();
	~TTimeBasedList();
public:
	void*	operator new			(MCSize byteCount)		{ return TCountedTimeBased::operator new	(byteCount); }
	void	operator delete			(void* block)			{ TCountedTimeBased::operator delete		(block); }
	void*	operator new[]			(MCSize byteCount)		{ return TCountedTimeBased::operator new[]	(byteCount); }
	void	operator delete[]		(void* block)			{ TCountedTimeBased::operator delete[]		(block); }


	virtual void	Clone(TTimeBasedList**, ECloneMode mode) const = 0;
	void			CopyTBListData(ECloneMode mode, TTimeBasedList* dest) const;
	virtual void	TransferAllElementsFrom(TTimeBasedList* aTBList, ECloneMode cloneMode);
	void			CopyElems(TMCCountedPtrArray<TTimeBased>*	fromList, 
		int32 			firstIndex, 
		int32 			nbItems, 
		int32 			insertIndex);
	
	virtual boolean	AddElem(const TTimeBased* item);
	virtual boolean	InsertElem(uint32 i, const TTimeBased* item);
	virtual boolean	RemoveElem(uint32 i, uint32 count);
	void			Remove(TTimeBased* item);
	void			RemoveAllElem();
	
	virtual void	CheckElementsForRead();
	virtual void     MCCOMAPI InvalidateCaches(int32 itsID, int32 itsIndex);
	
protected:
	virtual void    RegisterParams();
	virtual int32	RegisterElement(int32 index, TTimeBased *elem) = 0;
	virtual void	CloneElement(TTimeBased ** clone, ECloneMode mode, const TTimeBased * elem) const = 0;
	virtual void	SetElement(int32 index, const TTimeBased *elem, ECloneMode cloneMode) = 0;
	void			SynchList();
	
	// EricB ! moved here from TComponentAnimList
	TMCArray<int32>	fParamIndices; // indices of the TParamInfo corresponding to the Element ( -1 means none )

	TMCArray<boolean>	fInvalidElements;
};

inline void TTimeBased::CheckParamForRead(int32 index) const
{
	if (fTimeBasedData)
	{
		fTimeBasedData->CheckParamForRead(index);
	}
}


//***************************************************************************************
class TCollapseCallback : public IForEachTimeLineCallback, public TMCObject
{
public:
	TCollapseCallback(I3DShTimeBasedData *aTB, I3DShParamTimeLine *merged, const TTimeInfo &previous);

	virtual void  TimeLine(I3DShParamTimeLine* inTimeLine, I3DShTimeBasedData* inMerged);
	boolean	      IsSelected() const {return fSelected;}
	void          GetBest(TTimeInfo &ti) const {ti=fBest;}
	I3DShTweener* GetTweener() const {return fTweener;}

protected:
	I3DShTimeBasedData *fTB;
	TMCCountedPtr<I3DShParamTimeLine> fMerged;
	TTimeInfo fPrevious;
	TTimeInfo fBest;
	boolean fSelected;
	I3DShTweener *fTweener;
};
/// \}
#endif

