//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

namespace mudbox {

/// Holds information about the a recent or in-progress file event. See m_pFileEvent for more information.
class MBDLL_DECL FileEvent : public Node
{
	DECLARE_CLASS;

	enum Type
	{
		/// The user is about to browse for a file to read. You can catch this event and change the default browsing path.
		typeBrowseForRead,
		/// The user is about to browse for a file to write. You can catch this event and change the default browsing path.
		typeBrowseForWrite,
		/// Mudbox is about to read a file. You can catch this event and specify an alternative file.
		typePreRead,
		/// Mudbox just finished reading a file. This event is for information only.
		typePostRead,
		/// Mudbox is about to write a file. You can catch this event and specify an alternative file.
		typePreWrite,
		/// Mudbox just wrote a file. This event is for information only.
		typePostWrite
	} m_eType;
	/// Name of the file, or path of the current operation. This member variable can be modified for some events.
	QString m_sFileName;
};

class MBDLL_DECL KeyboardEvent : public Node
{
	DECLARE_CLASS;

	/// Type of the event.
	enum Type
	{
		ePressed,
		eReleased
	} m_eType;
	/// Code of the key that was pressed or released.
	int m_iKey;
	/// The keyboard modifier flags that existed immediately after the event occurred. See the description of Qt::KeyboardModifier
	/// for the possible values.
	int m_iModifiers;
};


class Operation;
/// \brief The main API access point to Mudbox, contains the most basic functions and data.
/// 
/// There is exactly one Kernel object, you use the Kernel() global function to access it.
class MBDLL_DECL Kernel : public Node
{
	DECLARE_CLASS;
public:
	enum MessageBoxType
	{
		msgInformation,
		msgWarning,
		msgQuestion,
		msgError
	};
	enum MessageBoxButton
	{
		buttonNone		= 0x00000000,
		buttonOk		= 0x00000400,
		buttonCancel	= 0x00400000,
		buttonClose		= 0x00200000,
		buttonYes		= 0x00004000,
		buttonYesToAll	= 0x00008000,
		buttonNo		= 0x00010000,
		buttonNoToAll	= 0x00020000,
		buttonAbort		= 0x00040000,
		buttonRetry		= 0x00080000,
		buttonIgnore	= 0x00100000,
		buttonHelp		= 0x01000000
	};
	enum HUDMessageType
	{
		HUDmsgPin,		///< keep the HUD message up until specifically cancelled
		HUDmsgFade		///< make the message fade away after a few seconds
	};

	enum StatusType
	{
		stNormal,		///< message
		stWarning,		///< warning
		stError			///< error
	};

	/// Constructor.  There is exactly one kernel in Mudbox, so you should never try to create one.
	Kernel( void );	

	/// \brief Writes a message to Mudbox's internal log.
	///
	/// The log can be viewed inside Mudbox in the "log" view, 
	/// or by readin the mudbox.log file written by the application. 
	/// (located at your documents/Mudbox/2009/data/Logs/mudbox.log on windows)
	///
	/// This method takes the same arguments as the standard printf call, allowing you to easily
	/// format your data.
	void Log( const char *pMessage, ... );
	
	/// Logs the current memory status. For debugging purposes only.
	void LogMemoryStatus(
		bool bCompact = true	///< [in] If \b true, write the status in a more compact form.
		);
	
	/// \brief Logs current memory blocks (which are used by the Store class).
	///
	/// Blocks smaller than fSizeLimit*(largest block size) 
	/// will not be logged. This call is mostly used to detect memory leaks.
	void LogMemoryBlocks(
		float fSizeLimit = 0.01	 ///< [in] Specifies the minimum size of block that will be logged (this value times the largest block)
		);
	
	/// Displays a modal message box to the user.
	int MessageBox(
		MessageBoxType iType,	///< [in] One of Kernel::msgInformation, Kernel::msgWarning, Kernel::msgQuestion or Kernel::msgError
		const QString &sTitle,	///< [in] The title of the message box
		const QString &sText,	///< [in] The text of the message
		int iButtons = buttonNone,	///< [in] The buttons to include.  Specify this as a bitwise OR of the available MessageBoxButton flags.
		int iDefaultButton = buttonNone	///< [in] Specifies which of the buttons should be the default when the window opens
		);

