/*
 * $Id: moddefs.h,v 1.25 2008-08-28 23:03:08 kybav1 Exp $
 *
 * Description  : One line description of file.
 * Author       : Vaclav Kyba <mail/Jabber: vaseo1@gmail.com>  <ICQ: 98576293>
 *
 * Purpose      :
 *     Long description of what the file is for.
 */


#ifndef __EVENTS__H__
#define __EVENTS__H__

#include "parameter.h"
#include "RenderTileData.h"
#include "VehicleSimulationData.h"
#include "TrafficInfoData.h"
#include "ArHudData.h"
#include "evtstructs.h"
#include "geometry.h"
#include "msgqueue.h"

#ifndef VRUT_HPC
#include "guienvironment.h" ///<For GUIParamInfo
#endif

namespace VRUT
{
	///Event class encapsulating event IDs and helper methods
	///
	/// When creating new event, don't forget to:
	///		- add event type into Event::EVENT_TYPE structure (events.h)
	///		- add GET_* static method into Event class (events.h)
	///		- add information about in into EVENT_INFO (events.h)
	///		- add code to release event data into EventHandler::ReleaseEvent (eventhandler.cpp)
	///		- add code to copy event data into EventHandler::CloneEvent (eventhandler.cpp)
	class Event : public MPMC_QueueNode
	{
	public:
		///Event types for thread-safe communication between modules and kernel
		///Event data defaults:
		///  ExtraLong    - sender module ID or nothing if sent from kernel
		///  String       - log message (use ClientData instead for strings where possible due to bad behavior when sending to modules in some cases)
		///  Id           - window id, scene id or other identifiers
		///  Int          - any other integer
		///  ClientData   - non-primitive data (allocated by sender, deleted by \c EventManager::EventHandler)
		enum EVENT_TYPE
		{
			//the list of events handled in main thread
			EVT_EXIT,                            ///<Exit module thread loop if sent to module or exit application if sent to kernel
			EVT_LOG,                             ///<Log message event (String=message, Int=loglevel)
			EVT_LOG_LEVEL_SET,                   ///<Set log level event (Int=loglevel)
			EVT_PARAM_SET_DO,                    ///<Set parameter (ClientData=paramNameValue in 'pool.param.inst=value' format)
			EVT_PARAM_SET,                       ///<Parameter has been set (ClientData=paramNameValue in 'pool.param.inst=value' format)
			EVT_PARAM_REGISTER,                  ///<Register parameter (ClientData=paramNameValue in 'pool.param.inst=value' format)
			EVT_PARAM_UNREGISTER,                ///<Unregister parameter (ClientData=paramNameValue in 'pool.param.inst' format)
			EVT_PARAM_GUIREGISTER,               ///<Register and show parameter control in GUI (String=value, ClientData=GUIParamInfo)
			EVT_PARAM_GUIUNREGISTER,             ///<Unregister and hide all parameter from a pool control from GUI (String=paramNameValue in 'pool.*.inst' format)
			EVT_PARAM_GUIENABLE,	             ///<Enable or disable a GUI control (Id=enable/disable, ClientData=GUIParamInfo)
			EVT_PARAM_GUISHOW,                   ///<Show or hide a GUI control (Id=show/hide, ClientData=GUIParamInfo)
			EVT_PARAM_GUI_BEGIN_GROUP,		     ///<Start of new GUI group (new sizer)
			EVT_PARAM_GUI_SET_LAYOUT,            ///<Set a new GUI layout from XRC for a given pool.*.* (String=XRCFileName, ClientData=Parameter::ParameterIdentifier)
			EVT_MODULE_PREFER,                   ///<Add module to preferred list (String=moduleName)
			EVT_MODULE_FORBID,                   ///<Add module to forbidden list (String=moduleName)
			EVT_MODULE_RELEASE,                  ///<Release module event (ExtraLong=moduleID to be deleted, sender by default)
			EVT_MODULE_RELEASED,                 ///<Module was released (String=moduleName, Id=moduleID)
			EVT_MODULE_RUN,                      ///<Create module instance and start its thread (String=moduleName)
			EVT_MODULE_INSTANTIATED,             ///<Module was started (String=moduleName, Id=moduleID)
			EVT_SCENE_IMAGE_ADD,                 ///<Load and add image to scene manager (Id=reload,Int=cubeSide,ClientData=image,String=filename|imageRefName,)
			EVT_IO_SCENE_IMPORT,                 ///<Initiate load scene from file (String=filename, Id=sceneID, Int=rootID)
			EVT_IO_SCENE_IMPORT_DO,              ///<Tell IOModule to load scene from file (Id=sceneID, Int=rootID, String=filename) (Use EVT_IO_SCENE_IMPORT instead)
			EVT_IO_SCENE_EXPORT,                 ///<Save scene to file (Id=sceneID, Int=rootID, String=filename)
			EVT_RENDER_SCENE,                    ///<Create window and render scene (Id=sceneID, Int=cameraID, ClientData=RenderData)
			EVT_RENDER_FULLSCREEN_SET,           ///<Enable/disable fullscreen mode of render window (Id=windowID, Int=fsMode (bit mask: 1 - use extern window, 2 - fullscreen, 4 - always on top, 8 - hide mouse, positionX, positionY, sizeX, sizeY, extWindowBgColorRGB (packed 8bit color)))
			EVT_RENDER_FULLSCREEN_TOGGLE,        ///<Toggle fullscreen of render window (Id=windowID)
			EVT_RENDER_SYNCHRONIZATION_REGISTER, ///<Increments the number of synchronized renderers (Id=windowID, Int=masterWindowID)
			EVT_RENDER_WIN_SHOW_CURSOR,          ///<Show/hide cursor in given render window (Id=windowID, Int=show)
			EVT_RENDER_WIN_FOCUS,                ///<Focus given render window (Id=windowID)
			EVT_RENDER_WIN_CLOSE,                ///<Render window closed (Id=windowID, Int=protectedCameraID(optional))
			EVT_GUI_PANE_SHOW,                   ///<Show or hide pane (Id=paneID, Int=show if nonzero)
			EVT_GUI_PARAM_SHOW,                  ///<Show or hide whole param page (String=fullParamName, Int=show if nonzero) (fullParamName.paramName has to be '*' if hiding)
			EVT_MAIN_THREAD_CALLBACK,            ///<Synchronoue event allowing modules to do something in main VRUT thread (Aurel should use it for OpenCV initialization)
			//the EVT_MAIN_THREAD_CALLBACK must be last event processed by main thread

			//the events handled by EventHandler thread
			EVT_SCENE_ADD,                    ///<Add new scene to scene manager (String=sceneName, Id=sceneID)
			EVT_SCENE_ADDED,                  ///<Scene added to scene manager (Id=sceneID)
			EVT_SCENE_REMOVE,                 ///<Remove scene from scene manager (Id=sceneID)
			EVT_SCENE_REMOVED,                 ///<Scene removed from the scene manager (Id=sceneID)
			EVT_SCENE_IMAGE_ADDED,            ///<Image has been loaded (or is not possible to load) and added to scene manager (String=filename, Id=cubeSide, Int=(bool)succesfull)
			EVT_SCENE_MATERIAL_ADD,           ///<Add material to scene (Id=sceneID, ClientData=material)
			EVT_SCENE_MATERIAL_ADDED,         ///<Material added or replaced (Id=sceneID, Int=materialID)
			EVT_SCENE_MATERIAL_REMOVE,        ///<Remove material (Id=sceneID, String=materialName)
			EVT_SCENE_MATERIAL_REMOVED,                  ///<Material removed (Id=sceneID, Int=materialID)
			EVT_SCENE_MATERIAL_CONVERT_TRANSP_TO_REFL,   ///<Convert material transparency to reflectivity as needed by FHS import (Id=sceneID, String=materialName)
			EVT_SCENE_GEOMETRY_ADD,                      ///<Add geometry to scene (Id=sceneID, ClientData=geometry)
			EVT_SCENE_GEOMETRY_ADDED,                    ///<Geometry added or replaced (Id=sceneID, Int=geometryID)
			EVT_SCENE_GEOMETRY_REMOVE,                   ///<Remove Geometry (Id=sceneID, Int=geometryID)
			EVT_SCENE_GEOMETRY_REMOVED,                  ///<Geometry removed (Id=sceneID, Int=geometryID)
			EVT_SCENE_VARIANT_ADD,                       ///<Add variant to scene (Id=sceneID, ClientData=variant)
			EVT_SCENE_VARIANT_ADDED,                     ///<Variant added or replaced (Id=sceneID, Int=variantID)
			EVT_SCENE_VARIANT_REMOVE,                    ///<Remove variant (Id=sceneID, Int=variantID)
			EVT_SCENE_VARIANT_REMOVED,                   ///<Variant removed (Id=sceneID, Int=variantID)
			EVT_SCENE_VARIANT_ACTIVESTATE_SET,           ///<Set active state for variant (Id=sceneID, Int=variantID, String=activeState)
			EVT_SCENE_VARIANT_ACTIVESTATE_CHANGED,       ///<New active state set to variant (Id=sceneID, Int=variantID, String=activeState)
			EVT_SCENE_VARIANT_DETAILSTATE_SET,           ///<Set status for detail for given state in variant (Id=sceneID, Int=variantID, String=state;detail;status)
			EVT_SCENE_ENVIRONMENT_PROBE_ADD,             ///<Add environment probe to scene (Id=sceneID, ClientData=envprobe)
			EVT_SCENE_ENVIRONMENT_PROBE_ADDED,           ///<Add environment probe to scene (Id=sceneID, Int=envprobeID)
			EVT_SCENE_ENVIRONMENT_PROBE_ENABLE,          ///<Add environment probe to scene (Id=sceneID, Int=envprobeID, String=enable)
			EVT_SCENE_ENVIRONMENT_PROBE_SET_SINGLE_SHOT, ///<Add environment probe to scene (Id=sceneID, Int=envprobeID, String=singleShot)
			EVT_SCENE_CLIPPING_PLANE_ADD,                ///<Add clipping plane to scene (Id=sceneID, String=clipping plane)
			EVT_SCENE_CLIPPING_PLANE_ADDED,   ///<clipping plane added or replaced (Id=sceneID, Int=clippingPlaneID)
			EVT_SCENE_NODE_COPY,              ///<Copy node and all its subnodes from one place to another (Id=sceneID, Int=srcNodeID, ClientData=tgtNodeID)
			EVT_SCENE_NODE_MOVE,              ///<Move node and all its subnodes from one place to another (Id=sceneID, Int=srcNodeID, ClientData=tgtNodeID)
			EVT_SCENE_NODE_MOVED,             ///<Node and all its subnodes have been moved to a new place in scene hierarchy (Id=sceneID, Int=nodeID, ClientData=tgtNodeID)
			EVT_SCENE_NODE_INDEX_CHANGE,      ///<Change node index in parents children list (Id=sceneID, Int=nodeID, ClientData=newIndex)
			EVT_SCENE_NODE_INDEX_CHANGED,     ///<Node index has been changed (Id=sceneID, Int=nodeID, ClientData=newIndex)
			EVT_SCENE_NODE_INSERT,            ///<Insert node to scene (Id=sceneID, Int=parentID, ClientData=node)
			EVT_SCENE_NODE_INSERTED,          ///<Node inserted into scene event (Id=sceneID, Int=nodeID, ClientData=tgtNodeID)
			EVT_SCENE_NODE_REMOVE,            ///<Remove node and all its subnodes from scene (Id=sceneID, Int=nodeID), removed nodes are deleted
			EVT_SCENE_NODE_REMOVED,           ///<Node removed from scene event (Id=sceneID, Int=nodeID)
			EVT_SCENE_NODE_NAME_SET,          ///<Set new name for node in scene (Id=sceneID, Int=nodeID, String=newName)
			EVT_SCENE_NODE_NAME_CHANGED,      ///<Node name changed (Id=sceneID, Int=nodeID)
			EVT_SCENE_NODE_TRANSFORM_PRE,     ///<Experimental synchronous event for node transformation
			EVT_SCENE_NODE_TRANSFORM_SET,     ///<Set new transformation matrix for node (Id=sceneID, Int=nodeID, ClientData=matrix)
			EVT_SCENE_NODE_TRANSFORM,         ///<Transform (multiply) node's matrix (Id=sceneID, Int=nodeID, ClientData=matrix)
			EVT_SCENE_NODE_TRANSLATE_ABS,     ///<Set node's translation (Id=sceneID, Int=nodeID, ClientData=Vector3)
			EVT_SCENE_NODE_TRANSFORMED,       ///<Node's transformation changed (Id=sceneID, Int=nodeID)
			EVT_SCENE_NODE_SELECTED,          ///<Node selected (Id=sceneID, ClientData=RayIntersectionInfo)
			EVT_SCENE_NODE_GEOMETRY_SET,      ///<Set node's geometry (Id=sceneID, Int=nodeID, ClientData=geometryID)
			EVT_SCENE_NODE_GEOMETRY_CHANGED,  ///<New geometry assigned to node (Id=sceneID, Int=nodeID, ClientData=geometryID)
			EVT_SCENE_NODE_MATERIAL_SET,      ///<Set node's material (Id=sceneID, Int=nodeID, ClientData=materialName)
			EVT_SCENE_NODE_MATERIAL_CHANGED,  ///<New material assigned to node (Id=sceneID, Int=nodeID, ClientData=materialID)
			EVT_SCENE_NODE_LIGHT_SET,         ///<Set node's light (Id=sceneID, Int=nodeID, ClientData=lightInstance)
			EVT_SCENE_NODE_LIGHT_CHANGED,     ///<New light assigned to node (Id=sceneID, Int=nodeID)
			EVT_SCENE_NODE_LOD_DISTANCE_SET,               ///<Set distance for LOD node (Id=sceneID, Int=LODAssemblyID, String=(ID:LODId;float))
			EVT_SCENE_NODE_SWITCH_ACTIVECHILD_SET,         ///<Set active child for SWITCH node (Id=sceneID, Int=activeChild)
			EVT_SCENE_NODE_SWITCH_ACTIVECHILD_CHANGED,     ///<New active child set to SWITCH node (Id=sceneID, Int=activeChild)
			EVT_SCENE_NODE_SOUND_SET,                      ///<Set parameters of SOUND node (Id=sceneID, Int=nodeID, String=(position;gain;looping;state;minGain;maxGain;referenceDistance;rollOffFactor;maxDistance;pitch;direction;coneInnerAngle;coneOuterAngle;coneOuterGain;secOffset;dataSource))
			EVT_SCENE_NODE_SOUND_STATE_SET,                ///<Set state of SOUND node (Id=sceneID, Int=nodeID, String=(state)
			EVT_SCENE_NODE_ACTIVE_SET,                     ///<Set active status for node (Id=sceneID, Int=nodeID, String=(active:recursive))
			EVT_SCENE_NODE_ACTIVE_CHANGED,                 ///<Active status for node was changed (Id=sceneID, Int=nodeID, String=(active))
			EVT_SCENE_CAM_FIT,                             ///<Fit camera's view (Id=sceneID, Int=camID, String=nodeID)
			EVT_SCENE_CAM_FIT_NEAR_FAR,                    ///<Fit camera's near and far plane (Id=sceneID, Int=camID, String=nodeID)
			EVT_SCENE_CAM_RESETVIEW,                       ///<Reset camera's view (Id=sceneID, Int=camID)
			EVT_SCENE_CAM_PROJECTION_SET,                  ///<Set camera parameters (Id=sceneID, Int=nodeID, String=(width;height;near;far;fov;fixUp))
			EVT_SCENE_CAM_SET_PERSPECTIVE_PARAMS,          ///<Set projection parameters for stereo (Id=sceneID, Int=nodeID, String=(width;height;near;far;eye), ClientData=offset)
			EVT_SCENE_CAM_PROJECTION_CHANGED,              ///<Camera node's projection changed (Id=sceneID, Int=camID)
			EVT_SCENE_CARPET_REGISTER,	                   ///<Declare a node as a root of a flying carpet (Id=sceneID, Int=NodeID, String=(isTracked;bodyID;eyeSeparation))
			EVT_SCENE_CARPET_REGISTERED,	               ///<Flying carpet has been registered (Id=sceneID, Int=CarpetID)
			EVT_SCENE_CARPET_UNREGISTER,	               ///<Unregister a carpet around a node (Id=sceneID, Int=NodeID)
			EVT_SCENE_CARPET_UNREGISTERED,	               ///<Flying carpet was unregistered (Id=sceneID, Int=CarpetID)
			EVT_SCENE_CARPET_SET_CAM_PARAMS,               ///<Change eye separation for a given FC (Id=sceneID, Int=rootID, String=(eyeSeparation, tracked, bodyID)
			EVT_SCENE_CARPET_SET_OBSERVER_POSITION,        ///<Set the observer position for a static stereo camera
			EVT_SCENE_COLLISION,                           ///<Collision detected (Id=sceneID, ClientData=CollisionReport)
			EVT_RENDER_SCENE_DONE,                         ///<Rendering of scene was started (Id=sceneID, Int=cameraID, ClientData=windowID)
			EVT_RENDER_UPDATE,				               ///<Redraw scene (Id=windowID, Int=renderState), when renderState is <0 then render modules should ignore it, EventHandler will resend it with positive value (to solve cluster clients problems)
			EVT_RENDER_WIN_CREATED,                        ///<Render window created (Id=windowID)
			EVT_RENDER_WIN_FOCUSED,                        ///<Given render window has focus (Id=windowID)
			EVT_RENDER_WIN_CLOSED,                         ///<Render window closed (Id=windowID)
			EVT_RENDER_WIN_RESIZED,                        ///<Render window resized
			EVT_RENDER_SYNCHRONIZATION_UNREGISTER,         ///<Decrements the number of synchronized renderers (Id=windowID)
			EVT_RENDER_SYNCHRONIZATION_FINISHED_RENDERING, ///<Signals the sync master cluster that this renderer has finished rendering. The syncmaster cluster increments the number of renderers which are ready for a buffer swap (Id=windowID, Int=renderState)
			EVT_RENDER_SYNCHRONIZATION_BARRIER_RELEASE,    ///<Signals the renderers to swap the buffers (Id=windowID, Int=renderState)
			EVT_INPUT_MOUSE,                               ///<Any mouse event (special event representing mouse event, ClientData=wxMouseEvent)
			EVT_INPUT_KEY,                     ///<Any key event (special event representing key event, ClientData=wxKeyEvent)
			EVT_INPUT_TRACKING,                ///<Tracking input event (ClientData=deviceData)
			EVT_MODULE_RUN_DONE,               ///<Module was started (String=moduleName, Id=moduleID)
			EVT_IO_SCENE_IMPORT_DONE,          ///<Scene import done (Id=sceneID, Int=rootID, String=filename)
			EVT_COLLISION_SYNCHRO,             ///<Collision synchronization (Id=sceneID, Int=iSynchroStamp)
			EVT_BVH_OPTIMIZE,                  ///<Optimize the BVH
			EVT_INTERPRETER_PROCESS_COMMANDS,  ///<process commands by interpreter (String=commands)
			EVT_SCENE_VEHICLE_SIMULATION_DATA, ///<simulation data send by vehicle simulator Id=sceneID, ClientData = data pointer
			EVT_JAVASCRIPT_RUN_SCRIPT,	       ///<Request to synchonously run script, data=JavascriptRunScriptData
			EVT_JAVASCRIPT_RELEASE_CTX,        ///<Request to release javascript context, ClientData=JSScriptingContextPtr
			EVT_RENDER_IMAGE,                  ///<Request to save current frame (Id=sceneID, Int=cameraID, Int=width, Int=height, String=path)
			EVT_RENDER_IMAGE_DONE,             ///<Information requested frame was saved (Id=sceneID, Int=cameraID, Int=width, Int=height, String=path)
			EVT_SCENE_FRAME_RENDERED,          ///<A scene was rendered from a camera (Id=sceneID, Int=cameraID). This message is sent before swapping buffers
			EVT_RENDER_TILE,                   ///<Request to render an image tile (Id=sceneID, Int=cameraID, String=tileIdx,passIdx)
			EVT_RENDER_TILE_DONE,              ///<Image tile rendered and pass as data (Id=sceneID, Int=cameraID, ClientData=RenderTileData)
			EVT_RENDER_TILE_DONE_SYNC,         ///<Image tile rendered and pass as data synchronously
			EVT_RENDER_TILE_LOCAL,             ///Information about start local rendering
			EVT_RENDER_TILE_LOCAL_DONE,        ///Information about end local rendering
			EVT_PRESENTATION_MODE,             ///<Enable/disable presentation mode (Int=enable if nonzero)
			EVT_IMAGE_SAVE_DONE,				/// Image was saved,requested thread pool job finished.

