Browse Source

Each docked editor widget container is now rendered in its own GUIWidget to better partition GUI updates

Marko Pintera 10 years ago
parent
commit
e93725619e

+ 4 - 3
BansheeEditor/Include/BsDockManager.h

@@ -35,19 +35,19 @@ namespace BansheeEngine
 			 *			to leaf (parent to widgets). This involves creating a widget container to
 			 *			to leaf (parent to widgets). This involves creating a widget container to
 			 *			which you can dock widgets to.
 			 *			which you can dock widgets to.
 			 *
 			 *
-			 * @param	widgetParent	GUI widget of the parent dock manager.
 			 * @param	parentWindow	Editor window of the parent dock manager.
 			 * @param	parentWindow	Editor window of the parent dock manager.
 			 */
 			 */
-			void makeLeaf(GUIWidget* widgetParent, EditorWindowBase* parentWindow);
+			void makeLeaf(EditorWindowBase* parentWindow);
 
 
 			/**
 			/**
 			 * @brief	Transforms the container from non-leaf (parent to other containers)
 			 * @brief	Transforms the container from non-leaf (parent to other containers)
 			 *			to leaf (parent to widgets). Unlike the other overload this one accepts
 			 *			to leaf (parent to widgets). Unlike the other overload this one accepts
 			 *			a previously created widget container.
 			 *			a previously created widget container.
 			 *
 			 *
+			 * @param	guiWidgetSO			Parent SceneObject of the GUIWidget used by the provided widget container.
 			 * @param	existingContainer	An existing widget container that may be used for docking widgets.
 			 * @param	existingContainer	An existing widget container that may be used for docking widgets.
 			 */
 			 */