	/// \brief Displays a message as text overlay (HUD) in the 3d view.
	///
	/// You can specify if the
	/// message is temporary (fading after a few seconds) or if it should stay "pinned" on the
	/// screen until overwritten or dismissed with HUDMessageHide().  New messages will replace previous
	/// ones.
	void HUDMessageShow(
		const QString &sMessage, ///< [in] The text of the message (may include some HTML tags, such as for <b>bold</b> or <i>italics</i>)
		HUDMessageType iType	///< [in] One of Kernel::HUDmsgPin or Kernel::HUDmsgFade
		);
		
	/// \brief Hides a text overlay (HUD) message created with a call to HUDMessageShow().
	///
	/// \b Note: if a message was displayed with the Kernel::HUDmsgFade parameter, then it will go away after
	/// a few seconds with no intervention.
	void HUDMessageHide();
	
	/// Display a message in the status bar, which is on the bottom edge of the Mudbox window.
	void SetStatus(
		StatusType iType,	///< [in] Determines the color of the message.  One of Kernel::stNormal, Kernel::stWarning, or Kernel::stError
		const QString& sMsg	///< [in] The text of the message
		);

	/// \brief Adds a new submenu to the interface that can be used to create and edit instances of a class you define in your plug-in.
	///
	/// For example, if you call:
	/// \code
	///		Kernel()->AddClassMenuItem( "Maps", "MyItem", myClass::StaticClass(), "Make New Instance" );
	/// \endcode
	/// A new submenu (named "MyItem") will be added to the end of the "Maps" menu.
	/// This new submenu will initially contain one item, called "Make New Instance".
	/// If you select this item, a new instance of myClass will be created, and 
	/// an editor opened for it so you can change its values.  The name of the new
	/// instance will also be added to the "MyItem" submenu, so that you can go
	/// back and edit it later.
	///
	/// Note that "StaticClass()" is automatically defined for any class that uses the IMPLEMENT_CLASS macro.
	///
	void AddClassMenuItem(
		const QString &sMenu,			///< [in] The name of the menu to which your sub-menu will be added.
		const QString &sSubmenu,		///< [in] The name of the sub-menu to be created
		const ClassDesc *pClass,		///< [in] The class to be created by the new menu item
		const QString &sCreatorText,	///< [in] The name of the menu item that will create your new class
		const int &index = -1			///< [in] The index where you want to insert the new menu, -1 means append to the end of menu
		);

	/// \brief Adds a new menu item that calls a callback function you specify in your plug-in.
	///
	/// The signature of your callback function must be:
	/// \code
	///		void myCallback();
	/// \endcode
	void AddCallbackMenuItem(
		const QString &sMenu,		///< [in] The name of the menu to which the item should be added
		const QString &sSubmenu,		///< [in] The name of a submenu to which the item should be added (if you don't want a submenu, pass in an empty QString)
		const QString &sItemName,	///< [in] The name of the new menu item that will call your callback
		void (*pCallback)(),		///< [in] A pointer to the callback function
		const int &index = -1		///< [in] The index where you want to insert the new menu, -1 means append to the end of menu
		);

	/// \brief Creates an empty mesh object and returns a pointer to it.
	///
	/// Mesh objects must be entirely triangles, or entirely quads.
	Mesh *CreateMesh(
		Topology::FaceType eType	///< [in] The mesh type, one of Topology::typeTriangular or Topology::typeQuadric
		);

	/// Displays a progress bar, to show a process beginning.  This will set the current progess value to 0.
	void ProgressStart(
		const QString &sDescription,		///< [in] A name or description for the process whose progress is being shown
		unsigned int iMaxValue			///< [in] A positive value representing the completion of the process
		);
	
	/// Updates the current progress bar.
	void ProgressSet(
		unsigned int iValue		///< [in] The new progress value (the maximum allowed value was specified in ProgressStart() )
		);
	
	/// Updates the current progress bar by adding one to the progress value used.
	void ProgressAdd( void );
	
	/// Removes the current progress bar, whether or not the process is complete.
	void ProgressEnd( void );
	
