///////////////////////////////////////////////////////////////////////////////
/// @file PluginCommon.hpp
/// @brief Common includes and definitions for the Destiny Edit Plugin Interface
///
/// @author jwvanderbeck                                                                
///                                                                                     
/// This file is the intellectual property of Novus Delta, LLC.. Usage of the
/// contents of this file is subject to the Destiny3D Member License which
/// can be found at http://www.destiny3d.com.  Any other usage is prohibited.
///
/// This file is distributed "AS IS" without warranty of any kind.  Novus
/// Delta, LLC. does not guarantee the fitness of the contents of this file
/// for any particular purpose.
///
/// Copyright (C) 2001-2003 Novus Delta, LLC. All Rights Reserved.
///                                                                                     
/// <hr>
///                                  Change History                                      
/// <hr>
/// 
/// @date March, 2002
/// @author jwvanderbeck
/// @remarks Initial creation                                                                                     
/// 
/// @date May, 2002
/// @author jwvanderbeck
/// @remarks Added comments for generated documentation
///
/// @bug RTF control not working propery on older Windows
/// @todo finish up command handler
/// @todo finish up this documentation
/// @todo add copy option to output logs
///////////////////////////////////////////////////////////////////////////////

#ifndef _PLUGINCOMMON_H_
#define _PLUGINCOMMON_H_

// Include Destiny3D master datatypes
#include "deGlobalTypes.hpp"
#include "deString.hpp"

/// Sets up the proper exports/imports.  Plugins need to define PLUGIN_EXPORTS somewhere before
/// including this file in order to get the right exports
#ifdef PLUGIN_EXPORTS
#define PLUGIN_API extern "C" DEDLL_EXPORT
#else
#define PLUGIN_API extern "C" DEDLL_IMPORT
#endif

/****************************
Forward Interface Definitions
****************************/
class IDPlugin;
class IDPControl;
class IDPObject;
class IDPManager;
class IDPMObject;
class IDPMScene;
class IDPMInterface;
class IDPMContextMenu;
class IDPMMenu;
class IDPMEventHandler;
class IDPMCommandHandler;
class IDPMUIHandler;
class IDPMSettingsManager;
/***********************
Create/Destroy functions
***********************/

/// The PluginManager uses this function to create an instance of the plugin. This should
/// never be used by a plugin.
/// @return New instance of the interface created
	PLUGIN_API IDPlugin* IDPlugin_Create();

/// The PluginManager uses this function to destroy an instance of the plugin. This should
/// never be used by a plugin.
/// @param pInterface Instance of the interface to be destroyed
	PLUGIN_API void IDPlugin_Destroy(IDPlugin* pInterface);

/// Used internally to create an instance of the PluginManager. This should never be used
/// by a plugin.
	PLUGIN_API IDPManager* IDPManager_Create();

/// Used internally to destroy an instance of the PluginManager. This should never be used
/// by a plugin.
	PLUGIN_API void IDPManager_Destroy(IDPManager* pInterface);

/// The PluginManager uses this function to create an instance of the plugin. This should
/// never be used by a plugin.
typedef IDPManager* (*fnIDPManager_Create)();

/// The PluginManager uses this function to destroy an instance of the plugin. This should
/// never be used by a plugin.
typedef void (*fnIDPManager_Destroy)(IDPManager*);

/// Used internally to create an instance of the PluginManager. This should never be used
/// by a plugin.
typedef IDPlugin* (*fnIDPlugin_Create)();

/// Used internally to destroy an instance of the PluginManager. This should never be used
/// by a plugin.
typedef void (*fnIDPlugin_Destroy)(IDPlugin*);

/***********
Result Codes
***********/

/// Standard result codes for Plugin use. These are the standard result codes that plugins
/// use to return from various functions.
enum IDPResult
{
	/// Indictates that no error occured
	IDP_OK = 0,
	/// The specified object property could not be found
	IDP_PROPERTY_NOT_FOUND = 1,
	/// The specified property's native data type varies from that used, and no conversion is possible
	IDP_CANNOT_CONVERT_PROPERTY = 2,
	/// An unspecified error has occurred
	IDP_ERROR = 3,
	/// The specified property could not be set
	IDP_PROPERTY_CANT_BE_SET = 4
};

