Просмотр исходного кода

Started work on scrollbar handle
Updated how layouts deal with clipping

Marko Pintera 12 лет назад
Родитель
Сommit
56edbdf1e4

+ 2 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -162,6 +162,7 @@
     <ClInclude Include="Include\BsGUILayoutX.h" />
     <ClInclude Include="Include\BsGUILayout.h" />
     <ClInclude Include="Include\BsGUILayoutY.h" />
+    <ClInclude Include="Include\BsGUIScrollBarHandle.h" />
     <ClInclude Include="Include\BsGUIScrollBarHorz.h" />
     <ClInclude Include="Include\BsGUIScrollBarVert.h" />
     <ClInclude Include="Include\BsGUISpace.h" />
@@ -214,6 +215,7 @@
     <ClCompile Include="Source\BsGUIManager.cpp" />
     <ClCompile Include="Source\BsGUIMaterialManager.cpp" />
     <ClCompile Include="Source\BsGUIMouseEvent.cpp" />
+    <ClCompile Include="Source\BsGUIScrollBarHandle.cpp" />
     <ClCompile Include="Source\BsGUIScrollBarHorz.cpp" />
     <ClCompile Include="Source\BsGUIScrollBarVert.cpp" />
     <ClCompile Include="Source\BsGUISkin.cpp" />

+ 6 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -180,6 +180,9 @@
     <ClInclude Include="Include\BsGUIScrollBarHorz.h">
       <Filter>Header Files\GUI</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsGUIScrollBarHandle.h">
+      <Filter>Header Files\GUI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsGUIElement.cpp">
@@ -305,5 +308,8 @@
     <ClCompile Include="Source\BsGUIScrollBarHorz.cpp">
       <Filter>Source Files\GUI</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGUIScrollBarHandle.cpp">
+      <Filter>Source Files\GUI</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 4 - 2
BansheeEngine/Include/BsGUIElementBase.h

@@ -29,9 +29,11 @@ namespace BansheeEngine
 		/**
 		 * @brief	Re-arranges the elements to fit the layout. (Internal use only)
 		 */
-		virtual void _updateLayout(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
+		virtual void _updateLayout(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, 
+			CM::Rect clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
 		virtual void _updateOptimalLayoutSizes();
-		virtual void _updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
+		virtual void _updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height,
+			CM::Rect clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
 
 		virtual CM::UINT32 _getOptimalWidth() const = 0;
 		virtual CM::UINT32 _getOptimalHeight() const = 0;

+ 1 - 1
BansheeEngine/Include/BsGUILayoutX.h

@@ -13,6 +13,6 @@ namespace BansheeEngine
 
 		void _updateOptimalLayoutSizes();
 	protected:
-		void _updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
+		void _updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, CM::Rect clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
 	};
 }

+ 1 - 1
BansheeEngine/Include/BsGUILayoutY.h

@@ -13,6 +13,6 @@ namespace BansheeEngine
 
 		void _updateOptimalLayoutSizes();
 	protected:
-		void _updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
+		void _updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, CM::Rect clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth);
 	};
 }

+ 57 - 0
BansheeEngine/Include/BsGUIScrollBarHandle.h

@@ -0,0 +1,57 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIElement.h"
+#include "BsImageSprite.h"
+
+namespace BansheeEngine
+{
+	class BS_EXPORT GUIScrollBarHandle : public GUIElement
+	{
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUIScrollBarHandle* create(GUIWidget& parent, const GUIElementStyle* style = nullptr);
+		static GUIScrollBarHandle* create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
+	protected:
+		~GUIScrollBarHandle();
+
+		/**
+		 * @copydoc GUIElement::getNumRenderElements()
+		 */
+		virtual CM::UINT32 getNumRenderElements() const;
+
+		/**
+		 * @copydoc GUIElement::getMaterial()
+		 */
+		virtual const CM::HMaterial& getMaterial(CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::getNumQuads()
+		 */
+		virtual CM::UINT32 getNumQuads(CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::fillBuffer()
+		 */
+		virtual void fillBuffer(CM::UINT8* vertices, CM::UINT8* uv, CM::UINT32* indices, CM::UINT32 startingQuad, 
+			CM::UINT32 maxNumQuads, CM::UINT32 vertexStride, CM::UINT32 indexStride, CM::UINT32 renderElementIdx) const;
+
+		/**
+		 * @copydoc GUIElement::updateRenderElementsInternal()
+		 */
+		virtual void updateRenderElementsInternal();
+
+		virtual CM::UINT32 _getOptimalWidth() const;
+		virtual CM::UINT32 _getOptimalHeight() const;
+	private:
+		ImageSprite* mImageSprite;
+		CM::UINT32 mHandleSize;
+		SpriteTexturePtr mCurTexture;
+		bool mHorizontal; // Otherwise its vertical
+
+		GUIScrollBarHandle(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions);
+
+		virtual bool mouseEvent(const GUIMouseEvent& ev);
+	};
+}

+ 2 - 1
BansheeEngine/Source/BsGUIArea.cpp

@@ -89,7 +89,8 @@ namespace BansheeEngine
 	{
 		if(isDirty())
 		{
-			mLayout->_updateLayout(mLeft, mTop, mWidth, mHeight, mWidget.getDepth(), mDepth);
+			Rect clipRect(mLeft, mTop, mWidth, mHeight);
+			mLayout->_updateLayout(mLeft, mTop, mWidth, mHeight, clipRect, mWidget.getDepth(), mDepth);
 			mIsDirty = false;
 		}
 	}

+ 4 - 4
BansheeEngine/Source/BsGUIElementBase.cpp

@@ -43,10 +43,10 @@ namespace BansheeEngine
 		mIsDirty |= 0x02;
 	}
 
-	void GUIElementBase::_updateLayout(UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT8 widgetDepth, UINT16 areaDepth)
+	void GUIElementBase::_updateLayout(UINT32 x, UINT32 y, UINT32 width, UINT32 height, Rect clipRect, UINT8 widgetDepth, UINT16 areaDepth)
 	{
 		_updateOptimalLayoutSizes(); // We calculate optimal sizes of all layouts as a pre-processing step, as they are requested often during update
-		_updateLayoutInternal(x, y, width, height, widgetDepth, areaDepth);
+		_updateLayoutInternal(x, y, width, height, clipRect, widgetDepth, areaDepth);
 	}
 
 	void GUIElementBase::_updateOptimalLayoutSizes()
@@ -57,11 +57,11 @@ namespace BansheeEngine
 		}
 	}
 
