Răsfoiți Sursa

WIP modal windows

Marko Pintera 11 ani în urmă
părinte
comite
78590c7cbc

+ 2 - 0
BansheeEditor/BansheeEditor.vcxproj

@@ -306,6 +306,7 @@
     <ClInclude Include="Include\BsHandleSliderLine.h" />
     <ClInclude Include="Include\BsHandleSliderLine.h" />
     <ClInclude Include="Include\BsHandleSliderPlane.h" />
     <ClInclude Include="Include\BsHandleSliderPlane.h" />
     <ClInclude Include="Include\BsEditorSettings.h" />
     <ClInclude Include="Include\BsEditorSettings.h" />
+    <ClInclude Include="Include\BsModalWindow.h" />
     <ClInclude Include="Include\BsScenePicking.h" />
     <ClInclude Include="Include\BsScenePicking.h" />
     <ClInclude Include="Include\BsProjectLibraryEntriesRTTI.h" />
     <ClInclude Include="Include\BsProjectLibraryEntriesRTTI.h" />
     <ClInclude Include="Include\BsEditorPrerequisites.h" />
     <ClInclude Include="Include\BsEditorPrerequisites.h" />
@@ -391,6 +392,7 @@
     <ClCompile Include="Source\BsHandleSliderPlane.cpp" />
     <ClCompile Include="Source\BsHandleSliderPlane.cpp" />
     <ClCompile Include="Source\BsMainEditorWindow.cpp" />
     <ClCompile Include="Source\BsMainEditorWindow.cpp" />
     <ClCompile Include="Source\BsEditorSettings.cpp" />
     <ClCompile Include="Source\BsEditorSettings.cpp" />
+    <ClCompile Include="Source\BsModalWindow.cpp" />
     <ClCompile Include="Source\BsScenePicking.cpp" />
     <ClCompile Include="Source\BsScenePicking.cpp" />
     <ClCompile Include="Source\BsProjectLibrary.cpp" />
     <ClCompile Include="Source\BsProjectLibrary.cpp" />
     <ClCompile Include="Source\BsProjectLibraryEntries.cpp" />
     <ClCompile Include="Source\BsProjectLibraryEntries.cpp" />

+ 6 - 0
BansheeEditor/BansheeEditor.vcxproj.filters

@@ -243,6 +243,9 @@
     <ClInclude Include="Include\BsEditorSettings.h">
     <ClInclude Include="Include\BsEditorSettings.h">
       <Filter>Header Files\Editor</Filter>
       <Filter>Header Files\Editor</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsModalWindow.h">
+      <Filter>Header Files\Editor</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
     <ClCompile Include="Source\BsEditorWidgetContainer.cpp">
@@ -434,5 +437,8 @@
     <ClCompile Include="Source\BsEditorSettings.cpp">
     <ClCompile Include="Source\BsEditorSettings.cpp">
       <Filter>Source Files\Editor</Filter>
       <Filter>Source Files\Editor</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsModalWindow.cpp">
+      <Filter>Source Files\Editor</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 1 - 0
BansheeEditor/Include/BsEditorPrerequisites.h

@@ -27,6 +27,7 @@ namespace BansheeEngine
 	class EditorWidgetContainer;
 	class EditorWidgetContainer;
 	class EditorWidgetManager;
 	class EditorWidgetManager;
 	class EditorWidgetLayout;
 	class EditorWidgetLayout;
+	class ModalWindow;
 	class GUITabbedTitleBar;
 	class GUITabbedTitleBar;
 	class GUITabButton;
 	class GUITabButton;
 	class GUIWindowDropArea;
 	class GUIWindowDropArea;

+ 1 - 1
BansheeEditor/Include/BsEditorWindow.h