/// Standard result codes for PluginManager use. These are the standard result codes that the
/// PluginManager will use to return from various functions.
enum IDPMResult
{
	/// Indictates that no error occured
	IDPM_OK = 0,
	/// Attempted to register an object type that already exists
	IDPM_DUPLICATE_OBJECT = 1,
	/// Attempted to create a menu that already exists
	IDPM_DUPLICATE_MENU = 2,
	/// The specified menu id was not found
	IDPM_MENU_NOT_FOUND = 3,
	/// No valid handler could be found for the specified object type
	IDPM_OBJECTHANDLER_NOT_FOUND = 4,
	/// The SceneManager was unable to create an object of the specified type
	IDPM_OBJECT_CREATE_FAILED = 5,
	/// The menu can not be created because the system has run out of menu ids.
	IDPM_NO_MORE_MENU_IDS = 6,
	/// An unspecified error was returned
	IDPM_ERROR = 7,
	/// Attempted to create a control of a type that already exists
	IDPM_DUPLICATE_CONTROL = 8
};



#define CONTROL_EDITBOX "EditBox"
#define CONTROL_STATIC "Static"
#define CONTROL_CHECKBOX "CheckBox"
#define CONTROL_LISTBOX "ListBox"
#define CONTROL_COLORPICKER "ColorPicker"
#define CONTROL_HIDDEN "Hidden"

#define DATATYPE_STRING "String"
#define DATATYPE_INT "Integer"
#define DATATYPE_REAL "Real"
#define DATATYPE_DWORD "DWORD"
#define DATATYPE_FLOAT "Real"
#define DATATYPE_DOUBLE "Real"
#define DATATYPE_UNSIGNEDINT "DWORD"
#define DATATYPE_INTEGER "Integer"
#define DATATYPE_BOOL "Boolean"
#define DATATYPE_LISTBOX_VALUES "ListBoxValues"

/**************
Data Structures
**************/
/// Details of an object's property make-up
struct IDPObjectProperty
{
	/// The name of the property
	const char* Name;
	/// The control type used for viewing/editing the property
	const char* ControlType;
	/// The property's native data type
	const char* NativeDataType;
	/// Extended help/info text displayed for the user for this property
	const char* HelpText;
};

/// Used to query the state of a menu item.  This struct is passed into the plugin's object, to 
/// retrieve the current state of a menu item prior to it being displayed to the user.
struct MenuState
{
	/// Specifies if the menu item should be shown as checked or unchecked
	BOOL	bChecked;
	/// Specifies if the menu item should be enabled or not.  If not enabled, it will be grayed out and unselectable.
	BOOL	bEnabled;
};

/// IDPlugin Interface. This is the main plugin interface
/// and is the starting point for all loaded plugins.  This interface <b>Must</b> be used
/// for any plugin.
class IDPlugin
{
public:
	/// Destructor
	virtual ~IDPlugin() {};

	/// Used to obtain the name of the plugin
	/// @return The name of the plugin as a string
	virtual const char* GetName() = 0;

	/// Used to obtain a description of the plugin
	/// @return Description of the plugin as a string
	virtual const char* GetDescription() = 0;

	/// Used to obtain the version of the plugin
	/// @return Version of the plugin as a string
	virtual const char* GetVersion() = 0;

	/// Used to obtain the author of the plugin
	/// @return Author of the plugin as a string
	virtual const char* GetAuthor() = 0;
	
	/// Used to obtain a contact email for the plugin
	/// @return Contact email as a string
	virtual const char* GetEmail() = 0;

	/// Used to obtain a contact URL for the plugin
	/// @return Contact URL for the plugin as a string
	virtual const char* GetURL() = 0;
	
	/// Called by the PluginManager when the plugin is first created. This event is called
	/// on the plugin immediately after it has been loaded by the system.  This is where any
	/// basic initialization should be done, as well as registration of object and control
	/// types.
	/// @return The plugin should return IDP_OK if everything is good and the plugin can be kept loaded
	/// by the system.  If the plugin returns anything other than IDP_OK, then the system will
	/// immediately unload the plugin.  In this case, the OnDestroy() event will NOT take place.
	/// @param PluginManager Pointer to the main PluginManager instance that the plugin can save
	/// and use throughout the life of the plugin.
	/// @warning At this stage, not all of the plugins will be loaded, therefore any operations
	/// that depend on another plugin should not be placed here (such as creating an object), but
	/// instead should be placed in the OnInitialUpdate() event.
	virtual IDPResult OnCreate(IDPManager* PluginManager) = 0;
	
