ソースを参照

Various ScrollArea fixes so that contents aren't just clipped

Marko Pintera 12 年 前
コミット
7d238b1ebb

+ 2 - 0
BansheeEngine/Source/BsGUILayoutX.cpp

@@ -70,6 +70,7 @@ namespace BansheeEngine
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 			{
 				optimalWidth = child->_getOptimalSize().x;
 				optimalWidth = child->_getOptimalSize().x;
+				optimalHeight = child->_getOptimalSize().y;
 			}
 			}
 
 
 			mOptimalSizes[childIdx].x = optimalWidth;
 			mOptimalSizes[childIdx].x = optimalWidth;
@@ -376,6 +377,7 @@ namespace BansheeEngine
 				element->_setClipRect(elemClipRect);
 				element->_setClipRect(elemClipRect);
 
 
 				RectI newClipRect(offset.x, offset.y, elemWidth, elemHeight);
 				RectI newClipRect(offset.x, offset.y, elemWidth, elemHeight);
+				newClipRect.clip(clipRect);
 				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, newClipRect, widgetDepth, areaDepth);
 				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, newClipRect, widgetDepth, areaDepth);
 
 
 				mActualHeight = std::max(mActualHeight, elemHeight);
 				mActualHeight = std::max(mActualHeight, elemHeight);

+ 2 - 0
BansheeEngine/Source/BsGUILayoutY.cpp

@@ -70,6 +70,7 @@ namespace BansheeEngine
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 			{
 				GUILayout* layout = static_cast<GUILayout*>(child);
 				GUILayout* layout = static_cast<GUILayout*>(child);
+				optimalWidth = layout->_getOptimalSize().x;
 				optimalHeight = layout->_getOptimalSize().y;
 				optimalHeight = layout->_getOptimalSize().y;
 			}
 			}
 
 
@@ -369,6 +370,7 @@ namespace BansheeEngine
 				element->_setClipRect(elemClipRect);
 				element->_setClipRect(elemClipRect);
 
 
 				RectI newClipRect(offset.x, offset.y, elemWidth, elemHeight);
 				RectI newClipRect(offset.x, offset.y, elemWidth, elemHeight);
+				newClipRect.clip(clipRect);
 				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, newClipRect, widgetDepth, areaDepth);
 				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, newClipRect, widgetDepth, areaDepth);
 
 
 				mActualWidth = std::max(mActualWidth, elemWidth);
 				mActualWidth = std::max(mActualWidth, elemWidth);

+ 44 - 23
BansheeEngine/Source/BsGUIScrollArea.cpp

@@ -45,15 +45,25 @@ namespace BansheeEngine
 	void GUIScrollArea::_updateLayoutInternal(INT32 x, INT32 y, UINT32 width, UINT32 height,
 	void GUIScrollArea::_updateLayoutInternal(INT32 x, INT32 y, UINT32 width, UINT32 height,
 		RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth)
 		RectI clipRect, UINT8 widgetDepth, UINT16 areaDepth)
 	{
 	{
-		mContentLayout->_updateLayoutInternal(x, y, width, height, clipRect, widgetDepth, areaDepth);
-		UINT32 contentWidth = mContentLayout->_getActualWidth();
-		UINT32 contentHeight = mContentLayout->_getActualHeight();
+		// We want elements to use their optimal height, since scroll area
+		// technically provides "infinite" space
+		UINT32 contentLayoutWidth = width;
+		if(mHorzBarType != ScrollBarType::NeverShow)
+			contentLayoutWidth = mContentLayout->_getOptimalSize().x;
+
+		UINT32 contentLayoutHeight = height;
+		if(mVertBarType != ScrollBarType::NeverShow)
+			contentLayoutHeight = mContentLayout->_getOptimalSize().y;
+
+		mContentLayout->_updateLayoutInternal(x, y, contentLayoutWidth, contentLayoutHeight, clipRect, widgetDepth, areaDepth);
+		mContentWidth = mContentLayout->_getActualWidth();
+		mContentHeight = mContentLayout->_getActualHeight();
 
 
 		mClippedContentWidth = width;
 		mClippedContentWidth = width;
 		mClippedContentHeight = height;
 		mClippedContentHeight = height;
 
 
 		RectI layoutClipRect = clipRect;
 		RectI layoutClipRect = clipRect;
-		bool addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentWidth > mWidth) || 
+		bool addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && mContentWidth > mWidth) || 
 			mHorzBarType == ScrollBarType::AlwaysShow && mHorzBarType != ScrollBarType::NeverShow;
 			mHorzBarType == ScrollBarType::AlwaysShow && mHorzBarType != ScrollBarType::NeverShow;
 
 
 		bool hasHorzScrollbar = false;
 		bool hasHorzScrollbar = false;
