Explorar o código

Fixed an issue where ScriptGUIScrollArea child layout's interop object wasn't being cleaned up

BearishSun %!s(int64=10) %!d(string=hai) anos
pai
achega
92f71af102

+ 1 - 2
SBansheeEditor/Source/BsScriptDropDownWindow.cpp

@@ -145,8 +145,7 @@ namespace BansheeEngine
 
 	ManagedDropDownWindow::~ManagedDropDownWindow()
 	{
-		mContentsPanel->destroyChildren();
-		mContentsPanel->markAsDestroyed();
+		mContentsPanel->destroy();
 		mContentsPanel = nullptr;
 
 		triggerOnDestroy();

+ 1 - 2
SBansheeEditor/Source/BsScriptEditorWindow.cpp

@@ -323,8 +323,7 @@ namespace BansheeEngine
 		mScriptOwner->mIsDestroyed = true;
 		mScriptOwner->mEditorWidget = nullptr;
 
-		mContentsPanel->destroyChildren();
-		mContentsPanel->markAsDestroyed();
+		mContentsPanel->destroy();
 		mContentsPanel = nullptr;
 
 		triggerOnDestroy();

+ 1 - 2
SBansheeEditor/Source/BsScriptModalWindow.cpp

@@ -233,8 +233,7 @@ namespace BansheeEngine
 	{
 		triggerOnDestroy();
 
-		mContentsPanel->destroyChildren();
-		mContentsPanel->markAsDestroyed();
+		mContentsPanel->destroy();
 		mContentsPanel = nullptr;
 
 		releaseManagedInstance();

+ 7 - 12
SBansheeEngine/Include/BsScriptGUILayout.h

@@ -51,22 +51,17 @@ namespace BansheeEngine
 		 * Destroys the layout and all of its managed children.
 		 */
 		void destroy() override;
+	private:
+		friend class ScriptGUIPanel;
 
 		/**
-		 * @brief	Destroys all of the layout managed children.
+		 * @brief	Constructor.
 		 *
-		 * @note	Useful if the children are managed but the layer itself is not.
-		 */
-		void destroyChildren();
-
-		/**
-		 * @brief	Marks the layout as destroyed. When destroyed managed operations will be ignored
-		 *			or return default values.
+		 * @param	instance	Managed GUILayout instance.
+		 * @param	layout  	Native GUILayout instance.
+		 * @param	ownsNative	Does this object own the native instance. If it does it will destroy the
+		 * 						object when ::destroy() is called, otherwise it is up to the caller to destroy it.
 		 */
-		void markAsDestroyed();
-	private:
-		friend class ScriptGUIPanel;
-
 		ScriptGUILayout(MonoObject* instance, GUILayout* layout, bool ownsNative = true);
 
 		GUILayout* mLayout;

+ 13 - 0
SBansheeEngine/Include/BsScriptGUIScrollArea.h

@@ -14,9 +14,22 @@ namespace BansheeEngine
 	public:
 		SCRIPT_OBJ(ENGINE_ASSEMBLY, "BansheeEngine", "GUIScrollArea")
 
+		/**
+		 * @brief	Initializes the interop object by providing it with the interop object for
+		 * 			the internal layout held by the scroll area.
+		 */
+		void initialize(ScriptGUILayout* layout);
+
 	private:
 		ScriptGUIScrollArea(MonoObject* instance, GUIScrollArea* scrollArea);
 
+		/**
+		 * @copydoc	TScriptGUIElement::destroy
+		 */
+		void destroy() override;
+
+		ScriptGUILayout* mLayout;
+
 		/************************************************************************/
 		/* 								CLR HOOKS						   		*/
 		/************************************************************************/

+ 9 - 17
SBansheeEngine/Source/BsScriptGUILayout.cpp

@@ -37,7 +37,11 @@ namespace BansheeEngine
 			if (mParent != nullptr)
 				mParent->removeChild(this);
 
-			destroyChildren();
+			while (mChildren.size() > 0)
+			{
+				ChildInfo childInfo = mChildren[0];
+				childInfo.element->destroy();
+			}
 
 			if (mOwnsNative)
 				GUILayout::destroy(mLayout);
@@ -47,21 +51,6 @@ namespace BansheeEngine
 		}
 	}
 
-	void ScriptGUILayout::destroyChildren()
-	{
-		while (mChildren.size() > 0)
-		{
-			ChildInfo childInfo = mChildren[0];
-			childInfo.element->destroy();
-		}
-	}
-
-	void ScriptGUILayout::markAsDestroyed()
-	{
-		mLayout = nullptr;
-		mIsDestroyed = true;
-	}
-
 	void ScriptGUILayout::addChild(ScriptGUIElementBaseTBase* element)
 	{
 		ChildInfo childInfo;
@@ -144,7 +133,10 @@ namespace BansheeEngine
 		GUILayout* nativeLayout = &scrollArea->getLayout();
 
 		ScriptGUILayout* nativeInstance = new (bs_alloc<ScriptGUILayout>())
-			ScriptGUILayout(instance, nativeLayout);
+			ScriptGUILayout(instance, nativeLayout, false);
+
+		// This method is expected to be called during GUIScrollArea construction, so we finish its initialization
+		scriptScrollArea->initialize(nativeInstance);
 	}
 
 	void ScriptGUILayout::internal_addElement(ScriptGUILayout* instance, ScriptGUIElementBaseTBase* element)

+ 29 - 1
SBansheeEngine/Source/BsScriptGUIScrollArea.cpp

@@ -17,7 +17,7 @@
 namespace BansheeEngine
 {
 	ScriptGUIScrollArea::ScriptGUIScrollArea(MonoObject* instance, GUIScrollArea* scrollArea)
-		:TScriptGUIElement(instance, scrollArea)
+		:TScriptGUIElement(instance, scrollArea), mLayout(nullptr)
 	{
 
 	}
@@ -33,6 +33,34 @@ namespace BansheeEngine
 		metaData.scriptClass->addInternalCall("Internal_GetScrollBarWidth", &ScriptGUIScrollArea::internal_getScrollBarWidth);
 	}
 
+	void ScriptGUIScrollArea::initialize(ScriptGUILayout* layout)
+	{
+		mLayout = layout;
+	}
+
+	void ScriptGUIScrollArea::destroy()
+	{
+		if (!mIsDestroyed)
+		{
+			if (mParent != nullptr)
+				mParent->removeChild(this);
+
+			if (mLayout != nullptr)
+			{
+				mLayout->destroy();
+				mLayout = nullptr;
+			}
+
+			if (mElement->_getType() == GUIElementBase::Type::Element)
+			{
+				GUIElement::destroy((GUIElement*)mElement);
+				mElement = nullptr;
+
+				mIsDestroyed = true;
+			}
+		}
+	}
+
 	void ScriptGUIScrollArea::internal_createInstance(MonoObject* instance, ScrollBarType vertBarType, ScrollBarType horzBarType, 
 		MonoString* scrollBarStyle, MonoString* scrollAreaStyle, MonoArray* guiOptions)
 	{