	/// Called by the PluginManager when the plugin is about to be unloaded.  This
	/// event is called on the plugin just before it is unloaded, and should be used for last minute
	/// cleanup and shutdown of the plugin and any objects it spawned.
	virtual void OnDestroy() = 0;

	/// The callback for most all plugin events.  OnEvent() is used for most all plugin events, such
	/// as frame calls, window resizing, context menus, etc.
	/// @param Event The event ID which caused this callback
	/// @param Param1 DWRORD param used for passing event specific values
	/// @param Param2 DWRORD param used for passing event specific values
	/// @note Information on specific parameter packign can be found documented with the
	/// specific event flag of interest.
	/// @note The plugin or object will only recieve a callback for the events it has
	/// enabled handlers for.  See the IDPMEventHandler interface, and IDPManager::GetEventHandler()
	/// for more information on setting up event handlers.
	virtual void OnEvent(int Event, DWORD Param1, DWORD Param2) = 0;

	/// Callback for user hotkeyed commands.  OnCommand() will be called by the interface
	/// whenever a hotkeyable command registerd by the plugin has been trigger by the user.
	/// param sCommand Name of the command that has been fired off as it was registered by the plugin initially
	virtual void OnCommand(deString* sCommand) = 0;

	/// Retrieves the last result code set by the plugin.  This allows the system, or another plugin
	/// to retrieve the last set result code, and is usefull in instances where a function doesn't
	/// permitt a result code to be returned, but has the chance for failure, such as CreateObject()
	/// @return The last IDPResult code set by the plugin
	virtual IDPResult GetLastResult() = 0;

	/// Retrieves an extended result code.  This allows plugins to return result codes that are 
	/// not system standard., but are more specific to the plugin.
	/// @return Integer value indiciating the last set extended result code
	virtual int GetLastResultEx() = 0;

	/// Converts an extended result code to user readable text.  Because extended result codes are meaningless
	/// to the system, this function can take an extended result code and return a user readable string
	/// which can then be displayed to the user to help explain the problem.
	/// @return User readable string describing the error
	/// @param Result Extended result code to be converted
	virtual const char* ResultToStringEx(int Result) = 0;

	/// Called by the PluginManager to create a new Scene Object. Called by the PluginManager when
	/// the user or another plugin has asked to create a new Scene Object of the specified type, and this
	/// is the plugin registered to handle it.
	/// @return Instance pointer for the new object
	/// @param ObjectType String indicating the name of the registered object type being requested
	virtual IDPObject* CreateObject(const char* ObjectType) = 0;

	/// Called by the PluginManager to create a new Custom Control.   If an object property calls for a custom
	/// control type, and this plugin is registered as the controller of that type, this method will be
	/// called to obtain a new control instance pointer.
	/// @return Instance pointer of the new control
	/// @param ControlType String indicating the type of control to be created
	virtual IDPControl* CreateControl(const char* ControlType) = 0;

	/// Queries the interface to determine if a specified interface is supported. At the present
	/// time there is only one revision level in each interface, and this is not used.  This function
	/// is for future expansion.
	/// @return TRUE if the interface specified is supported, or FALSE if not
	/// @param InterfaceName Name of the interface to query for
	virtual BOOL SupportsInterface(const char* InterfaceName) = 0;
};

/// IDPObject Interface. This interface is used to implement a Scene Object in the editor's scene.
/// Scene Objects can be pretty much anything, but in basic terms, it is an instance of an object that
/// exists in some form in the scene (rendered or not) and exposes 0 or more properties which the user
/// may or may not be able to see or edit.  Flexible enough for you? :p
class IDPObject
{
public:
	/// Destructor
	virtual ~IDPObject() {};

	// object flags
	virtual DWORD GetFlags() = 0;
	virtual BOOL HasFlags(DWORD Flags) = 0;
	virtual IDPResult SetFlags(DWORD Flags) = 0;