@@ -65,14 +75,17 @@ namespace BansheeEngine
 			layoutClipRect.height = mClippedContentHeight;
 			layoutClipRect.height = mClippedContentHeight;
 			hasHorzScrollbar = true;
 			hasHorzScrollbar = true;
 
 
+			if(mVertBarType == ScrollBarType::NeverShow)
+				contentLayoutHeight = mClippedContentHeight;
+
 			mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y, 
 			mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y, 
-				mClippedContentWidth + Math::floorToInt(mHorzOffset), mClippedContentHeight, layoutClipRect, widgetDepth, areaDepth);
+				contentLayoutWidth, contentLayoutHeight, layoutClipRect, widgetDepth, areaDepth);
 
 
-			contentWidth = mContentLayout->_getActualWidth();
-			contentHeight = mContentLayout->_getActualHeight();
+			mContentWidth = mContentLayout->_getActualWidth();
+			mContentHeight = mContentLayout->_getActualHeight();
 		}
 		}
 
 
-		bool addVertScrollbar = (mVertBarType == ScrollBarType::ShowIfDoesntFit && contentHeight > mClippedContentHeight) || 
+		bool addVertScrollbar = (mVertBarType == ScrollBarType::ShowIfDoesntFit && mContentHeight > mClippedContentHeight) || 
 			mVertBarType == ScrollBarType::AlwaysShow && mVertBarType != ScrollBarType::NeverShow;
 			mVertBarType == ScrollBarType::AlwaysShow && mVertBarType != ScrollBarType::NeverShow;
 
 
 		if(addVertScrollbar)
 		if(addVertScrollbar)
@@ -82,25 +95,28 @@ namespace BansheeEngine
 			layoutClipRect.width = mClippedContentWidth;
 			layoutClipRect.width = mClippedContentWidth;
 			hasVertScrollbar = true;
 			hasVertScrollbar = true;
 
 
+			if(mHorzBarType == ScrollBarType::NeverShow)
+				contentLayoutWidth = mClippedContentWidth;
+
 			if(hasHorzScrollbar)
 			if(hasHorzScrollbar)
 			{
 			{
 				mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y - Math::floorToInt(mVertOffset), 
 				mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y - Math::floorToInt(mVertOffset), 
-					mClippedContentWidth + Math::floorToInt(mHorzOffset), mClippedContentHeight + Math::floorToInt(mVertOffset), 
+					contentLayoutWidth, contentLayoutHeight, 
 					layoutClipRect, widgetDepth, areaDepth);
 					layoutClipRect, widgetDepth, areaDepth);
 			}
 			}
 			else
 			else
 			{
 			{
 				mContentLayout->_updateLayoutInternal(x, y - Math::floorToInt(mVertOffset), 
 				mContentLayout->_updateLayoutInternal(x, y - Math::floorToInt(mVertOffset), 
-					mClippedContentWidth, mClippedContentHeight + Math::floorToInt(mVertOffset), 
+					contentLayoutWidth, contentLayoutHeight, 
 					layoutClipRect, widgetDepth, areaDepth);
 					layoutClipRect, widgetDepth, areaDepth);
 			}
 			}
 
 
