Procházet zdrojové kódy

Hooked up DropDownBox scrolling up/down

Marko Pintera před 12 roky
rodič
revize
977e1609d0

+ 4 - 2
BansheeEngine/Include/BsGUIDropDownBox.h

@@ -53,7 +53,9 @@ namespace BansheeEngine
 		static const CM::UINT32 DROP_DOWN_BOX_WIDTH;
 
 		CM::Vector<GUIDropDownData>::type mElements;
-		CM::UINT32 mDropDownStartIdx;
+		CM::UINT32 mPage;
+		CM::INT32 x, y;
+		CM::UINT32 width, height;
 
 		CM::Vector<GUITexture*>::type mCachedSeparators;
 		CM::Vector<GUIButton*>::type mCachedEntryBtns;
@@ -75,7 +77,7 @@ namespace BansheeEngine
 		GUIArea* mContentArea;
 		GUILayout* mContentLayout;
 
-		void updateGUIElements(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height);
+		void updateGUIElements();
 
 		void scrollDown();
 		void scrollUp();

+ 44 - 53
BansheeEngine/Source/BsGUIDropDownBox.cpp

@@ -34,10 +34,10 @@ namespace BansheeEngine
 	}
 
 	GUIDropDownBox::GUIDropDownBox(const HSceneObject& parent)
-		:GUIWidget(parent), mDropDownStartIdx(0), mBackgroundFrame(nullptr), mScrollUpStyle(nullptr),
+		:GUIWidget(parent), mPage(0), mBackgroundFrame(nullptr), mScrollUpStyle(nullptr),
 		mScrollDownStyle(nullptr), mEntryBtnStyle(nullptr), mEntryExpBtnStyle(nullptr), 
 		mSeparatorStyle(nullptr), mBackgroundStyle(nullptr), mBackgroundArea(nullptr), mContentArea(nullptr), 
-		mContentLayout(nullptr), mScrollUpBtn(nullptr), mScrollDownBtn(nullptr)
+		mContentLayout(nullptr), mScrollUpBtn(nullptr), mScrollDownBtn(nullptr), x(0), y(0), width(0), height(0)
 	{
 
 	}
@@ -82,25 +82,24 @@ namespace BansheeEngine
 
 		Rect dropDownListBounds = parentElem->getBounds();
 
-		Int2 position;
 		// Determine x position and whether to align to left or right side of the drop down list
 		UINT32 availableRightwardWidth = (UINT32)std::max(0, (target->getLeft() + target->getWidth()) - dropDownListBounds.x);
 		UINT32 availableLeftwardWidth = (UINT32)std::max(0, (dropDownListBounds.x + dropDownListBounds.width) - target->getLeft());
 
 		//// Prefer right if possible
 		if(DROP_DOWN_BOX_WIDTH <= availableRightwardWidth)
-			position.x = dropDownListBounds.x;
+			x = dropDownListBounds.x;
 		else
 		{
 			if(availableRightwardWidth >= availableLeftwardWidth)
-				position.x = dropDownListBounds.x;
+				x = dropDownListBounds.x;
 			else
-				position.x = dropDownListBounds.x - std::min(DROP_DOWN_BOX_WIDTH, availableLeftwardWidth);
+				x = dropDownListBounds.x - std::min(DROP_DOWN_BOX_WIDTH, availableLeftwardWidth);
 		}
 
 		// Determine maximum width
-		UINT32 maxPossibleWidth = (UINT32)std::max(0, (target->getLeft() + target->getWidth()) - position.x);
-		UINT32 width = std::min(DROP_DOWN_BOX_WIDTH, maxPossibleWidth);
+		UINT32 maxPossibleWidth = (UINT32)std::max(0, (target->getLeft() + target->getWidth()) - x);
+		width = std::min(DROP_DOWN_BOX_WIDTH, maxPossibleWidth);
 
 		// Determine y position and whether to open upward or downward
 		UINT32 helperElementHeight = mScrollUpStyle->height + mScrollDownStyle->height + mBackgroundStyle->margins.top + mBackgroundStyle->margins.bottom;
@@ -114,58 +113,57 @@ namespace BansheeEngine
 		UINT32 availableUpwardHeight = (UINT32)std::max(0, dropDownListBounds.y - target->getTop());
 
 		//// Prefer down if possible
-		UINT32 height = 0;
+		height = 0;
 		if(maxNeededHeight <= availableDownwardHeight)
 		{
-			position.y = dropDownListBounds.y + dropDownListBounds.height;
+			y = dropDownListBounds.y + dropDownListBounds.height;
 			height = availableDownwardHeight;
 		}
 		else
 		{
 			if(availableDownwardHeight >= availableUpwardHeight)
 			{
-				position.y = dropDownListBounds.y + dropDownListBounds.height;
+				y = dropDownListBounds.y + dropDownListBounds.height;
 				height = availableDownwardHeight;
 			}
 			else
 			{
-				position.y = dropDownListBounds.y - std::min(maxNeededHeight, availableUpwardHeight);
+				y = dropDownListBounds.y - std::min(maxNeededHeight, availableUpwardHeight);
 				height = availableUpwardHeight;
 			}
 		}
 
 		// Content area
-		mContentArea = GUIArea::create(*this, position.x, position.y, width, height);
+		mContentArea = GUIArea::create(*this, x, y, width, height);
 		mContentLayout = &mContentArea->getLayout().addLayoutY();
 
 		// Background frame