	/// The callback for most all plugin events.  OnEvent() is used for most all plugin events, such
	/// as frame calls, window resizing, context menus, etc.
	/// @param Event The event ID which caused this callback
	/// @param Param1 DWRORD param used for passing event specific values
	/// @param Param2 DWRORD param used for passing event specific values
	/// @note Information on specific parameter packign can be found documented with the
	/// specific event flag of interest.
	/// @note The plugin or object will only recieve a callback for the events it has
	/// enabled handlers for.  See the IDPMEventHandler interface, and IDPManager::GetEventHandler()
	/// for more information on setting up event handlers.
	virtual void OnEvent(int Event, DWORD Param1, DWORD Param2) = 0;

	/// Callback for user hotkeyed commands.  OnCommand() will be called by the interface
	/// whenever a hotkeyable command registerd by the plugin has been trigger by the user.
	/// param sCommand Name of the command that has been fired off as it was registered by the plugin initially
	virtual void OnCommand(deString* sCommand) = 0;

	/// Used to retrive a semicolon delimitted list of valid object properies.
	/// @return IDPResult code
	/// @param Name pointer to a deString which will be filled by the plugin with a semicolon delmitted list of properties
	/// @note The list must be delimtted with semicolons between each valid property.  There should be no leading or trailing semicolon.
	virtual IDPResult GetPropertyNames(deString* Name) = 0;

	/// Used to retrieve details on a specific property.  This method is used to retrive the details on a property
	/// such as what control it uses, native data type, and help text prompt
	/// @return IDPResult code
	/// @param Name deString pointer to the name of the property on which details should be returned
	/// @param Property Pointer to a IDPObjectProperty struct which should be filled in for this property
	virtual IDPResult GetPropertyDetails(const char* Name, IDPObjectProperty* Property) = 0;
	
	// object properties
	virtual IDPResult SetProperty(const char* Name, deString* Value) = 0;
	virtual IDPResult SetProperty(const char* Name, int Value) = 0;
	virtual IDPResult SetProperty(const char* Name, double Value) = 0;
	virtual IDPResult SetProperty(const char* Name, DWORD Value) = 0;
	
	virtual IDPResult GetProperty(const char* Name, deString* Value) = 0;
	virtual IDPResult GetProperty(const char* Name, int* Value) = 0;
	virtual IDPResult GetProperty(const char* Name, double* Value) = 0;
	virtual IDPResult GetProperty(const char* Name, DWORD* Value) = 0;
	
	/// Queries the interface to determine if a specified interface is supported. At the present
	/// time there is only one revision level in each interface, and this is not used.  This function
	/// is for future expansion.
	/// @return TRUE if the interface specified is supported, or FALSE if not
	/// @param InterfaceName Name of the interface to query for
	virtual BOOL SupportsInterface(const char* InterfaceName) = 0;
};

/*******************
IDPManager interface
*******************/
class IDPManager
{
public:
	virtual ~IDPManager() {};

	virtual IDPMObject* GetObjectManager() = 0;
	virtual IDPMScene* GetSceneManager() = 0;
	virtual IDPMInterface* GetInterfaceManager() = 0;
	virtual IDPMEventHandler* GetEventHandler() = 0;
	virtual IDPMCommandHandler* GetCommandHandler() = 0;

	virtual int GetPluginCount() = 0;
	virtual IDPlugin* GetNextPlugin(IDPlugin* CurrentPlugin) = 0;

	virtual BOOL SupportsInterface(const char* InterfaceName) = 0;
};

/*******************
IDPMObject Interface
*******************/
class IDPMObject
{
public:
	virtual ~IDPMObject() {};
	virtual IDPMResult RegisterObject(const char* ObjectType, IDPlugin* ObjectPlugin) = 0;
	
	virtual BOOL SupportsInterface(const char* InterfaceName) = 0;
};

/******************
IDPMScene Interface
******************/
class IDPMScene
{
public:
	virtual ~IDPMScene() {};
	virtual IDPObject* CreateObject(const char* ObjectType) = 0;
	virtual IDPMResult RemoveObject(IDPObject* Object) = 0;
	virtual int GetObjectCount() = 0;
	virtual IDPObject* GetNextObject(IDPObject* CurrentObject) = 0;

	/// Called to inform the system that changes have been made to an object.
	virtual void UpdateObject(IDPObject* Object) = 0;

	virtual BOOL SupportsInterface(const char* InterfaceName) = 0;
};