	/// \brief Returns true if the user cancelled an operation in progress.
	///
	/// When a progress bar is displayed, the user can cancel out of the operation in progress by clicking the
	/// cancel button, or by hitting the ESC key.  If your plug-in is running a long process with a progress bar
	/// showing, it should call this method regularly to see if the user has cancelled the operation.
	bool ProgressIsCancelRequested( void );

	/// \brief Opens a modal file dialog so the user can choose an existing file to open.  Returns the path to the file.
	///
	/// If the user cancels out of the file dialog, an empty QString is returned.
	QString LoadFileDialog(
		const QString &sTitle,	///< [in] The title to display in the file dialog
		const QString &sPath,	///< [in] The initial path to display when the file dialog opens
		const QString &sFilter	///< [in] A QString that specifies which kind of files should be displayed.  For example: "TIFF images (*.tif);;PNG images (*.png)"
		) const;
	
	/// \brief Opens a modal file dialog so the user can choose a file name to save to.  Returns the path to the file.
	///
	/// If the user cancels out of the file dialog, an empty QString is returned.
	QString SaveFileDialog(
		const QString &sTitle,			///< [in] The title to display in the file dialog
		const QString &sPath,			///< [in] The initial path to display when the file dialog opens
		const QString &sFilter,			///< [in] A string that filters which kind of files should be displayed.  For example: "TIFF images (*.tif);;PNG images (*.png)"
		bool bAskForOverwrite = true,	///< [in] If \b true, when the user chooses an existing file, he will be asked if he wants to overwrite it.
		QString* sSelectedFilter = 0		///< [in] The filter that should be used by default
		) const;
		
	/// Show the wait cursor.
	void WaitCursorStart( void );
	
	/// Restore the previous cursor after calling WaitCursorStart().
	void WaitCursorEnd( void );

	// Automation

	/// \brief Records a command to the mudbox automation file.
	///
	/// As commands are executed in Mudbox, it records them into an automation file so that they can be played back
	/// later, usually for testing or debugging purposes.  If you want your plugin actions to be recorded, call this
	/// method to record what it did.  The format of this recordins should be a unique name for the command, followed
	/// by a list of arguments.
	///
	/// \b Note: this method takes the same arguments as standard printf, making it easy to specify arguments in your call.
	///
	/// If you record your plugin commands, then you also need to be able to play them back from your recording.  To do
	/// this, define a variable of type \b astring in your plugin, and connect it to the m_sNextCommand variable of the
	/// Kernel, which always contains the string value of the next command to be performed.  This connection is done
	/// like this:
	/// \code
	///		astring myNextCommand;
	///		...
	///		myNextCommand.Connect( Kernel()->m_sNextCommand );
	/// \endcode
	/// Once you have done this, myNextCommand will change every time the variable in the Kernel changes, and you can
	/// capture that even to see if it is your command string.  If it is, you run the command like this:
	/// \code
	///		void myClass::OnNodeEvent( const Attribute &cAttribute, NodeEventType eType )
	///		{
	///			if ( eType == etValueChanged && cAttribute == myNextCommand )
	///			{
	///				// get the first word in the command
	///				String sOperation = myNextCommand.Value().Section( ' ', 0 ); 
	///				if ( sOperation == "myCommandName" ){
	///					...get arguments and process your command here
	///	\endcode
	void RecordCommand( const char *sCommand, ... );

	/// This attribute always contains the next command. Plugins can link their own attribute to this one, and can process commands this way.  See RecordCommand().
	astring m_sNextCommand;

	/// Creates a default mudbox scene and returns it.
	class Scene *CreateDefaultScene( void );

	// plugin management
	/// \brief Returns the 'preferred descendant' of a public interface, which must be used to create instances.
	///
	/// In the mudbox SDK you will find lots of interfaces defined without any functionality, such as Texture and Image.
	/// Plugins can implement these interfaces by defining their own classes inherited from an SDK interface.
	/// When the functionality is needed somewhere, then this function can tell you what the 
	/// best available implementation is.  You can then create one instance of that class and access the
	/// functionality you need. You should use the CreateInstance() global templated function to create
	/// those object.  (It uses PreferredDescendant() internally, but provides a more comfortable way to
	/// access those functionalities.)
	const ClassDesc *PreferredDescendant(
		const ClassDesc *pClass		//< [in] The ClassDesc of a base class (obtained via the StaticClass() function:  myClass::StaticClass() )
		) const;
	