-			void makeLeaf(EditorWidgetContainer* existingContainer);
+			void makeLeaf(const HSceneObject& guiWidgetSO, EditorWidgetContainer* existingContainer);
 
 
 			/**
 			/**
 			 * @brief	Splits a leaf container containing a widget container (or may be empty in the case of root with no elements) 
 			 * @brief	Splits a leaf container containing a widget container (or may be empty in the case of root with no elements) 
@@ -142,6 +142,7 @@ namespace BansheeEngine
 			DockContainer* mParent;
 			DockContainer* mParent;
 			DockManager* mManager;
 			DockManager* mManager;
 			EditorWidgetContainer* mWidgets;
 			EditorWidgetContainer* mWidgets;
+			HSceneObject mGUIWidgetSO;
 			GUIDockSlider* mSlider;
 			GUIDockSlider* mSlider;
 			Rect2I mArea;
 			Rect2I mArea;
 			float mSplitPosition;
 			float mSplitPosition;

+ 33 - 10
BansheeEditor/Source/BsDockManager.cpp

@@ -56,8 +56,14 @@ namespace BansheeEngine
 
 
 	DockManager::DockContainer::~DockContainer()
 	DockManager::DockContainer::~DockContainer()
 	{
 	{
-		if(mIsLeaf && mWidgets != nullptr)
-			bs_delete(mWidgets);
+		if (mIsLeaf)
+		{
+			if (mWidgets != nullptr)
+				bs_delete(mWidgets);
+
+			if (mGUIWidgetSO != nullptr)
+				mGUIWidgetSO->destroy();
+		}
 
 
 		if(!mIsLeaf)
 		if(!mIsLeaf)
 		{
 		{
@@ -127,10 +133,15 @@ namespace BansheeEngine
 		}
 		}
 	}
 	}
 
 
-	void DockManager::DockContainer::makeLeaf(GUIWidget* widgetParent, EditorWindowBase* parentWindow)
+	void DockManager::DockContainer::makeLeaf(EditorWindowBase* parentWindow)
 	{
 	{
+		mGUIWidgetSO = SceneObject::create("DockContainer", SOF_Internal | SOF_Persistent | SOF_DontSave);
+		HGUIWidget guiWidget = mGUIWidgetSO->addComponent<GUIWidget>(parentWindow->getGUICamera()->getViewport().get());
+		guiWidget->setDepth(128);
+		guiWidget->setSkin(BuiltinEditorResources::instance().getSkin());
+
 		mIsLeaf = true;
 		mIsLeaf = true;
-		mWidgets = bs_new<EditorWidgetContainer>(widgetParent, parentWindow);
+		mWidgets = bs_new<EditorWidgetContainer>(guiWidget.get(), parentWindow);
 
 
 		mWidgets->onWidgetClosed.connect(std::bind(&DockManager::DockContainer::widgetRemoved, this));
 		mWidgets->onWidgetClosed.connect(std::bind(&DockManager::DockContainer::widgetRemoved, this));
 
 
@@ -144,10 +155,11 @@ namespace BansheeEngine
 		mWidgets->setSize(mArea.width, mArea.height);
 		mWidgets->setSize(mArea.width, mArea.height);
 	}
 	}
 
 
-	void DockManager::DockContainer::makeLeaf(EditorWidgetContainer* existingContainer)
+	void DockManager::DockContainer::makeLeaf(const HSceneObject& guiWidgetSO, EditorWidgetContainer* existingContainer)
 	{
 	{
 		mIsLeaf = true;
 		mIsLeaf = true;
 		mWidgets = existingContainer;
 		mWidgets = existingContainer;
+		mGUIWidgetSO = guiWidgetSO;
 
 
 		mWidgets->onWidgetClosed.connect(std::bind(&DockManager::DockContainer::widgetRemoved, this));
 		mWidgets->onWidgetClosed.connect(std::bind(&DockManager::DockContainer::widgetRemoved, this));
 
 
@@ -205,10 +217,11 @@ namespace BansheeEngine
 
 
 		mWidgets->onWidgetClosed.clear();
 		mWidgets->onWidgetClosed.clear();
 		
 		
-		children[idxA]->makeLeaf(mManager->_getParentWidget(), mManager->mParentWindow);
-		children[idxB]->makeLeaf(mWidgets);
+		children[idxA]->makeLeaf(mManager->mParentWindow);
+		children[idxB]->makeLeaf(mGUIWidgetSO, mWidgets);
 
 
 		mWidgets = nullptr;
 		mWidgets = nullptr;
+		mGUIWidgetSO = nullptr;
 		makeSplit(children[0], children[1], horizontal, splitPosition);
 		makeSplit(children[0], children[1], horizontal, splitPosition);
 	}
 	}
 
 
@@ -227,6 +240,12 @@ namespace BansheeEngine
 			mWidgets = nullptr;
 			mWidgets = nullptr;
 		}
 		}
 
 
+		if (mGUIWidgetSO != nullptr)
+		{
+			mGUIWidgetSO->destroy();
+			mGUIWidgetSO = nullptr;
+		}
+
 		if (mSlider != nullptr)
 		if (mSlider != nullptr)
 		{
 		{
 			GUIElement::destroy(mSlider);
 			GUIElement::destroy(mSlider);
@@ -287,6 +306,9 @@ namespace BansheeEngine
 				bs_delete(mWidgets);
 				bs_delete(mWidgets);
 				mWidgets = nullptr;
 				mWidgets = nullptr;
 
 
+				mGUIWidgetSO->destroy();
+				mGUIWidgetSO = nullptr;
+
 				mIsLeaf = true;
 				mIsLeaf = true;
 				mSplitPosition = 0.5f;
 				mSplitPosition = 0.5f;
 				mIsHorizontal = false;
 				mIsHorizontal = false;
@@ -304,8 +326,9 @@ namespace BansheeEngine
 				{
 				{
 					sibling->mWidgets->onWidgetClosed.clear();
 					sibling->mWidgets->onWidgetClosed.clear();
 
 
-					mParent->makeLeaf(sibling->mWidgets);
+					mParent->makeLeaf(sibling->mGUIWidgetSO, sibling->mWidgets);
 					sibling->mWidgets = nullptr;
 					sibling->mWidgets = nullptr;
+					sibling->mGUIWidgetSO = nullptr;
 				}
 				}
 				else
 				else
 				{
 				{
@@ -528,7 +551,7 @@ namespace BansheeEngine
 			if(mRootContainer.mWidgets != nullptr)
 			if(mRootContainer.mWidgets != nullptr)
 				BS_EXCEPT(InternalErrorException, "Trying to insert a widget into dock manager root container but one already exists.");
 				BS_EXCEPT(InternalErrorException, "Trying to insert a widget into dock manager root container but one already exists.");
 
 
-			mRootContainer.makeLeaf(_getParentWidget(), mParentWindow);
+			mRootContainer.makeLeaf(mParentWindow);
 			mRootContainer.addWidget(widgetToInsert);
 			mRootContainer.addWidget(widgetToInsert);
 		}
 		}
 	}
 	}
@@ -705,7 +728,7 @@ namespace BansheeEngine
 
 
 		if(leafEntry->widgetNames.size() > 0) // If zero, entire layout is empty
 		if(leafEntry->widgetNames.size() > 0) // If zero, entire layout is empty
 		{
 		{
-			mRootContainer.makeLeaf(_getParentWidget(), mParentWindow);
+			mRootContainer.makeLeaf(mParentWindow);
 			OpenWidgets(&mRootContainer, leafEntry->widgetNames);
 			OpenWidgets(&mRootContainer, leafEntry->widgetNames);
 
 
 			if(!rootEntry->isLeaf)
 			if(!rootEntry->isLeaf)

+ 6 - 6
BansheeEngine/Include/BsGUIElementContainer.h

@@ -18,32 +18,32 @@ namespace BansheeEngine
 		/**
 		/**
 		 * @copydoc GUIElement::getNumRenderElements
 		 * @copydoc GUIElement::getNumRenderElements
 		 */
 		 */