			EVT_SG_SELECT_NODES_BY_MATERIAL,    ///<SceneGraph select nodes with given material (Id=sceneID, Int=MaterialID)
			EVT_SG_APPLY_MATERIAL_TO_SELECTION, ///<SceneGraph apply given material to selected nodes (Id=sceneID, Int=MaterialID)
			EVT_SCENE_TRAFFIC_INFO_DATA,        ///<traffic info data send by traffic module Id=sceneID, ClientData = data pointer
			EVT_AR_HUD_DATA,                    ///<traffic info data send by traffic module ClientData = data pointer

			EVT_LOCAL_REMOTE_RATIO,            /// Local/remote ratio
			EVT_RENDER_TILE_DONE_SYNC_FOR_DATASOURCE, /// EVT_RENDER_TILE_DONE_SYNC is called directly on kernel. This goes "normal" way trough dataSource.

			EVT_HIGHEST
		};

		EVENT_TYPE type;
		Event(EVENT_TYPE type) : MPMC_QueueNode(), type(type) {}
	};

	//events that must be processed in main VRUT thread
	class EventMain : public Event {
	public:
		EventMain(EVENT_TYPE type) : Event(type) {}
	};

	//events that can (and will) be processed in EventHandler thread
	class EventNormal : public Event {
	public:
		EventNormal(EVENT_TYPE type) : Event(type) {}
	};


	//Definition of events processed in main VRUT thread
	//Currently some of them need not to be really processed in main thread:
	//EventSceneImageAdd - it is only (temporary) workaround to use more threads for scene import, TODO: use thread pool
	//EventLogLevelSet, EventModuleReleased, EventModuleInstantiated and maybe others - must be checked

	class EventExit : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_EXIT;
		EventExit() : EventMain(ClassType) {}
	};

	inline EventMain * GET_EVT_EXIT()
	{
		return new EventExit();
	}

	class EventLog : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_LOG;
		wxString msg;
		wxLogLevel loglevel;
		EventLog(const wxString & msg, const wxLogLevel loglevel) : EventMain(ClassType), msg(msg), loglevel(loglevel) {}
	};
	
	inline EventMain * GET_EVT_LOG(const wxString & msg, const wxLogLevel loglevel)
	{
		return new EventLog(msg, loglevel);
	}

	class EventLogLevelSet : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_LOG_LEVEL_SET;
		wxLogLevel loglevel;
		EventLogLevelSet(const wxLogLevel loglevel) : EventMain(ClassType), loglevel(loglevel) {}
	};
	
	inline EventMain * GET_EVT_LOG_LEVEL_SET(const wxLogLevel loglevel)
	{
		return new EventLogLevelSet(loglevel);
	}

	class EventParamSetDo : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_SET_DO;
		Parameter::ParameterIdentifier paramIdentifier;
		wxString value;
		EventParamSetDo(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & value) : EventMain(ClassType), paramIdentifier(paramIdentifier), value(value) {}
	};
	
	inline EventMain * GET_EVT_PARAM_SET_DO(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & value)
	{
		return new EventParamSetDo(paramIdentifier, value);
	}

	class EventParamSet : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_SET;
		Parameter::ParameterIdentifier paramIdentifier;
		wxString value;
		wxString originId; // This parameter can be (optionaly) used to identify origin of the event. Based on it the event can be ignored if necessary out.
		EventParamSet(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & value, const wxString & originId)
			: EventMain(ClassType), paramIdentifier(paramIdentifier), value(value), originId(originId) {}
	};

	inline EventMain * GET_EVT_PARAM_SET(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & value, const wxString & originId = wxEmptyString)
	{
		return new EventParamSet(paramIdentifier, value, originId);
	}

	class EventParamRegister : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_REGISTER;
		Parameter::ParameterIdentifier paramIdentifier;
		wxString value;
		EventParamRegister(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & value) : EventMain(ClassType), paramIdentifier(paramIdentifier), value(value) {}
	};

	inline EventMain * GET_EVT_PARAM_REGISTER(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & value)
	{
		return new EventParamRegister(paramIdentifier, value);
	}

	class EventParamUnregister : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_UNREGISTER;
		Parameter::ParameterIdentifier paramIdentifier;
		EventParamUnregister(const Parameter::ParameterIdentifier & paramIdentifier) : EventMain(ClassType), paramIdentifier(paramIdentifier) {}
	};

	inline EventMain * GET_EVT_PARAM_UNREGISTER(const Parameter::ParameterIdentifier & paramIdentifier)
	{
		return new EventParamUnregister(paramIdentifier);
	}

#ifndef VRUT_HPC
	class EventParamGuiRegister : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_GUIREGISTER;
		GUIEnvironment::GUIParamInfo paramInfo;
		wxString value;
		EventParamGuiRegister(const GUIEnvironment::GUIParamInfo & paramInfo, const wxString & value) : EventMain(ClassType), paramInfo(paramInfo), value(value) {}
	};

	inline EventMain * GET_EVT_PARAM_GUIREGISTER(const GUIEnvironment::GUIParamInfo & paramInfo, const wxString & value)
	{
		return new EventParamGuiRegister(paramInfo, value);
	}

	class EventParamGuiUnregister : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_GUIUNREGISTER;
		Parameter::ParameterIdentifier paramIdentifier;
		EventParamGuiUnregister(const Parameter::ParameterIdentifier & paramIdentifier) : EventMain(ClassType), paramIdentifier(paramIdentifier) {}
	};

	inline EventMain * GET_EVT_PARAM_GUIUNREGISTER(const Parameter::ParameterIdentifier & paramIdentifier)
	{
		return new EventParamGuiUnregister(paramIdentifier);
	}

	class EventParamGuiEnable : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_GUIENABLE;
		GUIEnvironment::GUIParamInfo paramInfo;
		bool enable;
		EventParamGuiEnable(const GUIEnvironment::GUIParamInfo & paramInfo, const bool enable) : EventMain(ClassType), paramInfo(paramInfo), enable(enable) {}
	};

	inline EventMain * GET_EVT_PARAM_GUIENABLE(const GUIEnvironment::GUIParamInfo & paramInfo, const bool enable)
	{
		return new EventParamGuiEnable(paramInfo, enable);
	}

	class EventParamGuiShow : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_GUISHOW;
		GUIEnvironment::GUIParamInfo paramInfo;
		bool show;
		EventParamGuiShow(const GUIEnvironment::GUIParamInfo & paramInfo, const bool show) : EventMain(ClassType), paramInfo(paramInfo), show(show) {}
	};

	inline EventMain * GET_EVT_PARAM_GUISHOW(const GUIEnvironment::GUIParamInfo & paramInfo, const bool show)
	{
		return new EventParamGuiShow(paramInfo, show);
	}

	class EventParamGuiBeginGroup : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_GUI_BEGIN_GROUP;
		GUIEnvironment::GUIParamGroup paramGroupInfo;
		EventParamGuiBeginGroup(const  GUIEnvironment::GUIParamGroup & paramGroupInfo) : EventMain(ClassType), paramGroupInfo(paramGroupInfo) {}
	};

	inline EventMain * GET_EVT_PARAM_GUI_BEGIN_GROUP(const GUIEnvironment::GUIParamGroup & paramGroupInfo)
	{
		return new EventParamGuiBeginGroup(paramGroupInfo);
	}

	class EventParamGuiSetLayout : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PARAM_GUI_SET_LAYOUT;
		Parameter::ParameterIdentifier paramIdentifier;
		wxString layoutFileName;
		EventParamGuiSetLayout(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & layoutFileName) : EventMain(ClassType), paramIdentifier(paramIdentifier), layoutFileName(layoutFileName) {}
	};

	inline EventMain * GET_EVT_PARAM_GUI_SET_LAYOUT(const Parameter::ParameterIdentifier & paramIdentifier, const wxString & layoutFileName)
	{
		return new EventParamGuiSetLayout(paramIdentifier, layoutFileName);
	}
