Browse Source

Delay compilation until editor window is in focus

BearishSun 10 years ago
parent
commit
36d1080271

+ 5 - 0
BansheeEditor/Include/BsEditorWindowBase.h

@@ -81,6 +81,11 @@ namespace BansheeEngine
 		 */	
 		HCamera getGUICamera() const { return mCamera; }
 
+		/**
+		 * @brief	Checks whether the window currently has keyboard focus.
+		 */	
+		bool hasFocus() const;
+
 	protected:
 		EditorWindowBase(bool isModal = false);
 		EditorWindowBase(const RenderWindowPtr& renderWindow);

+ 5 - 0
BansheeEditor/Include/BsEditorWindowManager.h

@@ -47,6 +47,11 @@ namespace BansheeEngine
 		 * @brief	Update to be called once per frame. Calls update on all active editor windows.
 		 */
 		void update();
+
+		/**
+		 * @brief	Checks if any editor window has keyboard focus.
+		 */
+		bool hasFocus() const;
 	protected:
 		MainEditorWindow* mMainWindow;
 

+ 5 - 0
BansheeEditor/Source/BsEditorWindowBase.cpp

@@ -112,4 +112,9 @@ namespace BansheeEngine
 	{
 		return (UINT32)mRenderWindow->getProperties().getHeight();
 	}
+
+	bool EditorWindowBase::hasFocus() const
+	{
+		return mRenderWindow->getProperties().hasFocus();
+	}
 }

+ 14 - 0
BansheeEditor/Source/BsEditorWindowManager.cpp

@@ -82,4 +82,18 @@ namespace BansheeEngine
 			window->update();
 		}
 	}
+
+	bool EditorWindowManager::hasFocus() const
+	{
+		if (mMainWindow->hasFocus())
+			return true;
+
+		for(auto& window : mEditorWindows)
+		{
+			if (window->hasFocus())
+				return true;
+		}
+
+		return false;
+	}
 }

+ 7 - 1
Documentation/Mono-3.8.0-IntegrationGuide.txt

@@ -2,7 +2,7 @@
 
  - Retrieve Mono 3.8.0 source from GitHub (NOT the tar ball)
     - Tar ball has a broken Visual Studio build. (You can try to fix it, likely only a small modification. I didn't bother.)
- - Open in VS2012 as is, or open in later VS and upgrade all projects to latest toolkit (v120 and vs140 tested and working)
+ - Open in VS2012 as is, or open in later VS and upgrade all projects to latest toolkit (v120 and v140 tested and working)
  - Add "mono/utils/mono-conc-hashtable.c"  and "mono/utils/mono-conc-hashtable.c" to libmonoutils project
  - For x64 release version make sure to disable "omit stack frames" optimization
 
@@ -18,6 +18,12 @@ In reflection.c change:
 to:
   MonoClass* mono_class_bind_generic_parameters (MonoClass *klass, int type_argc, MonoType **types, mono_bool is_dynamic)
 
+In mini-amd64.h:
+  Find where definitions of MONO_ARCH_NOMAP32BIT are for various platforms, and below them add:
+   #ifdef HOST_WIN32
+   #define MONO_ARCH_NOMAP32BIT
+   #endif
+
  - Compile mono project with desired configuration (debug/release, 32/64 bit, SGen builds were not tested). You will receive mono-2.0.dll and mono-2.0.lib as output.
  - Add mono-2.0.dll to (BansheeRootDir)/bin/(Platform)/(Configuration)
  - Add mono-2.0.lib to (BansheeRootDir)/Dependencies/lib/(Platform)/(Configuration)

+ 11 - 0
MBansheeEditor/EditorApplication.cs

@@ -145,6 +145,14 @@ namespace BansheeEditor
             get { return !IsPlaying && !IsPaused; }
         }
 
+        /// <summary>
+        /// Checks whether the editor currently has focus.
+        /// </summary>
+        public static bool HasFocus
+        {
+            get { return Internal_HasFocus(); }
+        }
+
         /// <summary>
         /// Render target that the main camera in the scene (if any) will render its view to. This generally means the main 
         /// game window when running standalone, or the Game viewport when running in editor.
@@ -854,5 +862,8 @@ namespace BansheeEditor
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_SetMainRenderTarget(IntPtr rendertarget);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern bool Internal_HasFocus();
     }
 }

+ 18 - 15
MBansheeEditor/ScriptCodeManager.cs

