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

		I3DExModule.h

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

		I3DExModule definition
		External modules interface

		Author:	Ray Dream
		Date:	3/2/98

		Revision History

		when		who					what & why
		==========	================	======================================================
		8/26/99		cph					Added family ids
		8/26/99		Yann				Changes related to undoable actions for creating/destroying sub modules (MMMM)
		08/11/99	Guillaume&Christy	Added inheritance to all the Basic* classes
		05/06/99	Arnaud				Added GetPreferredRoom
		2/19/99		Joshua				Documented new Initialize call flow for modelers.
		1/18/99		Joshua				Added BuildMenuBar
		12/03/98	EricG				Moved some functionality to I3DEx3DViewClient
		11/23/98	pbk					Separating 3DDB from MCFrame
		9/18/98		Greg				Changed Module API (major change)

*****************************************************************************************/
#ifndef __I3DEXMODULE__
#define __I3DEXMODULE__

#if CP_PRAGMA_ONCE
#pragma once
#endif

#include "IExtension.h"
#include "I3DShScene.h"
#include "I3DShUtilities.h"
#include "InterfaceIDs.h"



struct IMFToolGroup;
struct IPropertiesClient;
struct IMCMenuBar;

//****** Globally Unique Ids **************************************************
MCDEFINE_GUID2(IID_I3DExModule, R_IID_I3DExModule);

/*****************************************************************************\
*  I3DExModule                                                                *
*                                                                             *
*   External modules interface                                                *
*                                                                             *
*                                                                             *
\*****************************************************************************/


#ifndef qDemoVersion //regular interface

/// \addtogroup ExternalInterface
///
/// \{


struct TToolBarInfo
{
	TToolBarInfo(int32 resID,IDType preferenceID,IDType resModule) : fResID(resID),fPreferenceID(preferenceID),fResModule(resModule) {}

	int32		fResID;				// resource ID of the tool bar
	IDType		fPreferenceID;		// ID for the preference of the toolbar
	IDType		fResModule;			// module when the resource is located
};

/// Struct used by the 3DView modelers (Vertex Modeler, 3D Paint...) to create the button
/// that activate them.
struct TModelerToolInfo
{
	TModelerToolInfo() : fImageResId(-1),fActionNumber(-1) {}

	int32					fImageResId;
	int32					fActionNumber;
	TMCDynamicString		fName;
};

/// <P>The I3DExModule Interface is used to create module of any kind, and to associate as many views
/// as you want. The cookbook example shows how to create a modeler. A module has Preferences, which
/// can be set by the user through the File menu> Preferences command just like any other module.
/// A module also has its own tool set and menu bar.</P>
///
/// <P>There are two entry points to a module. First, a module can edit data of some known type. Second,
/// if the type of data is not known, the module may import the data into a familiar type. Refer to
/// I3DExModule::Edit() for details.</P>
///
/// <P><B>Resources:</B></P>
/// <P>In addition to the usual 'Comp' and 'PMAP' resources,
///  you need to provide a 'Modu' resource of the same ID to specify parameters
///   such as the 'MBAR' (Menu Bar) ID, the 'TBAR' (Tool Bar) ID, the Preferences
///  'View' ID, etc. See ExternalAPI.r.</P>
///
/// <P><B>Preferences:</B></P>
/// <P>The Shell can read and write your Module Preferences data automatically
/// from/to the Preferences file, and gives this data to your Module using
/// the I3DExModule::SetPrefs() call just before calling I3DExModule::Edit().</P>
///   - In the 'Modu' resource, choose a Preferences View ID and a 'Prfs' ID
///     (the 'Prfs' resource contains the default values if a Preferences
///     file has to be created from scratch by the Shell. To make a 'Prfs'
///	    resource, copy/paste the part of the Preferences File related to
///	    your Module into the 'Prfs' resource.
///
///	  - Build your Preferences View
///
///	  - Add to the Module's 'PMAP' the items of the View. You will note that
///	    the same PMAP is used for the Module's View and its Preferences. This
///		is not a real problem as int32 as you use distinct IDs for the UI
///		elements (buttons, check boxes, etc.).
///		If you do not wish to have Preferences, put 0 in the Preferences View ID
///		of the 'Modu' resource.
///
///	<P>Note that the preference 'PMAP' is used only for preferences global to the
///	application. Preferences local to a document can be set using the 'PMAP' of the
///	modul (this is valid only for a 'scene' modul). To save the local preferences in
///	the .car file, SavesInNativeFormat() must be implemented and return true.</P>
///
struct I3DExModule : public IMCUnknown
{
	/// <P>Initialize() is called during creation of the module to initialize UI elements,
	/// and set the editing element.  inElement is the element that the module
	/// edits.  Override this function to create UI elements such as windows and
	/// initialize any data for your module.</P>
	/// <P>Use QueryInterface on the inElement object to get the specific interface
	/// you need.  Scene Document Modules will get an I3DShGroup object.</P>
	/// <P>Modelers get two calls to Initialize.  First, they get passed the universe
	/// group as all Scene Document Modules do.  Next, they get passed the master object
	/// in the scene selection which they are to edit.  In addition, if the user leaves
	/// the modeling room and re-enters with a different object selected, Initialize
	/// is called again with the new object to edit.</P>
	///
	/// <P>Global Modules do not get any object, the have a NULL inElement.</P>
	///
	virtual MCCOMErr MCCOMAPI Initialize(IMCUnknown* inElement) = 0;
		