#endif // VRUT_HPC

	class EventModulePrefer : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MODULE_PREFER;
		wxString moduleName;
		EventModulePrefer(const wxString & moduleName) : EventMain(ClassType), moduleName(moduleName) {}
	};

	inline EventMain * GET_EVT_MODULE_PREFER(const wxString & moduleName)
	{
		return new EventModulePrefer(moduleName);
	}

	class EventModuleForbid : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MODULE_FORBID;
		wxString moduleName;
		EventModuleForbid(const wxString & moduleName) : EventMain(ClassType), moduleName(moduleName) {}
	};

	inline EventMain * GET_EVT_MODULE_FORBID(const wxString & moduleName)
	{
		return new EventModuleForbid(moduleName);
	}

	class EventModuleRelease : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MODULE_RELEASE;
		MODULE_ID moduleID;
		EventModuleRelease(const MODULE_ID & moduleID) : EventMain(ClassType), moduleID(moduleID) {}
	};

	inline EventMain * GET_EVT_MODULE_RELEASE(const MODULE_ID & moduleID)
	{
		return new EventModuleRelease(moduleID);
	}

	class EventModuleReleased : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MODULE_RELEASED;
		wxString moduleName;
		MODULE_ID moduleID;
		EventModuleReleased(const wxString & moduleName, const MODULE_ID & moduleID) : EventMain(ClassType), moduleName(moduleName), moduleID(moduleID) {}
	};

	inline EventMain * GET_EVT_MODULE_RELEASED(const wxString & moduleName, const MODULE_ID & moduleID)
	{
		return new EventModuleReleased(moduleName, moduleID);
	}

	class EventModuleRun : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MODULE_RUN;
		wxString moduleName;
		EventModuleRun(const wxString & moduleName) : EventMain(ClassType), moduleName(moduleName) {}
	};

	inline EventMain * GET_EVT_MODULE_RUN(const wxString & moduleName)
	{
		return new EventModuleRun(moduleName);
	}

	class EventModuleInstantiated : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MODULE_INSTANTIATED;
		wxString moduleName;
		MODULE_ID moduleID;
		EventModuleInstantiated(const wxString & moduleName, const MODULE_ID & moduleID) : EventMain(ClassType), moduleName(moduleName), moduleID(moduleID) {}
	};

	inline EventMain * GET_EVT_MODULE_INSTANTIATED(const wxString & moduleName, MODULE_ID moduleID)
	{
		return new EventModuleInstantiated(moduleName, moduleID);
	}

	class EventSceneImageAdd : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_IMAGE_ADD;
		wxString texFile;
		Image *image;			///< Must be allocated by 'new'. Deallocated automatically.
		int cubeSide;
		wxString imageRefName;
		bool reload;
		int flip;		// See Image::Load for more info about 'flip'
		EventSceneImageAdd(const wxString & texFile, Image *image=NULL, int cubeSide=-1, const wxString imageRefName=wxT(""), bool reload=false, int flip=0) : EventMain(ClassType), texFile(texFile), image(image), cubeSide(cubeSide),
			imageRefName(imageRefName), reload(reload), flip(flip) {}
	};

	inline EventMain * GET_EVT_SCENE_IMAGE_ADD(const wxString & texFile, Image *image=NULL, int cubeSide=-1, const wxString imageRefName=wxT(""), bool reload=false, int flip=0)
	{
		return new EventSceneImageAdd(texFile, image, cubeSide, imageRefName, reload, flip);
	}

	class EventIoSceneImport : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_IO_SCENE_IMPORT;
		wxString sceneFile;
		SCENE_ID sceneID;
		NODE_ID rootID;
		EventIoSceneImport(const wxString & sceneFile, SCENE_ID sceneID=SCENE_ID_NONE, NODE_ID rootID=NODE_ID_NONE) : EventMain(ClassType), sceneFile(sceneFile), sceneID(sceneID), rootID(rootID) {}
	};

	inline EventMain * GET_EVT_IO_SCENE_IMPORT(const wxString & sceneFile, SCENE_ID sceneID=SCENE_ID_NONE, NODE_ID rootID=NODE_ID_NONE)
	{
		return new EventIoSceneImport(sceneFile, sceneID, rootID);
	}

	class EventIoSceneImportDo : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_IO_SCENE_IMPORT_DO;
		wxString sceneFile;
		SCENE_ID sceneID;
		NODE_ID rootID;
		EventIoSceneImportDo(const wxString & sceneFile, SCENE_ID sceneID, NODE_ID rootID) : EventMain(ClassType), sceneFile(sceneFile), sceneID(sceneID), rootID(rootID) {}
	};

	inline EventMain * GET_EVT_IO_SCENE_IMPORT_DO(const SCENE_ID sceneID, const NODE_ID rootID, const wxString & sceneFile)
	{
		return new EventIoSceneImportDo(sceneFile, sceneID, rootID);
	}

	class EventIoSceneExport : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_IO_SCENE_EXPORT;
		wxString sceneFile;
		SCENE_ID sceneID;
		NODE_ID rootID;
		EventIoSceneExport(const wxString & sceneFile, SCENE_ID sceneID, NODE_ID rootID) : EventMain(ClassType), sceneFile(sceneFile), sceneID(sceneID), rootID(rootID) {}
	};

	inline EventMain * GET_EVT_IO_SCENE_EXPORT(const SCENE_ID sceneID, const NODE_ID rootID, const wxString & sceneFile)
	{
		return new EventIoSceneExport(sceneFile, sceneID, rootID);
	}

	class EventRenderScene : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_SCENE;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		RENDER_WINDOW_ID windowID;
		bool useActiveStereo;
		EventRenderScene(const SCENE_ID sceneID, const NODE_ID cameraID=NODE_ID_NONE, const RENDER_WINDOW_ID windowID=RENDER_WINDOW_ID_NONE, bool useActiveStereo=false) : EventMain(ClassType),
			sceneID(sceneID), cameraID(cameraID), windowID(windowID), useActiveStereo(useActiveStereo) {}
	};

	inline EventMain * GET_EVT_RENDER_SCENE(const SCENE_ID sceneID, const NODE_ID cameraID = NODE_ID_NONE, const RENDER_WINDOW_ID windowID=RENDER_WINDOW_ID_NONE, bool useActiveStereo = false)
	{
		return new EventRenderScene(sceneID, cameraID, windowID, useActiveStereo);
	}

	class EventRenderFullscreenSet : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_FULLSCREEN_SET;
		RENDER_WINDOW_ID windowID;
		int fsMode;
		int positionX, positionY;
		int sizeX, sizeY;
		unsigned long colorRGB;
		EventRenderFullscreenSet(const RENDER_WINDOW_ID windowID, const int fsMode, const int positionX=0, const int positionY=0, const int sizeX=-1, const int sizeY=-1, const unsigned long colorRGB=0)
			: EventMain(ClassType), windowID(windowID), fsMode(fsMode), positionX(positionX), positionY(positionY), sizeX(sizeX), sizeY(sizeY), colorRGB(colorRGB) {}
	};

	inline EventMain * GET_EVT_RENDER_FULLSCREEN_SET(const RENDER_WINDOW_ID windowID, const int fsMode, const int positionX=-1, const int positionY=-1, const int sizeX=-1, const int sizeY=-1, const unsigned long colorRGB=0)
	{
		return new EventRenderFullscreenSet(windowID, fsMode, positionX, positionY, sizeX, sizeY, colorRGB);
	}

	class EventRenderFullscreenToggle : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_FULLSCREEN_TOGGLE;
		RENDER_WINDOW_ID windowID;
		EventRenderFullscreenToggle(const RENDER_WINDOW_ID windowID) : EventMain(ClassType), windowID(windowID) {}
	};

	inline EventMain * GET_EVT_RENDER_FULLSCREEN_TOGGLE(const RENDER_WINDOW_ID windowID)
	{
		return new EventRenderFullscreenToggle(windowID);;
	}

	class EventRenderSynchronizationRegister : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_SYNCHRONIZATION_REGISTER;
		RENDER_WINDOW_ID windowID;
		RENDER_WINDOW_ID masterWindowID;
		EventRenderSynchronizationRegister(const RENDER_WINDOW_ID windowID, const RENDER_WINDOW_ID masterWindowID) : EventMain(ClassType), windowID(windowID), masterWindowID(masterWindowID) {}
	};

	inline EventMain * GET_EVT_RENDER_SYNCHRONIZATION_REGISTER(const RENDER_WINDOW_ID windowID, const RENDER_WINDOW_ID masterWindowID)
	{
		return new EventRenderSynchronizationRegister(windowID, masterWindowID);
	}

	class EventRenderWinShowCursor : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_WIN_SHOW_CURSOR;
		RENDER_WINDOW_ID windowID;
		bool show;
		EventRenderWinShowCursor(const RENDER_WINDOW_ID windowID, const bool show) : EventMain(ClassType), windowID(windowID), show(show) {}
	};

	inline EventMain * GET_EVT_RENDER_WIN_SHOW_CURSOR(const RENDER_WINDOW_ID windowID, bool show)
	{
		return new EventRenderWinShowCursor(windowID, show);
	}

	class EventRenderWinFocus : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_WIN_FOCUS;
		RENDER_WINDOW_ID windowID;
		EventRenderWinFocus(const RENDER_WINDOW_ID windowID) : EventMain(ClassType), windowID(windowID) {}
	};

	inline EventMain * GET_EVT_RENDER_WIN_FOCUS(const RENDER_WINDOW_ID windowID)
	{
		return new EventRenderWinFocus(windowID);
	}

	class EventRenderWinClose : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_WIN_CLOSE;
		RENDER_WINDOW_ID windowID;
		NODE_ID protectedCameraID;
		EventRenderWinClose(const RENDER_WINDOW_ID windowID, const NODE_ID protectedCameraID=NODE_ID_NONE) : EventMain(ClassType), windowID(windowID), protectedCameraID(protectedCameraID) {}
	};

	inline EventMain * GET_EVT_RENDER_WIN_CLOSE(const RENDER_WINDOW_ID windowID, int protectedCameraID = -1)
	{
		return new EventRenderWinClose(windowID, protectedCameraID);
	}

	class EventGuiPaneShow : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_GUI_PANE_SHOW;
		int paneID;
		bool show;
		EventGuiPaneShow(const int paneID, const bool show) : EventMain(ClassType), paneID(paneID), show(show) {}
	};

	inline EventMain * GET_EVT_GUI_PANE_SHOW(const int paneID, const bool show)
	{
		return new EventGuiPaneShow(paneID, show);
	}

	class EventGuiParamShow : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_GUI_PARAM_SHOW;
		Parameter::ParameterIdentifier paramIdentifier;
		bool show;
		EventGuiParamShow(const Parameter::ParameterIdentifier & paramIdentifier, const bool show) : EventMain(ClassType), paramIdentifier(paramIdentifier), show(show) {}
	};

	inline EventMain * GET_EVT_GUI_PARAM_SHOW(const Parameter::ParameterIdentifier & paramIdentifier, const bool show)
	{
		return new EventGuiParamShow(paramIdentifier, show);
	}

	class EventMainThreadCallback : public EventMain
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MAIN_THREAD_CALLBACK;
		MODULE_ID moduleID;
		int callID;
		EventMainThreadCallback(const MODULE_ID moduleID, const int callID) : EventMain(ClassType), moduleID(moduleID), callID(callID) {}
	};

	inline EventMain * GET_EVT_MAIN_THREAD_CALLBACK(MODULE_ID moduleID, int callID)
	{
		return new EventMainThreadCallback(moduleID, callID);
	}


	//Definition of events processed in EventHandler thread

	class EventSceneAdd : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_ADD;
		wxString sceneName;
		SCENE_ID sceneID;
		EventSceneAdd(const wxString &sceneName, const SCENE_ID sceneID=SCENE_ID_NONE) : EventNormal(ClassType), sceneName(sceneName), sceneID(sceneID) {}
	};

	inline EventNormal * GET_EVT_SCENE_ADD(const wxString &sceneName, SCENE_ID sceneID=SCENE_ID_NONE)
	{
		return new EventSceneAdd(sceneName, sceneID);
	}

	class EventSceneAdded : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_ADDED;
		SCENE_ID sceneID;
		EventSceneAdded(const SCENE_ID sceneID) : EventNormal(ClassType), sceneID(sceneID) {}
	};

	inline EventNormal * GET_EVT_SCENE_ADDED(SCENE_ID sceneID)
	{
		return new EventSceneAdded(sceneID);
	}

	class EventSceneRemove : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_REMOVE;
		SCENE_ID sceneID;
		EventSceneRemove(const SCENE_ID sceneID) : EventNormal(ClassType), sceneID(sceneID) {}
	};

	inline EventNormal * GET_EVT_SCENE_REMOVE(SCENE_ID sceneID)
	{
		return new EventSceneRemove(sceneID);
	}

	class EventSceneRemoved : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_REMOVED;
		SCENE_ID sceneID;
		EventSceneRemoved(const SCENE_ID sceneID) : EventNormal(ClassType), sceneID(sceneID) {}
	};

	inline EventNormal * GET_EVT_SCENE_REMOVED(SCENE_ID sceneID)
	{
		return new EventSceneRemoved(sceneID);
	}

	class EventSceneImageAdded : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_IMAGE_ADDED;
		wxString texFile;		// TODO Is this the path of the image, or its reference name? Listeners use this as a path,
								//		but SceneManager sets its value to the reference name.
		bool successful;
		int cubeSide;
		EventSceneImageAdded(const wxString & texFile, const bool successful, const int cubeSide) : EventNormal(ClassType), texFile(texFile), successful(successful), cubeSide(cubeSide) {}
	};

	inline EventNormal * GET_EVT_SCENE_IMAGE_ADDED(const wxString & texFile, const bool successful, int cubeSide)
	{
		return new EventSceneImageAdded(texFile, successful, cubeSide);
	}

	class EventSceneMaterialAdd : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_MATERIAL_ADD;
		SCENE_ID sceneID;
		Material * material;
		EventSceneMaterialAdd(const SCENE_ID sceneID, Material * material) : EventNormal(ClassType), sceneID(sceneID), material(material) {}
	};

	inline EventNormal * GET_EVT_SCENE_MATERIAL_ADD(const SCENE_ID sceneID, Material * material)
	{
		return new EventSceneMaterialAdd(sceneID, material);
	}

	class EventSceneMaterialAdded : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_MATERIAL_ADDED;
		SCENE_ID sceneID;
		MATERIAL_ID materialID;
		EventSceneMaterialAdded(const SCENE_ID sceneID, const MATERIAL_ID materialID) : EventNormal(ClassType), sceneID(sceneID), materialID(materialID) {}
	};

	inline EventNormal * GET_EVT_SCENE_MATERIAL_ADDED(const SCENE_ID sceneID, const MATERIAL_ID materialID)
	{
		return new EventSceneMaterialAdded(sceneID, materialID);
	}

	class EventSceneMaterialRemove : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_MATERIAL_REMOVE;
		SCENE_ID sceneID;
		wxString materialName;
		EventSceneMaterialRemove(const SCENE_ID sceneID, const wxString &materialName) : EventNormal(ClassType), sceneID(sceneID), materialName(materialName) {}
	};

	inline EventNormal * GET_EVT_SCENE_MATERIAL_REMOVE(const SCENE_ID sceneID, const wxString &materialName)
	{
		return new EventSceneMaterialRemove(sceneID, materialName);
	}

	class EventSceneMaterialRemoved : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_MATERIAL_REMOVED;
		SCENE_ID sceneID;
		MATERIAL_ID materialID;
		EventSceneMaterialRemoved(const SCENE_ID sceneID, const MATERIAL_ID materialID) : EventNormal(ClassType), sceneID(sceneID), materialID(materialID) {}
	};

	inline EventNormal * GET_EVT_SCENE_MATERIAL_REMOVED(const SCENE_ID sceneID, const MATERIAL_ID materialID)
	{
		return new EventSceneMaterialRemoved(sceneID, materialID);
	}

	class EventSceneMaterialConvertTranspToRefl : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_MATERIAL_CONVERT_TRANSP_TO_REFL;
		SCENE_ID sceneID;
		wxString materialName;
		EventSceneMaterialConvertTranspToRefl(const SCENE_ID sceneID, const wxString &materialName) : EventNormal(ClassType), sceneID(sceneID), materialName(materialName) {}
	};

	inline EventNormal * GET_EVT_SCENE_MATERIAL_CONVERT_TRANSP_TO_REFL(const SCENE_ID sceneID, const wxString &materialName)
	{
		return new EventSceneMaterialConvertTranspToRefl(sceneID, materialName);
	}

	class EventSceneGeometryAdd : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_GEOMETRY_ADD;
		SCENE_ID sceneID;
		Geometry * geometry;
		EventSceneGeometryAdd(const SCENE_ID sceneID, Geometry * geometry) : EventNormal(ClassType), sceneID(sceneID), geometry(geometry) {}
	};

	inline EventNormal * GET_EVT_SCENE_GEOMETRY_ADD(const SCENE_ID sceneID, Geometry * geometry)
	{
		return new EventSceneGeometryAdd(sceneID, geometry);
	}

	class EventSceneGeometryAdded : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_GEOMETRY_ADDED;
		SCENE_ID sceneID;
		GEOMETRY_ID geometryID;
		EventSceneGeometryAdded(const SCENE_ID sceneID, GEOMETRY_ID geometryID) : EventNormal(ClassType), sceneID(sceneID), geometryID(geometryID) {}
	};

	inline EventNormal * GET_EVT_SCENE_GEOMETRY_ADDED(const SCENE_ID sceneID, const GEOMETRY_ID geometryID)
	{
		return new EventSceneGeometryAdded(sceneID, geometryID);
	}

	class EventSceneGeometryRemove : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_GEOMETRY_REMOVE;
		SCENE_ID sceneID;
		GEOMETRY_ID geometryID;
		EventSceneGeometryRemove(const SCENE_ID sceneID, const GEOMETRY_ID geometryID) : EventNormal(ClassType), sceneID(sceneID), geometryID(geometryID) {}
	};

	inline EventNormal * GET_EVT_SCENE_GEOMETRY_REMOVE(const SCENE_ID sceneID, const GEOMETRY_ID geometryID)
	{
		return new EventSceneGeometryRemove(sceneID, geometryID);
	}

	class EventSceneGeometryRemoved : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_GEOMETRY_REMOVED;
		SCENE_ID sceneID;
		GEOMETRY_ID geometryID;
		EventSceneGeometryRemoved(const SCENE_ID sceneID, const GEOMETRY_ID geometryID) : EventNormal(ClassType), sceneID(sceneID), geometryID(geometryID) {}
	};

	inline EventNormal * GET_EVT_SCENE_GEOMETRY_REMOVED(const SCENE_ID sceneID, const GEOMETRY_ID geometryID)
	{
		return new EventSceneGeometryRemoved(sceneID, geometryID);
	}

	class EventSceneVariantAdd : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VARIANT_ADD;
		SCENE_ID sceneID;
		Variant * variant;
		EventSceneVariantAdd(const SCENE_ID sceneID, Variant * variant) : EventNormal(ClassType), sceneID(sceneID), variant(variant) {}
	};

	inline EventNormal * GET_EVT_SCENE_VARIANT_ADD(const SCENE_ID sceneID, Variant * variant)
	{
		return new EventSceneVariantAdd(sceneID, variant);
	}

	class EventSceneVariantAdded : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VARIANT_ADDED;
		SCENE_ID sceneID;
		VARIANT_ID variantID;
		EventSceneVariantAdded(const SCENE_ID sceneID, const VARIANT_ID variantID) : EventNormal(ClassType), sceneID(sceneID), variantID(variantID) {}
	};

	inline EventNormal * GET_EVT_SCENE_VARIANT_ADDED(const SCENE_ID sceneID, const VARIANT_ID variantID)
	{
		return new EventSceneVariantAdded(sceneID, variantID);
	}

	class EventSceneVariantRemove : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VARIANT_REMOVE;
		SCENE_ID sceneID;
		VARIANT_ID variantID;
		EventSceneVariantRemove(const SCENE_ID sceneID, const VARIANT_ID variantID) : EventNormal(ClassType), sceneID(sceneID), variantID(variantID) {}
	};

	inline EventNormal * GET_EVT_SCENE_VARIANT_REMOVE(const SCENE_ID sceneID, const VARIANT_ID variantID)
	{
		return new EventSceneVariantRemove(sceneID, variantID);
	}

	class EventSceneVariantRemoved : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VARIANT_REMOVED;
		SCENE_ID sceneID;
		VARIANT_ID variantID;
		EventSceneVariantRemoved(const SCENE_ID sceneID, const VARIANT_ID variantID) : EventNormal(ClassType), sceneID(sceneID), variantID(variantID) {}
	};

	inline EventNormal * GET_EVT_SCENE_VARIANT_REMOVED(const SCENE_ID sceneID, const VARIANT_ID variantID)
	{
		return new EventSceneVariantRemoved(sceneID, variantID);
	}

	class EventSceneVariantActiveStateSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VARIANT_ACTIVESTATE_SET;
		SCENE_ID sceneID;
		VARIANT_ID variantID;
		size_t activeState;
		EventSceneVariantActiveStateSet(const SCENE_ID sceneID, const VARIANT_ID variantID, const size_t activeState) : EventNormal(ClassType), sceneID(sceneID), variantID(variantID), activeState(activeState) {}
	};

	inline EventNormal * GET_EVT_SCENE_VARIANT_ACTIVESTATE_SET(const SCENE_ID sceneID, const VARIANT_ID variantID, const size_t activeState)
	{
		return new EventSceneVariantActiveStateSet(sceneID, variantID, activeState);
	}

	class EventSceneVariantActiveStateChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VARIANT_ACTIVESTATE_CHANGED;
		SCENE_ID sceneID;
		VARIANT_ID variantID;
		size_t activeState;
		EventSceneVariantActiveStateChanged(const SCENE_ID sceneID, const VARIANT_ID variantID, const size_t activeState) : EventNormal(ClassType), sceneID(sceneID), variantID(variantID), activeState(activeState) {}
	};

	inline EventNormal * GET_EVT_SCENE_VARIANT_ACTIVESTATE_CHANGED(const SCENE_ID sceneID, const VARIANT_ID variantID, size_t activeState)
	{
		return new class EventSceneVariantActiveStateChanged(sceneID, variantID, activeState);
	}

	class EventSceneVariantDetailStateSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VARIANT_DETAILSTATE_SET;
		SCENE_ID sceneID;
		wxString variantName;
		wxString state;
		wxString detail;
		wxString status;
		EventSceneVariantDetailStateSet(const SCENE_ID sceneID, const wxString &variantName, const wxString &state, const wxString &detail, const wxString &status) : EventNormal(ClassType),
			sceneID(sceneID), variantName(variantName), state(state), detail(detail), status(status) {}
	};

	inline EventNormal * GET_EVT_SCENE_VARIANT_DETAILSTATE_SET(const SCENE_ID sceneID, const wxString &variantName, const wxString &state, const wxString &detail, const wxString &status)
	{
		return new EventSceneVariantDetailStateSet(sceneID, variantName, state, detail, status);
	}

	class EventSceneEnvironmentProbeAdd : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_ENVIRONMENT_PROBE_ADD;
		SCENE_ID sceneID;
		EnvironmentProbe * environmentProbe;
		EventSceneEnvironmentProbeAdd(const SCENE_ID sceneID, EnvironmentProbe * environmentProbe) : EventNormal(ClassType), sceneID(sceneID), environmentProbe(environmentProbe) {}
	};

	inline EventNormal * GET_EVT_SCENE_ENVIRONMENT_PROBE_ADD(const SCENE_ID sceneID, EnvironmentProbe * environmentProbe)
	{
		return new EventSceneEnvironmentProbeAdd(sceneID, environmentProbe);
	}

	class EventSceneEnvironmentProbeAdded : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_ENVIRONMENT_PROBE_ADDED;
		SCENE_ID sceneID;
		ENVIRONMENT_PROBE_ID envProbeID;
		EventSceneEnvironmentProbeAdded(const SCENE_ID sceneID, const ENVIRONMENT_PROBE_ID envProbeID) : EventNormal(ClassType), sceneID(sceneID), envProbeID(envProbeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_ENVIRONMENT_PROBE_ADDED(const SCENE_ID sceneID, const ENVIRONMENT_PROBE_ID envProbeID)
	{
		return new EventSceneEnvironmentProbeAdded(sceneID, envProbeID);
	}

	class EventSceneEnvironmentProbeEnable : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_ENVIRONMENT_PROBE_ENABLE;
		SCENE_ID sceneID;
		ENVIRONMENT_PROBE_ID envProbeID;
		bool enable;
		EventSceneEnvironmentProbeEnable(const SCENE_ID sceneID, const ENVIRONMENT_PROBE_ID envProbeID, const bool enable) : EventNormal(ClassType), sceneID(sceneID), envProbeID(envProbeID), enable(enable) {}
	};

	inline EventNormal * GET_EVT_SCENE_ENVIRONMENT_PROBE_ENABLE(const SCENE_ID sceneID, const ENVIRONMENT_PROBE_ID envProbeID, const bool enable)
	{
		return new EventSceneEnvironmentProbeEnable(sceneID, envProbeID, enable);
	}

	class EventSceneEnvironmentProbeSetSingleShot : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_ENVIRONMENT_PROBE_SET_SINGLE_SHOT;
		SCENE_ID sceneID;
		ENVIRONMENT_PROBE_ID envProbeID;
		bool singleShot;
		EventSceneEnvironmentProbeSetSingleShot(const SCENE_ID sceneID, const ENVIRONMENT_PROBE_ID envProbeID, const bool singleShot) : EventNormal(ClassType), sceneID(sceneID), envProbeID(envProbeID),
			singleShot(singleShot) {}
	};

	inline EventNormal * GET_EVT_SCENE_ENVIRONMENT_PROBE_SET_SINGLE_SHOT(const SCENE_ID sceneID, const ENVIRONMENT_PROBE_ID envProbeID, const bool singleShot)
	{
		return new EventSceneEnvironmentProbeSetSingleShot(sceneID, envProbeID, singleShot);
	}

	class EventSceneClippingPlaneAdd : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CLIPPING_PLANE_ADD;
		SCENE_ID sceneID;
		ClippingPlane clippingPlane;
		EventSceneClippingPlaneAdd(const SCENE_ID sceneID, const ClippingPlane &clippingPlane) : EventNormal(ClassType), sceneID(sceneID), clippingPlane(clippingPlane) {}
	};

	inline EventNormal * GET_EVT_SCENE_CLIPPING_PLANE_ADD(const SCENE_ID sceneID, const ClippingPlane &clippingPlane)
	{
		return new EventSceneClippingPlaneAdd(sceneID, clippingPlane);
	}

	class EventSceneClippingPlaneAdded : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CLIPPING_PLANE_ADDED;
		SCENE_ID sceneID;
		CLIPPING_PLANE_ID clippingPlaneID;
		EventSceneClippingPlaneAdded(const SCENE_ID sceneID, const CLIPPING_PLANE_ID &clippingPlaneID) : EventNormal(ClassType), sceneID(sceneID), clippingPlaneID(clippingPlaneID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CLIPPING_PLANE_ADDED(const SCENE_ID sceneID, const CLIPPING_PLANE_ID clippingPlaneID)
	{
		return new EventSceneClippingPlaneAdded(sceneID, clippingPlaneID);
	}

	class EventSceneNodeCopy : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_COPY;
		SCENE_ID sceneID;
		SCENE_ID srcSceneID;
		NODE_ID srcID;
		NODE_ID targetID;
		EventSceneNodeCopy(const SCENE_ID sceneID, const SCENE_ID srcSceneID, const NODE_ID srcID, const NODE_ID targetID) : EventNormal(ClassType), sceneID(sceneID), srcSceneID(srcSceneID), srcID(srcID), targetID(targetID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_COPY(const SCENE_ID sceneID, const SCENE_ID srcSceneID, NODE_ID srcID, NODE_ID targetID)
	{
		return new EventSceneNodeCopy(sceneID, srcSceneID, srcID, targetID);
	}

	class EventSceneNodeMove : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_MOVE;
		SCENE_ID sceneID;
		NODE_ID srcID;
		NODE_ID targetID;
		EventSceneNodeMove(const SCENE_ID sceneID, const NODE_ID srcID, const NODE_ID targetID) : EventNormal(ClassType), sceneID(sceneID), srcID(srcID), targetID(targetID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_MOVE(const SCENE_ID sceneID, const NODE_ID srcID, const NODE_ID targetID)
	{
		return new EventSceneNodeMove(sceneID, srcID, targetID);
	}

	class EventSceneNodeMoved : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_MOVED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		NODE_ID parentID;
		EventSceneNodeMoved(const SCENE_ID sceneID, const NODE_ID nodeID, const NODE_ID parentID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), parentID(parentID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_MOVED(const SCENE_ID sceneID, const NODE_ID nodeID, const NODE_ID parentID)
	{
		return new EventSceneNodeMoved(sceneID, nodeID, parentID);
	}

	class EventSceneNodeIndexChange : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_INDEX_CHANGE;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		size_t newIndex;
		EventSceneNodeIndexChange(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t newIndex) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), newIndex(newIndex) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_INDEX_CHANGE(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t newIndex)
	{
		return new EventSceneNodeIndexChange(sceneID, nodeID, newIndex);
	}

	class EventSceneNodeIndexChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_INDEX_CHANGED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		size_t newIndex;
		EventSceneNodeIndexChanged(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t newIndex) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), newIndex(newIndex) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_INDEX_CHANGED(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t newIndex)
	{
		return new EventSceneNodeIndexChanged(sceneID, nodeID, newIndex);
	}

	class EventSceneNodeInsert : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_INSERT;
		SCENE_ID sceneID;
		SceneNode * node;
		NODE_ID parentID;
		EventSceneNodeInsert(const SCENE_ID sceneID, SceneNode * node, const NODE_ID parentID) : EventNormal(ClassType), sceneID(sceneID), node(node), parentID(parentID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_INSERT(const SCENE_ID sceneID, SceneNode *node, const NODE_ID parentID)
	{
		return new EventSceneNodeInsert(sceneID, node, parentID);
	}

	class EventSceneNodeInserted : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_INSERTED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		NODE_ID parentID;
		EventSceneNodeInserted(const SCENE_ID sceneID, const NODE_ID nodeID, const NODE_ID parentID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), parentID(parentID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_INSERTED(const SCENE_ID sceneID, const NODE_ID nodeID, const NODE_ID parentID)
	{
		return new EventSceneNodeInserted(sceneID, nodeID, parentID);
	}

	class EventSceneNodeRemove : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_REMOVE;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		EventSceneNodeRemove(const SCENE_ID sceneID, const NODE_ID nodeID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_REMOVE(const SCENE_ID sceneID, const NODE_ID nodeID)
	{
		return new EventSceneNodeRemove(sceneID, nodeID);
	}

	class EventSceneNodeRemoved : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_REMOVED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		EventSceneNodeRemoved(const SCENE_ID sceneID, const NODE_ID nodeID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_REMOVED(const SCENE_ID sceneID, const NODE_ID nodeID)
	{
		return new EventSceneNodeRemoved(sceneID, nodeID);
	}

	class EventSceneNodeNameSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_NAME_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		wxString newName;
		EventSceneNodeNameSet(const SCENE_ID sceneID, const NODE_ID nodeID, const wxString & newName) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), newName(newName) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_NAME_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const wxString & newName)
	{
		return new EventSceneNodeNameSet(sceneID, nodeID, newName);
	}

	class EventSceneNodeNameChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_NAME_CHANGED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		EventSceneNodeNameChanged(const SCENE_ID sceneID, const NODE_ID nodeID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_NAME_CHANGED(const SCENE_ID sceneID, const NODE_ID nodeID)
	{
		return new EventSceneNodeNameChanged(sceneID, nodeID);
	}

	class EventSceneNodeTransformSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_TRANSFORM_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		Matrix matrix;
		EventSceneNodeTransformSet(const SCENE_ID sceneID, const NODE_ID nodeID, const Matrix & matrix) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), matrix(matrix) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_TRANSFORM_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const Matrix & matrix)
	{
		return new EventSceneNodeTransformSet(sceneID, nodeID, matrix);
	}

	class EventSceneNodeTransform : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_TRANSFORM;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		Matrix matrix;
		EventSceneNodeTransform(const SCENE_ID sceneID, const NODE_ID nodeID, const Matrix & matrix) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), matrix(matrix) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_TRANSFORM(const SCENE_ID sceneID, const NODE_ID nodeID, const Matrix & matrix)
	{
		return new EventSceneNodeTransform(sceneID, nodeID, matrix);
	}

	class EventSceneNodeTranslateAbs : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_TRANSLATE_ABS;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		Vector3 vector;
		EventSceneNodeTranslateAbs(const SCENE_ID sceneID, const NODE_ID nodeID, const Vector3 & vector) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), vector(vector) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_TRANSLATE_ABS(const SCENE_ID sceneID, const NODE_ID nodeID, const Vector3 & vector)
	{
		return new EventSceneNodeTranslateAbs(sceneID, nodeID, vector);
	}

	class EventSceneNodeTransformed : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_TRANSFORMED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		Matrix transMatrix;
		EventSceneNodeTransformed(const SCENE_ID sceneID, const NODE_ID nodeID, const Matrix &transMatrix) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), transMatrix(transMatrix) {}
		wxString ToString() {return wxString::Format(wxT("EventSceneNodeTransformed sceneID=%i, nodeID=%i"), sceneID, nodeID);}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_TRANSFORMED(const SCENE_ID sceneID, const NODE_ID nodeID, const Matrix &transMatrix)
	{
		return new EventSceneNodeTransformed(sceneID, nodeID, transMatrix);
	}

	class EventSceneNodeSelected : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_SELECTED;
		SCENE_ID sceneID;
		RayIntersectionInfo rayIntersectionInfo;
		EventSceneNodeSelected(const SCENE_ID sceneID, const RayIntersectionInfo & rayIntersectionInfo) : EventNormal(ClassType), sceneID(sceneID), rayIntersectionInfo(rayIntersectionInfo) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_SELECTED(const SCENE_ID sceneID, const RayIntersectionInfo & rayIntersectionInfo)
	{
		return new EventSceneNodeSelected(sceneID, rayIntersectionInfo);
	}

	class EventSceneNodeGeometrySet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_GEOMETRY_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		GEOMETRY_ID geometryID;
		EventSceneNodeGeometrySet(const SCENE_ID sceneID, const NODE_ID nodeID, const GEOMETRY_ID geometryID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), geometryID(geometryID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_GEOMETRY_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const GEOMETRY_ID geometryID)
	{
		return new EventSceneNodeGeometrySet(sceneID, nodeID, geometryID);
	}

	class EventSceneNodeGeometryChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_GEOMETRY_CHANGED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		GEOMETRY_ID geometryID;
		EventSceneNodeGeometryChanged(const SCENE_ID sceneID, const NODE_ID nodeID, const GEOMETRY_ID geometryID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), geometryID(geometryID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_GEOMETRY_CHANGED(const SCENE_ID sceneID, const NODE_ID nodeID, const GEOMETRY_ID geometryID)
	{
		return new EventSceneNodeGeometryChanged(sceneID, nodeID, geometryID);
	}

	class EventSceneNodeMaterialSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_MATERIAL_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		wxString materialName;
		EventSceneNodeMaterialSet(const SCENE_ID sceneID, const NODE_ID nodeID, const wxString & materialName) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), materialName(materialName) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_MATERIAL_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const wxString & materialName)
	{
		return new EventSceneNodeMaterialSet(sceneID, nodeID, materialName);
	}

	class EventSceneNodeMaterialChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_MATERIAL_CHANGED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		MATERIAL_ID materialID;
		EventSceneNodeMaterialChanged(const SCENE_ID sceneID, const NODE_ID nodeID, const MATERIAL_ID materialID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), materialID(materialID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_MATERIAL_CHANGED(const SCENE_ID sceneID, const NODE_ID nodeID, const MATERIAL_ID materialID)
	{
		return new EventSceneNodeMaterialChanged(sceneID, nodeID, materialID);
	}

	class EventSceneNodeLightSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_LIGHT_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		Light light;
		EventSceneNodeLightSet(const SCENE_ID sceneID, const NODE_ID nodeID, const Light & light) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), light(light) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_LIGHT_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const Light & light)
	{
		return new EventSceneNodeLightSet(sceneID, nodeID, light);
	}

	class EventSceneNodeLightChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_LIGHT_CHANGED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		EventSceneNodeLightChanged(const SCENE_ID sceneID, const NODE_ID nodeID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_LIGHT_CHANGED(const SCENE_ID sceneID, const NODE_ID nodeID)
	{
		return new EventSceneNodeLightChanged(sceneID, nodeID);
	}

	class EventSceneNodeLodDistanceSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_LOD_DISTANCE_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		NODE_ID LODID;
		float distance;
		EventSceneNodeLodDistanceSet(const SCENE_ID sceneID, const NODE_ID nodeID, const NODE_ID LODID, const float distance) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), LODID(LODID), distance(distance) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_LOD_DISTANCE_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const NODE_ID LODID, const float distance)
	{
		return new EventSceneNodeLodDistanceSet(sceneID, nodeID, LODID, distance);
	}

	class EventSceneNodeSwitchActiveChildSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_SWITCH_ACTIVECHILD_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		size_t activeChild;
		EventSceneNodeSwitchActiveChildSet(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t activeChild) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), activeChild(activeChild) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_SWITCH_ACTIVECHILD_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t activeChild)
	{
		return new EventSceneNodeSwitchActiveChildSet(sceneID, nodeID, activeChild);
	}

	class EventSceneNodeSwitchActiveChildChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_SWITCH_ACTIVECHILD_CHANGED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		size_t activeChild;
		EventSceneNodeSwitchActiveChildChanged(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t activeChild) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), activeChild(activeChild) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_SWITCH_ACTIVECHILD_CHANGED(const SCENE_ID sceneID, const NODE_ID nodeID, const size_t activeChild)
	{
		return new EventSceneNodeSwitchActiveChildChanged(sceneID, nodeID, activeChild);
	}

	class EventSceneNodeSoundSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_SOUND_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		float gain;
		bool looping;
		const SoundSourceNode::SoundSourceState state;
		float minGain, maxGain, referenceDistance, rollOffFactor, maxDistance, pitch;
		Vector3 direction;
		float coneInnerAngle, coneOuterAngle, coneOuterGain, secOffset;
		wxString dataSource;
		EventSceneNodeSoundSet(const SCENE_ID sceneID, const NODE_ID nodeID, const float gain, const bool looping, const SoundSourceNode::SoundSourceState state,
			const float minGain, const float maxGain, const float referenceDistance, const float rollOffFactor, const float maxDistance, const float pitch, const Vector3 &direction, const float coneInnerAngle,
			const float coneOuterAngle, const float coneOuterGain, const float secOffset, const wxString &dataSource) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), gain(gain),
			looping(looping), state(state), minGain(minGain), maxGain(maxGain), referenceDistance(referenceDistance), rollOffFactor(rollOffFactor), maxDistance(maxDistance), pitch(pitch), direction(direction),
			coneInnerAngle(coneInnerAngle), coneOuterAngle(coneOuterAngle), coneOuterGain(coneOuterGain), secOffset(secOffset), dataSource(dataSource) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_SOUND_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const float gain, const bool looping, const SoundSourceNode::SoundSourceState state,
		const float minGain, const float maxGain, const float referenceDistance, const float rollOffFactor, const float maxDistance, const float pitch, const Vector3 &direction, const float coneInnerAngle,
		const float coneOuterAngle, const float coneOuterGain, const float secOffset, const wxString &dataSource)
	{
		return new EventSceneNodeSoundSet(sceneID, nodeID, gain, looping, state, minGain, maxGain, referenceDistance, rollOffFactor, maxDistance, pitch, direction, coneInnerAngle, coneOuterAngle,
			coneOuterGain, secOffset, dataSource);
	}

	class EventSceneNodeSoundStateSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_SOUND_STATE_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		SoundSourceNode::SoundSourceState state;
		EventSceneNodeSoundStateSet(const SCENE_ID sceneID, const NODE_ID nodeID, const SoundSourceNode::SoundSourceState state) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), state(state) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_SOUND_STATE_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const SoundSourceNode::SoundSourceState state)
	{
		return new EventSceneNodeSoundStateSet(sceneID, nodeID, state);
	}

	class EventSceneNodeActiveSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_ACTIVE_SET;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		bool active;
		EventSceneNodeActiveSet(const SCENE_ID sceneID, const NODE_ID nodeID, const bool active) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), active(active) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_ACTIVE_SET(const SCENE_ID sceneID, const NODE_ID nodeID, const bool active)
	{
		return new EventSceneNodeActiveSet(sceneID, nodeID, active);
	}

	class EventSceneNodeActiveChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_NODE_ACTIVE_CHANGED;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		bool active;
		bool isImplied;			// TODO What is "isImplied"
		EventSceneNodeActiveChanged(const SCENE_ID sceneID, const NODE_ID nodeID, const bool active, const bool isImplied) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), active(active), isImplied(isImplied) {}
	};

	inline EventNormal * GET_EVT_SCENE_NODE_ACTIVE_CHANGED(const SCENE_ID sceneID, const NODE_ID nodeID, const bool active, const bool isImplied)
	{
		return new EventSceneNodeActiveChanged(sceneID, nodeID, active, isImplied);
	}

	class EventSceneCameraFit : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CAM_FIT;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		NODE_ID nodeID;
		EventSceneCameraFit(const SCENE_ID sceneID, const NODE_ID cameraID, const NODE_ID nodeID=NODE_ID_NONE) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), nodeID(nodeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CAM_FIT(const SCENE_ID sceneID, const NODE_ID cameraID, const NODE_ID nodeID=NODE_ID_NONE)
	{
		return new EventSceneCameraFit(sceneID, cameraID, nodeID);
	}

	class EventSceneCameraFitNearFar : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CAM_FIT_NEAR_FAR;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		NODE_ID nodeID;
		EventSceneCameraFitNearFar(const SCENE_ID sceneID, const NODE_ID cameraID, const NODE_ID nodeID=NODE_ID_NONE) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), nodeID(nodeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CAM_FIT_NEAR_FAR(const SCENE_ID sceneID, const NODE_ID cameraID, const NODE_ID nodeID=NODE_ID_NONE)
	{
		return new EventSceneCameraFitNearFar(sceneID, cameraID, nodeID);
	}

	class EventSceneCamResetView : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CAM_RESETVIEW;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		EventSceneCamResetView(const SCENE_ID sceneID, const NODE_ID cameraID) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CAM_RESETVIEW(const SCENE_ID sceneID, const NODE_ID cameraID)
	{
		return new EventSceneCamResetView(sceneID, cameraID);
	}

	class EventSceneCameraProjectionSet : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CAM_PROJECTION_SET;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		unsigned int projWidth, projHeight;
		float projNear, projFar, projFov;
		Camera::UP_FIX upFix;
		EventSceneCameraProjectionSet(const SCENE_ID sceneID, const NODE_ID cameraID, const unsigned int projWidth = 0, const unsigned int projHeight = 0, const float projNear = 0.0f, const float projFar = 0.0f,
			const float projFov = 0.0f, const Camera::UP_FIX upFix = Camera::UP_FREE) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), projWidth(projWidth), projHeight(projHeight),
			projNear(projNear), projFar(projFar), projFov(projFov), upFix(upFix) {}
	};

	inline EventNormal * GET_EVT_SCENE_CAM_PROJECTION_SET(const SCENE_ID sceneID, const NODE_ID cameraID, const unsigned int projWidth = 0, const unsigned int projHeight = 0, const float projNear = 0.0f,
		const float projFar = 0.0f, const float projFov = 0.0f, const Camera::UP_FIX upFix = Camera::UP_FREE)
	{
		return new EventSceneCameraProjectionSet(sceneID, cameraID, projWidth, projHeight, projNear, projFar, projFov, upFix);
	}

	class EventSceneCamSetPerspectiveParams : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CAM_SET_PERSPECTIVE_PARAMS;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		float nearPlane, farPlane;
		Vector3 offset;
		int eye;
		float eyeSeparation;
		Vector3 pa, pb, pc, eyeAxis, lookAt;
		EventSceneCamSetPerspectiveParams(const SCENE_ID sceneID, const NODE_ID cameraID, const float nearPlane, const float farPlane, const Vector3 & offset, const int eye, const float eyeSeparation,
			const Vector3 & pa, const Vector3 & pb, const Vector3 & pc, const Vector3 & eyeAxis, const Vector3& lookAt) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), nearPlane(nearPlane), farPlane(farPlane),
			offset(offset), eye(eye), eyeSeparation(eyeSeparation), pa(pa), pb(pb), pc(pc), eyeAxis(eyeAxis), lookAt(lookAt) {}
	};

	inline EventNormal * GET_EVT_SCENE_CAM_SET_PERSPECTIVE_PARAMS(const SCENE_ID sceneID, const NODE_ID cameraID, const float nearPlane, const float farPlane, const Vector3 & offset, const int eye, const float eyeSeparation,
		const Vector3 & pa, const Vector3 & pb, const Vector3 & pc, const Vector3 & eyeAxis, const Vector3& lookAt)
	{
		return new EventSceneCamSetPerspectiveParams(sceneID, cameraID, nearPlane, farPlane, offset, eye, eyeSeparation, pa, pb, pc, eyeAxis, lookAt);
	}

	class EventSceneCamProjectionChanged : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CAM_PROJECTION_CHANGED;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		EventSceneCamProjectionChanged(const SCENE_ID sceneID, const NODE_ID cameraID) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CAM_PROJECTION_CHANGED(const SCENE_ID sceneID, const NODE_ID cameraID)
	{
		return new EventSceneCamProjectionChanged(sceneID, cameraID);
	}

	class EventSceneCarpetRegister : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CARPET_REGISTER;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		bool isTracked;
		int bodyID;
		float eyeSeparation;
		EventSceneCarpetRegister(const SCENE_ID sceneID, const NODE_ID nodeID, const bool isTracked, const int bodyID, const float eyeSeparation) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID),
			isTracked(isTracked), bodyID(bodyID), eyeSeparation(eyeSeparation) {}
	};

	inline EventNormal * GET_EVT_SCENE_CARPET_REGISTER(const SCENE_ID sceneID, const NODE_ID nodeID, const bool isTracked, const int bodyID, const float eyeSeparation)
	{
		return new EventSceneCarpetRegister(sceneID, nodeID, isTracked, bodyID, eyeSeparation);
	}

	class EventSceneCarpetRegistered : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CARPET_REGISTERED;
		SCENE_ID sceneID;
		size_t carpetID;
		EventSceneCarpetRegistered(const SCENE_ID sceneID, const size_t carpetID) : EventNormal(ClassType), sceneID(sceneID), carpetID(carpetID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CARPET_REGISTERED(const SCENE_ID sceneID, const size_t carpetID)
	{
		return new EventSceneCarpetRegistered(sceneID, carpetID);
	}

	class EventSceneCarpetUnregister : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CARPET_UNREGISTER;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		EventSceneCarpetUnregister(const SCENE_ID sceneID, const NODE_ID nodeID) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CARPET_UNREGISTER(const SCENE_ID sceneID, const NODE_ID nodeID)
	{
		return new EventSceneCarpetUnregister(sceneID, nodeID);
	}

	class EventSceneCarpetUnregistered : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CARPET_UNREGISTERED;
		SCENE_ID sceneID;
		size_t carpetID;
		EventSceneCarpetUnregistered(const SCENE_ID sceneID, const size_t carpetID) : EventNormal(ClassType), sceneID(sceneID), carpetID(carpetID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CARPET_UNREGISTERED(const SCENE_ID sceneID, const size_t carpetID)
	{
		return new EventSceneCarpetUnregistered(sceneID, carpetID);
	}

	class EventSceneCarpetSetCamParams : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CARPET_SET_CAM_PARAMS;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		float eyeSeparation;
		int isTracked, bodyID;
		EventSceneCarpetSetCamParams(const SCENE_ID sceneID, const NODE_ID nodeID, const float eyeSeparation, const int isTracked=-1, const int bodyID=0) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID),
			eyeSeparation(eyeSeparation), isTracked(isTracked), bodyID(bodyID) {}
	};

	inline EventNormal * GET_EVT_SCENE_CARPET_SET_CAM_PARAMS(const SCENE_ID sceneID, const NODE_ID nodeID, const float eyeSeparation, const int isTracked=-1, const int bodyID=0)
	{
		return new EventSceneCarpetSetCamParams(sceneID, nodeID, eyeSeparation, isTracked, bodyID);
	}

	class EventSceneCarpetSetObserverPosition : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_CARPET_SET_OBSERVER_POSITION;
		SCENE_ID sceneID;
		NODE_ID nodeID;
		Vector3 position;
		EventSceneCarpetSetObserverPosition(const SCENE_ID sceneID, const NODE_ID nodeID, const Vector3 & position) : EventNormal(ClassType), sceneID(sceneID), nodeID(nodeID), position(position) {}
	};

	inline EventNormal * GET_EVT_SCENE_CARPET_SET_OBSERVER_POSITION(const SCENE_ID sceneID, const NODE_ID nodeID, const Vector3 & position)
	{
		return new EventSceneCarpetSetObserverPosition(sceneID, nodeID, position);
	}

	class EventSceneCollision : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_COLLISION;
		SCENE_ID sceneID;
		CollisionReport colReport;
		EventSceneCollision(const SCENE_ID sceneID, const CollisionReport & colReport) : EventNormal(ClassType), sceneID(sceneID), colReport(colReport) {}
	};

	inline EventNormal * GET_EVT_SCENE_COLLISION(const SCENE_ID sceneID, const CollisionReport & colReport)
	{
		return new EventSceneCollision(sceneID, colReport);
	}

	class EventRenderSceneDone : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_SCENE_DONE;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		RENDER_WINDOW_ID windowID;
		EventRenderSceneDone(const SCENE_ID sceneID, const NODE_ID cameraID, const RENDER_WINDOW_ID windowID) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), windowID(windowID) {}
	};

	inline EventNormal * GET_EVT_RENDER_SCENE_DONE(const SCENE_ID sceneID, const NODE_ID cameraID, const RENDER_WINDOW_ID windowID)
	{
		return new EventRenderSceneDone(sceneID, cameraID, windowID);
	}

	class EventRenderUpdate : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_UPDATE;
		RENDER_WINDOW_ID windowID;
		int renderState;
		EventRenderUpdate(const RENDER_WINDOW_ID windowID, const int renderState=0) : EventNormal(ClassType), windowID(windowID), renderState(renderState) {}
	};

	inline EventNormal * GET_EVT_RENDER_UPDATE(const RENDER_WINDOW_ID windowID, const int renderState=0)
	{
		return new EventRenderUpdate(windowID, renderState);
	}

	class EventRenderWinCreated : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_WIN_CREATED;
		RENDER_WINDOW_ID windowID;
		EventRenderWinCreated(const RENDER_WINDOW_ID windowID) : EventNormal(ClassType), windowID(windowID) {}
	};

	inline EventNormal * GET_EVT_RENDER_WIN_CREATED(const RENDER_WINDOW_ID windowID)
	{
		return new EventRenderWinCreated(windowID);
	}

	class EventRenderWinFocused : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_WIN_FOCUSED;
		RENDER_WINDOW_ID windowID;
		SCENE_ID sceneID;
		EventRenderWinFocused(const RENDER_WINDOW_ID windowID, const SCENE_ID sceneID = SCENE_ID_NONE) : EventNormal(ClassType), windowID(windowID), sceneID(sceneID) {}
	};

	inline EventNormal * GET_EVT_RENDER_WIN_FOCUSED(const RENDER_WINDOW_ID windowID, const SCENE_ID sceneID = SCENE_ID_NONE)
	{
		return new EventRenderWinFocused(windowID, sceneID);
	}

	class EventRenderWinClosed : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_WIN_CLOSED;
		RENDER_WINDOW_ID windowID;
		EventRenderWinClosed(const RENDER_WINDOW_ID windowID) : EventNormal(ClassType), windowID(windowID) {}
	};

	inline EventNormal * GET_EVT_RENDER_WIN_CLOSED(const RENDER_WINDOW_ID windowID)
	{
		return new EventRenderWinClosed(windowID);
	}

	class EventRenderWinResized : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_WIN_RESIZED;
		RENDER_WINDOW_ID windowID;
		EventRenderWinResized(const RENDER_WINDOW_ID windowID) : EventNormal(ClassType), windowID(windowID) {}
	};

	inline EventNormal * GET_EVT_RENDER_WIN_RESIZED(const RENDER_WINDOW_ID windowID)
	{
		return new EventRenderWinResized(windowID);
	}

	class EventRenderSynchronizationUnregister : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_SYNCHRONIZATION_UNREGISTER;
		RENDER_WINDOW_ID windowID;
		EventRenderSynchronizationUnregister(const RENDER_WINDOW_ID windowID) : EventNormal(ClassType), windowID(windowID) {}
	};

	inline EventNormal * GET_EVT_RENDER_SYNCHRONIZATION_UNREGISTER(const RENDER_WINDOW_ID windowID)
	{
		return new EventRenderSynchronizationUnregister(windowID);
	}

	class EventRenderSynchronizationFinishedRendering : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_SYNCHRONIZATION_FINISHED_RENDERING;
		RENDER_WINDOW_ID windowID;
		int renderState;
		EventRenderSynchronizationFinishedRendering(const RENDER_WINDOW_ID windowID, const int renderState) : EventNormal(ClassType), windowID(windowID), renderState(renderState) {}
	};

	inline EventNormal * GET_EVT_RENDER_SYNCHRONIZATION_FINISHED_RENDERING(const RENDER_WINDOW_ID windowID, const int renderState)
	{
		return new EventRenderSynchronizationFinishedRendering(windowID, renderState);
	}

	class EventRenderSynchronizationBarrierRelease : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_SYNCHRONIZATION_BARRIER_RELEASE;
		RENDER_WINDOW_ID windowID;
		int renderState;
		EventRenderSynchronizationBarrierRelease(const RENDER_WINDOW_ID windowID, const int renderState) : EventNormal(ClassType), windowID(windowID), renderState(renderState) {}
	};

	inline EventNormal * GET_EVT_RENDER_SYNCHRONIZATION_BARRIER_RELEASE(const RENDER_WINDOW_ID windowID, const int renderState)
	{
		return new EventRenderSynchronizationBarrierRelease(windowID, renderState);
	}

