Просмотр исходного кода

Properly clean up C# GUIPanels when window is closed or when assembly refresh occurs
Fixed Gizmo and Handle manager so they don't keep a handle to non-core RenderTarget

Marko Pintera 11 лет назад
Родитель
Сommit
2ba6cb589b

+ 2 - 2
BansheeEditor/Include/BsGizmoManager.h

@@ -218,12 +218,12 @@ namespace BansheeEngine
 		void renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, SPtr<MeshCoreBase> mesh, GizmoManager::GizmoMaterial material);
 		void renderGizmos(Matrix4 viewMatrix, Matrix4 projMatrix, SPtr<MeshCoreBase> mesh, GizmoManager::GizmoMaterial material);
 		void renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial);
 		void renderIconGizmos(Rect2I screenArea, SPtr<MeshCoreBase> mesh, GizmoManager::IconRenderDataVecPtr renderData, bool usePickingMaterial);
 
 
-		void updateData(const RenderTargetPtr& rt, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
+		void updateData(const SPtr<RenderTargetCore>& rt, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
 			const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData);
 			const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData);
 
 
 		static const float PICKING_ALPHA_CUTOFF;
 		static const float PICKING_ALPHA_CUTOFF;
 
 
-		RenderTargetPtr mSceneRenderTarget;
+		SPtr<RenderTargetCore> mSceneRenderTarget;
 
 
 		SPtr<MeshCoreBase> mSolidMesh;
 		SPtr<MeshCoreBase> mSolidMesh;
 		SPtr<MeshCoreBase> mWireMesh;
 		SPtr<MeshCoreBase> mWireMesh;

+ 2 - 2
BansheeEditor/Include/BsHandleDrawManager.h

@@ -84,10 +84,10 @@ namespace BansheeEngine
 
 
 		void initialize(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat);
 		void initialize(const SPtr<MaterialCore>& wireMat, const SPtr<MaterialCore>& solidMat);
 
 
-		void updateData(const RenderTargetPtr& rt, const Vector<MeshData>& meshes);
+		void updateData(const SPtr<RenderTargetCore>& rt, const Vector<MeshData>& meshes);
 		void render(const CameraHandlerCore& camera);
 		void render(const CameraHandlerCore& camera);
 
 
-		RenderTargetPtr mSceneRenderTarget;
+		SPtr<RenderTargetCore> mSceneRenderTarget;
 		Vector<MeshData> mMeshes;
 		Vector<MeshData> mMeshes;
 
 
 		// Immutable
 		// Immutable

+ 6 - 7
BansheeEditor/Source/BsGizmoManager.cpp

@@ -264,7 +264,8 @@ namespace BansheeEngine
 		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
 		mIconMesh = buildIconMesh(camera, mIconData, false, iconRenderData);
 		SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
 		SPtr<MeshCoreBase> iconMesh = mIconMesh->getCore();
 
 
-		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, mCore, rt, solidMesh, wireMesh, iconMesh, iconRenderData));
+		gCoreAccessor().queueCommand(std::bind(&GizmoManagerCore::updateData, mCore, rt->getCore(), 
+			solidMesh, wireMesh, iconMesh, iconRenderData));
 	}
 	}
 
 
 	void GizmoManager::renderForPicking(const CameraHandlerPtr& camera, std::function<Color(UINT32)> idxToColorCallback)
 	void GizmoManager::renderForPicking(const CameraHandlerPtr& camera, std::function<Color(UINT32)> idxToColorCallback)
@@ -703,7 +704,7 @@ namespace BansheeEngine
 		activeRenderer->onCorePostRenderViewport.connect(std::bind(&GizmoManagerCore::render, this, _1));
 		activeRenderer->onCorePostRenderViewport.connect(std::bind(&GizmoManagerCore::render, this, _1));
 	}
 	}
 
 