	/// Destroy() is called once when the module is to be destroyed (e.g., Scene Document Modules
	/// are called when the document closes, Global Modules are called when the
	/// application is quit).  Override this function to destroy UI elements and
	/// cleanup any data---you need destroy your slave modules, since you are in charge of them
	virtual MCCOMErr MCCOMAPI Destroy() = 0;
		
	/// Hydrate() is called when the module is to be hydrated; that is, the room that it occupies
	/// is entered.  If this module is a main module (i.e., it defines a room), override
	/// this function to show any main windows and call Hydrate() on slave modules.
	/// If this module is a slave module, override this function to prepare to be
	/// activated and call Hydrate() on any subslave modules.  This may involve showing
	/// windows, but should not install parts in shared windows since Hydrate() does
	/// not mean the module is active (see Activate() below). Also note that your
	/// window may have been closed by someone else (in this case you had been told thru
	/// AboutToCloseMainWindow), so you will have to recreate your window.
	virtual MCCOMErr MCCOMAPI Hydrate() = 0;
	
	/// Dehydrate() is called when the module is to be dehydrated; that is, the room that it occupies
	/// is exited.  If this module is a main module (i.e., it defines a room), override
	/// this function to hide any main windows and call Dehydrate() on slave modules.
	/// If this module is a slave module, override this function to destroy large
	/// caches and parts and call Dehydrate() on any subslave modules.
	/// NOTE: Deactive() is called before Dehydrate() on an active module.
	virtual MCCOMErr MCCOMAPI Dehydrate() = 0;

	/// Activate() is called when the module is to be activated.  If this module is a main module 
	/// (i.e., it defines a room), one of its main windows has been activated; override
	/// this function to call Activate() on slave modules.  If this module is a slave module, 
	/// override this function to activate and call Activate() on any subslave modules.
	/// This may involve showing windows, and may install parts in shared windows.
	virtual MCCOMErr MCCOMAPI Activate() = 0;
		
	/// Deactivate() is called when the module is to be deactivated.  If this module is a main module 
	/// (i.e., it defines a room), all of its main windows has been deactivated; override
	/// this function to call Deactivate() on slave modules.  If this module is a slave module, 
	/// override this function to deactivate and call Deactivate() on any subslave modules.
	/// This may involve hiding windows, and may uninstall parts out of shared windows.
	virtual MCCOMErr MCCOMAPI Deactivate() = 0;

	/// Import() is called when the module is asked to import some foreign data. For example,
	/// a modeler could be asked to import the facets of another primitive. It is up to the
	/// module to do something or not with 'inElement'. The module should rely on inElement->QueryInterface 
	/// to decide if it can do anything with it of not. In any case, 'inElement' should be left intact.
	/// 'inImportData' points to some data block depending on the type import. For example, for
	/// modelers, 'inImportData' will be a real32* containing the Fidelity.
	virtual	MCCOMErr MCCOMAPI Import(IMCUnknown* inElement, void* inImportData) = 0;

	/// BuildMenuBar() gives you opportunity to add menus dynamically (instead os using a MBAR resource)
	/// Use gShMenuUtilities to add menu items
	virtual MCCOMErr MCCOMAPI BuildMenuBar(IMCMenuBar* theBar) = 0;
	
	/// If the module does not define a room (eg the rendering module), this function is called 
	/// to determine in which room the module wants to be put in.
	/// By default the module will be added in the current room.
	virtual MCCOMErr MCCOMAPI GetPreferredRoom(IDType& roomId) = 0;

	/// Tell if the module can be inserted in the current room
	virtual boolean MCCOMAPI WantsToBeInCurrentRoom() = 0;

	/// SubModuleClosedMainWindow() will be called by any sub module that have its Main Window being closed, 
	/// so you can react and tell it that it is OK to commit suicide (return true).
	/// (Note : you tell a sub module that you are its "master" by calling I3DShModule::SetMasterModule())
	virtual boolean MCCOMAPI SubModuleClosedMainWindow(I3DShModule* subModule) = 0;

	/// SubModuleAboutToBeDestroyed() will be called by any sub module that is about to be destroyed, 
	/// so you can react.
	/// (Note : you tell a sub module that you are its "master" by calling I3DShModule::SetMasterModule())
	virtual MCCOMErr MCCOMAPI SubModuleAboutToBeDestroyed(I3DShModule* subModule) = 0;