/************
IDPMInterface
************/
class IDPMInterface
{
public:
	virtual ~IDPMInterface() {};

	virtual HWND GetWindowHandle() = 0;
	virtual IDPMResult GetWindowSize(deRect* WindowRect) = 0;

	virtual IDPMResult RegisterControlType(const char* ControlType, IDPlugin* Plugin) = 0;
	virtual void SuspendUserInput(IDPControl* Control, BOOL Suspend = TRUE) = 0;
	virtual void CommitControlChanges(IDPControl* Control) = 0;

	virtual void AddLogEntry(const char* szText, int iLevel) = 0;

	// interface handlers
	virtual IDPMMenu* GetMenuHandler(const char* Parent, IDPlugin* Plugin) = 0;
	virtual IDPMMenu* GetMenuHandler(const char* Parent, IDPObject* Object) = 0;
	virtual IDPMMenu* GetMenuHandler(HMENU hMenu, IDPlugin* Plugin) = 0;
	virtual IDPMMenu* GetMenuHandler(HMENU hMenu, IDPObject* Object) = 0;
	virtual IDPMResult ReleaseMenuHandler(IDPMMenu* Handler) = 0;
	virtual IDPMUIHandler* GetUIHandler() = 0;
};
/**************
IDPMContextMenu
**************/
class IDPMContextMenu
{
public:
	virtual ~IDPMContextMenu() {};

	virtual int AddItem(const char* Name) = 0;
	virtual int AddItem(HMENU SubMenu, const char* Name) = 0;
	virtual HMENU AddMenu(const char* Name) = 0;
};
/*******
IDPMMenu
*******/
class IDPMMenu
{
public:
	virtual ~IDPMMenu() {};

	virtual int AddItem(const char* Name) = 0;
	virtual HMENU AddMenu(const char* Name) = 0;

	virtual IDPMResult RemoveItem(int MenuID) = 0;
	virtual IDPMResult RemoveMenu(HMENU hMenu) = 0;
};

/*****************
IDPMCommandHandler
*****************/
class IDPMCommandHandler
{
public:
	virtual ~IDPMCommandHandler() {};

	/// Used to register a "command" with the system.  A command is simply some form of command that the 
	/// plugin can perform in response to a user selectable hotkey. An example is menu items, but is not 
	/// limited to such.
	/// @return IDPMResult code.  IDPM_ERROR if the command couldn't be registered (this should only happen
	/// if the exact same name and pluginID is already used).  IDPM_OK otherwise.
	/// @param Plugin Instance of the plugin which should receive the notification when the command is triggered
	/// @param sCommandName Short, user readable name of the command.  This is shown to the user, and is also what will
	/// be sent in the OnCommand callback to identify the command.
	/// @param sCommandDesc An extended description explaining to the user just what the command does.
	/// @param sPluginID This is a short string of characters, not shown to the user, which is used to help make commands "unique"
	/// @param amongst plugins.  The sPluginID should always be the same, and should be something likely to be unique.
	virtual IDPMResult RegisterCommand(IDPlugin* Plugin, deString* sCommandName, deString* sCommandDesc, deString* sPluginID) = 0;

	/// Used to register a "command" with the system.  A command is simply some form of command that the 
	/// plugin can perform in response to a user selectable hotkey. An example is menu items, but is not 
	/// limited to such.
	/// @return IDPMResult code.  IDPM_ERROR if the command couldn't be registered (this should only happen
	/// if the exact same name and pluginID is already used).  IDPM_OK otherwise.
	/// @param Object Instance of the object which should receive the notification when the command is triggered
	/// @param sCommandName Short, user readable name of the command.  This is shown to the user, and is also what will
	/// be sent in the OnCommand callback to identify the command.
	/// @param sCommandDesc An extended description explaining to the user just what the command does.
	/// @param sPluginID This is a short string of characters, not shown to the user, which is used to help make commands "unique"
	/// @param amongst plugins.  The sPluginID should always be the same, and should be something likely to be unique.
	virtual IDPMResult RegisterCommand(IDPObject* Object, deString* sCommandName, deString* sCommandDesc, deString* sPluginID) = 0;
};

/***************
IDPMEventHandler
***************/

// Event Handler Flags