-		mBackgroundArea = GUIArea::create(*this, position.x, position.y, width, height);
+		mBackgroundArea = GUIArea::create(*this, x, y, width, height);
 		mBackgroundArea->setDepth(102);
 		mBackgroundArea->getLayout().addElement(GUITexture::create(*this, GUIImageScaleMode::ScaleToFit, mBackgroundStyle));
 
-		updateGUIElements(position.x, position.y, width, height);
+		updateGUIElements();
 	}
 
-	void GUIDropDownBox::updateGUIElements(CM::INT32 x, CM::INT32 y, CM::UINT32 width, CM::UINT32 height)
+	void GUIDropDownBox::updateGUIElements()
 	{
 		// Remove all elements from content layout
 		while(mContentLayout->getNumChildren() > 0)
 			mContentLayout->removeChildAt(mContentLayout->getNumChildren() - 1);
 
 		// Determine if we need scroll up and/or down buttons, number of visible elements and actual height
-		bool needsScrollUp = mDropDownStartIdx > 0;
+		bool needsScrollUp = mPage > 0;
 		UINT32 numElements = (UINT32)mElements.size();
 
 		UINT32 usedHeight = mBackgroundStyle->margins.top + mBackgroundStyle->margins.bottom;
-		if(needsScrollUp)
-			usedHeight += mScrollUpStyle->height;
 
-		UINT32 numVisibleElements = 0;
+		UINT32 pageStart = 0, pageEnd = 0;
+		UINT32 curPage = 0;
 		bool needsScrollDown = false;
 		for(UINT32 i = 0; i < numElements; i++)
 		{
 			usedHeight += getElementHeight(i);
-			numVisibleElements++;
+			pageEnd++;
 
 			if(usedHeight > height)
 			{
@@ -173,16 +171,27 @@ namespace BansheeEngine
 				needsScrollDown = true;
 
 				// Remove last few elements until we fit again
-				UINT32 j = i;
-				while(usedHeight > height && j >= 0)
+				while(usedHeight > height && i >= 0)
 				{
-					usedHeight -= getElementHeight(j);
-					numVisibleElements--;
+					usedHeight -= getElementHeight(i);
+					pageEnd--;
 
-					j--;
+					i--;
 				}
 
-				break;
+				// We found our page and are done
+				if(curPage == mPage)
+					break;
+
+				// Nothing fits, break out of infinite loop
+				if(pageStart == pageEnd)
+					break;
+
+				pageStart = pageEnd;
+				usedHeight = mBackgroundStyle->margins.top + mBackgroundStyle->margins.bottom;
+				usedHeight += mScrollUpStyle->height;
+
+				curPage++;
 			}
 		}
 
@@ -209,7 +218,7 @@ namespace BansheeEngine
 		CM::Vector<GUITexture*>::type newSeparators;
 		CM::Vector<GUIButton*>::type newEntryBtns;
 		CM::Vector<GUIButton*>::type newExpEntryBtns;
-		for(UINT32 i = 0; i < numVisibleElements; i++)
+		for(UINT32 i = pageStart; i < pageEnd; i++)
 		{
 			GUIDropDownData& element = mElements[i];
 
@@ -321,34 +330,16 @@ namespace BansheeEngine
 
 	void GUIDropDownBox::scrollDown()
 	{
-		//INT32 maxNumElements = (INT32)mDropDownElements.size();
-		//INT32 numVisibleElements = (INT32)mDropDownElementButtons.size();
-
-		//INT32 newIdx = mDropDownStartIdx + numVisibleElements;
-		//INT32 clampedNewIdx = std::min(newIdx, maxNumElements - numVisibleElements);
-		//mDropDownStartIdx = (UINT32)std::min(newIdx, clampedNewIdx);
-
-		//UINT32 i = mDropDownStartIdx;
-		//for(auto& button : mDropDownElementButtons)
-		//{
-		//	button->setContent(GUIContent(mDropDownElements[i]));
-		//	i++;
-		//}
+		mPage++;
+		updateGUIElements();
 	}
 
 	void GUIDropDownBox::scrollUp()
 	{
-		//INT32 numVisibleElements = (INT32)mDropDownElementButtons.size();
-
-		//INT32 newIdx = mDropDownStartIdx - numVisibleElements;
-		//INT32 clampedNewIdx = std::max(newIdx, 0);
-		//mDropDownStartIdx = (UINT32)std::min(newIdx, clampedNewIdx);
-
-		//UINT32 i = mDropDownStartIdx;
-		//for(auto& button : mDropDownElementButtons)
-		//{
-		//	button->setContent(GUIContent(mDropDownElements[i]));
-		//	i++;
-		//}
+		if(mPage > 0)
+		{
+			mPage--;
+			updateGUIElements();
+		}
 	}
 }

+ 8 - 2
DropDown.txt

@@ -2,9 +2,15 @@ GUI ignores image in GUIContent for most elements.
 
 Immediate TODO:
  - Hook up ScrollUp and ScrollDown events in GUIDropDownBox
- - Add support to GUIManager to deal with multiple different GUIDropDownBoxes
 
-Figure out how to deal with sub-menus
+ GUIMenuBar
+ - Create top level buttons in PS
+ - Derives from GUIWidget and can be easily added to a window
+ - AddMenuItem("Scene/Components/Camera", addCameraCallback)
+  - Automatically creates entire menu hierarchy (or just adds it to an existing submenu)
+ - GetMenuItem("Scene/Components")
+  - Returns a MenuItem which may have multiple MenuItem children
+ - RemoveMenuItem(MenuItem* item)
 
 ----------------------------
  - Elements can call addContextAction("Name", "Callback")