-	void GUIElementBase::_updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, CM::UINT8 widgetDepth, CM::UINT16 areaDepth)
+	void GUIElementBase::_updateLayoutInternal(CM::UINT32 x, CM::UINT32 y, CM::UINT32 width, CM::UINT32 height, Rect clipRect, CM::UINT8 widgetDepth, CM::UINT16 areaDepth)
 	{
 		for(auto& child : mChildren)
 		{
-			child->_updateLayoutInternal(x, y, width, height, widgetDepth, areaDepth);
+			child->_updateLayoutInternal(x, y, width, height, clipRect, widgetDepth, areaDepth);
 		}
 	}
 

+ 8 - 6
BansheeEngine/Source/BsGUILayoutX.cpp

@@ -78,7 +78,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void GUILayoutX::_updateLayoutInternal(UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT8 widgetDepth, UINT16 areaDepth)
+	void GUILayoutX::_updateLayoutInternal(UINT32 x, UINT32 y, UINT32 width, UINT32 height, Rect clipRect, UINT8 widgetDepth, UINT16 areaDepth)
 	{
 		UINT32 totalOptimalSize = _getOptimalWidth();
 		UINT32 totalNonClampedSize = 0;
@@ -357,16 +357,18 @@ namespace BansheeEngine
 				element->_setWidgetDepth(widgetDepth);
 				element->_setAreaDepth(areaDepth);
 
-				UINT32 clippedWidth = (UINT32)std::min((INT32)element->_getWidth(), (INT32)width - (INT32)xOffset);
-				UINT32 clippedHeight = (UINT32)std::min((INT32)element->_getHeight(), (INT32)height - (INT32)yOffset);
+				Rect elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+				element->_setClipRect(elemClipRect);
 
-				element->_setClipRect(Rect(0, 0, clippedWidth, clippedHeight));
-				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, widgetDepth, areaDepth);
+				Rect newClipRect(offset.x, offset.y, elemWidth, elemHeight);
+				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, newClipRect, widgetDepth, areaDepth);
 			}
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 				GUILayout* layout = static_cast<GUILayout*>(child);
-				layout->_updateLayoutInternal(x + xOffset, y, elemWidth, height, widgetDepth, areaDepth);
+
+				Rect newClipRect(x + xOffset, y, elemWidth, height);
+				layout->_updateLayoutInternal(x + xOffset, y, elemWidth, height, newClipRect, widgetDepth, areaDepth);
 			}
 
 			xOffset += elemWidth;

+ 8 - 6
BansheeEngine/Source/BsGUILayoutY.cpp

@@ -79,7 +79,7 @@ namespace BansheeEngine
 		}
 	}
 