-	void GizmoManagerCore::updateData(const RenderTargetPtr& rt, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
+	void GizmoManagerCore::updateData(const SPtr<RenderTargetCore>& rt, const SPtr<MeshCoreBase>& solidMesh, const SPtr<MeshCoreBase>& wireMesh,
 		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
 		const SPtr<MeshCoreBase>& iconMesh, const GizmoManager::IconRenderDataVecPtr& iconRenderData)
 	{
 	{
 		mSceneRenderTarget = rt;
 		mSceneRenderTarget = rt;
@@ -718,13 +719,11 @@ namespace BansheeEngine
 		if (mSceneRenderTarget == nullptr)
 		if (mSceneRenderTarget == nullptr)
 			return;
 			return;
 
 
-		SPtr<RenderTargetCore> sceneRenderTarget = mSceneRenderTarget->getCore();
-
-		if (camera.getViewport()->getTarget() != sceneRenderTarget)
+		if (camera.getViewport()->getTarget() != mSceneRenderTarget)
 			return;
 			return;
 
 
-		float width = (float)sceneRenderTarget->getProperties().getWidth();
-		float height = (float)sceneRenderTarget->getProperties().getHeight();
+		float width = (float)mSceneRenderTarget->getProperties().getWidth();
+		float height = (float)mSceneRenderTarget->getProperties().getHeight();
 
 
 		Rect2 normArea = camera.getViewport()->getNormArea();
 		Rect2 normArea = camera.getViewport()->getNormArea();
 
 

+ 5 - 6
BansheeEditor/Source/BsHandleDrawManager.cpp

@@ -178,7 +178,7 @@ namespace BansheeEngine
 		RenderTargetPtr sceneRenderTarget = camera->getViewport()->getTarget();
 		RenderTargetPtr sceneRenderTarget = camera->getViewport()->getTarget();
 
 
 		gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::updateData, mCore, 
 		gCoreAccessor().queueCommand(std::bind(&HandleDrawManagerCore::updateData, mCore, 
-			sceneRenderTarget, proxyData));
+			sceneRenderTarget->getCore(), proxyData));
 
 
 		mDrawHelper->clear();
 		mDrawHelper->clear();
 	}
 	}
@@ -204,7 +204,7 @@ namespace BansheeEngine
 		activeRenderer->onCorePostRenderViewport.connect(std::bind(&HandleDrawManagerCore::render, this, _1));
 		activeRenderer->onCorePostRenderViewport.connect(std::bind(&HandleDrawManagerCore::render, this, _1));
 	}
 	}
 
 