	/// SubModuleAboutToBeHydrated() will be called by any sub module that is about to be hydrated, 
	/// so you can react.
	/// (Note : you tell a sub module that you are its "master" by calling I3DShModule::SetMasterModule())
	virtual MCCOMErr MCCOMAPI SubModuleAboutToBeHydrated(I3DShModule* subModule) = 0;

	/// Returns true if this master module have a sub module active
	virtual boolean			MCCOMAPI HaveSubModuleActive			() = 0;

	/// AboutToCloseMainWindow() is called when your main window is about to be closed by someone else.
	/// It is very important to release any references that your module may have on your window. You do not 
	/// need to close it, since this "someone" is going to do it.
	virtual MCCOMErr MCCOMAPI AboutToCloseMainWindow() = 0;

	///whether the module wants to save data in the nativefile format
	virtual	boolean			MCCOMAPI SavesInNativeFormat() = 0;


	// ****************************************************************************
	//								GetToolBarsInfo
	// 
	/// Returns the toolbars associated with the module (the first one should the main toolbar)
	/// 
	/// \param toolbarList  The list of toolbars that should be created.
	/// 
	virtual void MCCOMAPI GetToolBarsInfo(TMCArray<TToolBarInfo>& toolbarList) = 0;

	//Adds tools to the module's toolgroup (implement only if you have a dynamic tool group).
	virtual	void			MCCOMAPI AddTools(int32 toolbarIndex,IMFToolGroup*	inToolGroup) = 0;


	/// Get the default properties client for this module.
	///
	/// \param outPropClient 
	/// 
	virtual	MCCOMErr		MCCOMAPI GetDefaultPropertiesClient(IPropertiesClient** outPropClient) = 0;


	/// Returns the size of your prefs buffer (eg sizeof(fPrefs)), 0 if you don't have one
	virtual int32			MCCOMAPI GetPrefsBufferSize			() const = 0;

	// ****************************************************************************
	//								GetMainToolInfo
	// 
	/// Returns the information about the main tool that activate the modeler in
	/// the 3DView. Note that this function is only implemented by modelers
	/// that can be instantiated in the 3DView (Vertex Modeler, 3D Paint...).
	///
	/// \param mainToolInfo		A struct describing the tool.
	/// 
	virtual MCCOMErr		MCCOMAPI GetMainToolInfo(TModelerToolInfo& mainToolInfo) = 0;

	// ****************************************************************************
	//								IsToolBarActive
	// 
	/// Returns true if the toolbar is active.
	///
	/// \param toolBarIndex		The index of the toolbar (same as in GetToolBarsInfo()).
	/// 
	virtual boolean			MCCOMAPI IsToolBarActive(int32 toolBarIndex)=0;

	/// Called when the internal module is attached to a document
	virtual void			MCCOMAPI DocumentAttached			() = 0;
};

/// \}

#else 	//(qDemoVersion) begin scrambled interface

struct I3DExModule : public IMCUnknown
{	
	virtual boolean MCCOMAPI SubModuleClosedMainWindow(I3DShModule* subModule) = 0;	
	virtual MCCOMErr MCCOMAPI Destroy() = 0;	
	virtual MCCOMErr MCCOMAPI Dehydrate() = 0;	
	virtual MCCOMErr MCCOMAPI Hydrate() = 0;
	virtual MCCOMErr MCCOMAPI Deactivate() = 0;
	virtual MCCOMErr MCCOMAPI Activate() = 0;
	virtual	MCCOMErr MCCOMAPI Import(IMCUnknown* inElement, void* inImportData) = 0;	
	virtual MCCOMErr MCCOMAPI BuildMenuBar(IMCMenuBar* theBar) = 0;
	virtual int32	 MCCOMAPI GetPrefsBufferSize			() const = 0;
	virtual	void	 MCCOMAPI AddTools(IMFToolGroup*	inToolGroup) = 0;
	virtual MCCOMErr MCCOMAPI GetPreferredRoom(IDType& roomId) = 0;	
	virtual boolean MCCOMAPI WantsToBeInCurrentRoom() = 0;	
	virtual MCCOMErr MCCOMAPI Initialize(IMCUnknown* inElement) = 0;
	virtual MCCOMErr MCCOMAPI AboutToCloseMainWindow() = 0;
	virtual MCCOMErr MCCOMAPI SubModuleAboutToBeDestroyed(I3DShModule* subModule) = 0;
	virtual MCCOMErr MCCOMAPI SubModuleAboutToBeHydrated(I3DShModule* subModule) = 0;
	virtual	MCCOMErr		MCCOMAPI GetDefaultPropertiesClient(IPropertiesClient** outPropClient) = 0;
	virtual	boolean			MCCOMAPI SavesInNativeFormat() = 0;
	virtual boolean			MCCOMAPI HaveSubModuleActive			() = 0;
};

#endif	//(qDemoVersion) end scrambled

#endif