@@ -29,30 +29,33 @@ namespace BansheeEditor
         /// </summary>
         internal void Update()
         {
-            if (CodeEditor.IsSolutionDirty)
+            if (EditorApplication.HasFocus && CodeEditor.IsSolutionDirty)
                 CodeEditor.SyncSolution();
 
             if (EditorApplication.IsStopped)
             {
                 if (compilerInstance == null)
                 {
-                    string outputDir = EditorApplication.ScriptAssemblyPath;
-
-                    if (isGameAssemblyDirty)
+                    if (EditorApplication.HasFocus)
                     {
-                        compilerInstance = ScriptCompiler.CompileAsync(
-                            ScriptAssemblyType.Game, BuildManager.ActivePlatform, true, outputDir);
+                        string outputDir = EditorApplication.ScriptAssemblyPath;
 
-                        EditorApplication.SetStatusCompiling(true);
-                        isGameAssemblyDirty = false;
-                    }
-                    else if (isEditorAssemblyDirty)
-                    {
-                        compilerInstance = ScriptCompiler.CompileAsync(
-                            ScriptAssemblyType.Editor, BuildManager.ActivePlatform, true, outputDir);
+                        if (isGameAssemblyDirty)
+                        {
+                            compilerInstance = ScriptCompiler.CompileAsync(
+                                ScriptAssemblyType.Game, BuildManager.ActivePlatform, true, outputDir);
 
-                        EditorApplication.SetStatusCompiling(true);
-                        isEditorAssemblyDirty = false;
+                            EditorApplication.SetStatusCompiling(true);
+                            isGameAssemblyDirty = false;
+                        }
+                        else if (isEditorAssemblyDirty)
+                        {
+                            compilerInstance = ScriptCompiler.CompileAsync(
+                                ScriptAssemblyType.Editor, BuildManager.ActivePlatform, true, outputDir);
+
+                            EditorApplication.SetStatusCompiling(true);
+                            isEditorAssemblyDirty = false;
+                        }
                     }
                 }
                 else

+ 86 - 85
SBansheeEditor/Include/BsScriptEditorApplication.h

@@ -1,86 +1,87 @@
-#pragma once
-
-#include "BsScriptEditorPrerequisites.h"
-#include "BsScriptObject.h"
-
-namespace BansheeEngine
-{
-	/**
-	 * @brief	Interop class between C++ & CLR for EditorApplication.
-	 */
-	class BS_SCR_BED_EXPORT ScriptEditorApplication : public ScriptObject <ScriptEditorApplication>
-	{
-	public:
-		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "EditorApplication")
-
-		/**
-		 * @brief	Registers internal callbacks. Must be called on scripting system load.
-		 */
-		static void startUp();
-
-		/**
-		 * @brief	Unregisters internal callbacks. Must be called on scripting system shutdown.
-		 */
-		static void shutDown();
-
-		/**
-		 * @brief	Called every frame. Triggers delayed project load.
-		 */
-		 static void update();
-
-	private:
-		ScriptEditorApplication(MonoObject* instance);
-
-		/**
-		 * @brief	Triggered when the user clicks on the editor's status bar.
-		 */
-		static void onStatusBarClicked();
-
-		static bool mRequestProjectLoad;
-		static bool mRequestAssemblyReload;
-		static Path mProjectLoadPath;
-		static HEvent OnStatusBarClickedConn;
-
-		/************************************************************************/
-		/* 								CLR HOOKS						   		*/
-		/************************************************************************/
-		static void internal_SetStatusScene(MonoString* name, bool modified);
-		static void internal_SetStatusProject(bool modified);
-		static void internal_SetStatusCompiling(bool compiling);
-		static MonoString* internal_GetProjectPath();
-		static MonoString* internal_GetProjectName();
-		static bool internal_GetProjectLoaded();
-		static MonoString* internal_GetCompilerPath();
-		static MonoString* internal_GetBuiltinReleaseAssemblyPath();
-		static MonoString* internal_GetBuiltinDebugAssemblyPath();
-		static MonoString* internal_GetScriptAssemblyPath();
-		static MonoString* internal_GetFrameworkAssemblyPath();
-		static MonoString* internal_GetEngineAssemblyName();
-		static MonoString* internal_GetEditorAssemblyName();
-		static MonoString* internal_GetScriptGameAssemblyName();
-		static MonoString* internal_GetScriptEditorAssemblyName();
-		static MonoObject* internal_SaveScene(MonoString* path);
-		static bool internal_IsValidProject(MonoString* path);
-		static void internal_SaveProject();
-		static void internal_LoadProject(MonoString* path);
-		static void internal_UnloadProject();
-		static void internal_CreateProject(MonoString* path);
-		static void internal_ReloadAssemblies();
-		static void internal_OpenExternally(MonoString* path);
-		static void internal_RunUnitTests();
-		static void internal_Quit();
-		static void internal_ToggleToolbarItem(MonoString* name, bool on);
-		static bool internal_GetIsPlaying();
-		static void internal_SetIsPlaying(bool value);
-		static bool internal_GetIsPaused();
-		static void internal_SetIsPaused(bool value);
-		static void internal_FrameStep();
-		static void internal_SetMainRenderTarget(ScriptRenderTarget* renderTarget);
-
-		typedef void(__stdcall *OnProjectLoadedThunkDef)(MonoException**);
-		typedef void(__stdcall *OnStatusBarClickedThunkDef) (MonoException**);
-
-		static OnProjectLoadedThunkDef onProjectLoadedThunk;
-		static OnStatusBarClickedThunkDef onStatusBarClickedThunk;
-	};
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+
+namespace BansheeEngine
+{
+	/**
+	 * @brief	Interop class between C++ & CLR for EditorApplication.
+	 */
+	class BS_SCR_BED_EXPORT ScriptEditorApplication : public ScriptObject <ScriptEditorApplication>
+	{
+	public:
+		SCRIPT_OBJ(EDITOR_ASSEMBLY, "BansheeEditor", "EditorApplication")
+
+		/**
+		 * @brief	Registers internal callbacks. Must be called on scripting system load.
+		 */
+		static void startUp();
+
+		/**
+		 * @brief	Unregisters internal callbacks. Must be called on scripting system shutdown.
+		 */
+		static void shutDown();
+
+		/**
+		 * @brief	Called every frame. Triggers delayed project load.
+		 */
+		 static void update();
+
+	private:
+		ScriptEditorApplication(MonoObject* instance);
+
+		/**
+		 * @brief	Triggered when the user clicks on the editor's status bar.
+		 */
+		static void onStatusBarClicked();
+
+		static bool mRequestProjectLoad;
+		static bool mRequestAssemblyReload;
+		static Path mProjectLoadPath;
+		static HEvent OnStatusBarClickedConn;
+
+		/************************************************************************/
+		/* 								CLR HOOKS						   		*/
+		/************************************************************************/
+		static void internal_SetStatusScene(MonoString* name, bool modified);
+		static void internal_SetStatusProject(bool modified);
+		static void internal_SetStatusCompiling(bool compiling);
+		static MonoString* internal_GetProjectPath();
+		static MonoString* internal_GetProjectName();
+		static bool internal_GetProjectLoaded();
+		static MonoString* internal_GetCompilerPath();
+		static MonoString* internal_GetBuiltinReleaseAssemblyPath();
+		static MonoString* internal_GetBuiltinDebugAssemblyPath();
+		static MonoString* internal_GetScriptAssemblyPath();
+		static MonoString* internal_GetFrameworkAssemblyPath();
+		static MonoString* internal_GetEngineAssemblyName();
+		static MonoString* internal_GetEditorAssemblyName();
+		static MonoString* internal_GetScriptGameAssemblyName();
+		static MonoString* internal_GetScriptEditorAssemblyName();
+		static MonoObject* internal_SaveScene(MonoString* path);
+		static bool internal_IsValidProject(MonoString* path);
+		static void internal_SaveProject();
+		static void internal_LoadProject(MonoString* path);
+		static void internal_UnloadProject();
+		static void internal_CreateProject(MonoString* path);
+		static void internal_ReloadAssemblies();
+		static void internal_OpenExternally(MonoString* path);
+		static void internal_RunUnitTests();
+		static void internal_Quit();
+		static void internal_ToggleToolbarItem(MonoString* name, bool on);
+		static bool internal_GetIsPlaying();
+		static void internal_SetIsPlaying(bool value);
+		static bool internal_GetIsPaused();
+		static void internal_SetIsPaused(bool value);
+		static void internal_FrameStep();
+		static void internal_SetMainRenderTarget(ScriptRenderTarget* renderTarget);
+		static bool internal_HasFocus();
+
+		typedef void(__stdcall *OnProjectLoadedThunkDef)(MonoException**);
+		typedef void(__stdcall *OnStatusBarClickedThunkDef) (MonoException**);
+
+		static OnProjectLoadedThunkDef onProjectLoadedThunk;
+		static OnStatusBarClickedThunkDef onStatusBarClickedThunk;
+	};
 }

+ 358 - 352
SBansheeEditor/Source/BsScriptEditorApplication.cpp

@@ -1,352 +1,358 @@
-#include "BsScriptEditorApplication.h"
-#include "BsMonoManager.h"
-#include "BsMonoClass.h"
-#include "BsMonoMethod.h"
-#include "BsMonoUtil.h"
-#include "BsEditorApplication.h"
-#include "BsProjectLibrary.h"
-#include "BsProjectResourceMeta.h"
-#include "BsPrefab.h"
-#include "BsSceneManager.h"
-#include "BsEditorWindowManager.h"
-#include "BsMainEditorWindow.h"
-#include "BsGUIStatusBar.h"
-#include "BsScriptEditorTestSuite.h"
-#include "BsTestOutput.h"
-#include "BsScriptManager.h"
-#include "BsGUIMenuBar.h"
-#include "BsPlayInEditorManager.h"
-#include "BsScriptRenderTarget.h"
-#include "BsScriptResourceManager.h"
-#include "BsFileSystem.h"
-#include "BsScriptPrefab.h"
-
-namespace BansheeEngine
-{
-	bool ScriptEditorApplication::mRequestProjectLoad = false;
-	bool ScriptEditorApplication::mRequestAssemblyReload = false;
-	Path ScriptEditorApplication::mProjectLoadPath;
-	HEvent ScriptEditorApplication::OnStatusBarClickedConn;
-
-	ScriptEditorApplication::OnProjectLoadedThunkDef ScriptEditorApplication::onProjectLoadedThunk;
-	ScriptEditorApplication::OnStatusBarClickedThunkDef ScriptEditorApplication::onStatusBarClickedThunk;
-
-	ScriptEditorApplication::ScriptEditorApplication(MonoObject* instance)
-		:ScriptObject(instance)
-	{ }
-
-	void ScriptEditorApplication::initRuntimeData()
-	{
-		metaData.scriptClass->addInternalCall("Internal_SetStatusScene", &ScriptEditorApplication::internal_SetStatusScene);
-		metaData.scriptClass->addInternalCall("Internal_SetStatusProject", &ScriptEditorApplication::internal_SetStatusProject);
-		metaData.scriptClass->addInternalCall("Internal_SetStatusCompiling", &ScriptEditorApplication::internal_SetStatusCompiling);
-		metaData.scriptClass->addInternalCall("Internal_GetProjectPath", &ScriptEditorApplication::internal_GetProjectPath);
-		metaData.scriptClass->addInternalCall("Internal_GetProjectName", &ScriptEditorApplication::internal_GetProjectName);
-		metaData.scriptClass->addInternalCall("Internal_GetProjectLoaded", &ScriptEditorApplication::internal_GetProjectLoaded);
-		metaData.scriptClass->addInternalCall("Internal_GetCompilerPath", &ScriptEditorApplication::internal_GetCompilerPath);
-		metaData.scriptClass->addInternalCall("Internal_GetBuiltinReleaseAssemblyPath", &ScriptEditorApplication::internal_GetBuiltinReleaseAssemblyPath);
-		metaData.scriptClass->addInternalCall("Internal_GetBuiltinDebugAssemblyPath", &ScriptEditorApplication::internal_GetBuiltinDebugAssemblyPath);
-		metaData.scriptClass->addInternalCall("Internal_GetScriptAssemblyPath", &ScriptEditorApplication::internal_GetScriptAssemblyPath);
-		metaData.scriptClass->addInternalCall("Internal_GetFrameworkAssemblyPath", &ScriptEditorApplication::internal_GetFrameworkAssemblyPath);
-		metaData.scriptClass->addInternalCall("Internal_GetEngineAssemblyName", &ScriptEditorApplication::internal_GetEngineAssemblyName);
-		metaData.scriptClass->addInternalCall("Internal_GetEditorAssemblyName", &ScriptEditorApplication::internal_GetEditorAssemblyName);
-		metaData.scriptClass->addInternalCall("Internal_GetScriptGameAssemblyName", &ScriptEditorApplication::internal_GetScriptGameAssemblyName);
-		metaData.scriptClass->addInternalCall("Internal_GetScriptEditorAssemblyName", &ScriptEditorApplication::internal_GetScriptEditorAssemblyName);
-		metaData.scriptClass->addInternalCall("Internal_SaveScene", &ScriptEditorApplication::internal_SaveScene);
-		metaData.scriptClass->addInternalCall("Internal_IsValidProject", &ScriptEditorApplication::internal_IsValidProject);
-		metaData.scriptClass->addInternalCall("Internal_SaveProject", &ScriptEditorApplication::internal_SaveProject);
-		metaData.scriptClass->addInternalCall("Internal_LoadProject", &ScriptEditorApplication::internal_LoadProject);
-		metaData.scriptClass->addInternalCall("Internal_UnloadProject", &ScriptEditorApplication::internal_UnloadProject);
-		metaData.scriptClass->addInternalCall("Internal_CreateProject", &ScriptEditorApplication::internal_CreateProject);
-		metaData.scriptClass->addInternalCall("Internal_ReloadAssemblies", &ScriptEditorApplication::internal_ReloadAssemblies);
-		metaData.scriptClass->addInternalCall("Internal_OpenExternally", &ScriptEditorApplication::internal_OpenExternally);
-		metaData.scriptClass->addInternalCall("Internal_RunUnitTests", &ScriptEditorApplication::internal_RunUnitTests);
-		metaData.scriptClass->addInternalCall("Internal_Quit", &ScriptEditorApplication::internal_Quit);
-		metaData.scriptClass->addInternalCall("Internal_ToggleToolbarItem", &ScriptEditorApplication::internal_ToggleToolbarItem);
-		metaData.scriptClass->addInternalCall("Internal_GetIsPlaying", &ScriptEditorApplication::internal_GetIsPlaying);
-		metaData.scriptClass->addInternalCall("Internal_SetIsPlaying", &ScriptEditorApplication::internal_SetIsPlaying);
-		metaData.scriptClass->addInternalCall("Internal_GetIsPaused", &ScriptEditorApplication::internal_GetIsPaused);
-		metaData.scriptClass->addInternalCall("Internal_SetIsPaused", &ScriptEditorApplication::internal_SetIsPaused);
-		metaData.scriptClass->addInternalCall("Internal_FrameStep", &ScriptEditorApplication::internal_FrameStep);
-		metaData.scriptClass->addInternalCall("Internal_SetMainRenderTarget", &ScriptEditorApplication::internal_SetMainRenderTarget);
-
-		onProjectLoadedThunk = (OnProjectLoadedThunkDef)metaData.scriptClass->getMethod("Internal_OnProjectLoaded")->getThunk();
-		onStatusBarClickedThunk = (OnStatusBarClickedThunkDef)metaData.scriptClass->getMethod("Internal_OnStatusBarClicked")->getThunk();
-	}
-
-	void ScriptEditorApplication::startUp()
-	{
-		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
-		OnStatusBarClickedConn = mainWindow->getStatusBar().onMessageClicked.connect(&ScriptEditorApplication::onStatusBarClicked);
-	}
-
-	void ScriptEditorApplication::shutDown()
-	{
-		OnStatusBarClickedConn.disconnect();
-	}
-
-	void ScriptEditorApplication::update()
-	{
-		// Project load must be delayed when requested from managed code because it
-		// triggers managed assembly reload, and that can't be performed when called
-		// from the Mono thread.
-		if (mRequestProjectLoad)
-		{
-			gEditorApplication().loadProject(mProjectLoadPath);
-
-			mRequestProjectLoad = false;
-			mRequestAssemblyReload = false;
-			MonoUtil::invokeThunk(onProjectLoadedThunk);
-		}
-		else if (mRequestAssemblyReload)
-		{
-			ScriptManager::instance().reload();
-			mRequestAssemblyReload = false;
-		}
-	}
-
-	void ScriptEditorApplication::onStatusBarClicked()
-	{
-		MonoUtil::invokeThunk(onStatusBarClickedThunk);
-	}
-
-	void ScriptEditorApplication::internal_SetStatusScene(MonoString* name, bool modified)
-	{
-		WString nativeScene = MonoUtil::monoToWString(name);
-
-		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
-		mainWindow->getStatusBar().setScene(nativeScene, modified);
-	}
-
-	void ScriptEditorApplication::internal_SetStatusProject(bool modified)
-	{
-		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
-
-		if (gEditorApplication().isProjectLoaded())
-			mainWindow->getStatusBar().setProject(gEditorApplication().getProjectName(), modified);
-		else
-			mainWindow->getStatusBar().setProject(L"None", false);
-	}
-
-	void ScriptEditorApplication::internal_SetStatusCompiling(bool compiling)
-	{
-		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
-		mainWindow->getStatusBar().setIsCompiling(compiling);
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetProjectPath()
-	{
-		Path projectPath = gEditorApplication().getProjectPath();
-
-		return MonoUtil::wstringToMono(projectPath.toWString());
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetProjectName()
-	{
-		WString projectName = gEditorApplication().getProjectName();
-
-		return MonoUtil::wstringToMono(projectName);
-	}
-
-	bool ScriptEditorApplication::internal_GetProjectLoaded()
-	{
-		return gEditorApplication().isProjectLoaded();
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetCompilerPath()
-	{
-		Path compilerPath = MonoManager::instance().getCompilerPath();
-
-		return MonoUtil::wstringToMono(compilerPath.toWString());
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetBuiltinReleaseAssemblyPath()
-	{
-		Path releaseAssemblyFolder = FileSystem::getWorkingDirectoryPath();
-		releaseAssemblyFolder.append(Paths::getReleaseAssemblyPath());
-
-		return MonoUtil::wstringToMono(releaseAssemblyFolder.toWString());
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetBuiltinDebugAssemblyPath()
-	{
-		Path debugAssemblyFolder = FileSystem::getWorkingDirectoryPath();
-		debugAssemblyFolder.append(Paths::getDebugAssemblyPath());
-
-		return MonoUtil::wstringToMono(debugAssemblyFolder.toWString());
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetScriptAssemblyPath()
-	{
-		Path assemblyFolder = gEditorApplication().getScriptAssemblyFolder();
-
-		return MonoUtil::wstringToMono(assemblyFolder.toWString());
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetFrameworkAssemblyPath()
-	{
-		Path assemblyFolder = MonoManager::instance().getFrameworkAssembliesFolder();
-		assemblyFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
-
-		return MonoUtil::wstringToMono(assemblyFolder.toWString());
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetEngineAssemblyName()
-	{
-		return MonoUtil::wstringToMono(toWString(ENGINE_ASSEMBLY) + L".dll");
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetEditorAssemblyName()
-	{
-		return MonoUtil::wstringToMono(toWString(EDITOR_ASSEMBLY) + L".dll");
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetScriptGameAssemblyName()
-	{
-		return MonoUtil::wstringToMono(toWString(SCRIPT_GAME_ASSEMBLY) + L".dll");
-	}
-
-	MonoString* ScriptEditorApplication::internal_GetScriptEditorAssemblyName()
-	{
-		return MonoUtil::wstringToMono(toWString(SCRIPT_EDITOR_ASSEMBLY) + L".dll");
-	}
-
-	MonoObject* ScriptEditorApplication::internal_SaveScene(MonoString* path)
-	{
-		Path nativePath = MonoUtil::monoToWString(path);
-		HSceneObject sceneRoot = gSceneManager().getRootNode();
-		
-		ProjectLibrary::LibraryEntry* entry = gProjectLibrary().findEntry(nativePath);
-		HPrefab scene;
-		if (entry != nullptr)
-		{
-			if (entry->type == ProjectLibrary::LibraryEntryType::Directory)
-				return nullptr;
-
-			ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(entry);
-			if (resEntry->meta == nullptr || resEntry->meta->getTypeID() != TID_Prefab)
-				return nullptr;
-
-			scene = static_resource_cast<Prefab>(gProjectLibrary().load(nativePath));
-			scene->update(sceneRoot);
-
-			gProjectLibrary().saveEntry(scene);
-		}
-		else
-		{
-			scene = Prefab::create(sceneRoot);
-			gProjectLibrary().createEntry(scene, nativePath);
-		}
-
-		ScriptPrefab* scriptPrefab;
-		ScriptResourceManager::instance().getScriptResource(scene, &scriptPrefab, true);
-
-		return scriptPrefab->getManagedInstance();
-	}
-
-	bool ScriptEditorApplication::internal_IsValidProject(MonoString* path)
-	{
-		Path nativePath = MonoUtil::monoToWString(path);
-		return gEditorApplication().isValidProjectPath(nativePath);
-	}
-
-	void ScriptEditorApplication::internal_SaveProject()
-	{
-		gEditorApplication().saveProject();
-	}
-
-	void ScriptEditorApplication::internal_LoadProject(MonoString* path)
-	{
-		mRequestProjectLoad = true;
-		mProjectLoadPath = MonoUtil::monoToWString(path);
-	}
-
-	void ScriptEditorApplication::internal_UnloadProject()
-	{
-		gEditorApplication().unloadProject();
-	}
-
-	void ScriptEditorApplication::internal_CreateProject(MonoString* path)
-	{
-		Path nativePath = MonoUtil::monoToWString(path);
-
-		gEditorApplication().createProject(nativePath);
-	}
-
-	void ScriptEditorApplication::internal_ReloadAssemblies()
-	{
-		mRequestAssemblyReload = true;
-	}
-
-	void ScriptEditorApplication::internal_OpenExternally(MonoString* path)
-	{
-		Path nativePath = MonoUtil::monoToWString(path);
-
-		PlatformUtility::open(nativePath);
-	}
-
-	void ScriptEditorApplication::internal_RunUnitTests()
-	{
-#if BS_DEBUG_MODE
-		TestSuitePtr testSuite = TestSuite::create<ScriptEditorTestSuite>();
-		ExceptionTestOutput testOutput;
-		testSuite->run(testOutput);
-#endif
-	}
-
-	void ScriptEditorApplication::internal_Quit()
-	{
-		gApplication().stopMainLoop();
-	}
-
-	void ScriptEditorApplication::internal_ToggleToolbarItem(MonoString* name, bool on)
-	{
-		String nativeName = MonoUtil::monoToString(name);
-
-		MainEditorWindow* editorWindow = EditorWindowManager::instance().getMainWindow();
-		editorWindow->getMenuBar().toggleToolbarButton(nativeName, on);
-	}
-
-	bool ScriptEditorApplication::internal_GetIsPlaying()
-	{
-		return PlayInEditorManager::instance().getState() == PlayInEditorState::Playing;
-	}
-
-	void ScriptEditorApplication::internal_SetIsPlaying(bool value)
-	{
-		if (value)
-			PlayInEditorManager::instance().setState(PlayInEditorState::Playing);
-		else
-			PlayInEditorManager::instance().setState(PlayInEditorState::Stopped);
-	}
-
-	bool ScriptEditorApplication::internal_GetIsPaused()
-	{
-		return PlayInEditorManager::instance().getState() == PlayInEditorState::Paused;
-	}
-
-	void ScriptEditorApplication::internal_SetIsPaused(bool value)
-	{
-		if (value)
-			PlayInEditorManager::instance().setState(PlayInEditorState::Paused);
-		else
-		{
-			bool isPaused = PlayInEditorManager::instance().getState() == PlayInEditorState::Paused;
-			if (isPaused)
-				PlayInEditorManager::instance().setState(PlayInEditorState::Playing);
-		}
-	}
-
-	void ScriptEditorApplication::internal_FrameStep()
-	{
-		PlayInEditorManager::instance().frameStep();
-	}
-
-	void ScriptEditorApplication::internal_SetMainRenderTarget(ScriptRenderTarget* renderTarget)
-	{
-		if (renderTarget == nullptr)
-			SceneManager::instance().setMainRenderTarget(nullptr);
-		else
-			SceneManager::instance().setMainRenderTarget(renderTarget->getNativeValue());
-	}
-}
+#include "BsScriptEditorApplication.h"
+#include "BsMonoManager.h"
+#include "BsMonoClass.h"
+#include "BsMonoMethod.h"
+#include "BsMonoUtil.h"
+#include "BsEditorApplication.h"
+#include "BsProjectLibrary.h"
+#include "BsProjectResourceMeta.h"
+#include "BsPrefab.h"
+#include "BsSceneManager.h"
+#include "BsEditorWindowManager.h"
+#include "BsMainEditorWindow.h"
+#include "BsGUIStatusBar.h"
+#include "BsScriptEditorTestSuite.h"
+#include "BsTestOutput.h"
+#include "BsScriptManager.h"
+#include "BsGUIMenuBar.h"
+#include "BsPlayInEditorManager.h"
+#include "BsScriptRenderTarget.h"
+#include "BsScriptResourceManager.h"
+#include "BsFileSystem.h"
+#include "BsScriptPrefab.h"
+
+namespace BansheeEngine
+{
+	bool ScriptEditorApplication::mRequestProjectLoad = false;
+	bool ScriptEditorApplication::mRequestAssemblyReload = false;
+	Path ScriptEditorApplication::mProjectLoadPath;
+	HEvent ScriptEditorApplication::OnStatusBarClickedConn;
+
+	ScriptEditorApplication::OnProjectLoadedThunkDef ScriptEditorApplication::onProjectLoadedThunk;
+	ScriptEditorApplication::OnStatusBarClickedThunkDef ScriptEditorApplication::onStatusBarClickedThunk;
+
+	ScriptEditorApplication::ScriptEditorApplication(MonoObject* instance)
+		:ScriptObject(instance)
+	{ }
+
+	void ScriptEditorApplication::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_SetStatusScene", &ScriptEditorApplication::internal_SetStatusScene);
+		metaData.scriptClass->addInternalCall("Internal_SetStatusProject", &ScriptEditorApplication::internal_SetStatusProject);
+		metaData.scriptClass->addInternalCall("Internal_SetStatusCompiling", &ScriptEditorApplication::internal_SetStatusCompiling);
+		metaData.scriptClass->addInternalCall("Internal_GetProjectPath", &ScriptEditorApplication::internal_GetProjectPath);
+		metaData.scriptClass->addInternalCall("Internal_GetProjectName", &ScriptEditorApplication::internal_GetProjectName);
+		metaData.scriptClass->addInternalCall("Internal_GetProjectLoaded", &ScriptEditorApplication::internal_GetProjectLoaded);
+		metaData.scriptClass->addInternalCall("Internal_GetCompilerPath", &ScriptEditorApplication::internal_GetCompilerPath);
+		metaData.scriptClass->addInternalCall("Internal_GetBuiltinReleaseAssemblyPath", &ScriptEditorApplication::internal_GetBuiltinReleaseAssemblyPath);
+		metaData.scriptClass->addInternalCall("Internal_GetBuiltinDebugAssemblyPath", &ScriptEditorApplication::internal_GetBuiltinDebugAssemblyPath);
+		metaData.scriptClass->addInternalCall("Internal_GetScriptAssemblyPath", &ScriptEditorApplication::internal_GetScriptAssemblyPath);
+		metaData.scriptClass->addInternalCall("Internal_GetFrameworkAssemblyPath", &ScriptEditorApplication::internal_GetFrameworkAssemblyPath);
+		metaData.scriptClass->addInternalCall("Internal_GetEngineAssemblyName", &ScriptEditorApplication::internal_GetEngineAssemblyName);
+		metaData.scriptClass->addInternalCall("Internal_GetEditorAssemblyName", &ScriptEditorApplication::internal_GetEditorAssemblyName);
+		metaData.scriptClass->addInternalCall("Internal_GetScriptGameAssemblyName", &ScriptEditorApplication::internal_GetScriptGameAssemblyName);
+		metaData.scriptClass->addInternalCall("Internal_GetScriptEditorAssemblyName", &ScriptEditorApplication::internal_GetScriptEditorAssemblyName);
+		metaData.scriptClass->addInternalCall("Internal_SaveScene", &ScriptEditorApplication::internal_SaveScene);
+		metaData.scriptClass->addInternalCall("Internal_IsValidProject", &ScriptEditorApplication::internal_IsValidProject);
+		metaData.scriptClass->addInternalCall("Internal_SaveProject", &ScriptEditorApplication::internal_SaveProject);
+		metaData.scriptClass->addInternalCall("Internal_LoadProject", &ScriptEditorApplication::internal_LoadProject);
+		metaData.scriptClass->addInternalCall("Internal_UnloadProject", &ScriptEditorApplication::internal_UnloadProject);
+		metaData.scriptClass->addInternalCall("Internal_CreateProject", &ScriptEditorApplication::internal_CreateProject);
+		metaData.scriptClass->addInternalCall("Internal_ReloadAssemblies", &ScriptEditorApplication::internal_ReloadAssemblies);
+		metaData.scriptClass->addInternalCall("Internal_OpenExternally", &ScriptEditorApplication::internal_OpenExternally);
+		metaData.scriptClass->addInternalCall("Internal_RunUnitTests", &ScriptEditorApplication::internal_RunUnitTests);
+		metaData.scriptClass->addInternalCall("Internal_Quit", &ScriptEditorApplication::internal_Quit);
+		metaData.scriptClass->addInternalCall("Internal_ToggleToolbarItem", &ScriptEditorApplication::internal_ToggleToolbarItem);
+		metaData.scriptClass->addInternalCall("Internal_GetIsPlaying", &ScriptEditorApplication::internal_GetIsPlaying);
+		metaData.scriptClass->addInternalCall("Internal_SetIsPlaying", &ScriptEditorApplication::internal_SetIsPlaying);
+		metaData.scriptClass->addInternalCall("Internal_GetIsPaused", &ScriptEditorApplication::internal_GetIsPaused);
+		metaData.scriptClass->addInternalCall("Internal_SetIsPaused", &ScriptEditorApplication::internal_SetIsPaused);
+		metaData.scriptClass->addInternalCall("Internal_FrameStep", &ScriptEditorApplication::internal_FrameStep);
+		metaData.scriptClass->addInternalCall("Internal_SetMainRenderTarget", &ScriptEditorApplication::internal_SetMainRenderTarget);
+		metaData.scriptClass->addInternalCall("Internal_HasFocus", &ScriptEditorApplication::internal_HasFocus);
+
+		onProjectLoadedThunk = (OnProjectLoadedThunkDef)metaData.scriptClass->getMethod("Internal_OnProjectLoaded")->getThunk();
+		onStatusBarClickedThunk = (OnStatusBarClickedThunkDef)metaData.scriptClass->getMethod("Internal_OnStatusBarClicked")->getThunk();
+	}
+
+	void ScriptEditorApplication::startUp()
+	{
+		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
+		OnStatusBarClickedConn = mainWindow->getStatusBar().onMessageClicked.connect(&ScriptEditorApplication::onStatusBarClicked);
+	}
+
+	void ScriptEditorApplication::shutDown()
+	{
+		OnStatusBarClickedConn.disconnect();
+	}
+
+	void ScriptEditorApplication::update()
+	{
+		// Project load must be delayed when requested from managed code because it
+		// triggers managed assembly reload, and that can't be performed when called
+		// from the Mono thread.
+		if (mRequestProjectLoad)
+		{
+			gEditorApplication().loadProject(mProjectLoadPath);
+
+			mRequestProjectLoad = false;
+			mRequestAssemblyReload = false;
+			MonoUtil::invokeThunk(onProjectLoadedThunk);
+		}
+		else if (mRequestAssemblyReload)
+		{
+			ScriptManager::instance().reload();
+			mRequestAssemblyReload = false;
+		}
+	}
+
+	void ScriptEditorApplication::onStatusBarClicked()
+	{
+		MonoUtil::invokeThunk(onStatusBarClickedThunk);
+	}
+
+	void ScriptEditorApplication::internal_SetStatusScene(MonoString* name, bool modified)
+	{
+		WString nativeScene = MonoUtil::monoToWString(name);
+
+		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
+		mainWindow->getStatusBar().setScene(nativeScene, modified);
+	}
+
+	void ScriptEditorApplication::internal_SetStatusProject(bool modified)
+	{
+		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
+
+		if (gEditorApplication().isProjectLoaded())
+			mainWindow->getStatusBar().setProject(gEditorApplication().getProjectName(), modified);
+		else
+			mainWindow->getStatusBar().setProject(L"None", false);
+	}
+
+	void ScriptEditorApplication::internal_SetStatusCompiling(bool compiling)
+	{
+		MainEditorWindow* mainWindow = EditorWindowManager::instance().getMainWindow();
+		mainWindow->getStatusBar().setIsCompiling(compiling);
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetProjectPath()
+	{
+		Path projectPath = gEditorApplication().getProjectPath();
+
+		return MonoUtil::wstringToMono(projectPath.toWString());
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetProjectName()
+	{
+		WString projectName = gEditorApplication().getProjectName();
+
+		return MonoUtil::wstringToMono(projectName);
+	}
+
+	bool ScriptEditorApplication::internal_GetProjectLoaded()
+	{
+		return gEditorApplication().isProjectLoaded();
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetCompilerPath()
+	{
+		Path compilerPath = MonoManager::instance().getCompilerPath();
+
+		return MonoUtil::wstringToMono(compilerPath.toWString());
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetBuiltinReleaseAssemblyPath()
+	{
+		Path releaseAssemblyFolder = FileSystem::getWorkingDirectoryPath();
+		releaseAssemblyFolder.append(Paths::getReleaseAssemblyPath());
+
+		return MonoUtil::wstringToMono(releaseAssemblyFolder.toWString());
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetBuiltinDebugAssemblyPath()
+	{
+		Path debugAssemblyFolder = FileSystem::getWorkingDirectoryPath();
+		debugAssemblyFolder.append(Paths::getDebugAssemblyPath());
+
+		return MonoUtil::wstringToMono(debugAssemblyFolder.toWString());
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetScriptAssemblyPath()
+	{
+		Path assemblyFolder = gEditorApplication().getScriptAssemblyFolder();
+
+		return MonoUtil::wstringToMono(assemblyFolder.toWString());
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetFrameworkAssemblyPath()
+	{
+		Path assemblyFolder = MonoManager::instance().getFrameworkAssembliesFolder();
+		assemblyFolder.makeAbsolute(FileSystem::getWorkingDirectoryPath());
+
+		return MonoUtil::wstringToMono(assemblyFolder.toWString());
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetEngineAssemblyName()
+	{
+		return MonoUtil::wstringToMono(toWString(ENGINE_ASSEMBLY) + L".dll");
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetEditorAssemblyName()
+	{
+		return MonoUtil::wstringToMono(toWString(EDITOR_ASSEMBLY) + L".dll");
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetScriptGameAssemblyName()
+	{
+		return MonoUtil::wstringToMono(toWString(SCRIPT_GAME_ASSEMBLY) + L".dll");
+	}
+
+	MonoString* ScriptEditorApplication::internal_GetScriptEditorAssemblyName()
+	{
+		return MonoUtil::wstringToMono(toWString(SCRIPT_EDITOR_ASSEMBLY) + L".dll");
+	}
+
+	MonoObject* ScriptEditorApplication::internal_SaveScene(MonoString* path)
+	{
+		Path nativePath = MonoUtil::monoToWString(path);
+		HSceneObject sceneRoot = gSceneManager().getRootNode();
+		
+		ProjectLibrary::LibraryEntry* entry = gProjectLibrary().findEntry(nativePath);
+		HPrefab scene;
+		if (entry != nullptr)
+		{
+			if (entry->type == ProjectLibrary::LibraryEntryType::Directory)
+				return nullptr;
+
+			ProjectLibrary::ResourceEntry* resEntry = static_cast<ProjectLibrary::ResourceEntry*>(entry);
+			if (resEntry->meta == nullptr || resEntry->meta->getTypeID() != TID_Prefab)
+				return nullptr;
+
+			scene = static_resource_cast<Prefab>(gProjectLibrary().load(nativePath));
+			scene->update(sceneRoot);
+
+			gProjectLibrary().saveEntry(scene);
+		}
+		else
+		{
+			scene = Prefab::create(sceneRoot);
+			gProjectLibrary().createEntry(scene, nativePath);
+		}
+
+		ScriptPrefab* scriptPrefab;
+		ScriptResourceManager::instance().getScriptResource(scene, &scriptPrefab, true);
+
+		return scriptPrefab->getManagedInstance();
+	}
+
+	bool ScriptEditorApplication::internal_IsValidProject(MonoString* path)
+	{
+		Path nativePath = MonoUtil::monoToWString(path);
+		return gEditorApplication().isValidProjectPath(nativePath);
+	}
+
+	void ScriptEditorApplication::internal_SaveProject()
+	{
+		gEditorApplication().saveProject();
+	}
+
+	void ScriptEditorApplication::internal_LoadProject(MonoString* path)
+	{
+		mRequestProjectLoad = true;
+		mProjectLoadPath = MonoUtil::monoToWString(path);
+	}
+
+	void ScriptEditorApplication::internal_UnloadProject()
+	{
+		gEditorApplication().unloadProject();
+	}
+
+	void ScriptEditorApplication::internal_CreateProject(MonoString* path)
+	{
+		Path nativePath = MonoUtil::monoToWString(path);
+
+		gEditorApplication().createProject(nativePath);
+	}
+
+	void ScriptEditorApplication::internal_ReloadAssemblies()
+	{
+		mRequestAssemblyReload = true;
+	}
+
+	void ScriptEditorApplication::internal_OpenExternally(MonoString* path)
+	{
+		Path nativePath = MonoUtil::monoToWString(path);
+
+		PlatformUtility::open(nativePath);
+	}
+
+	void ScriptEditorApplication::internal_RunUnitTests()
+	{
+#if BS_DEBUG_MODE
+		TestSuitePtr testSuite = TestSuite::create<ScriptEditorTestSuite>();
+		ExceptionTestOutput testOutput;
+		testSuite->run(testOutput);
+#endif
+	}
+
+	void ScriptEditorApplication::internal_Quit()
+	{
+		gApplication().stopMainLoop();
+	}
+
+	void ScriptEditorApplication::internal_ToggleToolbarItem(MonoString* name, bool on)
+	{
+		String nativeName = MonoUtil::monoToString(name);
+
+		MainEditorWindow* editorWindow = EditorWindowManager::instance().getMainWindow();
+		editorWindow->getMenuBar().toggleToolbarButton(nativeName, on);
+	}
+
+	bool ScriptEditorApplication::internal_GetIsPlaying()
+	{
+		return PlayInEditorManager::instance().getState() == PlayInEditorState::Playing;
+	}
+
+	void ScriptEditorApplication::internal_SetIsPlaying(bool value)
+	{
+		if (value)
+			PlayInEditorManager::instance().setState(PlayInEditorState::Playing);
+		else
+			PlayInEditorManager::instance().setState(PlayInEditorState::Stopped);
+	}
+
+	bool ScriptEditorApplication::internal_GetIsPaused()
+	{
+		return PlayInEditorManager::instance().getState() == PlayInEditorState::Paused;
+	}
+
+	void ScriptEditorApplication::internal_SetIsPaused(bool value)
+	{
+		if (value)
+			PlayInEditorManager::instance().setState(PlayInEditorState::Paused);
+		else
+		{
+			bool isPaused = PlayInEditorManager::instance().getState() == PlayInEditorState::Paused;
+			if (isPaused)
+				PlayInEditorManager::instance().setState(PlayInEditorState::Playing);
+		}
+	}
+
+	void ScriptEditorApplication::internal_FrameStep()
+	{
+		PlayInEditorManager::instance().frameStep();
+	}
+
+	void ScriptEditorApplication::internal_SetMainRenderTarget(ScriptRenderTarget* renderTarget)
+	{
+		if (renderTarget == nullptr)
+			SceneManager::instance().setMainRenderTarget(nullptr);
+		else
+			SceneManager::instance().setMainRenderTarget(renderTarget->getNativeValue());
+	}
+
+	bool ScriptEditorApplication::internal_HasFocus()
+	{
+		return EditorWindowManager::instance().hasFocus();
+	}
+}