#ifndef VRUT_HPC
	class EventInputMouse : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_INPUT_MOUSE;
		wxMouseEvent mevt;
		EventInputMouse(const wxMouseEvent & mevt) : EventNormal(ClassType), mevt(mevt) {}
	};

	inline EventNormal * GET_EVT_INPUT_MOUSE(const wxMouseEvent & mevt)
	{
		return new EventInputMouse(mevt);
	}

	class EventInputKey : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_INPUT_KEY;
		wxKeyEvent kevt;
		EventInputKey(const wxKeyEvent & kevt) : EventNormal(ClassType), kevt(kevt) {}
	};

	inline EventNormal * GET_EVT_INPUT_KEY(const wxKeyEvent & kevt)
	{
		return new EventInputKey(kevt);
	}
#endif

	class EventInputTracking : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_INPUT_TRACKING;
		DeviceData deviceData;
		EventInputTracking(const DeviceData & deviceData) : EventNormal(ClassType), deviceData(deviceData) {}
	};

	inline EventNormal * GET_EVT_INPUT_TRACKING(const DeviceData & deviceData)
	{
		return new EventInputTracking(deviceData);
	}

	class EventModuleRunDone : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_MODULE_RUN_DONE;
		wxString moduleName;
		MODULE_ID moduleID;
		EventModuleRunDone(const wxString & moduleName, const MODULE_ID moduleID) : EventNormal(ClassType), moduleName(moduleName), moduleID(moduleID) {}
	};

	inline EventNormal * GET_EVT_MODULE_RUN_DONE(const wxString & moduleName, const MODULE_ID moduleID)
	{
		return new EventModuleRunDone(moduleName, moduleID);
	}

	class EventIoSceneImportDone : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_IO_SCENE_IMPORT_DONE;
		SCENE_ID sceneID;
		NODE_ID rootID;
		wxString sceneFile;
		EventIoSceneImportDone(const SCENE_ID sceneID, const NODE_ID rootID, const wxString & sceneFile) : EventNormal(ClassType), sceneID(sceneID), rootID(rootID), sceneFile(sceneFile) {}
	};

	inline EventNormal * GET_EVT_IO_SCENE_IMPORT_DONE(const SCENE_ID sceneID, const NODE_ID rootID, const wxString & sceneFile)
	{
		return new EventIoSceneImportDone(sceneID, rootID, sceneFile);
	}

	class EventCollisionSynchro : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_COLLISION_SYNCHRO;
		SCENE_ID sceneID;
		int iSynchroStamp;
		EventCollisionSynchro(const SCENE_ID sceneID, const int iSynchroStamp) : EventNormal(ClassType), sceneID(sceneID), iSynchroStamp(iSynchroStamp) {}
	};

	inline EventNormal * GET_EVT_COLLISION_SYNCHRO(const SCENE_ID sceneID, const int iSynchroStamp)
	{
		return new EventCollisionSynchro(sceneID, iSynchroStamp);
	}

	class EventBvhOptimize : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_BVH_OPTIMIZE;
		EventBvhOptimize() : EventNormal(ClassType) {}
	};

	inline EventNormal * GET_EVT_BVH_OPTIMIZE()
	{
		return new EventBvhOptimize();
	}

	class EventInterpreterProcessCommands : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_INTERPRETER_PROCESS_COMMANDS;
		wxString commands;
		EventInterpreterProcessCommands(const wxString & commands) : EventNormal(ClassType), commands(commands) {}
	};

	inline EventNormal * GET_EVT_INTERPRETER_PROCESS_COMMANDS(const wxString & commands)
	{
		return new EventInterpreterProcessCommands(commands);
	}

	class EventSceneVehicleSimulationData : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_VEHICLE_SIMULATION_DATA;
		SCENE_ID sceneID;
		VehicleSimulationData vehicleSimulationData;
		EventSceneVehicleSimulationData(const SCENE_ID sceneID, const VehicleSimulationData & vehicleSimulationData) : EventNormal(ClassType), sceneID(sceneID), vehicleSimulationData(vehicleSimulationData) {}
	};

	inline EventNormal * GET_EVT_SCENE_VEHICLE_SIMULATION_DATA(const SCENE_ID sceneID, const VehicleSimulationData & vehicleSimulationData)
	{
		return new EventSceneVehicleSimulationData(sceneID, vehicleSimulationData);
	}

	class EventSceneTrafficInfoData : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SCENE_TRAFFIC_INFO_DATA;
		SCENE_ID sceneID;
		TrafficInfoData trafficInfoData;
		EventSceneTrafficInfoData(const SCENE_ID sceneID, const TrafficInfoData & trafficInfoData) : EventNormal(ClassType), sceneID(sceneID), trafficInfoData(trafficInfoData) {}
	};

	inline EventNormal * GET_EVT_SCENE_TRAFFIC_INFO_DATA(const SCENE_ID sceneID, const TrafficInfoData & trafficInfoData)
	{
		return new EventSceneTrafficInfoData(sceneID, trafficInfoData);
	}

	class EventArHudData : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_AR_HUD_DATA;
		ArHudData arHudData;
		EventArHudData(const ArHudData & data) : EventNormal(ClassType), arHudData(data) {}
	};

	inline EventNormal * GET_EVT_AR_HUD_DATA(const ArHudData & arHudData)
	{
		return new EventArHudData(arHudData);
	}

	class EventJavaScriptReleaseCtx : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_JAVASCRIPT_RELEASE_CTX;
		JSScriptingContextPtr ctx;
		EventJavaScriptReleaseCtx(const JSScriptingContextPtr ctx) : EventNormal(ClassType), ctx(ctx) {}
	};

	inline EventNormal * GET_EVT_JAVASCRIPT_RELEASE_CTX(const JSScriptingContextPtr ctx)
	{
		return new EventJavaScriptReleaseCtx(ctx);
	}

	class EventRenderImage : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_IMAGE;
		SCENE_ID sceneID;		///< SceneID of the scene to be rendered
		NODE_ID cameraID;		///< NodeID of the camera to be used to render
		int width, height;		///< Width/Height of the texture. If set, it overrides the camera width/height. If (-1), camera width/height is used.
		wxString filename;		///< Name of the texture to be updated.
		bool save, addImage;
		int cubeSide;
		wxString imageRefName;
		EventRenderImage(const SCENE_ID sceneID, const NODE_ID cameraID, const int width, const int height, const wxString &filename, const bool save, const bool addImage, int cubeSide = -1,
			const wxString imageRefName = wxT("")) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), width(width), height(height), filename(filename), save(save), addImage(addImage),
			cubeSide(cubeSide), imageRefName(imageRefName) {}
	};

	inline EventNormal * GET_EVT_RENDER_IMAGE(const SCENE_ID sceneID, const NODE_ID cameraID, const int width, const int height, const wxString &filename, const bool save, const bool addImage,
		int cubeSide = -1, const wxString imageRefName = wxT(""))
	{
		return new EventRenderImage(sceneID, cameraID, width, height, filename, save, addImage, cubeSide, imageRefName);
	}

	class EventRenderImageDone : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_IMAGE_DONE;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		int width, height;
		wxString filename;
		EventRenderImageDone(const SCENE_ID sceneID, const NODE_ID cameraID, const int width, const int height, const wxString & filename) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID),
			width(width), height(height), filename(filename) {}
	};

	inline EventNormal * GET_EVT_RENDER_IMAGE_DONE(const SCENE_ID sceneID, const NODE_ID cameraID, const int width, const int height, const wxString & filename)
	{
		return new EventRenderImageDone(sceneID, cameraID, width, height, filename);
	}


	class EventImageSaveDone : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_IMAGE_SAVE_DONE;
		wxString filename;
		EventImageSaveDone(const wxString & filename) : EventNormal(ClassType), filename(filename)
		{}
	};

	inline EventNormal * GET_EVT_IMAGE_SAVE_DONE(const wxString & filename)
	{
		return new EventImageSaveDone(filename);
	}

	class EventSceneFrameRendered : public EventNormal
	{
	public:
		/// Description and purpose: This event is raised when the rendering of a scene with
		///		a given camera is done. Its purpose is not very clear, however. The purpose
		///		is (most probably) to inform the animation part of a simulation that rendering
		///		of the previous frame is done, and the data of the new frame may be written into
		///		the scene. That's why the event is raised immediately after the rendering is done
		///		before swapping the buffers, and not after swapping the buffers.
		///
		///		If this is the purpose, than it is not precise and correct. First, the synchronization
		///		should be based on some sort of frame counters. Second, the cameraID would be irrelevant.
		///		Third, there should be an event requesting rendering a frame of that simulation.
		///
		///		See also EVT_RENDER_SYNCHRONIZATION_FINISHED_RENDERING, EVT_RENDER_SYNCHRONIZATION_BARRIER_RELEASE,
		///		and EVT_RENDER_UPDATE, since they are also used to synchronize the rendering.
		///		However, they are different, since they synchronize between multiple rendering
		///		modules, and not between a render module and an animation module.

		static const EVENT_TYPE ClassType = EVT_SCENE_FRAME_RENDERED;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		EventSceneFrameRendered(const SCENE_ID sceneID, const NODE_ID cameraID) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID) {}
	};

	inline EventNormal * GET_EVT_SCENE_FRAME_RENDERED(SCENE_ID sceneID, NODE_ID cameraID)
	{
		return new EventSceneFrameRendered(sceneID, cameraID);
	}

	class EventRenderTile: public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_TILE;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		RenderTileData renderTileData;
		EventRenderTile(const SCENE_ID sceneID, const NODE_ID cameraID, const RenderTileData & renderTileData) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), renderTileData(renderTileData) {}
	};

	inline EventNormal * GET_EVT_RENDER_TILE(const SCENE_ID sceneID, const NODE_ID cameraID, const RenderTileData & renderTileData)
	{
		return new EventRenderTile(sceneID, cameraID, renderTileData);
	}

	class EventRenderTileDone: public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_TILE_DONE;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		RenderTileData renderTileData;
		EventRenderTileDone(const SCENE_ID sceneID, const NODE_ID cameraID, const RenderTileData & renderTileData) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), renderTileData(renderTileData) {}
	};

	inline EventNormal * GET_EVT_RENDER_TILE_DONE(const SCENE_ID sceneID, const NODE_ID cameraID, const RenderTileData & renderTileData)
	{
		return new EventRenderTileDone(sceneID, cameraID, renderTileData);
	}

	class EventRenderTileDoneSync : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_TILE_DONE_SYNC;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		std::shared_ptr<RenderTileData> renderTileData;
		EventRenderTileDoneSync(const SCENE_ID sceneID, const NODE_ID cameraID, const std::shared_ptr<RenderTileData> renderTileData) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), renderTileData(renderTileData) {}
	};

	inline EventNormal * GET_EVT_RENDER_TILE_DONE_SYNC(const SCENE_ID sceneID, const NODE_ID cameraID, const std::shared_ptr<RenderTileData> renderTileData)
	{
		return new EventRenderTileDoneSync(sceneID, cameraID, renderTileData);
	}

	class EventRenderTileLocal : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_TILE_LOCAL;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		RenderTileData renderTileData;
		EventRenderTileLocal(const SCENE_ID sceneID, const NODE_ID cameraID, const RenderTileData & renderTileData) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), renderTileData(renderTileData) {}
	};

	inline EventNormal * GET_EVT_RENDER_TILE_LOCAL(const SCENE_ID sceneID, const NODE_ID cameraID, const RenderTileData & renderTileData)
	{
		return new EventRenderTileLocal(sceneID, cameraID, renderTileData);
	}

	class EventRenderTileLocalDone : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_TILE_LOCAL_DONE;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		RenderTileData renderTileData;
		EventRenderTileLocalDone(const SCENE_ID sceneID, const NODE_ID cameraID, const RenderTileData & renderTileData) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), renderTileData(renderTileData) {}
	};

	inline EventNormal * GET_EVT_RENDER_TILE_LOCAL_DONE(const SCENE_ID sceneID, const NODE_ID cameraID, RenderTileData & renderTileData)
	{
		return new EventRenderTileLocalDone(sceneID, cameraID, renderTileData);
	}

	class EventSGSelectNodesByMaterial : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SG_SELECT_NODES_BY_MATERIAL;
		SCENE_ID sceneID;
		MATERIAL_ID materialID;
		EventSGSelectNodesByMaterial(const SCENE_ID sceneID, const MATERIAL_ID materialID) : EventNormal(ClassType), sceneID(sceneID), materialID(materialID) {}
	};

	inline EventNormal * GET_EVT_SG_SELECT_NODES_BY_MATERIAL(const SCENE_ID sceneID, const MATERIAL_ID materialID)
	{
		return new EventSGSelectNodesByMaterial(sceneID, materialID);
	}

	class EventSGApplyMaterialToSelection : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_SG_APPLY_MATERIAL_TO_SELECTION;
		SCENE_ID sceneID;
		MATERIAL_ID materialID;
		EventSGApplyMaterialToSelection(const SCENE_ID sceneID, const MATERIAL_ID materialID) : EventNormal(ClassType), sceneID(sceneID), materialID(materialID) {}
	};

	inline EventNormal * GET_EVT_SG_APPLY_MATERIAL_TO_SELECTION(const SCENE_ID sceneID, const MATERIAL_ID materialID)
	{
		return new EventSGApplyMaterialToSelection(sceneID, materialID);
	}

	class EventPresentationMode : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_PRESENTATION_MODE;
		bool enable;
		EventPresentationMode(const bool enable) : EventNormal(ClassType), enable(enable) {}
	};

	inline EventNormal * GET_EVT_PRESENTATION_MODE(const bool enable)
	{
		return new EventPresentationMode(enable);
	}

	class EventLocalRemoteRatio : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_LOCAL_REMOTE_RATIO;
		double ratio;
		EventLocalRemoteRatio(const double ratio) : EventNormal(ClassType), ratio(ratio) {}
	};

	inline EventNormal * GET_EVT_LOCAL_REMOTE_RATIO(const double ratio)
	{
		return new EventLocalRemoteRatio(ratio);
	}

	class EventRenderTileDoneSyncForDatasource : public EventNormal
	{
	public:
		static const EVENT_TYPE ClassType = EVT_RENDER_TILE_DONE_SYNC_FOR_DATASOURCE;
		SCENE_ID sceneID;
		NODE_ID cameraID;
		std::shared_ptr<RenderTileData> renderTileData;
		EventRenderTileDoneSyncForDatasource(const SCENE_ID sceneID, const NODE_ID cameraID, const std::shared_ptr<RenderTileData> renderTileData) : EventNormal(ClassType), sceneID(sceneID), cameraID(cameraID), renderTileData(renderTileData) {}
	};

	inline EventNormal * GET_EVT_RENDER_TILE_DONE_SYNC_FOR_DATASOURCE(const SCENE_ID sceneID, const NODE_ID cameraID, const std::shared_ptr<RenderTileData> renderTileData)
	{
		return new EventRenderTileDoneSyncForDatasource(sceneID, cameraID, renderTileData);
	}

	
	inline void ReleaseEvent(Event *evt)
	{
#define IMPLEMENT_RELEASE_CASE(type) case type::ClassType: delete (type *)evt; break;

		switch (evt->type)
		{
			
			IMPLEMENT_RELEASE_CASE(EventExit);
			IMPLEMENT_RELEASE_CASE(EventLog);
			IMPLEMENT_RELEASE_CASE(EventLogLevelSet);
			IMPLEMENT_RELEASE_CASE(EventParamSetDo);
			IMPLEMENT_RELEASE_CASE(EventParamSet);
			IMPLEMENT_RELEASE_CASE(EventParamRegister);
			IMPLEMENT_RELEASE_CASE(EventParamUnregister);
#ifndef VRUT_HPC
			IMPLEMENT_RELEASE_CASE(EventParamGuiRegister);
			IMPLEMENT_RELEASE_CASE(EventParamGuiUnregister);
			IMPLEMENT_RELEASE_CASE(EventParamGuiEnable);
			IMPLEMENT_RELEASE_CASE(EventParamGuiShow);
			IMPLEMENT_RELEASE_CASE(EventParamGuiBeginGroup);
			IMPLEMENT_RELEASE_CASE(EventParamGuiSetLayout);
#endif
			IMPLEMENT_RELEASE_CASE(EventModulePrefer);
			IMPLEMENT_RELEASE_CASE(EventModuleForbid);
			IMPLEMENT_RELEASE_CASE(EventModuleRelease);
			IMPLEMENT_RELEASE_CASE(EventModuleReleased);
			IMPLEMENT_RELEASE_CASE(EventModuleRun);
			IMPLEMENT_RELEASE_CASE(EventModuleInstantiated);
			IMPLEMENT_RELEASE_CASE(EventSceneImageAdd);
			IMPLEMENT_RELEASE_CASE(EventIoSceneImport);
			IMPLEMENT_RELEASE_CASE(EventIoSceneImportDo);
			IMPLEMENT_RELEASE_CASE(EventIoSceneExport);
			IMPLEMENT_RELEASE_CASE(EventRenderScene);
			IMPLEMENT_RELEASE_CASE(EventRenderFullscreenSet);
			IMPLEMENT_RELEASE_CASE(EventRenderFullscreenToggle);
			IMPLEMENT_RELEASE_CASE(EventRenderSynchronizationRegister);
			IMPLEMENT_RELEASE_CASE(EventRenderWinShowCursor);
			IMPLEMENT_RELEASE_CASE(EventRenderWinFocus);
			IMPLEMENT_RELEASE_CASE(EventRenderWinClose);
			IMPLEMENT_RELEASE_CASE(EventGuiPaneShow);
			IMPLEMENT_RELEASE_CASE(EventGuiParamShow);
			IMPLEMENT_RELEASE_CASE(EventMainThreadCallback);

			IMPLEMENT_RELEASE_CASE(EventSceneAdd);
			IMPLEMENT_RELEASE_CASE(EventSceneAdded);
			IMPLEMENT_RELEASE_CASE(EventSceneRemove);
			IMPLEMENT_RELEASE_CASE(EventSceneRemoved);
			IMPLEMENT_RELEASE_CASE(EventSceneImageAdded);
			IMPLEMENT_RELEASE_CASE(EventSceneMaterialAdd);
			IMPLEMENT_RELEASE_CASE(EventSceneMaterialAdded);
			IMPLEMENT_RELEASE_CASE(EventSceneMaterialRemove);
			IMPLEMENT_RELEASE_CASE(EventSceneMaterialRemoved);
			IMPLEMENT_RELEASE_CASE(EventSceneMaterialConvertTranspToRefl);
			IMPLEMENT_RELEASE_CASE(EventSceneGeometryAdd);
			IMPLEMENT_RELEASE_CASE(EventSceneGeometryAdded);
			IMPLEMENT_RELEASE_CASE(EventSceneGeometryRemove);
			IMPLEMENT_RELEASE_CASE(EventSceneGeometryRemoved);
			IMPLEMENT_RELEASE_CASE(EventSceneVariantAdd);
			IMPLEMENT_RELEASE_CASE(EventSceneVariantAdded);
			IMPLEMENT_RELEASE_CASE(EventSceneVariantRemove);
			IMPLEMENT_RELEASE_CASE(EventSceneVariantRemoved);
			IMPLEMENT_RELEASE_CASE(EventSceneVariantActiveStateSet);
			IMPLEMENT_RELEASE_CASE(EventSceneVariantActiveStateChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneVariantDetailStateSet);
			IMPLEMENT_RELEASE_CASE(EventSceneEnvironmentProbeAdd);
			IMPLEMENT_RELEASE_CASE(EventSceneEnvironmentProbeAdded);
			IMPLEMENT_RELEASE_CASE(EventSceneEnvironmentProbeEnable);
			IMPLEMENT_RELEASE_CASE(EventSceneEnvironmentProbeSetSingleShot);
			IMPLEMENT_RELEASE_CASE(EventSceneClippingPlaneAdd);
			IMPLEMENT_RELEASE_CASE(EventSceneClippingPlaneAdded);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeCopy);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeMove);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeMoved);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeIndexChange);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeIndexChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeInsert);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeInserted);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeRemove);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeRemoved);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeNameSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeNameChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeTransformSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeTransform);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeTranslateAbs);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeTransformed);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeSelected);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeGeometrySet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeGeometryChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeMaterialSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeMaterialChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeLightSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeLightChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeLodDistanceSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeSwitchActiveChildSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeSwitchActiveChildChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeSoundSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeSoundStateSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeActiveSet);
			IMPLEMENT_RELEASE_CASE(EventSceneNodeActiveChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneCameraFit);
			IMPLEMENT_RELEASE_CASE(EventSceneCameraFitNearFar);
			IMPLEMENT_RELEASE_CASE(EventSceneCamResetView);
			IMPLEMENT_RELEASE_CASE(EventSceneCameraProjectionSet);
			IMPLEMENT_RELEASE_CASE(EventSceneCamSetPerspectiveParams);
			IMPLEMENT_RELEASE_CASE(EventSceneCamProjectionChanged);
			IMPLEMENT_RELEASE_CASE(EventSceneCarpetRegister);
			IMPLEMENT_RELEASE_CASE(EventSceneCarpetRegistered);
			IMPLEMENT_RELEASE_CASE(EventSceneCarpetUnregister);
			IMPLEMENT_RELEASE_CASE(EventSceneCarpetUnregistered);
			IMPLEMENT_RELEASE_CASE(EventSceneCarpetSetCamParams);
			IMPLEMENT_RELEASE_CASE(EventSceneCarpetSetObserverPosition);
			IMPLEMENT_RELEASE_CASE(EventSceneCollision);
			IMPLEMENT_RELEASE_CASE(EventRenderSceneDone);
			IMPLEMENT_RELEASE_CASE(EventRenderUpdate);
			IMPLEMENT_RELEASE_CASE(EventRenderWinCreated);
			IMPLEMENT_RELEASE_CASE(EventRenderWinFocused);
			IMPLEMENT_RELEASE_CASE(EventRenderWinClosed);
			IMPLEMENT_RELEASE_CASE(EventRenderWinResized);
			IMPLEMENT_RELEASE_CASE(EventRenderSynchronizationUnregister);
			IMPLEMENT_RELEASE_CASE(EventRenderSynchronizationFinishedRendering);
			IMPLEMENT_RELEASE_CASE(EventRenderSynchronizationBarrierRelease);