-			contentWidth = mContentLayout->_getActualWidth();
-			contentHeight = mContentLayout->_getActualHeight();
+			mContentWidth = mContentLayout->_getActualWidth();
+			mContentHeight = mContentLayout->_getActualHeight();
 
 
 			if(!hasHorzScrollbar) // Since width has been reduced, we need to check if we require the horizontal scrollbar
 			if(!hasHorzScrollbar) // Since width has been reduced, we need to check if we require the horizontal scrollbar
 			{
 			{
-				addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentWidth > mClippedContentWidth) && mHorzBarType != ScrollBarType::NeverShow;
+				addHorzScrollbar = (mHorzBarType == ScrollBarType::ShowIfDoesntFit && mContentWidth > mClippedContentWidth) && mHorzBarType != ScrollBarType::NeverShow;
 
 
 				if(addHorzScrollbar)
 				if(addHorzScrollbar)
 				{
 				{
@@ -108,15 +124,23 @@ namespace BansheeEngine
 					mClippedContentHeight = (UINT32)std::max(0, (INT32)height - (INT32)ScrollBarWidth);
 					mClippedContentHeight = (UINT32)std::max(0, (INT32)height - (INT32)ScrollBarWidth);
 					layoutClipRect.height = mClippedContentHeight;
 					layoutClipRect.height = mClippedContentHeight;
 
 
+					if(mVertBarType == ScrollBarType::NeverShow)
+						contentLayoutHeight = mClippedContentHeight;
+
 					mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y - Math::floorToInt(mVertOffset), 
 					mContentLayout->_updateLayoutInternal(x - Math::floorToInt(mHorzOffset), y - Math::floorToInt(mVertOffset), 
-						mClippedContentWidth + Math::floorToInt(mHorzOffset), mClippedContentHeight + Math::floorToInt(mVertOffset), 
+						contentLayoutWidth, contentLayoutHeight, 
 						layoutClipRect, widgetDepth, areaDepth);
 						layoutClipRect, widgetDepth, areaDepth);
+
+					mContentWidth = mContentLayout->_getActualWidth();
+					mContentHeight = mContentLayout->_getActualHeight();
+
+					hasHorzScrollbar = true;
 				}
 				}
 			}
 			}
 		}
 		}
 
 
 		// Add/remove/update vertical scrollbar as needed
 		// Add/remove/update vertical scrollbar as needed