	/// \brief Creates an instance of the preferred descendant of an interface class.
	///
	/// See PreferredDescendant() for more
	/// details. We recommend using the CreateInstance() global function instead of this.
	Node *CreateClassInstance( const ClassDesc *pClass ) const;

	/// Creates a new image instance, loads a file to it, and returns the pointer.
	///
	/// It is the responsibility of the caller to delete the returned Image.
	///
	/// /b Note: This function will be removed from future releases of the SDK.
	Image *LoadImage(
		const QString &sFileName		///< [in] Path of the image file to be opened.
		) const;

	/// Checks to see if there was an OpenGL error, and writes it to the mudbox log.  Used for debugging.
	void GLCheckError(
		const char *sSourceFileName,	///< [in] The name of the file where this is being called
		const char *sFunctionName,		///< [in] The name of the function from which this is being called
		unsigned int iLine				///< [in] The line number where this is being called
		) const;
	
	/// Checks if the opengl states are all set to their default values, and writes the result to the Mudbox log.  Used for debugging.
	void GLCheckStates(
		const char *sSourceFileName,	///< [in] The name of the file where this is being called
		const char *sFunctionName,		///< [in] The name of the function from which this is being called
		unsigned int iLine				///< [in] The line number where this is being called
		) const;


	/// \brief Forces a full refresh of the 3d viewport.
	///
	/// This function is obsolete, use ViewPort::Redraw instead.
	void Redraw( void );

	/// Returns a pointer to the current scene.
	class Scene *Scene( void ) const;
	
	/// Returns a pointer to the preferences.
	mudbox::Preferences *Preferences( void ) const;
	
	/// Returns a pointer to the interface.
	class mudbox::Interface *Interface( void ) const;

	/// Returns a pointer to the program statistics.
	class Statistics *Statistics( void ) const;
	
	/// Returns a pointer to the current viewport.
	class ViewPort *ViewPort( void ) const;
	
	/// Returns a pointer to the main window.
	QWidget *MainWindow( void ) const;

	/// Adds a view in the central widget.
	void AddView(QString className, QString windowTitle, const bool select = false) const;

	/// Registers the Mudbox Community web browser
	void RegisterWindowPlugin(WindowPlugin* plugin) const;

	/// Returns a pointer to the tray accessor.
	mudbox::TrayAccessor *TrayAccessor( void ) const;

	/// Extracts an archived file to destination.
	bool ExtractArchiveFile(QString sArchiveFilePath, QString sDestPath);
	bool CreateArchiveFile(QString sArchiveFilePath, QStringList files);

	/// Adds a mesh to the Create->Mesh menu.
	void AddToCreateMeshMenu(QFileInfo fileInfo);
	
	/// Returns the path to where the Mudbox application is installed.
	QString ApplicationDirectory( void ) const;
	
	/// Returns the path of the project files
	QString ProjectFilesDirectory( void ) const;
	
	/// Returns the root path to where the application can safely write files.
	QString SafeWritableDirectory( void ) const;
	
	/// Returns the path from which the specified plugin was loaded
	QString PluginDirectory( const QString& pluginName ) const;
	
	/// Returns \b true if the application is in testing mode 
    /// (i.e. was started with the -test command line parameter).
	bool IsTestModeOn( void ) const;
	
	/// Refresh all dialogs
	void RefreshUI( void ) const;
	
    /// Describes how to render the scene off-screen with RenderScene
    enum SceneRenderMode {
        srmNormal = 0,          ///< Renders the scene as it would appear in the interactive viewport
        srmFlatTexturesOnBlack, ///< flat shaded, textures on black material background, no grids, curves or background
        srmFlatTexturesOnWhite, ///< flat shaded, textures on white material background, no grids, curves or background
        srmFlatNoTextures,      ///< flat shaded, no textures, grids, curves or background
        srmNoTextures           ///< flat shading off, textures off, no grids, curves or background 
    };