/// Event for changes in the view's window size
#define IDPMEVENT_WINDOW_RESIZE		1
/// Event for each frame of the editor
#define IDPMEVENT_FRAME				2
/// Indicates a scene object has been changed
#define IDPMEVENT_UPDATE_OBJECT		3
/// The editor is about to display a context menu
#define IDPMEVENT_CONTEXT_MENU		4
/// The user has selected a menu item
#define IDPMEVENT_MENU				5
/// Event to query the state of a menu item
#define IDPMEVENT_MENU_STATE		6
/// Called when the user moves the mouse in the view area
#define IDPMEVENT_MOUSEMOVE			7
/// Called when the user double clicks the left mouse button in the view area
#define IDPMEVENT_LBUTTONDBLCLK		8
/// Called when the user presses down the left mouse button in the view area
#define IDPMEVENT_LBUTTONDOWN		9
/// Called when the user releases the left mouse button in the view area
#define IDPMEVENT_LBUTTONUP			10
/// Called when the user double clicks the right mouse button in the view area
#define IDPMEVENT_RBUTTONDBLCLK		11
/// Called when the user presses down the right mouse button in the view area
#define IDPMEVENT_RBUTTONDOWN		12
/// Called when the user releases the right mouse button in the view area
#define IDPMEVENT_RBUTTONUP			13
/// Called when the user spins the mousewheel and the mouse is inthe view area
#define IDPMEVENT_MOUSEWHEEL		14
/// Called when the user preses a key down
#define IDPMEVENT_KEYDOWN			15
/// Called when the user releases a key
#define IDPMEVENT_KEYUP				16
/// Called to indicate a new scene object has been added to the scene
#define IDPMEVENT_ADD_OBJECT		17
/// Called to indicate that a scene object has been removed from the scene
#define IDPMEVENT_DELETE_OBJECT		18
/// Called on the very first frame event for the plugin/object
#define IDPMEVENT_INITIALFRAME		19
/// Called to indicate that the workspace settings are about to be displayed
/// Param1 in OnEvent() will be packed with a pointer to an IDPMSettingsHandler
/// which can be used to add settings to be displayed for the user.
#define IDPMEVENT_SHOW_SETTINGS		20
/// This event signifies that the user has clicked APPLY in the workspace settings
/// dialog and the plugin should run through its settings and apply any changes
/// Param1 will be a packaed pointer to an IDPMSettingsHandler
#define IDPMEVENT_APPLY_SETTINGS	21
/// This event signifies that the user has clicked OK to close the workspace
/// settings dialog and the plugin should run through its settings and apply
/// any changes.
/// Param1 will be a packaed pointer to an IDPMSettingsHandler
#define IDPMEVENT_CLOSE_SETTINGS	22

/// Starting point for plugin registered event ids
#define IDPMEVENT_CUSTOM			60000

/// Indicates ALL events above
#define IDPMEVENTS_ALL				65000


class IDPMEventHandler
{
public:
	virtual ~IDPMEventHandler() {};

	/// Adds an event handler for the plugin/object.  This function creates a new event handler
	/// for the plugin or object for the specified event(s).  The function uses variable arguments
	/// so that you may specify as many events in one call as you wish.
	/// @return IDPMResult code
	/// @param Plugin The instance of the plugin which should receive the event calls specified
	/// @param ... Variable argument list of events (ints) that the plugin/object wants to receive
	/// calls for.  The last event </b>must</b> be 0.
	/// @warning You <b>must</b> use the number 0 as the last event tpo signal the end of the
	/// events.  If you do not, you will most likely corrupt the stack and crash the editor.
	virtual IDPMResult AddEventHandler(IDPlugin* Plugin, ...) = 0;

	/// Adds an event handler for the plugin/object.  This function creates a new event handler
	/// for the plugin or object for the specified event(s).  The function uses variable arguments
	/// so that you may specify as many events in one call as you wish.
	/// @return IDPMResult code
	/// @param Object The instance of the object which should receive the event calls specified
	/// @param ... Variable argument list of events (ints) that the plugin/object wants to receive
	/// calls for.  The last event </b>must</b> be 0.
	/// @warning You <b>must</b> use the number 0 as the last event tpo signal the end of the
	/// events.  If you do not, you will most likely corrupt the stack and crash the editor.
	virtual IDPMResult AddEventHandler(IDPObject* Object, ...) = 0;