-		if((mVertBarType == ScrollBarType::ShowIfDoesntFit && contentHeight > mClippedContentHeight) || mVertBarType == ScrollBarType::AlwaysShow &&
+		if((mVertBarType == ScrollBarType::ShowIfDoesntFit && mContentHeight > mClippedContentHeight) || mVertBarType == ScrollBarType::AlwaysShow &&
 			mVertBarType != ScrollBarType::NeverShow)
 			mVertBarType != ScrollBarType::NeverShow)
 		{
 		{
 			if(mVertScroll == nullptr)
 			if(mVertScroll == nullptr)
@@ -152,10 +176,10 @@ namespace BansheeEngine
 			mVertScroll->_updateLayout(offset.x, offset.y, ScrollBarWidth, scrollBarHeight, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 			mVertScroll->_updateLayout(offset.x, offset.y, ScrollBarWidth, scrollBarHeight, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 
 
 			// Set new handle size and update position to match the new size
 			// Set new handle size and update position to match the new size
-			UINT32 newHandleSize = (UINT32)Math::floorToInt(mVertScroll->getMaxHandleSize() * (scrollBarHeight / (float)contentHeight));
+			UINT32 newHandleSize = (UINT32)Math::floorToInt(mVertScroll->getMaxHandleSize() * (scrollBarHeight / (float)mContentHeight));
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 
 
-			UINT32 scrollableHeight = (UINT32)std::max(0, INT32(contentHeight) - INT32(scrollBarHeight));
+			UINT32 scrollableHeight = (UINT32)std::max(0, INT32(mContentHeight) - INT32(scrollBarHeight));
 			float newScrollPct = 0.0f;
 			float newScrollPct = 0.0f;
 
 
 			if(scrollableHeight > 0)
 			if(scrollableHeight > 0)
@@ -176,7 +200,7 @@ namespace BansheeEngine
 		}
 		}
 
 
 		// Add/remove/update horizontal scrollbar as needed
 		// Add/remove/update horizontal scrollbar as needed
-		if((mHorzBarType == ScrollBarType::ShowIfDoesntFit && contentWidth > mClippedContentWidth) || mHorzBarType == ScrollBarType::AlwaysShow &&
+		if((mHorzBarType == ScrollBarType::ShowIfDoesntFit && mContentWidth > mClippedContentWidth) || mHorzBarType == ScrollBarType::AlwaysShow &&
 			mHorzBarType != ScrollBarType::NeverShow)
 			mHorzBarType != ScrollBarType::NeverShow)
 		{ 
 		{ 
 			if(mHorzScroll == nullptr)
 			if(mHorzScroll == nullptr)
@@ -212,10 +236,10 @@ namespace BansheeEngine
 			mHorzScroll->_updateLayout(offset.x, offset.y, scrollBarWidth, ScrollBarWidth, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 			mHorzScroll->_updateLayout(offset.x, offset.y, scrollBarWidth, ScrollBarWidth, scrollBarLayoutClipRect, widgetDepth, areaDepth);
 
 
 			// Set new handle size and update position to match the new size
 			// Set new handle size and update position to match the new size
-			UINT32 newHandleSize = (UINT32)Math::floorToInt(mHorzScroll->getMaxHandleSize() * (scrollBarWidth / (float)contentWidth));
+			UINT32 newHandleSize = (UINT32)Math::floorToInt(mHorzScroll->getMaxHandleSize() * (scrollBarWidth / (float)mContentWidth));
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 			newHandleSize = std::max(newHandleSize, MinHandleSize);
 
 
-			UINT32 scrollableWidth = (UINT32)std::max(0, INT32(contentWidth) - INT32(scrollBarWidth));
+			UINT32 scrollableWidth = (UINT32)std::max(0, INT32(mContentWidth) - INT32(scrollBarWidth));
 			float newScrollPct = 0.0f;
 			float newScrollPct = 0.0f;
 			
 			
 			if(scrollableWidth > 0)
 			if(scrollableWidth > 0)
@@ -234,9 +258,6 @@ namespace BansheeEngine
 
 
 			mHorzOffset = 0.0f;
 			mHorzOffset = 0.0f;
 		}
 		}
-
-		mContentWidth = contentWidth;
-		mContentHeight = contentHeight;
 	}
 	}
 
 
 	void GUIScrollArea::vertScrollUpdate(float scrollPos)
 	void GUIScrollArea::vertScrollUpdate(float scrollPos)

+ 24 - 3
CamelotClient/Source/CmTestTextSprite.cpp

@@ -25,6 +25,7 @@
 #include "BsGUIContent.h"
 #include "BsGUIContent.h"
 #include "CmStringTable.h"
 #include "CmStringTable.h"
 #include "BsGUISceneTreeView.h"
 #include "BsGUISceneTreeView.h"
+#include "BsGUIScrollArea.h"
 
 
 using namespace CamelotFramework;
 using namespace CamelotFramework;
 using namespace BansheeEngine;
 using namespace BansheeEngine;
@@ -50,9 +51,22 @@ namespace BansheeEditor
 		mSceneTreeView = GUISceneTreeView::create(*this, GUIOptions(GUIOption::flexibleWidth(), GUIOption::flexibleHeight()));
 		mSceneTreeView = GUISceneTreeView::create(*this, GUIOptions(GUIOption::flexibleWidth(), GUIOption::flexibleHeight()));
 
 
 		GUILayout& sceneTreeViewLayout = area->getLayout().addLayoutY();
 		GUILayout& sceneTreeViewLayout = area->getLayout().addLayoutY();
-		sceneTreeViewLayout.addFlexibleSpace();
-		sceneTreeViewLayout.addElement(mSceneTreeView);
-		sceneTreeViewLayout.addFlexibleSpace();
+		
+		//sceneTreeViewLayout.addElement(mSceneTreeView);
+		
+
+		SceneObject::create("FILLER_A");
+		SceneObject::create("FILLER_B");
+		SceneObject::create("FILLER_C");
+		SceneObject::create("FILLER_D");
+		SceneObject::create("FILLER_E");
+		SceneObject::create("FILLER_F");
+		SceneObject::create("FILLER_G");
+		SceneObject::create("FILLER_H");
+		SceneObject::create("FILLER_I");
+		SceneObject::create("FILLER_J");
+		SceneObject::create("FILLER_K");
+		SceneObject::create("FILLER_L");
 
 
 		//area->getLayout().addElement(GUIRenderTexture::create(*this, sceneView, GUIOptions(GUIOption::fixedWidth(800), GUIOption::fixedHeight(600))));
 		//area->getLayout().addElement(GUIRenderTexture::create(*this, sceneView, GUIOptions(GUIOption::fixedWidth(800), GUIOption::fixedHeight(600))));
 		//mLabel = GUILabel::create(*this, HString(L""));
 		//mLabel = GUILabel::create(*this, HString(L""));
@@ -65,6 +79,13 @@ namespace BansheeEditor
 		//mListBox = GUIListBox::create(*this, dropDownElements, GUIOptions(GUIOption::fixedWidth(50), GUIOption::fixedHeight(13)));
 		//mListBox = GUIListBox::create(*this, dropDownElements, GUIOptions(GUIOption::fixedWidth(50), GUIOption::fixedHeight(13)));
 		//area->getLayout().addElement(mListBox);
 		//area->getLayout().addElement(mListBox);
 
 
+		GUIScrollArea* scrollArea = GUIScrollArea::create(*this, GUIOptions(GUIOption::fixedWidth(100), GUIOption::fixedHeight(100)));
+		sceneTreeViewLayout.addFlexibleSpace();
+		area->getLayout().addElement(scrollArea);
+		sceneTreeViewLayout.addFlexibleSpace();
+
+		scrollArea->getLayout().addElement(mSceneTreeView);
+
 		GUIButton* button = GUIButton::create(*this, HString(L"dbgBtn"));
 		GUIButton* button = GUIButton::create(*this, HString(L"dbgBtn"));
 		button->onClick.connect(boost::bind(&TestTextSprite::dbgBtn, this));
 		button->onClick.connect(boost::bind(&TestTextSprite::dbgBtn, this));
 		area->getLayout().addElement(button);
 		area->getLayout().addElement(button);

+ 0 - 9
TreeView.txt

@@ -9,15 +9,6 @@ TODO:
  - Support for icons next to tree elements
  - Support for icons next to tree elements
  - Ability to move selection via arrow keys
  - Ability to move selection via arrow keys
 
 
-Drag and drop problem:
- - Test it properly
- If I make three element deep tree
-  A
-  --B
-  ----C
-
-And the move C to have parent A, nothing will happen when I first do it. And when I do it next time element will move properly but a ghost element will remain.
-
 MenuBar problems:
 MenuBar problems:
  - Clicking the top menu item closes and immediately opens the menu again (it should only close it)
  - Clicking the top menu item closes and immediately opens the menu again (it should only close it)
    - Something similar probably also happens with ListBox
    - Something similar probably also happens with ListBox