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

		ISceneSelection.h

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

		ISceneSelection definition

		Author:	Greg
		Date:	4/23/98
		
		Revision History

		when		who			what & why
		==========	==========	======================================================
		09/15/99	Yann		GetPath() and GetLeaves() can now return const lists
		6/10/99		Ian			Array API changes.
		4/20/99		Greg		ISceneSelection uses arrays instead of linked lists
		11/3/98		Joshua		Added Clone and Select
		6/3/98		Joshua		Converted SelectionNodes to be a linked list

*****************************************************************************************/
#ifndef __ISCENESELECTION__
#define __ISCENESELECTION__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "COMTypes.h"

#include "MCCountedPtr.h"
#include "ISelectableObject.h"

struct I3DShTreeElement;
template<class T> class TMCPtrArray;

//****** Globally Unique Ids *************************************************
MCDEFINE_GUID(IID_ISceneSelection, 0x9ab72e26, 0xd94f, 0x11d1, 0xa0, 0xd5, 0x0, 0xaa, 0x0, 0xd3, 0x7, 0xeb);

/// \addtogroup ShellInterface
/// \{

const int32	kSceneSelectionChannel = 128;


///Defines the known values TSelectionNode::fSelectedObjectKind
///Third parties should register their IDs if they need one (unlikely)
enum ESelectedObjectKind
{									//Selected object is a:
	kSelMaster3DObject			= '3DOb',	///<I3DShObject
	kSelMasterShader			= 'Shad',	///<I3DShMasterShader
	kSelMasterClip				= 'Clip',	///<I3DShMasterClip
	kSelParamInfo				= 'PrmI',	///<I3DShParamInfo
	kSelKeyFrame				= 'KeyF',	///<I3DShKeyFrame
	kSelTree					= 'Tree',	///<I3DShTreeElement
	kSelTweener					= 'Twee',	///<I3DShTweener
	kSelSceneEffects			= 'Efkt',	///<scene effects (for hierarchy)
	kSelMasterSound				= 'Msnd',	///<IShMasterSound
	kSelSoundInstance			= 'Soun',	///<IShSound
	kSelAttributesSetControler	= 'AtSC',	///<I3DShAttributesSetControler
	kSelInvalid					= 0,		///<something we dont know (shouldn't happen)
};

///<P>Each TSelectionNode contains information about a single selected object.  It contains an object kind 
///identifier to show what kind of object it is, plus an ID which will allow the parent of the object to 
///find it.  This can be specific to that kind of object and is not standardized.</P>
class TSelectionNode : public TMCObject
{
public:
	TSelectionNode	();
	~TSelectionNode	();

	IDType								fSelectedObjectKind;	///<One of the ESelectedObjectKind constants (or a third party's)
	IDType								fSelectedObjectID;		///<some way for the parent of the selected object to find it (can be an ID, or an index if you're carefull with insertions)
	TMCCountedPtr<ISelectableObject>	fSelectedData;			///<DEPRECATED (but still used for everything except kSelParamInfo) because some operations can cause that pointer to become "invalid" (eg deceased parent ParamInfo)

	boolean operator==(const TSelectionNode& sn) const;
};

class TSelectionPath : public TMCClassArray<TSelectionNode>
{
public:
	// ****************************************************************************
	//								GetObjectKind
	// 
	/// \see ESelectedObjectKind
	/// 
	/// \param TODO
	/// 
	IDType		GetObjectKind() const { return LastElem().fSelectedObjectKind; }
	boolean		operator==(const TSelectionPath& sp) const;
};


///<P>The Scene Selection handles selection of objects.  It provides methods for selecting single objects
///or trees, and accessor methods for getting lists of selectables from the scene.</P>  
struct ISceneSelection : public IMCUnknown
{
	// ****************************************************************************
	//								Clone
	// 
	/// Clone this selection. If this selection is the current selection of the scene, the new one
	/// will be considered as a copy and not as the current selection of the scene.
	/// \see IsCurrentSelection
	/// 
	/// \param newSelection    A pointer to the pointer being returned.
	/// 
	virtual void			MCCOMAPI	Clone(ISceneSelection** newSelection) = 0;

	// ****************************************************************************
	//								Select
	// 
	/// Select all the objects selected by another selection. Previous selection will be cleared.
	/// 
	/// \param inSelection  The other selection. Must be in the same scene.
	/// 
	virtual	MCCOMErr		MCCOMAPI	Select(ISceneSelection* inSelection) = 0;

	// ****************************************************************************
	//								IsMultipleSelection
	// 
	/// Return true if the selection contains more than one object.
	/// 
	/// 
	virtual boolean			MCCOMAPI	IsMultipleSelection() = 0;

	// ****************************************************************************
	//								IsEmpty
	// 
	/// Return true if the selection is empty.
	/// 
	/// 
	virtual boolean			MCCOMAPI	IsEmpty() = 0;
	