-	void HandleDrawManagerCore::updateData(const RenderTargetPtr& rt, const Vector<MeshData>& meshes)
+	void HandleDrawManagerCore::updateData(const SPtr<RenderTargetCore>& rt, const Vector<MeshData>& meshes)
 	{
 	{
 		mSceneRenderTarget = rt;
 		mSceneRenderTarget = rt;
 		mMeshes = meshes;
 		mMeshes = meshes;
@@ -217,12 +217,11 @@ namespace BansheeEngine
 		if (mSceneRenderTarget == nullptr)
 		if (mSceneRenderTarget == nullptr)
 			return;
 			return;
 
 
-		SPtr<RenderTargetCore> sceneRenderTarget = mSceneRenderTarget->getCore();
-		if (camera.getViewport()->getTarget() != sceneRenderTarget)
+		if (camera.getViewport()->getTarget() != mSceneRenderTarget)
 			return;
 			return;
 
 
-		float width = (float)sceneRenderTarget->getProperties().getWidth();
-		float height = (float)sceneRenderTarget->getProperties().getHeight();
+		float width = (float)mSceneRenderTarget->getProperties().getWidth();
+		float height = (float)mSceneRenderTarget->getProperties().getHeight();
 
 
 		Rect2 normArea = camera.getViewport()->getNormArea();
 		Rect2 normArea = camera.getViewport()->getNormArea();
 
 

+ 21 - 0
MBansheeEditor/EditorWindow.cs

@@ -1,4 +1,5 @@
 using System;
 using System;
+using System.Collections.Generic;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using BansheeEngine;
 using BansheeEngine;
 
 
@@ -11,6 +12,7 @@ namespace BansheeEditor
         public bool HasFocus { get { return Internal_HasFocus(mCachedPtr); } }
         public bool HasFocus { get { return Internal_HasFocus(mCachedPtr); } }
 
 
         protected GUIPanel GUI;
         protected GUIPanel GUI;
+        private List<GUIPanel> panels = new List<GUIPanel>();
 
 
         public static T OpenWindow<T>() where T : EditorWindow
         public static T OpenWindow<T>() where T : EditorWindow
         {
         {
@@ -36,6 +38,14 @@ namespace BansheeEditor
             GUI = CreatePanel(0, 0, Width, Height);
             GUI = CreatePanel(0, 0, Width, Height);
         }
         }
 
 
+        private void OnDestroyInternal()
+        {
+            GUIPanel[] panelsCopy = panels.ToArray();
+
+            for (int i = 0; i < panelsCopy.Length; i++)
+                DestroyPanel(panelsCopy[i]);
+        }
+
         protected virtual void WindowResized(int width, int height)
         protected virtual void WindowResized(int width, int height)
         {
         {
             GUI.SetArea(0, 0, width, height);
             GUI.SetArea(0, 0, width, height);
@@ -53,15 +63,26 @@ namespace BansheeEditor
             newPanel.Initialize();
             newPanel.Initialize();
             newPanel.SetArea(x, y, width, height);
             newPanel.SetArea(x, y, width, height);
 
 
+            panels.Add(newPanel);
             return newPanel;
             return newPanel;
         }
         }
 
 
+        internal void DestroyPanel(GUIPanel panel)
+        {
+            panel.Destroy();
+            panels.Remove(panel);
+            Internal_DestroyGUIPanel(mCachedPtr, panel);
+        }
+
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern EditorWindow Internal_CreateOrGetInstance(string ns, string typeName);
         private static extern EditorWindow Internal_CreateOrGetInstance(string ns, string typeName);
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_InitializeGUIPanel(IntPtr nativeInstance, GUIPanel panel);
         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)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern int Internal_GetWidth(IntPtr nativeInstance);
         private static extern int Internal_GetWidth(IntPtr nativeInstance);
 
 

+ 5 - 2
MBansheeEditor/Inspector/Inspector.cs

@@ -12,11 +12,14 @@ namespace BansheeEditor
         protected GUILayoutY layout;
         protected GUILayoutY layout;
         protected object referencedObject;
         protected object referencedObject;
 
 
-        internal void Initialize(GUIPanel gui, object instance)
+        private InspectorWindow parentWindow;
+
+        internal void Initialize(InspectorWindow parentWindow, GUIPanel gui, object instance)
         {
         {
             GUI = gui;
             GUI = gui;
             layout = gui.layout.AddLayoutY();
             layout = gui.layout.AddLayoutY();
             referencedObject = instance;
             referencedObject = instance;
+            this.parentWindow = parentWindow;
         }
         }
 
 
         internal void SetArea(int x, int y, int width, int height)
         internal void SetArea(int x, int y, int width, int height)
@@ -32,7 +35,7 @@ namespace BansheeEditor
         internal void Destroy()
         internal void Destroy()
         {
         {
             layout.Destroy();
             layout.Destroy();
-            GUI.Destroy();
+            parentWindow.DestroyPanel(GUI);
         }
         }
 
 
         internal abstract bool Refresh();
         internal abstract bool Refresh();

+ 1 - 1
MBansheeEditor/Inspector/InspectorWindow.cs

@@ -40,7 +40,7 @@ namespace BansheeEditor
                 inspectorLayout.AddElement(data.container);
                 inspectorLayout.AddElement(data.container);
 
 
                 data.inspector = GetInspector(allComponents[i].GetType());
                 data.inspector = GetInspector(allComponents[i].GetType());
-                data.inspector.Initialize(inspectorPanel, allComponents[i]);
+                data.inspector.Initialize(this, inspectorPanel, allComponents[i]);
 
 
                 data.foldout.SetExpanded(true);
                 data.foldout.SetExpanded(true);
                 data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);
                 data.foldout.OnToggled += (bool expanded) => OnComponentFoldoutToggled(data, expanded);