#ifndef VRUT_HPC
			IMPLEMENT_RELEASE_CASE(EventInputMouse);
			IMPLEMENT_RELEASE_CASE(EventInputKey);
#endif
			IMPLEMENT_RELEASE_CASE(EventInputTracking);
			IMPLEMENT_RELEASE_CASE(EventModuleRunDone);
			IMPLEMENT_RELEASE_CASE(EventIoSceneImportDone);
			IMPLEMENT_RELEASE_CASE(EventCollisionSynchro);
			IMPLEMENT_RELEASE_CASE(EventBvhOptimize);
			IMPLEMENT_RELEASE_CASE(EventInterpreterProcessCommands);
			IMPLEMENT_RELEASE_CASE(EventSceneVehicleSimulationData);
			IMPLEMENT_RELEASE_CASE(EventSceneTrafficInfoData);
			IMPLEMENT_RELEASE_CASE(EventJavaScriptReleaseCtx);
			IMPLEMENT_RELEASE_CASE(EventRenderImage);
			IMPLEMENT_RELEASE_CASE(EventRenderImageDone);
			IMPLEMENT_RELEASE_CASE(EventImageSaveDone);
			IMPLEMENT_RELEASE_CASE(EventSceneFrameRendered);
			IMPLEMENT_RELEASE_CASE(EventRenderTile);
			IMPLEMENT_RELEASE_CASE(EventRenderTileDone);
			IMPLEMENT_RELEASE_CASE(EventRenderTileDoneSync);
			IMPLEMENT_RELEASE_CASE(EventRenderTileLocal);
			IMPLEMENT_RELEASE_CASE(EventRenderTileLocalDone);
			IMPLEMENT_RELEASE_CASE(EventSGSelectNodesByMaterial);
			IMPLEMENT_RELEASE_CASE(EventSGApplyMaterialToSelection);
			IMPLEMENT_RELEASE_CASE(EventPresentationMode);
			IMPLEMENT_RELEASE_CASE(EventArHudData);
			IMPLEMENT_RELEASE_CASE(EventLocalRemoteRatio);
			IMPLEMENT_RELEASE_CASE(EventRenderTileDoneSyncForDatasource);

		default:
			LOGERROR(wxString::Format(wxT("ReleaseEvent: unknown event type %i"), evt->type));
			break;
		}
	}

	inline Event * CloneEvent(Event *evt)
	{
#define IMPLEMENT_CLONE_CASE(type) case type::ClassType: {type *t=new type(*(type *)evt);t->next=nullptr;return t;}

		switch (evt->type)
		{
			
			IMPLEMENT_CLONE_CASE(EventExit);
			IMPLEMENT_CLONE_CASE(EventLog);
			IMPLEMENT_CLONE_CASE(EventLogLevelSet);
			IMPLEMENT_CLONE_CASE(EventParamSetDo);
			IMPLEMENT_CLONE_CASE(EventParamSet);
			IMPLEMENT_CLONE_CASE(EventParamRegister);
			IMPLEMENT_CLONE_CASE(EventParamUnregister);
#ifndef VRUT_HPC
			IMPLEMENT_CLONE_CASE(EventParamGuiRegister);
			IMPLEMENT_CLONE_CASE(EventParamGuiUnregister);
			IMPLEMENT_CLONE_CASE(EventParamGuiEnable);
			IMPLEMENT_CLONE_CASE(EventParamGuiShow);
			IMPLEMENT_CLONE_CASE(EventParamGuiBeginGroup);
			IMPLEMENT_CLONE_CASE(EventParamGuiSetLayout);
#endif
			IMPLEMENT_CLONE_CASE(EventModulePrefer);
			IMPLEMENT_CLONE_CASE(EventModuleForbid);
			IMPLEMENT_CLONE_CASE(EventModuleRelease);
			IMPLEMENT_CLONE_CASE(EventModuleReleased);
			IMPLEMENT_CLONE_CASE(EventModuleRun);
			IMPLEMENT_CLONE_CASE(EventModuleInstantiated);
			IMPLEMENT_CLONE_CASE(EventSceneImageAdd);
			IMPLEMENT_CLONE_CASE(EventIoSceneImport);
			IMPLEMENT_CLONE_CASE(EventIoSceneImportDo);
			IMPLEMENT_CLONE_CASE(EventIoSceneExport);
			IMPLEMENT_CLONE_CASE(EventRenderScene);
			IMPLEMENT_CLONE_CASE(EventRenderFullscreenSet);
			IMPLEMENT_CLONE_CASE(EventRenderFullscreenToggle);
			IMPLEMENT_CLONE_CASE(EventRenderSynchronizationRegister);
			IMPLEMENT_CLONE_CASE(EventRenderWinShowCursor);
			IMPLEMENT_CLONE_CASE(EventRenderWinFocus);
			IMPLEMENT_CLONE_CASE(EventRenderWinClose);
			IMPLEMENT_CLONE_CASE(EventGuiPaneShow);
			IMPLEMENT_CLONE_CASE(EventGuiParamShow);
			IMPLEMENT_CLONE_CASE(EventMainThreadCallback);

			IMPLEMENT_CLONE_CASE(EventSceneAdd);
			IMPLEMENT_CLONE_CASE(EventSceneAdded);
			IMPLEMENT_CLONE_CASE(EventSceneRemove);
			IMPLEMENT_CLONE_CASE(EventSceneRemoved);
			IMPLEMENT_CLONE_CASE(EventSceneImageAdded);
			IMPLEMENT_CLONE_CASE(EventSceneMaterialAdd);
			IMPLEMENT_CLONE_CASE(EventSceneMaterialAdded);
			IMPLEMENT_CLONE_CASE(EventSceneMaterialRemove);
			IMPLEMENT_CLONE_CASE(EventSceneMaterialRemoved);
			IMPLEMENT_CLONE_CASE(EventSceneMaterialConvertTranspToRefl);
			IMPLEMENT_CLONE_CASE(EventSceneGeometryAdd);
			IMPLEMENT_CLONE_CASE(EventSceneGeometryAdded);
			IMPLEMENT_CLONE_CASE(EventSceneGeometryRemove);
			IMPLEMENT_CLONE_CASE(EventSceneGeometryRemoved);
			IMPLEMENT_CLONE_CASE(EventSceneVariantAdd);
			IMPLEMENT_CLONE_CASE(EventSceneVariantAdded);
			IMPLEMENT_CLONE_CASE(EventSceneVariantRemove);
			IMPLEMENT_CLONE_CASE(EventSceneVariantRemoved);
			IMPLEMENT_CLONE_CASE(EventSceneVariantActiveStateSet);
			IMPLEMENT_CLONE_CASE(EventSceneVariantActiveStateChanged);
			IMPLEMENT_CLONE_CASE(EventSceneVariantDetailStateSet);
			IMPLEMENT_CLONE_CASE(EventSceneEnvironmentProbeAdd);
			IMPLEMENT_CLONE_CASE(EventSceneEnvironmentProbeAdded);
			IMPLEMENT_CLONE_CASE(EventSceneEnvironmentProbeEnable);
			IMPLEMENT_CLONE_CASE(EventSceneEnvironmentProbeSetSingleShot);
			IMPLEMENT_CLONE_CASE(EventSceneClippingPlaneAdd);
			IMPLEMENT_CLONE_CASE(EventSceneClippingPlaneAdded);
			IMPLEMENT_CLONE_CASE(EventSceneNodeCopy);
			IMPLEMENT_CLONE_CASE(EventSceneNodeMove);
			IMPLEMENT_CLONE_CASE(EventSceneNodeMoved);
			IMPLEMENT_CLONE_CASE(EventSceneNodeIndexChange);
			IMPLEMENT_CLONE_CASE(EventSceneNodeIndexChanged);
			IMPLEMENT_CLONE_CASE(EventSceneNodeInsert);
			IMPLEMENT_CLONE_CASE(EventSceneNodeInserted);
			IMPLEMENT_CLONE_CASE(EventSceneNodeRemove);
			IMPLEMENT_CLONE_CASE(EventSceneNodeRemoved);
			IMPLEMENT_CLONE_CASE(EventSceneNodeNameSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeNameChanged);
			IMPLEMENT_CLONE_CASE(EventSceneNodeTransformSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeTransform);
			IMPLEMENT_CLONE_CASE(EventSceneNodeTranslateAbs);
			IMPLEMENT_CLONE_CASE(EventSceneNodeTransformed);
			IMPLEMENT_CLONE_CASE(EventSceneNodeSelected);
			IMPLEMENT_CLONE_CASE(EventSceneNodeGeometrySet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeGeometryChanged);
			IMPLEMENT_CLONE_CASE(EventSceneNodeMaterialSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeMaterialChanged);
			IMPLEMENT_CLONE_CASE(EventSceneNodeLightSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeLightChanged);
			IMPLEMENT_CLONE_CASE(EventSceneNodeLodDistanceSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeSwitchActiveChildSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeSwitchActiveChildChanged);
			IMPLEMENT_CLONE_CASE(EventSceneNodeSoundSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeSoundStateSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeActiveSet);
			IMPLEMENT_CLONE_CASE(EventSceneNodeActiveChanged);
			IMPLEMENT_CLONE_CASE(EventSceneCameraFit);
			IMPLEMENT_CLONE_CASE(EventSceneCameraFitNearFar);
			IMPLEMENT_CLONE_CASE(EventSceneCamResetView);
			IMPLEMENT_CLONE_CASE(EventSceneCameraProjectionSet);
			IMPLEMENT_CLONE_CASE(EventSceneCamSetPerspectiveParams);
			IMPLEMENT_CLONE_CASE(EventSceneCamProjectionChanged);
			IMPLEMENT_CLONE_CASE(EventSceneCarpetRegister);
			IMPLEMENT_CLONE_CASE(EventSceneCarpetRegistered);
			IMPLEMENT_CLONE_CASE(EventSceneCarpetUnregister);
			IMPLEMENT_CLONE_CASE(EventSceneCarpetUnregistered);
			IMPLEMENT_CLONE_CASE(EventSceneCarpetSetCamParams);
			IMPLEMENT_CLONE_CASE(EventSceneCarpetSetObserverPosition);
			IMPLEMENT_CLONE_CASE(EventSceneCollision);
			IMPLEMENT_CLONE_CASE(EventRenderSceneDone);
			IMPLEMENT_CLONE_CASE(EventRenderUpdate);
			IMPLEMENT_CLONE_CASE(EventRenderWinCreated);
			IMPLEMENT_CLONE_CASE(EventRenderWinFocused);
			IMPLEMENT_CLONE_CASE(EventRenderWinClosed);
			IMPLEMENT_CLONE_CASE(EventRenderWinResized);
			IMPLEMENT_CLONE_CASE(EventRenderSynchronizationUnregister);
			IMPLEMENT_CLONE_CASE(EventRenderSynchronizationFinishedRendering);
			IMPLEMENT_CLONE_CASE(EventRenderSynchronizationBarrierRelease);
#ifndef VRUT_HPC
			IMPLEMENT_CLONE_CASE(EventInputMouse);
			IMPLEMENT_CLONE_CASE(EventInputKey);
#endif
			IMPLEMENT_CLONE_CASE(EventInputTracking);
			IMPLEMENT_CLONE_CASE(EventModuleRunDone);
			IMPLEMENT_CLONE_CASE(EventIoSceneImportDone);
			IMPLEMENT_CLONE_CASE(EventCollisionSynchro);
			IMPLEMENT_CLONE_CASE(EventBvhOptimize);
			IMPLEMENT_CLONE_CASE(EventInterpreterProcessCommands);
			IMPLEMENT_CLONE_CASE(EventSceneVehicleSimulationData);
			IMPLEMENT_CLONE_CASE(EventSceneTrafficInfoData);
			IMPLEMENT_CLONE_CASE(EventJavaScriptReleaseCtx);
			IMPLEMENT_CLONE_CASE(EventRenderImage);
			IMPLEMENT_CLONE_CASE(EventRenderImageDone);
			IMPLEMENT_CLONE_CASE(EventImageSaveDone);
			IMPLEMENT_CLONE_CASE(EventSceneFrameRendered);
			IMPLEMENT_CLONE_CASE(EventRenderTile);
			IMPLEMENT_CLONE_CASE(EventRenderTileDone);
			IMPLEMENT_CLONE_CASE(EventRenderTileLocal);
			IMPLEMENT_CLONE_CASE(EventRenderTileLocalDone);
			IMPLEMENT_CLONE_CASE(EventRenderTileDoneSync);
			IMPLEMENT_CLONE_CASE(EventSGSelectNodesByMaterial);
			IMPLEMENT_CLONE_CASE(EventSGApplyMaterialToSelection);
			IMPLEMENT_CLONE_CASE(EventPresentationMode);
			IMPLEMENT_CLONE_CASE(EventArHudData);
			IMPLEMENT_CLONE_CASE(EventLocalRemoteRatio);
			IMPLEMENT_CLONE_CASE(EventRenderTileDoneSyncForDatasource);

		default:
			LOGERROR(wxString::Format(wxT("CloneEvent: unknown event type %i"), evt->type));
			break;
		}
		return nullptr;
	}

	inline wxString EventToString(Event *evt)
	{
#define IMPLEMENT_LOG_CASE(type) case type::ClassType: {return wxT(#type);}
#define IMPLEMENT_LOG_CASE2(type) case type::ClassType: {return ((type*)evt)->ToString();}

		switch (evt->type)
		{
			
			IMPLEMENT_LOG_CASE(EventExit);
			IMPLEMENT_LOG_CASE(EventLog);
			IMPLEMENT_LOG_CASE(EventLogLevelSet);
			IMPLEMENT_LOG_CASE(EventParamSetDo);
			IMPLEMENT_LOG_CASE(EventParamSet);
			IMPLEMENT_LOG_CASE(EventParamRegister);
			IMPLEMENT_LOG_CASE(EventParamUnregister);
#ifndef VRUT_HPC
			IMPLEMENT_LOG_CASE(EventParamGuiRegister);
			IMPLEMENT_LOG_CASE(EventParamGuiUnregister);
			IMPLEMENT_LOG_CASE(EventParamGuiEnable);
			IMPLEMENT_LOG_CASE(EventParamGuiShow);
			IMPLEMENT_LOG_CASE(EventParamGuiBeginGroup);
			IMPLEMENT_LOG_CASE(EventParamGuiSetLayout);
#endif
			IMPLEMENT_LOG_CASE(EventModulePrefer);
			IMPLEMENT_LOG_CASE(EventModuleForbid);
			IMPLEMENT_LOG_CASE(EventModuleRelease);
			IMPLEMENT_LOG_CASE(EventModuleReleased);
			IMPLEMENT_LOG_CASE(EventModuleRun);
			IMPLEMENT_LOG_CASE(EventModuleInstantiated);
			IMPLEMENT_LOG_CASE(EventSceneImageAdd);
			IMPLEMENT_LOG_CASE(EventIoSceneImport);
			IMPLEMENT_LOG_CASE(EventIoSceneImportDo);
			IMPLEMENT_LOG_CASE(EventIoSceneExport);
			IMPLEMENT_LOG_CASE(EventRenderScene);
			IMPLEMENT_LOG_CASE(EventRenderFullscreenSet);
			IMPLEMENT_LOG_CASE(EventRenderFullscreenToggle);
			IMPLEMENT_LOG_CASE(EventRenderSynchronizationRegister);
			IMPLEMENT_LOG_CASE(EventRenderWinShowCursor);
			IMPLEMENT_LOG_CASE(EventRenderWinFocus);
			IMPLEMENT_LOG_CASE(EventRenderWinClose);
			IMPLEMENT_LOG_CASE(EventGuiPaneShow);
			IMPLEMENT_LOG_CASE(EventGuiParamShow);
			IMPLEMENT_LOG_CASE(EventMainThreadCallback);

			IMPLEMENT_LOG_CASE(EventSceneAdd);
			IMPLEMENT_LOG_CASE(EventSceneAdded);
			IMPLEMENT_LOG_CASE(EventSceneRemove);
			IMPLEMENT_LOG_CASE(EventSceneRemoved);
			IMPLEMENT_LOG_CASE(EventSceneImageAdded);
			IMPLEMENT_LOG_CASE(EventSceneMaterialAdd);
			IMPLEMENT_LOG_CASE(EventSceneMaterialAdded);
			IMPLEMENT_LOG_CASE(EventSceneMaterialRemove);
			IMPLEMENT_LOG_CASE(EventSceneMaterialRemoved);
			IMPLEMENT_LOG_CASE(EventSceneMaterialConvertTranspToRefl);
			IMPLEMENT_LOG_CASE(EventSceneGeometryAdd);
			IMPLEMENT_LOG_CASE(EventSceneGeometryAdded);
			IMPLEMENT_LOG_CASE(EventSceneGeometryRemove);
			IMPLEMENT_LOG_CASE(EventSceneGeometryRemoved);
			IMPLEMENT_LOG_CASE(EventSceneVariantAdd);
			IMPLEMENT_LOG_CASE(EventSceneVariantAdded);
			IMPLEMENT_LOG_CASE(EventSceneVariantRemove);
			IMPLEMENT_LOG_CASE(EventSceneVariantRemoved);
			IMPLEMENT_LOG_CASE(EventSceneVariantActiveStateSet);
			IMPLEMENT_LOG_CASE(EventSceneVariantActiveStateChanged);
			IMPLEMENT_LOG_CASE(EventSceneVariantDetailStateSet);
			IMPLEMENT_LOG_CASE(EventSceneEnvironmentProbeAdd);
			IMPLEMENT_LOG_CASE(EventSceneEnvironmentProbeAdded);
			IMPLEMENT_LOG_CASE(EventSceneEnvironmentProbeEnable);
			IMPLEMENT_LOG_CASE(EventSceneEnvironmentProbeSetSingleShot);
			IMPLEMENT_LOG_CASE(EventSceneClippingPlaneAdd);
			IMPLEMENT_LOG_CASE(EventSceneClippingPlaneAdded);
			IMPLEMENT_LOG_CASE(EventSceneNodeCopy);
			IMPLEMENT_LOG_CASE(EventSceneNodeMove);
			IMPLEMENT_LOG_CASE(EventSceneNodeMoved);
			IMPLEMENT_LOG_CASE(EventSceneNodeIndexChange);
			IMPLEMENT_LOG_CASE(EventSceneNodeIndexChanged);
			IMPLEMENT_LOG_CASE(EventSceneNodeInsert);
			IMPLEMENT_LOG_CASE(EventSceneNodeInserted);
			IMPLEMENT_LOG_CASE(EventSceneNodeRemove);
			IMPLEMENT_LOG_CASE(EventSceneNodeRemoved);
			IMPLEMENT_LOG_CASE(EventSceneNodeNameSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeNameChanged);
			IMPLEMENT_LOG_CASE(EventSceneNodeTransformSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeTransform);
			IMPLEMENT_LOG_CASE(EventSceneNodeTranslateAbs);
			IMPLEMENT_LOG_CASE2(EventSceneNodeTransformed);
			IMPLEMENT_LOG_CASE(EventSceneNodeSelected);
			IMPLEMENT_LOG_CASE(EventSceneNodeGeometrySet);
			IMPLEMENT_LOG_CASE(EventSceneNodeGeometryChanged);
			IMPLEMENT_LOG_CASE(EventSceneNodeMaterialSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeMaterialChanged);
			IMPLEMENT_LOG_CASE(EventSceneNodeLightSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeLightChanged);
			IMPLEMENT_LOG_CASE(EventSceneNodeLodDistanceSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeSwitchActiveChildSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeSwitchActiveChildChanged);
			IMPLEMENT_LOG_CASE(EventSceneNodeSoundSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeSoundStateSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeActiveSet);
			IMPLEMENT_LOG_CASE(EventSceneNodeActiveChanged);
			IMPLEMENT_LOG_CASE(EventSceneCameraFit);
			IMPLEMENT_LOG_CASE(EventSceneCameraFitNearFar);
			IMPLEMENT_LOG_CASE(EventSceneCamResetView);
			IMPLEMENT_LOG_CASE(EventSceneCameraProjectionSet);
			IMPLEMENT_LOG_CASE(EventSceneCamSetPerspectiveParams);
			IMPLEMENT_LOG_CASE(EventSceneCamProjectionChanged);
			IMPLEMENT_LOG_CASE(EventSceneCarpetRegister);
			IMPLEMENT_LOG_CASE(EventSceneCarpetRegistered);
			IMPLEMENT_LOG_CASE(EventSceneCarpetUnregister);
			IMPLEMENT_LOG_CASE(EventSceneCarpetUnregistered);
			IMPLEMENT_LOG_CASE(EventSceneCarpetSetCamParams);
			IMPLEMENT_LOG_CASE(EventSceneCarpetSetObserverPosition);
			IMPLEMENT_LOG_CASE(EventSceneCollision);
			IMPLEMENT_LOG_CASE(EventRenderSceneDone);
			IMPLEMENT_LOG_CASE(EventRenderUpdate);
			IMPLEMENT_LOG_CASE(EventRenderWinCreated);
			IMPLEMENT_LOG_CASE(EventRenderWinFocused);
			IMPLEMENT_LOG_CASE(EventRenderWinClosed);
			IMPLEMENT_LOG_CASE(EventRenderWinResized);
			IMPLEMENT_LOG_CASE(EventRenderSynchronizationUnregister);
			IMPLEMENT_LOG_CASE(EventRenderSynchronizationFinishedRendering);
			IMPLEMENT_LOG_CASE(EventRenderSynchronizationBarrierRelease);
#ifndef VRUT_HPC
			IMPLEMENT_LOG_CASE(EventInputMouse);
			IMPLEMENT_LOG_CASE(EventInputKey);
#endif
			IMPLEMENT_LOG_CASE(EventInputTracking);
			IMPLEMENT_LOG_CASE(EventModuleRunDone);
			IMPLEMENT_LOG_CASE(EventIoSceneImportDone);
			IMPLEMENT_LOG_CASE(EventCollisionSynchro);
			IMPLEMENT_LOG_CASE(EventBvhOptimize);
			IMPLEMENT_LOG_CASE(EventInterpreterProcessCommands);
			IMPLEMENT_LOG_CASE(EventSceneVehicleSimulationData);
			IMPLEMENT_LOG_CASE(EventSceneTrafficInfoData);
			IMPLEMENT_LOG_CASE(EventJavaScriptReleaseCtx);
			IMPLEMENT_LOG_CASE(EventRenderImage);
			IMPLEMENT_LOG_CASE(EventRenderImageDone);
			IMPLEMENT_LOG_CASE(EventImageSaveDone);
			IMPLEMENT_LOG_CASE(EventSceneFrameRendered);
			IMPLEMENT_LOG_CASE(EventRenderTile);
			IMPLEMENT_LOG_CASE(EventRenderTileDone);
			IMPLEMENT_LOG_CASE(EventRenderTileLocal);
			IMPLEMENT_LOG_CASE(EventRenderTileLocalDone);
			IMPLEMENT_LOG_CASE(EventRenderTileDoneSync);
			IMPLEMENT_LOG_CASE(EventSGSelectNodesByMaterial);
			IMPLEMENT_LOG_CASE(EventSGApplyMaterialToSelection);
			IMPLEMENT_LOG_CASE(EventPresentationMode);
			IMPLEMENT_LOG_CASE(EventArHudData);
			IMPLEMENT_LOG_CASE(EventLocalRemoteRatio);
			IMPLEMENT_LOG_CASE(EventRenderTileDoneSyncForDatasource);

		default:
			LOGERROR(wxString::Format(wxT("LogEvent: unknown event type %i"), evt->type));
			break;
		}
		return wxT("");
	}

	class EventQueue : public MPMC_Queue<Event>
	{
	public:
		Event* WaitForEvent(Event * evt, unsigned long timeout)
		{
			wxCriticalSectionLocker locker(m_mutex);
			const wxMilliClock_t waitUntil = wxGetLocalTimeMillis() + timeout;
			wxMilliClock_t now;
			do
			{
				Event *ret=tail;
				Event *prev=nullptr;
				bool found=false;
				while (ret)
				{
					if (evt->type==ret->type)
					{
						switch (evt->type)
						{
						case Event::EVT_PARAM_SET:
							if (!((EventParamSet*)ret)->paramIdentifier.Matches(((EventParamSet*)evt)->paramIdentifier))
								break;
							if (!((EventParamSet*)evt)->value.empty() && (((EventParamSet*)evt)->value!=((EventParamSet*)ret)->value))
								break;
							found=true;
							break;
						case Event::EVT_IO_SCENE_IMPORT:
							if ((((EventIoSceneImport*)evt)->sceneID!=SCENE_ID_NONE) && (((EventIoSceneImport*)evt)->sceneID!=((EventIoSceneImport*)ret)->sceneID))
								break;
							if ((((EventIoSceneImport*)evt)->rootID!=NODE_ID_NONE) && (((EventIoSceneImport*)evt)->rootID!=((EventIoSceneImport*)ret)->rootID))
								break;
							if (!((EventIoSceneImport*)evt)->sceneFile.empty() && (((EventIoSceneImport*)evt)->sceneFile!=((EventIoSceneImport*)ret)->sceneFile))
								break;
							found=true;
							break;
						case Event::EVT_SCENE_IMAGE_ADDED:
							if (((EventSceneImageAdded*)evt)->successful && !((EventSceneImageAdded*)ret)->successful)
								break;
							if (!((EventSceneImageAdded*)evt)->texFile.empty() && (((EventSceneImageAdded*)evt)->texFile != ((EventSceneImageAdded*)ret)->texFile))
								break;
							if ((((EventSceneImageAdded*)evt)->cubeSide!=-1) && (((EventSceneImageAdded*)evt)->cubeSide != ((EventSceneImageAdded*)ret)->cubeSide))
								break;
							found = true;
							break;
						case Event::EVT_RENDER_SCENE_DONE:
							if ((((EventRenderSceneDone*)evt)->sceneID!=SCENE_ID_NONE) && (((EventRenderSceneDone*)evt)->sceneID!=((EventRenderSceneDone*)ret)->sceneID))
								break;
							if ((((EventRenderSceneDone*)evt)->cameraID!=NODE_ID_NONE) && (((EventRenderSceneDone*)evt)->cameraID!=((EventRenderSceneDone*)ret)->cameraID))
								break;
							if ((((EventRenderSceneDone*)evt)->windowID!=RENDER_WINDOW_ID_NONE) && (((EventRenderSceneDone*)evt)->windowID!=((EventRenderSceneDone*)ret)->windowID))
								break;
							found=true;
							break;
						case Event::EVT_SCENE_NODE_REMOVE:
							if ((((EventSceneNodeRemove*)evt)->sceneID!=SCENE_ID_NONE) && (((EventSceneNodeRemove*)evt)->sceneID!=((EventSceneNodeRemove*)ret)->sceneID))
								break;
							if ((((EventSceneNodeRemove*)evt)->nodeID!=NODE_ID_NONE) && (((EventSceneNodeRemove*)evt)->nodeID!=((EventSceneNodeRemove*)ret)->nodeID))
								break;
							found=true;
							break;
						case Event::EVT_SCENE_NODE_REMOVED:
							if ((((EventSceneNodeRemoved*)evt)->sceneID!=SCENE_ID_NONE) && (((EventSceneNodeRemoved*)evt)->sceneID!=((EventSceneNodeRemoved*)ret)->sceneID))
								break;
							if ((((EventSceneNodeRemoved*)evt)->nodeID!=NODE_ID_NONE) && (((EventSceneNodeRemoved*)evt)->nodeID!=((EventSceneNodeRemoved*)ret)->nodeID))
								break;
							found=true;
							break;
						case Event::EVT_SCENE_COLLISION:
							if ((((EventSceneCollision*)evt)->sceneID != SCENE_ID_NONE) && (((EventSceneCollision*)evt)->sceneID != ((EventSceneCollision*)ret)->sceneID))
								break;
							found = true;
							break;
						case Event::EVT_RENDER_SYNCHRONIZATION_BARRIER_RELEASE:
							if ((((EventRenderSynchronizationBarrierRelease*)evt)->windowID!=RENDER_WINDOW_ID_NONE) 
								&& (((EventRenderSynchronizationBarrierRelease*)evt)->windowID!=((EventRenderSynchronizationBarrierRelease*)ret)->windowID))
								break;
							if ((((EventRenderSynchronizationBarrierRelease*)evt)->renderState!=-1) 
								&& (((EventRenderSynchronizationBarrierRelease*)evt)->renderState!=((EventRenderSynchronizationBarrierRelease*)ret)->renderState))
								break;
							found=true;
							break;
						case Event::EVT_IO_SCENE_IMPORT_DONE:
							if ((((EventIoSceneImportDone*)evt)->sceneID!=SCENE_ID_NONE) && (((EventIoSceneImportDone*)evt)->sceneID!=((EventIoSceneImportDone*)ret)->sceneID))
								break;
							if ((((EventIoSceneImportDone*)evt)->rootID!=NODE_ID_NONE) && (((EventIoSceneImportDone*)evt)->rootID!=((EventIoSceneImportDone*)ret)->rootID))
								break;
							if (!((EventIoSceneImportDone*)evt)->sceneFile.empty() && (((EventIoSceneImportDone*)evt)->sceneFile!=((EventIoSceneImportDone*)ret)->sceneFile))
								break;
							found=true;
							break;
						case Event::EVT_RENDER_IMAGE_DONE:
							if ((((EventRenderImageDone*)evt)->sceneID != SCENE_ID_NONE) && (((EventRenderImageDone*)evt)->sceneID != ((EventRenderImageDone*)ret)->sceneID))
								break;
							if ((((EventRenderImageDone*)evt)->cameraID != NODE_ID_NONE) && (((EventRenderImageDone*)evt)->cameraID != ((EventRenderImageDone*)ret)->cameraID))
								break;
							if ((((EventRenderImageDone*)evt)->width != -1) && (((EventRenderImageDone*)evt)->width != ((EventRenderImageDone*)ret)->width))
								break;
							if ((((EventRenderImageDone*)evt)->height != -1) && (((EventRenderImageDone*)evt)->height != ((EventRenderImageDone*)ret)->height))
								break;
							if (!((EventRenderImageDone*)evt)->filename.empty() && (((EventRenderImageDone*)evt)->filename != ((EventRenderImageDone*)ret)->filename))
								break;
							found = true;
							break;
						case Event::EVT_IMAGE_SAVE_DONE:
							if (!((EventImageSaveDone*)evt)->filename.empty() && (((EventImageSaveDone*)evt)->filename != ((EventImageSaveDone*)ret)->filename))
								break;
							found = true;
							break;
						default:
							LOGERROR(wxString::Format(wxT("WaitForEvent: unknown event type %i"), evt->type));
							break;
						}
						if (found)
						{
							if (ret==tail)
							{
								tail=(Event*)tail->next;
								if (!tail)
									head=nullptr;
							}
							else
							{
								prev->next=ret->next;
								if (ret==head)
									head=prev;
							}
							ReleaseEvent(evt);
							return ret;
						}
					}
					prev=ret;
					ret=(Event*)ret->next;
				}
				if (m_conditionNotEmpty.WaitTimeout(timeout)!=wxCOND_NO_ERROR)
					break;
				now = wxGetLocalTimeMillis();
				timeout = (waitUntil - now).ToLong();
			} while (now < waitUntil);
			ReleaseEvent(evt);
			return nullptr;
		}

		Event * FilterEvent(Event * evt)
		{
			wxCriticalSectionLocker locker(m_mutex);
			if (IsEmpty())
				return evt;
			Event *iter = tail;
			Event *prev = nullptr;
			Event *ret = nullptr;
			size_t eventIndex = 0;
			while (iter)
			{
				bool found = false;
				if (evt->type == iter->type)
				{
					bool foundEnd = false;
					switch (evt->type)
					{
					case Event::EVT_SCENE_NODE_TRANSFORMED:
						if ((((EventSceneNodeTransformed*)evt)->sceneID != ((EventSceneNodeTransformed*)iter)->sceneID) || (((EventSceneNodeTransformed*)evt)->nodeID != ((EventSceneNodeTransformed*)iter)->nodeID))
							break;
						found = true;
						break;
					case Event::EVT_INPUT_TRACKING:
						if ((((EventInputTracking*)evt)->deviceData.id != -1) && (((EventInputTracking*)evt)->deviceData.id != ((EventInputTracking*)iter)->deviceData.id))
							break;
						if ((((EventInputTracking*)evt)->deviceData.buttons != -1) && (((EventInputTracking*)evt)->deviceData.buttons != ((EventInputTracking*)iter)->deviceData.buttons))
							foundEnd = true;
						else
							found = true;
						break;
					default:
						LOGWARNING(wxT("EventQueue::FilterEvent: Bad event type for filtering (Not implemented yet)."));
						break;
					}
					if (foundEnd)
						break;
					if (found)
					{
						if (iter == tail)
						{
							tail = (Event*)tail->next;
							if (!tail)
								head = nullptr;
						}
						else
						{
							prev->next = iter->next;
							if (iter == head)
								head = prev;
						}
						if (ret)
							ReleaseEvent(ret);
						ret = iter;
						if (eventIndex < hPrioMesCount)
						{
							--eventIndex;
							--hPrioMesCount;
						}
					}
				}
				if (!found)
					prev = iter;
				iter = (Event*)iter->next;
				++eventIndex;
			}
			if (ret)
				return ret;
			return evt;
		}
		wxString EventsToString()
		{
			wxCriticalSectionLocker locker(m_mutex);
			if (IsEmpty())
				return wxT("");
			Event *iter = tail;
			size_t eventIndex = 0;
			wxString res;
			while (iter)
			{
				if (eventIndex != 0)
					res += wxT("\n");
				res += TextWriter::WriteToWxStringSize_t(eventIndex)+wxT(" ");
				if (eventIndex < hPrioMesCount)
					res += wxT("HP:");
				res += EventToString(iter);
				iter = (Event*)iter->next;
				++eventIndex;
			}
			return res;
		}
	};
}

#endif