	/// \brief Renders the scene, and returns it in an image
	///
	/// Does not include extra things like the HUD or the cursor ring.  
    /// Returns a pointer to an image object that the scene was rendered into.  
    /// You can specify  the desired size for the rendering, or leave the input 
    /// variables set to 0  to render at the current screen resolution.
    /// 
    /// You can also describe a render mode -- the different render modes can be 
    /// used together to  extract unprojected textures or extract shading/shadow 
    /// information.
	///
    /// currently only 8 bit images are supported by this operation  
	/// \b Note:  Once the image is returned, it is your responsibility to delete
	/// it when you are done with it.
	Image *RenderScene(
		const QString &sChannel, ///< [in] the name of the channel to render
		int  iWidth,		///< [in] The width of the rendering in pixels.  Set to 0 to use current screen size.
		int  iHeight,		///< [in] The height of the rendering in pixels.  Set to 0 to use current screen size.
        SceneRenderMode renderMode, ///< describes variations on how to render the scene.
        enum Image::Format fmt = Image::e8integer, ///< [in] Desired image format. 
        bool bTiledImg = true ///< [in] hint -- true if the resulting image is to be tiled, false if contiguous.
		);

	/// \brief Renders the scene, and returns it in an image
	///
	/// Does not include extra things like the HUD or the cursor ring.  
    /// Returns a pointer to an image object that the scene was rendered into.  
    /// You can specify  the desired size for the rendering, or leave the input 
    /// variables set to 0  to render at the current screen resolution.
    /// 
    /// You can also describe a render mode -- the different render modes can be 
    /// used together to  extract unprojected textures or extract shading/shadow 
    /// information.
	///
    /// currently only 8 bit images are supported by this operation  
	/// \b Note:  Once the image is returned, it is your responsibility to delete
	/// it when you are done with it.
	Image *RenderScene(
		int  iWidth,		///< [in] The width of the rendering in pixels.  Set to 0 to use current screen size.
		int  iHeight,		///< [in] The height of the rendering in pixels.  Set to 0 to use current screen size.
        SceneRenderMode renderMode, ///< describes variations on how to render the scene.
        enum Image::Format fmt = Image::e8integer, ///< [in] Desired image format. 
        bool bTiledImg = true ///< [in] hint -- true if the resulting image is to be tiled, false if contiguous.
		);

	/// \brief Renders the scene, including background and post-process filters, 
    /// and returns it in an image
	///
	/// Does not include extra things like the HUD or the cursor ring.  Returns
	/// a pointer to an image object that the scene was rendered into.  You can 
    /// specify  the desired size for the rendering, or leave the input 
    /// variables set to 0  to render at the current screen resolution.
	///
    /// currently only 8 bit images are supported by this operation  
	/// \b Note:  Once the image is returned, it is your responsibility to delete
	/// it when you are done with it.
	Image *RenderScene(
		int  iWidth,	      ///< [in] The width of the rendering in pixels.  Set to 0 to use current screen size.
		int  iHeight,		  ///< [in] The height of the rendering in pixels.  Set to 0 to use current screen size.
        enum Image::Format fmt = Image::e8integer, ///< [in] Desired image format. 
        bool bTiledImg = true ///< [in] hint -- true if the resulting image is to be tiled, false if contiguous.
		) const;


    /// Creates a 4 channel image containing the unprojected textures of the 
    /// scene using the current camera position and settings. The image will 
    /// be rendered at the specified size, or if the  specified width and 
    /// height are 0, it will use the current viewport size. 
    /// currently only 8 bit images are supported by this operation  
    /// Resulting images currently must be untiled.          

    Image *ExtractUnprojectedTextures(const QString &sChannel, ///< [in] the name of the channel to render
									  int  iWidth,   ///< [in] The width of the rendering in pixels.  Set to 0 to use current screen size.   
                                      int  iHeight,  ///< [in] The height of the rendering in pixels.  Set to 0 to use current screen size.  
                                      enum Image::Format fmt = Image::e8integer, ///< [in] Desired image format. Currently must be e8integer
                                      bool bTiledImg = false ///< [in] hint -- true if the resulting image is to be tiled, false if contiguous.
        );

    Image *ExtractUnprojectedTextures(int  iWidth,   ///< [in] The width of the rendering in pixels.  Set to 0 to use current screen size.   
                                      int  iHeight,  ///< [in] The height of the rendering in pixels.  Set to 0 to use current screen size.  
                                      enum Image::Format fmt = Image::e8integer, ///< [in] Desired image format. Currently must be e8integer
                                      bool bTiledImg = false ///< [in] hint -- true if the resulting image is to be tiled, false if contiguous.
        );

