Selaa lähdekoodia

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 vuotta sitten
vanhempi
sitoutus
bc8ebe3ca5

+ 9 - 37
BansheeEditor/Source/BsDockManager.cpp

@@ -23,6 +23,7 @@
 #include "BsBuiltinResources.h"
 #include "BsBuiltinResources.h"
 #include "BsDockManagerLayout.h"
 #include "BsDockManagerLayout.h"
 #include "BsEditorWindow.h"
 #include "BsEditorWindow.h"
+#include "BsGUIPanel.h"
 
 
 #include "BsGUISkin.h"
 #include "BsGUISkin.h"
 #include "BsGUIButton.h"
 #include "BsGUIButton.h"
@@ -97,7 +98,6 @@ namespace BansheeEngine
 	{
 	{
 		if(!mIsLeaf && mChildren[0] != nullptr && mChildren[1] != nullptr)
 		if(!mIsLeaf && mChildren[0] != nullptr && mChildren[1] != nullptr)
 		{
 		{
-			Rect2I clipRect = mArea;
 			if(mIsHorizontal)
 			if(mIsHorizontal)
 			{
 			{
 				UINT32 remainingSize = (UINT32)std::max(0, (INT32)mArea.height - (INT32)SLIDER_SIZE);
 				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[0]->setArea(mArea.x, mArea.y, mArea.width, sizeTop);
 				mChildren[1]->setArea(mArea.x, mArea.y + sizeTop + SLIDER_SIZE, mArea.width, sizeBottom);
 				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
 			else
 			{
 			{
@@ -125,14 +120,9 @@ namespace BansheeEngine
 				mChildren[0]->setArea(mArea.x, mArea.y, sizeLeft, mArea.height);
 				mChildren[0]->setArea(mArea.x, mArea.y, sizeLeft, mArea.height);
 				mChildren[1]->setArea(mArea.x + sizeLeft + SLIDER_SIZE, mArea.y, sizeRight, 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;
 			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));
 		mSlider->onDragged.connect(std::bind(&DockManager::DockContainer::sliderDragged, this, _1));
 
 
 		setArea(mArea.x, mArea.y, mArea.width, mArea.height);
 		setArea(mArea.x, mArea.y, mArea.width, mArea.height);

+ 2 - 2
BansheeEngine/Include/BsGUIElement.h

@@ -208,7 +208,7 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc	GUIElementBase::_changeParentWidget
 		 * @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
 		 * @brief	Returns depth for a specific render element. This contains a combination
@@ -242,7 +242,7 @@ namespace BansheeEngine
 		 *
 		 *
 		 * @note	Internal method.
 		 * @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.
 		 * @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);
 		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.
 		 * @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 "BsGUIManager.h"
 #include "BsException.h"
 #include "BsException.h"
 #include "BsGUILayoutUtility.h"
 #include "BsGUILayoutUtility.h"
+#include "BsDebug.h"
 
 
 namespace BansheeEngine
 namespace BansheeEngine
 {
 {
@@ -17,7 +18,9 @@ namespace BansheeEngine
 	}
 	}
 
 
 	GUIElement::~GUIElement()
 	GUIElement::~GUIElement()
-	{ }
+	{
+
+	}
 
 
 	void GUIElement::_updateRenderElements()
 	void GUIElement::_updateRenderElements()
 	{
 	{
@@ -84,6 +87,9 @@ namespace BansheeEngine
 
 
 	void GUIElement::_changeParentWidget(GUIWidget* widget)
 	void GUIElement::_changeParentWidget(GUIWidget* widget)
 	{
 	{
+		if (_isDestroyed())
+			return;
+
 		bool doRefreshStyle = false;
 		bool doRefreshStyle = false;
 		if(mParentWidget != widget)
 		if(mParentWidget != widget)
 			doRefreshStyle = true;
 			doRefreshStyle = true;

+ 4 - 0
BansheeEngine/Source/BsGUIElementBase.cpp

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

+ 5 - 1
BansheeEngine/Source/BsGUILayout.cpp

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

+ 4 - 3
BansheeEngine/Source/BsGUIWidget.cpp

@@ -208,12 +208,13 @@ namespace BansheeEngine
 
 
 	void GUIWidget::_registerElement(GUIElementBase* elem)
 	void GUIWidget::_registerElement(GUIElementBase* elem)
 	{
 	{
-		assert(elem != nullptr);
+		assert(elem != nullptr && !elem->_isDestroyed());
 
 
 		if (elem->_getType() == GUIElementBase::Type::Element)
 		if (elem->_getType() == GUIElementBase::Type::Element)
+		{
 			mElements.push_back(static_cast<GUIElement*>(elem));
 			mElements.push_back(static_cast<GUIElement*>(elem));
-
-		mWidgetIsDirty = true;
+			mWidgetIsDirty = true;
+		}
 	}
 	}
 
 
 	void GUIWidget::_unregisterElement(GUIElementBase* elem)
 	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
 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?)
 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 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?)
 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
 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
  so it splits space with Hierarchy vertically the dock area appears over both hierarchy and scene, and the when docked it looks wrong