-	void GUILayoutY::_updateLayoutInternal(UINT32 x, UINT32 y, UINT32 width, UINT32 height, UINT8 widgetDepth, UINT16 areaDepth)
+	void GUILayoutY::_updateLayoutInternal(UINT32 x, UINT32 y, UINT32 width, UINT32 height, Rect clipRect, UINT8 widgetDepth, UINT16 areaDepth)
 	{
 		UINT32 totalOptimalSize = _getOptimalHeight();
 		UINT32 totalNonClampedSize = 0;
@@ -357,16 +357,18 @@ namespace BansheeEngine
 				element->_setWidgetDepth(widgetDepth);
 				element->_setAreaDepth(areaDepth);
 
-				UINT32 clippedWidth = (UINT32)std::min((INT32)element->_getWidth(), (INT32)width - (INT32)xOffset);
-				UINT32 clippedHeight = (UINT32)std::min((INT32)element->_getHeight(), (INT32)height - (INT32)yOffset);
+				Rect elemClipRect(clipRect.x - offset.x, clipRect.y - offset.y, clipRect.width, clipRect.height);
+				element->_setClipRect(elemClipRect);
 
-				element->_setClipRect(Rect(0, 0, clippedWidth, clippedHeight));
-				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, widgetDepth, areaDepth);
+				Rect newClipRect(offset.x, offset.y, elemWidth, elemHeight);
+				element->_updateLayoutInternal(offset.x, offset.y, elemWidth, elemHeight, newClipRect, widgetDepth, areaDepth);
 			}
 			else if(child->_getType() == GUIElementBase::Type::Layout)
 			{
 				GUILayout* layout = static_cast<GUILayout*>(child);
-				layout->_updateLayoutInternal(x, y + yOffset, width, elemHeight, widgetDepth, areaDepth);
+
+				Rect newClipRect(x, y + yOffset, width, elemHeight);
+				layout->_updateLayoutInternal(x, y + yOffset, width, elemHeight, newClipRect, widgetDepth, areaDepth);
 			}
 
 			yOffset += elemHeight;

+ 151 - 0
BansheeEngine/Source/BsGUIScrollBarHandle.cpp

@@ -0,0 +1,151 @@
+#include "BsGUIScrollBarHandle.h"
+#include "BsImageSprite.h"
+#include "BsGUIWidget.h"
+#include "BsGUISkin.h"
+#include "BsSpriteTexture.h"
+#include "BsTextSprite.h"
+#include "BsGUILayoutOptions.h"
+#include "BsGUIMouseEvent.h"
+#include "CmTexture.h"
+
+using namespace CamelotFramework;
+
+namespace BansheeEngine
+{
+	const String& GUIScrollBarHandle::getGUITypeName()
+	{
+		static String name = "ScrollBarHandle";
+		return name;
+	}
+
+	GUIScrollBarHandle::GUIScrollBarHandle(GUIWidget& parent, const GUIElementStyle* style, const GUILayoutOptions& layoutOptions)
+		:GUIElement(parent, style, layoutOptions), mHorizontal(false), mHandleSize(2)
+	{
+		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
+		mCurTexture = style->normal.texture;
+	}
+
+	GUIScrollBarHandle::~GUIScrollBarHandle()
+	{
+		cm_delete<PoolAlloc>(mImageSprite);
+	}
+
+	GUIScrollBarHandle* GUIScrollBarHandle::create(GUIWidget& parent, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIScrollBarHandle, PoolAlloc>()) GUIScrollBarHandle(parent, style, getDefaultLayoutOptions(style));
+	}
+
+	GUIScrollBarHandle* GUIScrollBarHandle::create(GUIWidget& parent, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIScrollBarHandle, PoolAlloc>()) GUIScrollBarHandle(parent, style, layoutOptions);
+	}
+
+	UINT32 GUIScrollBarHandle::getNumRenderElements() const
+	{
+		return mImageSprite->getNumRenderElements();
+	}
+
+	const HMaterial& GUIScrollBarHandle::getMaterial(UINT32 renderElementIdx) const
+	{
+		return mImageSprite->getMaterial(renderElementIdx);
+	}
+
+	UINT32 GUIScrollBarHandle::getNumQuads(UINT32 renderElementIdx) const
+	{
+		return mImageSprite->getNumQuads(renderElementIdx);
+	}
+
+	void GUIScrollBarHandle::updateRenderElementsInternal()
+	{		
+		IMAGE_SPRITE_DESC desc;
+		desc.texture = mCurTexture;
+
+		if(mHorizontal)
+		{
+			desc.width = mHandleSize;
+			desc.height = mHeight;
+		}
+		else
+		{
+			desc.width = mWidth;
+			desc.height = mHandleSize;
+		}
+
+		mImageSprite->update(desc);
+		mBounds = Rect(mOffset.x, mOffset.y, mWidth, mHeight);
+		mBounds.clip(mClipRect);
+	}
+
+	UINT32 GUIScrollBarHandle::_getOptimalWidth() const
+	{
+		if(mCurTexture != nullptr)
+		{
+			return mCurTexture->getTexture()->getWidth();
+		}
+
+		return 0;
+	}
+
+	UINT32 GUIScrollBarHandle::_getOptimalHeight() const
+	{
+		if(mCurTexture != nullptr)
+		{
+			return mCurTexture->getTexture()->getHeight();
+		}
+
+		return 0;
+	}
+
+	void GUIScrollBarHandle::fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
+		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
+	{
+		mImageSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
+			vertexStride, indexStride, renderElementIdx, mOffset, mClipRect);
+	}
+
+	bool GUIScrollBarHandle::mouseEvent(const GUIMouseEvent& ev)
+	{
+		if(ev.getType() == GUIMouseEventType::MouseOver)
+		{
+			mCurTexture = mStyle->hover.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseOut)
+		{
+			mCurTexture = mStyle->normal.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDown)
+		{
+			mCurTexture = mStyle->active.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseUp)
+		{
+			mCurTexture = mStyle->hover.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+		
+		return false;
+	}
+}