Kaynağa Gözat

Fixed crash when re-docking editor widgets due to invalid parent of dock slider
Fixed potential issues with re-parenting GUI elements after they have been destroyed

Marko Pintera 10 yıl önce
ebeveyn
işleme
bc8ebe3ca5

+ 9 - 37
BansheeEditor/Source/BsDockManager.cpp

@@ -23,6 +23,7 @@
 #include "BsBuiltinResources.h"
 #include "BsDockManagerLayout.h"
 #include "BsEditorWindow.h"
+#include "BsGUIPanel.h"
 
 #include "BsGUISkin.h"
 #include "BsGUIButton.h"
@@ -97,7 +98,6 @@ namespace BansheeEngine
 	{
 		if(!mIsLeaf && mChildren[0] != nullptr && mChildren[1] != nullptr)
 		{
-			Rect2I clipRect = mArea;
 			if(mIsHorizontal)
 			{
 				UINT32 remainingSize = (UINT32)std::max(0, (INT32)mArea.height - (INT32)SLIDER_SIZE);
@@ -107,14 +107,9 @@ namespace BansheeEngine
 				mChildren[0]->setArea(mArea.x, mArea.y, mArea.width, sizeTop);
 				mChildren[1]->setArea(mArea.x, mArea.y + sizeTop + SLIDER_SIZE, mArea.width, sizeBottom);
 
-				GUILayoutData layoutData = mSlider->_getLayoutData();
-				layoutData.area = mArea;
-				layoutData.area.y += sizeTop;
-				layoutData.area.height = SLIDER_SIZE;
-				layoutData.clipRect = clipRect;
-
-				mSlider->_setLayoutData(layoutData);
-				mSlider->_markContentAsDirty();
+				mSlider->setWidth(mArea.width);
+				mSlider->setHeight(SLIDER_SIZE);
+				mSlider->setPosition(mArea.x, mArea.y + sizeTop);
 			}
 			else
 			{
@@ -125,14 +120,9 @@ namespace BansheeEngine
 				mChildren[0]->setArea(mArea.x, mArea.y, sizeLeft, mArea.height);
 				mChildren[1]->setArea(mArea.x + sizeLeft + SLIDER_SIZE, mArea.y, sizeRight, mArea.height);
 
-				GUILayoutData layoutData = mSlider->_getLayoutData();
-				layoutData.area = mArea;
-				layoutData.area.x += sizeLeft;
-				layoutData.area.width = SLIDER_SIZE;
-				layoutData.clipRect = clipRect;
-
-				mSlider->_setLayoutData(layoutData);
-				mSlider->_markContentAsDirty();
+				mSlider->setWidth(SLIDER_SIZE);
+				mSlider->setHeight(mArea.height);
+				mSlider->setPosition(mArea.x + sizeLeft, mArea.y);
 			}
 		}
 	}
@@ -243,26 +233,8 @@ namespace BansheeEngine
 			mSlider = nullptr;
 		}
 
-		if (horizontal)
-		{
-			mSlider = GUIDockSlider::create(true, "DockSliderBtn");
-
-			GUILayoutData layoutData = mSlider->_getLayoutData();
-			layoutData.setWidgetDepth(widgetParent->getDepth());
-			mSlider->_setLayoutData(layoutData);
-			mSlider->_markMeshAsDirty();
-		}
-		else
-		{
-			mSlider = GUIDockSlider::create(false, "DockSliderBtn");
-			GUILayoutData layoutData = mSlider->_getLayoutData();
-			layoutData.setWidgetDepth(widgetParent->getDepth());
-			mSlider->_setLayoutData(layoutData);
-			mSlider->_markMeshAsDirty();
-		}
-
-		mSlider->_changeParentWidget(widgetParent);
-
+		mSlider = GUIDockSlider::create(horizontal, "DockSliderBtn");
+		widgetParent->getPanel()->addElement(mSlider);
 		mSlider->onDragged.connect(std::bind(&DockManager::DockContainer::sliderDragged, this, _1));
 
 		setArea(mArea.x, mArea.y, mArea.width, mArea.height);

+ 2 - 2
BansheeEngine/Include/BsGUIElement.h

@@ -208,7 +208,7 @@ namespace BansheeEngine
 		/**
 		 * @copydoc	GUIElementBase::_changeParentWidget
 		 */
-		virtual void _changeParentWidget(GUIWidget* widget);
+		virtual void _changeParentWidget(GUIWidget* widget) override;
 
 		/**
 		 * @brief	Returns depth for a specific render element. This contains a combination
@@ -242,7 +242,7 @@ namespace BansheeEngine
 		 *
 		 * @note	Internal method.
 		 */