+ 1 - 0
MBansheeEngine/GUI/GUIArea.cs

@@ -28,6 +28,7 @@ namespace BansheeEngine
                 parent.childAreas.Add(this);
                 parent.childAreas.Add(this);
         }
         }
 
 
+        // Note: Should only ever be called by its parent GUIPanel
         internal static GUIArea Create(GUIPanel parent, int x, int y, int width, int height, short depth)
         internal static GUIArea Create(GUIPanel parent, int x, int y, int width, int height, short depth)
         {
         {
             GUIArea newArea = new GUIArea();
             GUIArea newArea = new GUIArea();

+ 1 - 5
MBansheeEngine/GUI/GUIPanel.cs

@@ -50,6 +50,7 @@ namespace BansheeEngine
             mainArea.SetArea(0, 0, width, height);
             mainArea.SetArea(0, 0, width, height);
         }
         }
 
 
+        // Note: Only to be called from EditorWindow.DestroyPanel
         internal void Destroy()
         internal void Destroy()
         {
         {
             GUIArea[] tempAreas = childAreas.ToArray();
             GUIArea[] tempAreas = childAreas.ToArray();
@@ -57,8 +58,6 @@ namespace BansheeEngine
                 tempAreas[i].Destroy();
                 tempAreas[i].Destroy();
 
 
             childAreas.Clear();
             childAreas.Clear();
-
-            Internal_Destroy(mCachedPtr);
         }
         }
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
@@ -66,8 +65,5 @@ namespace BansheeEngine
 
 
         [MethodImpl(MethodImplOptions.InternalCall)]
         [MethodImpl(MethodImplOptions.InternalCall)]
         private static extern void Internal_CreateInstance(GUIPanel instance);
         private static extern void Internal_CreateInstance(GUIPanel instance);
-
-        [MethodImpl(MethodImplOptions.InternalCall)]
-        private static extern void Internal_Destroy(IntPtr nativeInstance);
     }
     }
 }
 }

+ 2 - 0
SBansheeEditor/Include/BsScriptEditorWindow.h

@@ -40,6 +40,7 @@ namespace BansheeEngine
 		static UINT32 internal_getHeight(ScriptEditorWindow* thisPtr);
 		static UINT32 internal_getHeight(ScriptEditorWindow* thisPtr);
 
 
 		static void internal_initializeGUIPanel(ScriptEditorWindow* thisPtr, MonoObject* panel);
 		static void internal_initializeGUIPanel(ScriptEditorWindow* thisPtr, MonoObject* panel);
+		static void internal_destroyGUIPanel(ScriptEditorWindow* thisPtr, MonoObject* panel);
 
 
 		void onWidgetMoved(INT32 x, INT32 y);
 		void onWidgetMoved(INT32 x, INT32 y);
 		void onWidgetResized(UINT32 width, UINT32 height);
 		void onWidgetResized(UINT32 width, UINT32 height);
@@ -65,6 +66,7 @@ namespace BansheeEngine
 		static MonoMethod* onResizedMethod;
 		static MonoMethod* onResizedMethod;
 		static MonoMethod* onFocusChangedMethod;
 		static MonoMethod* onFocusChangedMethod;
 		static MonoMethod* onInitializedInternalMethod;
 		static MonoMethod* onInitializedInternalMethod;
+		static MonoMethod* onDestroyInternalMethod;
 
 
 		// Global editor window management methods
 		// Global editor window management methods
 		static void registerScriptEditorWindow(ScriptEditorWindow* editorWindow);
 		static void registerScriptEditorWindow(ScriptEditorWindow* editorWindow);