@@ -5,7 +5,7 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	class EditorWindow : public EditorWindowBase
+	class BS_ED_EXPORT EditorWindow : public EditorWindowBase
 	{
 	{
 	public:
 	public:
 		virtual ~EditorWindow();
 		virtual ~EditorWindow();

+ 7 - 2
BansheeEditor/Include/BsEditorWindowBase.h

@@ -5,7 +5,7 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	class EditorWindowBase
+	class BS_ED_EXPORT EditorWindowBase
 	{
 	{
 	public:
 	public:
 		virtual ~EditorWindowBase();
 		virtual ~EditorWindowBase();
@@ -37,8 +37,13 @@ namespace BansheeEngine
 		 */
 		 */
 		RenderWindowPtr getRenderWindow() const { return mRenderWindow; }
 		RenderWindowPtr getRenderWindow() const { return mRenderWindow; }
 
 
+		/**
+		 * @brief	Returns the GUI widget used for displaying all GUI contents in the window.
+		 */
+		HGUIWidget getGUIWidget() const { return mGUI; }
+
 	protected:
 	protected:
-		EditorWindowBase();
+		EditorWindowBase(bool isModal = false);
 		EditorWindowBase(const RenderWindowPtr& renderWindow);
 		EditorWindowBase(const RenderWindowPtr& renderWindow);
 
 
 		RenderWindowPtr mRenderWindow;
 		RenderWindowPtr mRenderWindow;

+ 1 - 0
BansheeEditor/Include/BsEditorWindowManager.h

@@ -14,6 +14,7 @@ namespace BansheeEngine
 
 
 		MainEditorWindow* createMain(const RenderWindowPtr& parentRenderWindow);
 		MainEditorWindow* createMain(const RenderWindowPtr& parentRenderWindow);
 		EditorWindow* create();
 		EditorWindow* create();
+		ModalWindow* createModal();
 		void destroy(EditorWindowBase* window);
 		void destroy(EditorWindowBase* window);
 
 
 		MainEditorWindow* getMainWindow() const { return mMainWindow; }
 		MainEditorWindow* getMainWindow() const { return mMainWindow; }

+ 1 - 1
BansheeEditor/Include/BsMainEditorWindow.h

@@ -5,7 +5,7 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	class MainEditorWindow : public EditorWindowBase
+	class BS_ED_EXPORT MainEditorWindow : public EditorWindowBase
 	{
 	{
 	public:
 	public:
 		~MainEditorWindow();
 		~MainEditorWindow();

+ 26 - 0
BansheeEditor/Include/BsModalWindow.h

@@ -0,0 +1,26 @@
+#pragma once
+
+#include "BsEditorPrerequisites.h"
+#include "BsEditorWindowBase.h"
+
+namespace BansheeEngine
+{
+	class BS_ED_EXPORT ModalWindow : public EditorWindowBase
+	{
+	public:
+		virtual ~ModalWindow();
+
+		virtual void update();
+
+		static ModalWindow* create();
+
+	protected:
+		friend class EditorWindowManager;
+
+		ModalWindow();
+
+		virtual void resized();
+	private:
+		void updateSize();
+	};
+}

+ 2 - 1
BansheeEditor/Source/BsEditorWindowBase.cpp

@@ -11,7 +11,7 @@
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
-	EditorWindowBase::EditorWindowBase()
+	EditorWindowBase::EditorWindowBase(bool isModal)
 		:mOwnsRenderWindow(true)
 		:mOwnsRenderWindow(true)
 	{
 	{
 		RENDER_WINDOW_DESC renderWindowDesc;
 		RENDER_WINDOW_DESC renderWindowDesc;
@@ -20,6 +20,7 @@ namespace BansheeEngine
 		renderWindowDesc.fullscreen = false;
 		renderWindowDesc.fullscreen = false;
 		renderWindowDesc.border = WindowBorder::None;
 		renderWindowDesc.border = WindowBorder::None;
 		renderWindowDesc.toolWindow = true;
 		renderWindowDesc.toolWindow = true;
+		renderWindowDesc.modal = isModal;
 
 
 		mRenderWindow = RenderWindow::create(renderWindowDesc, gCoreApplication().getPrimaryWindow());
 		mRenderWindow = RenderWindow::create(renderWindowDesc, gCoreApplication().getPrimaryWindow());
 
 

+ 10 - 0
BansheeEditor/Source/BsEditorWindowManager.cpp

@@ -1,5 +1,6 @@
 #include "BsEditorWindowManager.h"
 #include "BsEditorWindowManager.h"
 #include "BsEditorWindow.h"
 #include "BsEditorWindow.h"
+#include "BsModalWindow.h"
 #include "BsMainEditorWindow.h"
 #include "BsMainEditorWindow.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
@@ -41,6 +42,15 @@ namespace BansheeEngine
 		return newWindow;
 		return newWindow;
 	}
 	}
 
 
+	ModalWindow* EditorWindowManager::createModal()
+	{
+		ModalWindow* newWindow = new (bs_alloc<ModalWindow>()) ModalWindow();
+		mEditorWindows.push_back(newWindow);
+
+		newWindow->initialize();
+		return newWindow;
+	}
+
 	void EditorWindowManager::destroy(EditorWindowBase* window)
 	void EditorWindowManager::destroy(EditorWindowBase* window)
 	{
 	{
 		auto iterFind = std::find(begin(mEditorWindows), end(mEditorWindows), window);
 		auto iterFind = std::find(begin(mEditorWindows), end(mEditorWindows), window);

+ 43 - 0
BansheeEditor/Source/BsModalWindow.cpp

@@ -0,0 +1,43 @@
+#include "BsModalWindow.h"
+#include "BsEditorWindowManager.h"
+#include "BsRenderWindow.h"
+#include "BsPlatform.h"
+
+namespace BansheeEngine
+{
+	ModalWindow::ModalWindow()
+		:EditorWindowBase(true)
+	{
+		updateSize();
+	}
+
+	ModalWindow::~ModalWindow()
+	{
+
+	}
+
+	void ModalWindow::update()
+	{
+
+	}
+
+	void ModalWindow::resized()
+	{
+		EditorWindowBase::resized();
+
+		updateSize();
+	}
+
+	void ModalWindow::updateSize()
+	{
+		Vector<Rect2I> captionAreas;
+		captionAreas.push_back(Rect2I(0, 0, getWidth(), 20));
+
+		Platform::setCaptionNonClientAreas(*mRenderWindow->getCore().get(), captionAreas);
+	}
+
+	ModalWindow* ModalWindow::create()
+	{
+		return EditorWindowManager::instance().createModal();
+	}
+}

+ 2 - 0
MBansheeEditor/MBansheeEditor.csproj

@@ -85,6 +85,8 @@
     <Compile Include="Inspector\InspectableVector4.cs" />
     <Compile Include="Inspector\InspectableVector4.cs" />
     <Compile Include="Inspector\Inspector.cs" />
     <Compile Include="Inspector\Inspector.cs" />
     <Compile Include="Inspector\InspectorWindow.cs" />
     <Compile Include="Inspector\InspectorWindow.cs" />
+    <Compile Include="ModalWindow.cs" />
+    <Compile Include="ProgressBar.cs" />
     <Compile Include="Scene\SceneCamera.cs" />
     <Compile Include="Scene\SceneCamera.cs" />
     <Compile Include="Scene\SceneViewHandler.cs" />
     <Compile Include="Scene\SceneViewHandler.cs" />
     <Compile Include="Scene\SceneWindow.cs" />
     <Compile Include="Scene\SceneWindow.cs" />

+ 62 - 0
MBansheeEditor/ModalWindow.cs

@@ -0,0 +1,62 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    public class ModalWindow : ScriptObject
+    {
+        public int Width { get { return Internal_GetWidth(mCachedPtr); } }
+        public int Height { get { return Internal_GetHeight(mCachedPtr); } }
+
+        protected GUIPanel GUI;
+
+        public static T Open<T>() where T : ModalWindow
+        {
+            return (T)Internal_CreateInstance(typeof(T).Namespace, typeof(T).Name);
+        }
+
+        private void OnInitializeInternal()
+        {
+            GUI = new GUIPanel();
+            Internal_InitializeGUIPanel(mCachedPtr, GUI);
+            GUI.Initialize();
+            GUI.SetArea(0, 0, Width, Height);
+        }
+
+        private void OnDestroyInternal()
+        {
+            GUI.Destroy();
+            Internal_DestroyGUIPanel(mCachedPtr, GUI);
+        }
+
+        protected virtual void OnWindowResized(int width, int height)
+        {
+            GUI.SetArea(0, 0, width, height);
+        }
+
+        protected void Close()
+        {
+            Internal_Close(mCachedPtr);
+        }
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern ModalWindow Internal_CreateInstance(string ns, string typeName);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_Close(IntPtr nativeInstance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_InitializeGUIPanel(IntPtr nativeInstance, GUIPanel panel);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern void Internal_DestroyGUIPanel(IntPtr nativeInstance, GUIPanel panel);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetWidth(IntPtr nativeInstance);
+
+        [MethodImpl(MethodImplOptions.InternalCall)]
+        private static extern int Internal_GetHeight(IntPtr nativeInstance);
+    }
+}

+ 16 - 0
MBansheeEditor/ProgressBar.cs

@@ -0,0 +1,16 @@
+using System;
+using BansheeEngine;
+
+namespace BansheeEditor
+{
+    public class ProgressBar : ModalWindow
+    {
+        private GUIProgressBar progressBar;
+
+        private void OnInitialize()
+        {
+            progressBar = new GUIProgressBar();
+            progressBar.Percent = 0.5f; // DEBUG ONLY
+        }
+    }
+}

+ 1 - 1
MBansheeEngine/GUI/GUIProgressBar.cs

@@ -16,7 +16,7 @@ namespace BansheeEngine
             Internal_CreateInstance(this, style, options);
             Internal_CreateInstance(this, style, options);
         }
         }
 
 
-        public GUIProgressBar(string style)
+        public GUIProgressBar(string style = "")
         {
         {
             Internal_CreateInstance(this, style, new GUIOption[0]);
             Internal_CreateInstance(this, style, new GUIOption[0]);
         }
         }

+ 89 - 0
SBansheeEditor/Include/BsScriptModalWindow.h

@@ -0,0 +1,89 @@
+#pragma once
+
+#include "BsScriptEditorPrerequisites.h"
+#include "BsScriptObject.h"
+#include "BsModalWindow.h"
+#include "BsVector2I.h"
+
+namespace BansheeEngine
+{
+	class ManagedModalWindow;
+
+	class BS_SCR_BED_EXPORT ScriptModalWindow : public ScriptObject <ScriptModalWindow, PersistentScriptObjectBase>
+	{
+		struct ModalWindowHandle
+		{
+			uint32_t gcHandle;
+			ManagedModalWindow* nativeObj;
+		};
+	public:
+		SCRIPT_OBJ(BansheeEditorAssemblyName, "BansheeEditor", "ModalWindow")
+
+		~ScriptModalWindow();
+
+	private:
+		friend class ManagedModalWindow;
+
+		ScriptModalWindow(ManagedModalWindow* editorWidget);
+
+		static MonoObject* internal_createInstance(MonoString* ns, MonoString* typeName);
+		static void internal_close(ScriptModalWindow* thisPtr);
+		static UINT32 internal_getWidth(ScriptModalWindow* thisPtr);
+		static UINT32 internal_getHeight(ScriptModalWindow* thisPtr);
+		static void internal_initializeGUIPanel(ScriptModalWindow* thisPtr, MonoObject* panel);
+
+		void onAssemblyRefreshStarted();
+
+		void _onManagedInstanceDeleted();
+		ScriptObjectBackup beginRefresh();
+		void endRefresh(const ScriptObjectBackup& backupData);
+		MonoObject* _createManagedInstance(bool construct);
+
+		ManagedModalWindow* mModalWindow;
+		ScriptGUIPanel* mGUIPanel;
+		HEvent mOnAssemblyRefreshStartedConn;
+		bool mRefreshInProgress;
+
+		static MonoMethod* onInitializedInternalMethod;
+		static MonoMethod* onDestroyInternalMethod;
+	};
+
+	class BS_SCR_BED_EXPORT ManagedModalWindow : public ModalWindow
+	{
+	public:
+		ManagedModalWindow(const String& ns, const String& type);
+		~ManagedModalWindow();
+
+		bool createManagedInstance();
+		void releaseManagedInstance();
+
+		void update();
+		void reloadMonoTypes(MonoClass* windowClass);
+		void triggerOnInitialize();
+		void triggerOnDestroy();
+
+		MonoObject* getManagedInstance() const { return mManagedInstance; }
+	protected:
+		virtual void resized();
+
+	private:
+		friend class ScriptModalWindow;
+
+		typedef void(__stdcall *OnInitializeThunkDef) (MonoObject*, MonoException**);
+		typedef void(__stdcall *OnDestroyThunkDef) (MonoObject*, MonoException**);
+		typedef void(__stdcall *UpdateThunkDef) (MonoObject*, MonoException**);
+
+		String mNamespace;
+		String mTypename;
+
+		OnInitializeThunkDef mOnInitializeThunk;
+		OnDestroyThunkDef mOnDestroyThunk;
+		UpdateThunkDef mUpdateThunk;
+		MonoMethod* mOnWindowResizedMethod;
+
+		MonoObject* mManagedInstance;
+		uint32_t mGCHandle;
+
+		ScriptModalWindow* mScriptParent;
+	};
+}

+ 2 - 0
SBansheeEditor/SBansheeEditor.vcxproj

@@ -262,6 +262,7 @@
     <ClInclude Include="Include\BsScriptHandleSliderLine.h" />
     <ClInclude Include="Include\BsScriptHandleSliderLine.h" />
     <ClInclude Include="Include\BsScriptHandleSliderManager.h" />
     <ClInclude Include="Include\BsScriptHandleSliderManager.h" />
     <ClInclude Include="Include\BsScriptHandleSliderPlane.h" />
     <ClInclude Include="Include\BsScriptHandleSliderPlane.h" />
+    <ClInclude Include="Include\BsScriptModalWindow.h" />
     <ClInclude Include="Include\BsScriptProjectLibrary.h" />
     <ClInclude Include="Include\BsScriptProjectLibrary.h" />
     <ClInclude Include="Include\BsScriptSceneViewHandler.h" />
     <ClInclude Include="Include\BsScriptSceneViewHandler.h" />
     <ClInclude Include="Include\BsScriptSelection.h" />
     <ClInclude Include="Include\BsScriptSelection.h" />
@@ -297,6 +298,7 @@
     <ClCompile Include="Source\BsScriptHandleSliderLine.cpp" />
     <ClCompile Include="Source\BsScriptHandleSliderLine.cpp" />
     <ClCompile Include="Source\BsScriptHandleSliderManager.cpp" />
     <ClCompile Include="Source\BsScriptHandleSliderManager.cpp" />
     <ClCompile Include="Source\BsScriptHandleSliderPlane.cpp" />
     <ClCompile Include="Source\BsScriptHandleSliderPlane.cpp" />
+    <ClCompile Include="Source\BsScriptModalWindow.cpp" />
     <ClCompile Include="Source\BsScriptProjectLibrary.cpp" />
     <ClCompile Include="Source\BsScriptProjectLibrary.cpp" />
     <ClCompile Include="Source\BsScriptSceneViewHandler.cpp" />
     <ClCompile Include="Source\BsScriptSceneViewHandler.cpp" />
     <ClCompile Include="Source\BsScriptSelection.cpp" />
     <ClCompile Include="Source\BsScriptSelection.cpp" />

+ 6 - 0
SBansheeEditor/SBansheeEditor.vcxproj.filters

@@ -114,6 +114,9 @@
     <ClInclude Include="Include\BsScriptEditorSettings.h">
     <ClInclude Include="Include\BsScriptEditorSettings.h">
       <Filter>Header Files</Filter>
       <Filter>Header Files</Filter>
     </ClInclude>
     </ClInclude>
+    <ClInclude Include="Include\BsScriptModalWindow.h">
+      <Filter>Header Files</Filter>
+    </ClInclude>
   </ItemGroup>
   </ItemGroup>
   <ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp">
     <ClCompile Include="Source\BsScriptEditorPlugin.cpp">
@@ -215,5 +218,8 @@
     <ClCompile Include="Source\BsScriptEditorSettings.cpp">
     <ClCompile Include="Source\BsScriptEditorSettings.cpp">
       <Filter>Source Files</Filter>
       <Filter>Source Files</Filter>
     </ClCompile>
     </ClCompile>
+    <ClCompile Include="Source\BsScriptModalWindow.cpp">
+      <Filter>Source Files</Filter>
+    </ClCompile>
   </ItemGroup>
   </ItemGroup>
 </Project>
 </Project>

+ 279 - 0
SBansheeEditor/Source/BsScriptModalWindow.cpp

@@ -0,0 +1,279 @@
+#include "BsScriptModalWindow.h"
+#include "BsScriptMeta.h"
+#include "BsScriptGUIPanel.h"
+#include "BsMonoField.h"
+#include "BsMonoClass.h"
+#include "BsMonoMethod.h"
+#include "BsMonoManager.h"
+#include "BsMonoUtil.h"
+#include "BsMonoAssembly.h"
+#include "BsScriptObjectManager.h"
+
+using namespace std::placeholders;
+
+namespace BansheeEngine
+{
+	MonoMethod* ScriptModalWindow::onInitializedInternalMethod = nullptr;
+	MonoMethod* ScriptModalWindow::onDestroyInternalMethod = nullptr;
+
+	ScriptModalWindow::ScriptModalWindow(ManagedModalWindow* window)
+		:ScriptObject(window->getManagedInstance()), mModalWindow(window), mRefreshInProgress(false)
+	{
+		mOnAssemblyRefreshStartedConn = ScriptObjectManager::instance().onRefreshStarted.connect(std::bind(&ScriptModalWindow::onAssemblyRefreshStarted, this));
+	}
+
+	ScriptModalWindow::~ScriptModalWindow()
+	{
+		mOnAssemblyRefreshStartedConn.disconnect();
+	}
+
+	void ScriptModalWindow::initRuntimeData()
+	{
+		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptModalWindow::internal_createInstance);
+		metaData.scriptClass->addInternalCall("Internal_Close", &ScriptModalWindow::internal_close);
+		metaData.scriptClass->addInternalCall("Internal_InitializeGUIPanel", &ScriptModalWindow::internal_initializeGUIPanel);
+		metaData.scriptClass->addInternalCall("Internal_GetWidth", &ScriptModalWindow::internal_getWidth);
+		metaData.scriptClass->addInternalCall("Internal_GetHeight", &ScriptModalWindow::internal_getHeight);
+
+		onInitializedInternalMethod = metaData.scriptClass->getMethod("OnInitializeInternal", 0);
+		onDestroyInternalMethod = metaData.scriptClass->getMethod("OnDestroyInternal", 0);
+	}
+
+	MonoObject* ScriptModalWindow::internal_createInstance(MonoString* ns, MonoString* typeName)
+	{
+		String strTypeName = toString(MonoUtil::monoToWString(typeName));
+		String strNamespace = toString(MonoUtil::monoToWString(ns));
+		String fullName = strNamespace + "." + strTypeName;
+
+		ManagedModalWindow* modalWindow = bs_new<ManagedModalWindow>(strNamespace, strTypeName);
+		ScriptModalWindow* nativeInstance = new (bs_alloc<ScriptModalWindow>()) ScriptModalWindow(modalWindow);
+
+		mono_runtime_object_init(modalWindow->getManagedInstance()); // Construct it
+		modalWindow->triggerOnInitialize();
+
+		return modalWindow->getManagedInstance();
+	}
+
+	void ScriptModalWindow::internal_close(ScriptModalWindow* thisPtr)
+	{
+		if (thisPtr->mModalWindow == nullptr)
+			return;
+
+		thisPtr->mModalWindow->triggerOnDestroy();
+		thisPtr->mModalWindow->releaseManagedInstance();
+		thisPtr->mModalWindow->close();
+		thisPtr->mModalWindow = nullptr;
+	}
+
+	void ScriptModalWindow::_onManagedInstanceDeleted()
+	{
+		if (!mRefreshInProgress)
+		{
+			// Note: This should only ever get triggered after "internal_close" is called
+
+			ScriptObject::_onManagedInstanceDeleted();
+		}
+		else
+			mManagedInstance = nullptr;
+	}
+
+	ScriptObjectBackup ScriptModalWindow::beginRefresh()
+	{
+		mRefreshInProgress = true;
+
+		if (mModalWindow != nullptr)
+			mModalWindow->releaseManagedInstance();
+
+		return PersistentScriptObjectBase::beginRefresh();
+	}
+
+	void ScriptModalWindow::endRefresh(const ScriptObjectBackup& backupData)
+	{
+		mRefreshInProgress = false;
+
+		if (mModalWindow != nullptr)
+			mManagedInstance = mModalWindow->getManagedInstance();
+		else
+			mManagedInstance = nullptr;
+
+		if (mManagedInstance != nullptr)
+		{
+			mModalWindow->triggerOnInitialize();
+		}
+		else
+		{
+			// We couldn't restore managed instance because window class cannot be found
+			_onManagedInstanceDeleted();
+		}
+
+		PersistentScriptObjectBase::endRefresh(backupData);
+	}
+
+	void ScriptModalWindow::onAssemblyRefreshStarted()
+	{
+		if (mModalWindow != nullptr)
+			mModalWindow->triggerOnDestroy();
+	}
+
+	MonoObject* ScriptModalWindow::_createManagedInstance(bool construct)
+	{
+		if (mModalWindow != nullptr)
+		{
+			mModalWindow->createManagedInstance();
+
+			return mModalWindow->getManagedInstance();
+		}
+		else
+			return nullptr;
+	}
+
+	UINT32 ScriptModalWindow::internal_getWidth(ScriptModalWindow* thisPtr)
+	{
+		if (thisPtr->mModalWindow != nullptr)
+			return thisPtr->mModalWindow->getWidth();
+
+		return 0;
+	}
+
+	UINT32 ScriptModalWindow::internal_getHeight(ScriptModalWindow* thisPtr)
+	{
+		if (thisPtr->mModalWindow != nullptr)
+			return thisPtr->mModalWindow->getHeight();
+
+		return 0;
+	}
+
+	void ScriptModalWindow::internal_initializeGUIPanel(ScriptModalWindow* thisPtr, MonoObject* panel)
+	{
+		ScriptGUIPanel* scriptGUIPanel = ScriptGUIPanel::toNative(panel);
+		thisPtr->mGUIPanel = scriptGUIPanel;
+
+		// TODO - Handle TitleBar when I add it
+		scriptGUIPanel->setParentArea(0, 0,
+			thisPtr->mModalWindow->getWidth(), thisPtr->mModalWindow->getHeight());
+
+		scriptGUIPanel->setParentWidget(thisPtr->mModalWindow->getGUIWidget().get());
+	}
+
+	ManagedModalWindow::ManagedModalWindow(const String& ns, const String& type)
+		:ModalWindow(), mNamespace(ns), mTypename(type), mUpdateThunk(nullptr), mManagedInstance(nullptr), 
+		mOnInitializeThunk(nullptr), mOnDestroyThunk(nullptr), mOnWindowResizedMethod(nullptr), mGCHandle(0)
+	{
+		createManagedInstance();
+	}
+
+	ManagedModalWindow::~ManagedModalWindow()
+	{
+
+	}
+
+	bool ManagedModalWindow::createManagedInstance()
+	{
+		MonoAssembly* assembly = MonoManager::instance().getAssembly(BansheeEditorAssemblyName);
+
+		if (assembly != nullptr)
+		{
+			MonoClass* editorWindowClass = assembly->getClass(mNamespace, mTypename);
+
+			if (editorWindowClass != nullptr)
+			{
+				mManagedInstance = editorWindowClass->createInstance();
+				mGCHandle = mono_gchandle_new(mManagedInstance, false);
+
+				reloadMonoTypes(editorWindowClass);
+				return true;
+			}
+		}
+
+		return false;
+	}
+
+	void ManagedModalWindow::releaseManagedInstance()
+	{
+		mono_gchandle_free(mGCHandle);
+		mGCHandle = 0;
+	}
+
+	void ManagedModalWindow::triggerOnInitialize()
+	{
+		if (mManagedInstance != nullptr)
+			ScriptModalWindow::onInitializedInternalMethod->invoke(mManagedInstance, nullptr);
+
+		if (mOnInitializeThunk != nullptr && mManagedInstance != nullptr)
+		{
+			MonoException* exception = nullptr;
+
+			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
+			// for some extra speed.
+			mOnInitializeThunk(mManagedInstance, &exception);
+
+			MonoUtil::throwIfException(exception);
+		}
+	}
+
+	void ManagedModalWindow::triggerOnDestroy()
+	{
+		if (mManagedInstance != nullptr)
+			ScriptModalWindow::onDestroyInternalMethod->invoke(mManagedInstance, nullptr);
+
+		if (mOnDestroyThunk != nullptr && mManagedInstance != nullptr)
+		{
+			MonoException* exception = nullptr;
+
+			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
+			// for some extra speed.
+			mOnDestroyThunk(mManagedInstance, &exception);
+
+			MonoUtil::throwIfException(exception);
+		}
+	}
+
+	void ManagedModalWindow::update()
+	{
+		if (mUpdateThunk != nullptr && mManagedInstance != nullptr)
+		{
+			MonoException* exception = nullptr;
+
+			// Note: Not calling virtual methods. Can be easily done if needed but for now doing this
+			// for some extra speed.
+			mUpdateThunk(mManagedInstance, &exception);
+
+			MonoUtil::throwIfException(exception);
+		}
+	}
+
+	void ManagedModalWindow::resized()
+	{
+		UINT32 width = getWidth();
+		UINT32 height = getHeight();
+
+		// TODO - Handle TitleBar when I add it
+		mScriptParent->mGUIPanel->setParentArea(0, 0, width, height);
+
+		if (mOnWindowResizedMethod != nullptr && mManagedInstance != nullptr)
+		{
+			void* params[] = { &width, &height };
+			mOnWindowResizedMethod->invokeVirtual(mManagedInstance, params);
+		}
+	}
+
+	void ManagedModalWindow::reloadMonoTypes(MonoClass* windowClass)
+	{
+		MonoMethod* updateMethod = windowClass->getMethod("OnEditorUpdate", 0);
+
+		if (updateMethod != nullptr)
+			mUpdateThunk = (UpdateThunkDef)updateMethod->getThunk();
+
+		MonoMethod* onInitializeMethod = windowClass->getMethod("OnInitialize", 0);
+
+		if (onInitializeMethod != nullptr)
+			mOnInitializeThunk = (OnInitializeThunkDef)onInitializeMethod->getThunk();
+
+		MonoMethod* onDestroyMethod = windowClass->getMethod("OnDestroy", 0);
+
+		if (onDestroyMethod != nullptr)
+			mOnDestroyThunk = (OnDestroyThunkDef)onDestroyMethod->getThunk();
+
+		mOnWindowResizedMethod = windowClass->getMethod("OnWindowResized", 2);
+	}
+}

+ 7 - 0
TODO.txt

@@ -10,6 +10,13 @@ Possibly set up automatic refresh in debug mode after initialization? As an ad-h
 Test file/folder open/save dialog
 Test file/folder open/save dialog
 
 
 Add a simple way to create modal dialogs (ModalDialog in C#, similar to EditorWindow)
 Add a simple way to create modal dialogs (ModalDialog in C#, similar to EditorWindow)
+Modal window needs a title bar probably (with an X button, which would be optional)
+ - When I add it make sure to update GUIPanel area in ScriptModalWindow
+
+C#:
+Dialog.Show(title, text, btn1 text, btn1 callback, btn2 text, btn2 callback, btn3 text, btn3 callback)
+ProgressBar.Show(float percent) / ProgressBar.Hide()
+
 
 
 Add C# wrappers GUIElement bounds and visible bounds (with ability to set non-visible bounds)
 Add C# wrappers GUIElement bounds and visible bounds (with ability to set non-visible bounds)