	// ****************************************************************************
	//								GetObjectCount
	// 
	/// Get the number of objects in the selection.
	/// 
	/// 
	virtual int32			MCCOMAPI	GetObjectCount() = 0;

	// ****************************************************************************
	//								GetSelectionPathByIndex
	// 
	/// 
	/// 
	/// \param TODO
	/// 
	virtual const TSelectionPath&	MCCOMAPI	GetSelectionPathByIndex(int32 index) = 0;

	// ****************************************************************************
	//								GetSelectableObjectByIndex
	// 
	/// Get an object of the selection by its index.
	/// 
	/// \param index				The index of the object in the selection.
	/// \param outSelectablePath	An array filled with the selectable objects in the path.
	/// 
	virtual ISelectableObject*		MCCOMAPI	GetSelectableObjectByIndex(int32 index, TMCPtrArray<ISelectableObject>* outSelectablePath = NULL) = 0;

	// ****************************************************************************
	//								GetTypedObjectByIndex
	// 
	/// Get an object of the selection by its index and one of its interface.
	/// 
	/// \param index   The index of the object in the selection. \see GetObjectCount
	/// \param riid    GUID of the interface.
	/// \param ppvObj  A pointer to the pointer being returned.
	/// 
	virtual MCCOMErr		MCCOMAPI	GetTypedObjectByIndex(int32 index, const MCIID& riid, void** ppvObj) = 0;

	// ****************************************************************************
	//								GetSelectedObject
	// 
	/// Get the first object in this selection that matches the given interface
	/// 
	/// \param riid GUID of the interface
	/// \param ppvObj A pointer to the pointer being returned.
	/// 
	virtual void			MCCOMAPI	GetSelectedObject(const MCIID& riid, void** ppvObj) = 0;

	// ****************************************************************************
	//								ClearSelection
	// 
	/// Remove all elements from selection.
	/// 
	/// 
	virtual void 			MCCOMAPI	ClearSelection() = 0;

	// ****************************************************************************
	//								ClearSelectionByKind
	// 
	/// Remove all elements of a kind from the selection.
	/// 
	/// \param objectKind  The kind of object to remove.
	/// \see ESelectedObjectKind
	/// 
	virtual void 			MCCOMAPI	ClearSelectionByKind(IDType objectKind) = 0;

	// ****************************************************************************
	//								IsCurrentSelection
	// 
	/// Return true if this selection is the current user selection of the document.
	/// Be careful when working on it.
	///
	/// \see Clone 
	/// 
	virtual boolean			MCCOMAPI	IsCurrentSelection() const = 0;

	// ****************************************************************************
	//								IsInSelection
	// 
	/// Check if the selection node is in the selection.
	/// 
	/// \param node	The node to check.
	/// 
	virtual ESelectState	MCCOMAPI	IsInSelection(const TSelectionNode& node) const = 0;

	// ****************************************************************************
	//								SelectTree
	// 
	/// Select a tree.
	/// 
	/// \param tree            The tree to select.
	/// \param addToSelection  If true, the tree will be added to the current selection, otherwise it will replace the selection.
	/// 
	virtual void			MCCOMAPI	SelectTree(	I3DShTreeElement* tree,boolean addToSelection) = 0;

	// ****************************************************************************
	//								CleanSelection
	// 
	/// Checks that the selected objects are still valid and removes them from the selection if needed
	/// but tries to select a parent if possible.
	/// For example, useful for an action that removes a modifier: its parameters might be selected, so the tree will replace them in the selection
	virtual void			MCCOMAPI	CleanSelection	() = 0;

	// ****************************************************************************
	//								ClearSelectionExceptKind
	// 
	/// Remove all elements of a kind other than specified from the selection.
	/// 
	/// \param objectKind  The kind of object to keep.
	/// \see ESelectedObjectKind 
    /// \see ClearSelectionByKind
	/// 
	virtual void 			MCCOMAPI	ClearSelectionExceptKind(IDType objectKind) = 0;

	// ****************************************************************************
	//								MakeCurrentSelection
	// 
	/// Make the selection the current one.
	///
	/// \param currentSelection		The current scene selection (this selection will be changed to be not current by the function)
	/// 
	virtual void			MCCOMAPI	MakeCurrentSelection(ISceneSelection* currentSelection) = 0;
};



class CWhileSwapCurrentSelection
{
public:
	CWhileSwapCurrentSelection(ISceneSelection* currentSelection, ISceneSelection* newSelection)
	: fCurrentSelection(currentSelection), fNewSelection(newSelection)
	{
		fNewSelection->MakeCurrentSelection(fCurrentSelection);
	}

	~CWhileSwapCurrentSelection()
	{
		fCurrentSelection->MakeCurrentSelection(fNewSelection);
	}

protected:
	TMCCountedPtr<ISceneSelection>		fCurrentSelection;
	TMCCountedPtr<ISceneSelection>		fNewSelection;
};

/// \}
#endif