	/// Creates a 4 channel image containing the shading of the scene using the
    /// current camera position and settings. The image will be rendered at the 
    /// specified size, or if the specified width and height are 0, it will use 
    /// the current viewport size. The result of this image, blended over a flat 
    /// shaded version of the scene will appear as though the shading and 
    /// shadowing were turned on.
    /// currently only 8 bit images are supported by this operation
    /// Resulting images currently must be untiled.         
     
    Image *ExtractShadingMap(int iWidth,            ///< [in] The width of the rendering in pixels.  Set to 0 to use current screen size.   
                             int iHeight,           ///< [in] The height of the rendering in pixels.  Set to 0 to use current screen size.  
                             enum Image::Format fmt = Image::e8integer,  ///< [in] Desired image format. Currently must be e8integer 
                             bool bTiledImg = false ///< [in] hint -- true if the resulting image is to be tiled, false if contiguous.
        );


	/// Returns the current width of the viewport in pixels
	int ViewportWidth() const;
	
	/// Returns the current height of the viewport in pixels
	int ViewportHeight() const;

	/// \brief Informs the kernel of video memory usage changes. 
	///
	/// When a plugin allocates or frees video memory, it should call this 
    /// function to inform mudbox about the change. If it doesn't call this 
    /// function, then Mudbox will not know how much video memory is available.
	/// This information is used to optimize some operations. When video memory 
    /// is deallocated, the iSize parameter should be negative.
	void ReportVideoMemoryUsage(
		int64 iSize		///< [in] The amount of video memory memory used (positive numbers) or released (negative numbers) in bytes
		);
	
	/// Returns the total amount of video memory currently in use in bytes
	int64 VideoMemoryUsage( void ) const;
	
	/// \brief This function executes an operation and makes it possible to undo/redo the operation later.
	///
	/// If a plugin wants an operation to be undoable, it must execute the operation using this function call.
	/// \see mudbox::Operation 
	bool DoOperation(
		Operation *pOp, ///< [in] Address of the operation which has to be executed.
		bool bMerge = false ///< [in] When this parameter is true, this operation will be undone/redone in a common step with the previous one.
		);

	/// This event is triggered when a new frame is displayed on the viewport. See the class EventGate for more details.
	aevent m_eFrame;
	
    /// This event is triggered when a new stroke is started. See the class EventGate for more details.
	aevent m_eStrokeBegin;
	
	/// This event is triggered when rendering a new image of the scene is finished. See the class EventGate for more details.
	aevent m_eEndRender;
	
	/// \brief This event is triggered when the memory status gets critical. 
	/// 
	/// Plugins should deallocate temporary buffers
	/// to help the situation. See the class EventGate for more details.
	aevent m_eLowMemory;
	
	/// This event is triggered when memory status is no longer critical. Plugins can allocate their temporary buffers
	/// and fill them with data if they wish. See the class EventGate for more details.
	aevent m_eRestoreMemory;
	
	/// This event is triggered at the end of rendering the scene into a rendertarget. Plugins can use this event to
	/// render additional content to the rendertargets, like gizmos or ovelays. See the class EventGate for more details.
	aevent m_ePostRender;

	/// \brief Trigger a file event. The returned filepath can be different than the one passed as parameter.
	///
	/// The mudbox kernel triggers file events every time when it:
	/// 1. About to open a file for reading
	/// 2. About to open a file for writing
	/// 3. Read a file
	/// 4. Wrote a file
	/// 5. About to let the user browse for a file to read
	/// 6. About to let the user browse for a file to write
	/// When a file operation happens in Mudbox, the events listed above are triggered. If your plugins reads or writes
	/// files, they should trigger the appropriate events by calling this method.
	/// The returned string is the filename, which is usually the same as the passed sFileName, but
	/// it might be modified by an entity that intercepted the file event.
	QString TriggerFileEvent(
		FileEvent::Type eType,		///< [in] One of FileEvent::typeBrowseForRead, FileEvent::typeBrowseForWrite, FileEvent::typePreRead, FileEvent::typePostRead, FileEvent::typePreWrite or FileEvent::typePostWrite 
		const QString &sFileName		///< [in] The filepath that is the intended target of the operation.  This can be changed by whoever intercepts the event.
		) const;