-		bool _isDestroyed() const { return mIsDestroyed; }
+		bool _isDestroyed() const override { return mIsDestroyed; }
 
 		/**
 		 * @brief	Update element style based on active GUI skin and style name.

+ 7 - 0
BansheeEngine/Include/BsGUIElementBase.h

@@ -277,6 +277,13 @@ namespace BansheeEngine
 		 */
 		void _unregisterChildElement(GUIElementBase* element);
 
+		/**
+		 * @brief	Checks if element has been destroyed and is queued for deletion.
+		 *
+		 * @note	Internal method.
+		 */
+		virtual bool _isDestroyed() const { return false; }
+
 		/**
 		 * @brief	Marks the elements contents as dirty, which causes the sprite meshes to be recreated from scratch.
 		 *

+ 7 - 1
BansheeEngine/Source/BsGUIElement.cpp

@@ -5,6 +5,7 @@
 #include "BsGUIManager.h"
 #include "BsException.h"
 #include "BsGUILayoutUtility.h"
+#include "BsDebug.h"
 
 namespace BansheeEngine
 {
@@ -17,7 +18,9 @@ namespace BansheeEngine
 	}
 
 	GUIElement::~GUIElement()
-	{ }
+	{
+
+	}
 
 	void GUIElement::_updateRenderElements()
 	{
@@ -84,6 +87,9 @@ namespace BansheeEngine
 
 	void GUIElement::_changeParentWidget(GUIWidget* widget)
 	{
+		if (_isDestroyed())
+			return;
+
 		bool doRefreshStyle = false;
 		if(mParentWidget != widget)
 			doRefreshStyle = true;

+ 4 - 0
BansheeEngine/Source/BsGUIElementBase.cpp

@@ -285,6 +285,8 @@ namespace BansheeEngine
 
 	void GUIElementBase::_registerChildElement(GUIElementBase* element)
 	{
+		assert(!element->_isDestroyed());
+
 		GUIElementBase* parentElement = element->_getParent();
 		if(parentElement != nullptr)
 		{
@@ -324,6 +326,8 @@ namespace BansheeEngine
 
 	void GUIElementBase::_changeParentWidget(GUIWidget* widget)
 	{
+		assert(!_isDestroyed());
+
 		if (mParentWidget != widget)
 		{
 			if (mParentWidget != nullptr)

+ 5 - 1
BansheeEngine/Source/BsGUILayout.cpp

@@ -22,7 +22,8 @@ namespace BansheeEngine
 
 	void GUILayout::addElement(GUIElementBase* element)
 	{
-		_registerChildElement(element);
+		if (!element->_isDestroyed())
+			_registerChildElement(element);
 	}
 
 	void GUILayout::removeElement(GUIElementBase* element)
@@ -35,6 +36,9 @@ namespace BansheeEngine
 		if(idx < 0 || idx > (UINT32)mChildren.size())
 			BS_EXCEPT(InvalidParametersException, "Index out of range: " + toString(idx) + ". Valid range: 0 .. " + toString((UINT32)mChildren.size()));
 
+		if (element->_isDestroyed())
+			return;
+
 		GUIElementBase* parentElement = element->_getParent();
 		if(parentElement != nullptr)
 		{

+ 4 - 3
BansheeEngine/Source/BsGUIWidget.cpp

@@ -208,12 +208,13 @@ namespace BansheeEngine
 
 	void GUIWidget::_registerElement(GUIElementBase* elem)
 	{
-		assert(elem != nullptr);
+		assert(elem != nullptr && !elem->_isDestroyed());
 
 		if (elem->_getType() == GUIElementBase::Type::Element)
+		{
 			mElements.push_back(static_cast<GUIElement*>(elem));
-
-		mWidgetIsDirty = true;
+			mWidgetIsDirty = true;
+		}
 	}
 
 	void GUIWidget::_unregisterElement(GUIElementBase* elem)

+ 2 - 0
TODO.txt

@@ -65,6 +65,8 @@ Polish stage 1
 When elements are docked in the main window the menu bar drop down appears behind them
 Click on empty part of the menu bar doesn't close the menu bar (ignoring NC area clicks?)
 Clicking on a parent of a menu item just reopens that item but I would expect it to close it
+Clicking on menu items doesn't seem to work
+GUI element that was deleted was part of a widget. This happened when I was docking windows and undocking them (scene, hierarchy, inspector)
 Attempting to dock a window that is not in focus will start drag instead (NC area incorrectly set up?)
 Docking problem: When I dock three windows next to each other, e.g. Hierarchy|Scene|Inspector and then try to dock another
  so it splits space with Hierarchy vertically the dock area appears over both hierarchy and scene, and the when docked it looks wrong