+ 15 - 0
SBansheeEditor/Source/BsScriptEditorWindow.cpp

@@ -21,6 +21,7 @@ namespace BansheeEngine
 	MonoMethod* ScriptEditorWindow::onResizedMethod = nullptr;
 	MonoMethod* ScriptEditorWindow::onResizedMethod = nullptr;
 	MonoMethod* ScriptEditorWindow::onFocusChangedMethod = nullptr;
 	MonoMethod* ScriptEditorWindow::onFocusChangedMethod = nullptr;
 	MonoMethod* ScriptEditorWindow::onInitializedInternalMethod = nullptr;
 	MonoMethod* ScriptEditorWindow::onInitializedInternalMethod = nullptr;
+	MonoMethod* ScriptEditorWindow::onDestroyInternalMethod = nullptr;
 
 
 	ScriptEditorWindow::ScriptEditorWindow(ScriptEditorWidget* editorWidget)
 	ScriptEditorWindow::ScriptEditorWindow(ScriptEditorWidget* editorWidget)
 		:ScriptObject(editorWidget->getManagedInstance()), mName(editorWidget->getName()), mEditorWidget(editorWidget), mRefreshInProgress(false)
 		:ScriptObject(editorWidget->getManagedInstance()), mName(editorWidget->getName()), mEditorWidget(editorWidget), mRefreshInProgress(false)
@@ -48,6 +49,7 @@ namespace BansheeEngine
 	{
 	{
 		metaData.scriptClass->addInternalCall("Internal_CreateOrGetInstance", &ScriptEditorWindow::internal_createOrGetInstance);
 		metaData.scriptClass->addInternalCall("Internal_CreateOrGetInstance", &ScriptEditorWindow::internal_createOrGetInstance);
 		metaData.scriptClass->addInternalCall("Internal_InitializeGUIPanel", &ScriptEditorWindow::internal_initializeGUIPanel);
 		metaData.scriptClass->addInternalCall("Internal_InitializeGUIPanel", &ScriptEditorWindow::internal_initializeGUIPanel);
+		metaData.scriptClass->addInternalCall("Internal_DestroyGUIPanel", &ScriptEditorWindow::internal_destroyGUIPanel);
 		metaData.scriptClass->addInternalCall("Internal_GetWidth", &ScriptEditorWindow::internal_getWidth);
 		metaData.scriptClass->addInternalCall("Internal_GetWidth", &ScriptEditorWindow::internal_getWidth);
 		metaData.scriptClass->addInternalCall("Internal_GetHeight", &ScriptEditorWindow::internal_getHeight);
 		metaData.scriptClass->addInternalCall("Internal_GetHeight", &ScriptEditorWindow::internal_getHeight);
 		metaData.scriptClass->addInternalCall("Internal_HasFocus", &ScriptEditorWindow::internal_hasFocus);
 		metaData.scriptClass->addInternalCall("Internal_HasFocus", &ScriptEditorWindow::internal_hasFocus);
@@ -57,6 +59,7 @@ namespace BansheeEngine
 		onResizedMethod = metaData.scriptClass->getMethod("WindowResized", 2);
 		onResizedMethod = metaData.scriptClass->getMethod("WindowResized", 2);
 		onFocusChangedMethod = metaData.scriptClass->getMethod("FocusChanged", 1);
 		onFocusChangedMethod = metaData.scriptClass->getMethod("FocusChanged", 1);
 		onInitializedInternalMethod = metaData.scriptClass->getMethod("OnInitializeInternal", 0);
 		onInitializedInternalMethod = metaData.scriptClass->getMethod("OnInitializeInternal", 0);
+		onDestroyInternalMethod = metaData.scriptClass->getMethod("OnDestroyInternal", 0);
 	}
 	}
 
 
 	MonoObject* ScriptEditorWindow::internal_createOrGetInstance(MonoString* ns, MonoString* typeName)
 	MonoObject* ScriptEditorWindow::internal_createOrGetInstance(MonoString* ns, MonoString* typeName)