	/// \brief This is a pointer to the latest file event.
	///
	/// Plugins can use this pointer to catch file event. When a new file event is triggered, this pointer will change
	/// its value to the new file event. Plugins can also have their own pointer with the same type. At startup they
	/// can connect their pointer to this pointer in kernel by calling the Connect() function on their pointer. This
	/// means that when the m_pFileEvent pointer in kernel changes, their own pointer will also change. They can
	/// then catch this in their OnNodeEvent() function. Using this pointer to anything else than connecting an own 
	/// pointer to it is forbidden. 
	mutable aptr<FileEvent> m_pFileEvent;

	/// \brief This is a pointer to the latest keyboard event.
	///
	/// Plugins can use this pointer to catch and respond to keyboard events. When a new event occurs, the value
	/// of this pointer changes to a structure which describes the event. The class should have it's own instance of
	/// a pointer with the same type, which should be connected to this pointer using the Attribute::Connect() function.
	/// The class can then catch and respond any changes made to this variable in its the OnNodeEvent() function.
	mutable aptr<KeyboardEvent> m_pKeyboardEvent;

	/// This pointer contains the address of the currently selected node in the scene. Plugins can connect their
	/// own pointers of the same type to this attribute to respond to selection related events. \see Attribute::Connect().
	aptr<Node> m_pSelectedNode;

	/// This pointer contains the address of the currently selected brush. Plugins can connect their own pointer
	/// of the same type to this attribute if they want to respond to brush activation events. \see Attribute::Connect().
	aptr<BrushOperation> m_pSelectedBrush;
};

/// Returns a pointer to the mudbox kernel object.
MBDLL_DECL Kernel *Kernel( void );

/// Helps finding performance issues. See the #MB_TIMER macro for more details.
class MBDLL_DECL Timer
{
	int m_iIndex;

public:
	/// Use the #MB_TIMER macro to construct timer objects instead of using this constructor.
	Timer( const char *sName, int &iIndex );
	~Timer( void );
	/// Used internally only.
	static unsigned int Current( void );
	/// This function resets all the collected information. Tipically you call this function before executing the operation
	/// which has to be measued (for example at the beginning of a stroke) and you call LogAll() at the end.
	static void ResetAll( void );
	/// This function dumps all the collected data to the log.
	static void LogAll( void );
};


/// Holds useful information about the current session of Mudbox
class MBDLL_DECL Statistics
{
public:
	void AddRenderedPolygonCount( unsigned int iPolygonCount );
	int FrameCount( void ) const;
};

/// This function provides an easy way to create objects based on interfaces. Example:
/// \code
/// Image *pMyImage = CreateInstance<Image>();
/// \endcode
/// See Kernel::PreferredDescendant() funtion for more details.
template < typename c >
c* CreateInstance( void ) { return dynamic_cast<c *>( Kernel()->CreateClassInstance( c::StaticClass() ) ); };

/// \brief This is a helper class to manage class instances implemented in plugins, provided for convenience.
///
/// The following two are equal:
/// \code
/// {
///    Image *pMyImage = CreateInstance<Image>();
///    pMyImage->DoSomething();
///    delete pMyImage;
/// }
/// \endcode
/// and
/// \code
/// {
///     Instance<Image> pMyImage;
///     pMyImage->DoSomething();
/// }
/// \endcode
/// In the second case, the target object will be automatically deleted when the block ends. You can also use 
/// this class to define member variables in your classes. This way when the owner class is constructed, the
/// instances of the needed classes will be created, and when the object destructed, those instances will be
/// removed from the memory too. For example:
/// \code
/// class MyClass
/// {
///     Instance<Image> m_pSourceImage, m_pDestinationImage;
/// public:
///		 // member functions which work with the two images
/// }
/// \endcode
template < typename c >
class MBDLL_TEMPLATE_DECL Instance
{
	c *m_pObject;

public:
	inline Instance( void ) { m_pObject = CreateInstance<c>(); };
	inline ~Instance( void ) { delete m_pObject; };
	inline c *operator ->( void ) { return m_pObject; };
	inline const c *operator ->( void ) const { return m_pObject; };
	inline operator c*( void ) { return m_pObject; };
};

}; // end of namespace mudbox