-		virtual UINT32 _getNumRenderElements() const;
+		virtual UINT32 _getNumRenderElements() const override;
 
 
 		/**
 		/**
 		 * @copydoc GUIElement::getMaterial
 		 * @copydoc GUIElement::getMaterial
 		 */
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const;
+		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
 		 * @copydoc GUIElement::getNumQuads
 		 * @copydoc GUIElement::getNumQuads
 		 */
 		 */
-		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const;
+		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
 		 * @copydoc GUIElement::fillBuffer
 		 * @copydoc GUIElement::fillBuffer
 		 */
 		 */
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
 		virtual void _fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, 
-			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const;
+			UINT32 maxNumQuads, UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const override;
 
 
 		/**
 		/**
 		 * @copydoc GUIElement::updateClippedBounds
 		 * @copydoc GUIElement::updateClippedBounds
 		 */
 		 */
-		virtual void updateClippedBounds();
+		virtual void updateClippedBounds() override;
 
 
 		/**
 		/**
 		 * @copydoc GUIElement::_getOptimalSize
 		 * @copydoc GUIElement::_getOptimalSize
 		 */
 		 */
-		virtual Vector2I _getOptimalSize() const;
+		virtual Vector2I _getOptimalSize() const override;
 	};
 	};
 }
 }

+ 0 - 23
TODO.txt

@@ -57,31 +57,8 @@ Code quality improvements:
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 Polish stage 1
 Polish stage 1
 
 
-UpdateMeshes is taking a long time to rebuild, try to optimize it
-
-Avoid fully recalculating layout for common operations like changing button states/toggles, and modifying input boxes.
- - Layout should be fully recalculated only if:
-   - optimal size changes
-   - padding changes
-   - dimensions change (x/y position only relevant for for panels) (perhaps even only LayoutSizeRange)
-    - if its fixed height/width then even that might not matter
-   - disabled state changes
-   - when initially created
- - I should probably just handle this on a case by case basis (e.g. if changing the active button texture is the same size as previous one don't call contentDirty)
-  - when button state changes, when input box contents change (by user or code), when text field data changes
- - ADDITIONALLY consider marking the mesh not dirty after layout update if size didn't change
-
 GET RID OF CONTENT STRING CALLBACKS - They're messsing with my optimization as I cannot calculate orig bounds before and after their update
 GET RID OF CONTENT STRING CALLBACKS - They're messsing with my optimization as I cannot calculate orig bounds before and after their update
 
 
-GUILabel
- - don't mark as dirty when contents change unless it affects optimal size
-GUIInputBox
- - don't mark as dirty when state changes unless it affects optimal size
- - don't mark as dirty when contents change unless it affects optimal size
-GUIButtonBase (toggle + normal button)
- - don't mark as dirty when state changes unless it affects optimal size
- - don't mark as dirty when contents change unless it affects optimal size
-
 Get rid of all the profiling calls
 Get rid of all the profiling calls
 
 
 Test inspector selection, selecting a resource and adding/removing component updates
 Test inspector selection, selecting a resource and adding/removing component updates