@@ -183,6 +186,15 @@ namespace BansheeEngine
 		scriptGUIPanel->setParentWidget(&thisPtr->mEditorWidget->_getParent()->getParentWidget());
 		scriptGUIPanel->setParentWidget(&thisPtr->mEditorWidget->_getParent()->getParentWidget());
 	}
 	}
 
 
+	void ScriptEditorWindow::internal_destroyGUIPanel(ScriptEditorWindow* thisPtr, MonoObject* panel)
+	{
+		ScriptGUIPanel* scriptGUIPanel = ScriptGUIPanel::toNative(panel);
+
+		auto findIter = std::find(thisPtr->mPanels.begin(), thisPtr->mPanels.end(), scriptGUIPanel);
+		if (findIter != thisPtr->mPanels.end())
+			thisPtr->mPanels.erase(findIter);
+	}
+
 	void ScriptEditorWindow::onWidgetMoved(INT32 x, INT32 y)
 	void ScriptEditorWindow::onWidgetMoved(INT32 x, INT32 y)
 	{
 	{
 		for(auto& panel : mPanels)
 		for(auto& panel : mPanels)
@@ -346,6 +358,9 @@ namespace BansheeEngine
 
 
 	void ScriptEditorWidget::triggerOnDestroy()
 	void ScriptEditorWidget::triggerOnDestroy()
 	{
 	{
+		if (mManagedInstance != nullptr)
+			ScriptEditorWindow::onDestroyInternalMethod->invoke(mManagedInstance, nullptr);
+
 		if (mOnDestroyThunk != nullptr && mManagedInstance != nullptr)
 		if (mOnDestroyThunk != nullptr && mManagedInstance != nullptr)
 		{
 		{
 			MonoException* exception = nullptr;
 			MonoException* exception = nullptr;

+ 2 - 0
SBansheeEditor/Source/BsScriptGUIPanelContainer.cpp

@@ -6,6 +6,7 @@
 #include "BsMonoManager.h"
 #include "BsMonoManager.h"
 #include "BsMonoMethod.h"
 #include "BsMonoMethod.h"
 #include "BsGUIOptions.h"
 #include "BsGUIOptions.h"
+#include "BsDebug.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -30,6 +31,7 @@ namespace BansheeEngine
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 			options.addOption(mono_array_get(guiOptions, GUIOption, i));
 
 
 		ScriptGUIPanel* guiPanel = ScriptGUIPanel::toNative(panel);
 		ScriptGUIPanel* guiPanel = ScriptGUIPanel::toNative(panel);
+		LOGWRN("Creating panel: " + toString((UINT64)guiPanel));
 		GUIPanelContainer* guiPanelContainer = GUIPanelContainer::create(*guiPanel, options);
 		GUIPanelContainer* guiPanelContainer = GUIPanelContainer::create(*guiPanel, options);
 
 
 		ScriptGUIPanelContainer* nativeInstance = new (bs_alloc<ScriptGUIPanelContainer>()) ScriptGUIPanelContainer(instance, guiPanelContainer);
 		ScriptGUIPanelContainer* nativeInstance = new (bs_alloc<ScriptGUIPanelContainer>()) ScriptGUIPanelContainer(instance, guiPanelContainer);

+ 4 - 0
SBansheeEngine/Include/BsScriptGUIPanel.h

@@ -23,6 +23,8 @@ namespace BansheeEngine
 		const Vector<ScriptGUIArea*>& getAreas() const { return mAreas; }
 		const Vector<ScriptGUIArea*>& getAreas() const { return mAreas; }
 		Rect2I getArea() const { return mMyArea; }
 		Rect2I getArea() const { return mMyArea; }
 
 
+		void destroy();
+
 	protected:
 	protected:
 		ScriptGUIPanel(MonoObject* instance);
 		ScriptGUIPanel(MonoObject* instance);
 
 
@@ -38,5 +40,7 @@ namespace BansheeEngine
 		Rect2I mParentArea;
 		Rect2I mParentArea;
 		Rect2I mMyArea;
 		Rect2I mMyArea;
 		Rect2I mClippedArea;
 		Rect2I mClippedArea;
+
+		static MonoMethod* mDestroyMethod;
 	};
 	};
 }
 }

+ 12 - 0
SBansheeEngine/Source/BsScriptGUIPanel.cpp

@@ -6,9 +6,12 @@
 #include "BsScriptGUIArea.h"
 #include "BsScriptGUIArea.h"
 #include "BsGUIArea.h"
 #include "BsGUIArea.h"
 #include "BsGUILayout.h"
 #include "BsGUILayout.h"
+#include "BsMonoMethod.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
+	MonoMethod* ScriptGUIPanel::mDestroyMethod = nullptr;
+
 	ScriptGUIPanel::ScriptGUIPanel(MonoObject* instance)
 	ScriptGUIPanel::ScriptGUIPanel(MonoObject* instance)
 		:ScriptObject(instance)
 		:ScriptObject(instance)
 	{
 	{
@@ -19,6 +22,8 @@ namespace BansheeEngine
 	{
 	{
 		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIPanel::internal_createInstance);
 		metaData.scriptClass->addInternalCall("Internal_CreateInstance", &ScriptGUIPanel::internal_createInstance);
 		metaData.scriptClass->addInternalCall("Internal_SetArea", &ScriptGUIPanel::internal_setArea);
 		metaData.scriptClass->addInternalCall("Internal_SetArea", &ScriptGUIPanel::internal_setArea);
+
+		mDestroyMethod = metaData.scriptClass->getMethod("Destroy", 0);
 	}
 	}
 
 
 	void ScriptGUIPanel::internal_createInstance(MonoObject* instance)
 	void ScriptGUIPanel::internal_createInstance(MonoObject* instance)
@@ -69,6 +74,13 @@ namespace BansheeEngine
 			mAreas.erase(iterFind);
 			mAreas.erase(iterFind);
 	}
 	}
 
 
+	void ScriptGUIPanel::destroy()
+	{
+		assert(mDestroyMethod != nullptr);
+
+		mDestroyMethod->invoke(mManagedInstance, nullptr);
+	}
+
 	void ScriptGUIPanel::updateArea()
 	void ScriptGUIPanel::updateArea()
 	{
 	{
 		mClippedArea = mMyArea;
 		mClippedArea = mMyArea;

+ 7 - 0
TODO.txt

@@ -7,8 +7,15 @@ Possibly set up automatic refresh in debug mode after initialization? As an ad-h
 
 
 I don't think GUI elements are properly cleaned up after assembly refresh
 I don't think GUI elements are properly cleaned up after assembly refresh
  - GUIPanelContainer was holding an invalid reference to mGUIPanel
  - GUIPanelContainer was holding an invalid reference to mGUIPanel
+ - GUI elements aren't destroyed when their managed reference is lost. Instead they remain owned by their GUIWidget.
+   - How to get around this when performing assembly refresh?
+   - Destroying them when reference is lost would be too clumsy as I would need to track when they're referenced by GUILayout or GUIArea and similar.
+   - I probably need to ensure that any GUIArea owned by EditorWindow gets destroyed properly.
+     - By definition this should be any area owned by a GUIPanel
+   - Later when I might have GUI elements in non-editor windows I can handle those on a case by case basis
 
 
 Scene grid disappears and scene view doesn't work after refresh
 Scene grid disappears and scene view doesn't work after refresh
+ - This might be related to GUI issue above, as the old GUI still remains so it might be rendering above the new stuff
 
 
 <<<<Multi-resource saving>>>>:
 <<<<Multi-resource saving>>>>:
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it
  - Modify Font so it doesn't contain a texture, but instead keeps a handle to it