فهرست منبع

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

Marko Pintera 10 سال پیش
والد
کامیت
e93725619e
4فایلهای تغییر یافته به همراه43 افزوده شده و 42 حذف شده
  1. 4 3
      BansheeEditor/Include/BsDockManager.h
  2. 33 10
      BansheeEditor/Source/BsDockManager.cpp
  3. 6 6
      BansheeEngine/Include/BsGUIElementContainer.h
  4. 0 23
      TODO.txt

+ 4 - 3
BansheeEditor/Include/BsDockManager.h

@@ -35,19 +35,19 @@ namespace BansheeEngine
 			 *			to leaf (parent to widgets). This involves creating a widget container 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.
 			 */
-			void makeLeaf(GUIWidget* widgetParent, EditorWindowBase* parentWindow);
+			void makeLeaf(EditorWindowBase* parentWindow);
 
 			/**
 			 * @brief	Transforms the container from non-leaf (parent to other containers)
 			 *			to leaf (parent to widgets). Unlike the other overload this one accepts
 			 *			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.
 			 */
-			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) 
@@ -142,6 +142,7 @@ namespace BansheeEngine
 			DockContainer* mParent;
 			DockManager* mManager;
 			EditorWidgetContainer* mWidgets;
+			HSceneObject mGUIWidgetSO;
 			GUIDockSlider* mSlider;
 			Rect2I mArea;
 			float mSplitPosition;

+ 33 - 10
BansheeEditor/Source/BsDockManager.cpp

@@ -56,8 +56,14 @@ namespace BansheeEngine
 
 	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)
 		{
@@ -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;
-		mWidgets = bs_new<EditorWidgetContainer>(widgetParent, parentWindow);
+		mWidgets = bs_new<EditorWidgetContainer>(guiWidget.get(), parentWindow);
 
 		mWidgets->onWidgetClosed.connect(std::bind(&DockManager::DockContainer::widgetRemoved, this));
 
@@ -144,10 +155,11 @@ namespace BansheeEngine
 		mWidgets->setSize(mArea.width, mArea.height);
 	}
 
-	void DockManager::DockContainer::makeLeaf(EditorWidgetContainer* existingContainer)
+	void DockManager::DockContainer::makeLeaf(const HSceneObject& guiWidgetSO, EditorWidgetContainer* existingContainer)
 	{
 		mIsLeaf = true;
 		mWidgets = existingContainer;
+		mGUIWidgetSO = guiWidgetSO;
 
 		mWidgets->onWidgetClosed.connect(std::bind(&DockManager::DockContainer::widgetRemoved, this));
 
@@ -205,10 +217,11 @@ namespace BansheeEngine
 
 		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;
+		mGUIWidgetSO = nullptr;
 		makeSplit(children[0], children[1], horizontal, splitPosition);
 	}
 
@@ -227,6 +240,12 @@ namespace BansheeEngine
 			mWidgets = nullptr;
 		}
 
+		if (mGUIWidgetSO != nullptr)
+		{
+			mGUIWidgetSO->destroy();
+			mGUIWidgetSO = nullptr;
+		}
+
 		if (mSlider != nullptr)
 		{
 			GUIElement::destroy(mSlider);
@@ -287,6 +306,9 @@ namespace BansheeEngine
 				bs_delete(mWidgets);
 				mWidgets = nullptr;
 
+				mGUIWidgetSO->destroy();
+				mGUIWidgetSO = nullptr;
+
 				mIsLeaf = true;
 				mSplitPosition = 0.5f;
 				mIsHorizontal = false;
@@ -304,8 +326,9 @@ namespace BansheeEngine
 				{
 					sibling->mWidgets->onWidgetClosed.clear();
 
-					mParent->makeLeaf(sibling->mWidgets);
+					mParent->makeLeaf(sibling->mGUIWidgetSO, sibling->mWidgets);
 					sibling->mWidgets = nullptr;
+					sibling->mGUIWidgetSO = nullptr;
 				}
 				else
 				{
@@ -528,7 +551,7 @@ namespace BansheeEngine
 			if(mRootContainer.mWidgets != nullptr)
 				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);
 		}
 	}
@@ -705,7 +728,7 @@ namespace BansheeEngine
 
 		if(leafEntry->widgetNames.size() > 0) // If zero, entire layout is empty
 		{
-			mRootContainer.makeLeaf(_getParentWidget(), mParentWindow);
+			mRootContainer.makeLeaf(mParentWindow);
 			OpenWidgets(&mRootContainer, leafEntry->widgetNames);
 
 			if(!rootEntry->isLeaf)

+ 6 - 6
BansheeEngine/Include/BsGUIElementContainer.h

@@ -18,32 +18,32 @@ namespace BansheeEngine
 		/**
 		 * @copydoc GUIElement::getNumRenderElements
 		 */
-		virtual UINT32 _getNumRenderElements() const;
+		virtual UINT32 _getNumRenderElements() const override;
 
 		/**
 		 * @copydoc GUIElement::getMaterial
 		 */
-		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const;
+		virtual const GUIMaterialInfo& _getMaterial(UINT32 renderElementIdx) const override;
 
 		/**
 		 * @copydoc GUIElement::getNumQuads
 		 */
-		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const;
+		virtual UINT32 _getNumQuads(UINT32 renderElementIdx) const override;
 
 		/**
 		 * @copydoc GUIElement::fillBuffer
 		 */
 		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
 		 */
-		virtual void updateClippedBounds();
+		virtual void updateClippedBounds() override;
 
 		/**
 		 * @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
 
-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
 
-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
 
 Test inspector selection, selecting a resource and adding/removing component updates