	virtual IDPMResult RemoveEventHandler(IDPlugin* Plugin, ...) = 0;
	virtual IDPMResult RemoveEventHandler(IDPObject* Object, ...) = 0;

	/// Creates a new event type in the system.  This function can be used to create a custom
	/// event type that lasts until the editor is shut down.  The first plugin to make this call
	/// will create a new event type with the specified event name, and receive an ID for that event.
	/// Any other plugin that calls this function with the same name, will get the same ID.  This allows
	/// a cusotm event to be created that all plugins can be aware of.  The returned ID is only valid for
	/// the session, and may be different next time the application is run.  Therefore it should not
	/// be saved.
	/// @return ID of the specified event name
	/// @param EventName Name of the event to create/return
	virtual int RegisterCustomEvent(const char* EventName) = 0;
};


struct IDPMSettingsItem
{
	int			Parent;
	deString	Label;
	deString	ControlType;
	deString	DataType;
	deString	HelpText;
};

class IDPMSettingsHandler
{
public:
	virtual ~IDPMSettingsHandler() {};
	
	virtual int FindItem(deString ItemLabel) = 0;
	virtual BOOL IsItemRoot(int Item) = 0;
	virtual int AddItem(IDPMSettingsItem *Item, deString *Value) = 0;
	virtual int AddItem(IDPMSettingsItem *Item, double Value) = 0;
	virtual int AddItem(IDPMSettingsItem *Item, int Value) = 0;
	virtual int AddItem(IDPMSettingsItem *Item, DWORD Value) = 0;
	virtual IDPMSettingsItem* GetItem(int Item) = 0;
	virtual BOOL GetItemValue(int Item, deString *Value) = 0;
	virtual BOOL GetItemValue(int Item, double *Value) = 0;
	virtual BOOL GetItemValue(int Item, int *Value) = 0;
	virtual BOOL GetItemValue(int Item, DWORD *Value) = 0;
};

/*************
UTILITY MACROS
*************/
/// Utility macro for returning details on a property
/// @param name deString variable that contains the Name value as passed in through GetPropertyDetails()
/// @param prop Pointer to Property structure to fill, as passed in through GetPropertyDetails()
/// @param propname Quoted string name of the property
/// @param propcontrol Quoted string name of the control type to use
/// @param proptype Quoted string name of the property's native data type
#define PROP_DETAILS(name, prop, propname, propcontrol, proptype)\
if (name == propname)\
{\
	prop->ControlType = propcontrol;\
	prop->Name = propname;\
	prop->NativeDataType = proptype;\
	return IDP_OK;\
}

/// Utility macro for indicating an IDP_CANNONT_CONVERT_PROPERTY return for a property
/// @param name deString variable that contains the Name value as passed in through Get/SetProperty()
/// @param propname Quoted string name of the property
#define PROP_BADTYPE(name, propname)\
if (name == propname)\
	return IDP_CANNOT_CONVERT_PROPERTY;

/// Utility macro for doing a very simple property value return
/// @param name deString variable that contains the Name value as passed in through GetProperty()
/// @param pvalue Value pointer as passed in through GetProperty()
/// @param propname Quoted string name of the property
/// @param propvalue Value of the property
#define PROP_SETVALUE(name, pvalue, propname, propvalue)\
if (name == propname)\
{\
	*pvalue = propvalue;\
	return IDP_OK;\
}

/// Utility macro for building the values of a listbox in GetProperty()
/// @param name deString variable that contains the Name value as passed in through GetProperty()
/// @param pvalue Value pointer as passed in through GetProperty()
/// @param propname Quoted string name of the property
/// @param propvalues Quoted string list of semicolon delimitted values for the listbox
#define PROP_MAKELISTBOX(name, pvalue, propname, propvalues) PROP_SETVALUE(name, pvalue, propname ":Values", propvalues)

/// Utility macro for indicating an IDP_PROPERTY_CANT_BE_SET return for a property
/// @param name deString variable that contains the Name value as passed in through SetProperty()
/// @param propname Quoted string name of the property
#define PROP_CANTSET(name, propname)\
if (name == propname)\
{\
	return IDP_PROPERTY_CANT_BE_SET;\
}

#endif
