Browse Source

Basic DropDown functionality

Marko Pintera 12 years ago
parent
commit
34ec6795ae

+ 1 - 0
BansheeEngine.sln

@@ -41,6 +41,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
 		CSharpWrap.txt = CSharpWrap.txt
 		Dependencies.txt = Dependencies.txt
 		DrawHelper.txt = DrawHelper.txt
+		DropDown.txt = DropDown.txt
 		EditorWindowDock.txt = EditorWindowDock.txt
 		Notes.txt = Notes.txt
 		PlatformPorting.txt = PlatformPorting.txt

+ 2 - 0
BansheeEngine/BansheeEngine.vcxproj

@@ -235,6 +235,7 @@
     <ClInclude Include="Include\BsGUIArea.h" />
     <ClInclude Include="Include\BsGUIButton.h" />
     <ClInclude Include="Include\BsGUICommandEvent.h" />
+    <ClInclude Include="Include\BsGUIDropDownList.h" />
     <ClInclude Include="Include\BsGUIElementBase.h" />
     <ClInclude Include="Include\BsGUIInputTool.h" />
     <ClInclude Include="Include\BsGUIInputBox.h" />
@@ -290,6 +291,7 @@
     <ClCompile Include="Source\BsEngineGUI.cpp" />
     <ClCompile Include="Source\BsGUIArea.cpp" />
     <ClCompile Include="Source\BsGUIButton.cpp" />
+    <ClCompile Include="Source\BsGUIDropDownList.cpp" />
     <ClCompile Include="Source\BsGUIElement.cpp" />
     <ClCompile Include="Source\BsGUIElementBase.cpp" />
     <ClCompile Include="Source\BsGUIInputBox.cpp" />

+ 6 - 0
BansheeEngine/BansheeEngine.vcxproj.filters

@@ -198,6 +198,9 @@
     <ClInclude Include="Include\BsDrawHelper3D.h">
       <Filter>Header Files</Filter>
     </ClInclude>
+    <ClInclude Include="Include\BsGUIDropDownList.h">
+      <Filter>Header Files\GUI</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ClCompile Include="Source\BsGUIElement.cpp">
@@ -341,5 +344,8 @@
     <ClCompile Include="Source\BsDrawHelper3D.cpp">
       <Filter>Source Files</Filter>
     </ClCompile>
+    <ClCompile Include="Source\BsGUIDropDownList.cpp">
+      <Filter>Source Files\GUI</Filter>
+    </ClCompile>
   </ItemGroup>
 </Project>

+ 16 - 0
BansheeEngine/Include/BsEngineGUI.h

@@ -68,5 +68,21 @@ namespace BansheeEngine
 		static const CM::String ScrollBarHandleVertActiveTex;
 
 		static const CM::String ScrollBarBgTex;
+
+		static const CM::String DropDownBtnNormalTex;
+		static const CM::String DropDownBtnHoverTex;
+
+		static const CM::String DropDownBoxBgTex;
+		static const CM::String DropDownBoxEntryNormalTex;
+		static const CM::String DropDownBoxEntryHoverTex;
+
+		static const CM::String DropDownBoxBtnUpNormalTex;
+		static const CM::String DropDownBoxBtnUpHoverTex;
+
+		static const CM::String DropDownBoxBtnDownNormalTex;
+		static const CM::String DropDownBoxBtnDownHoverTex;
+
+		static const CM::String DropDownBoxBtnUpBgTex;
+		static const CM::String DropDownBoxBtnDownBgTex;
 	};
 }

+ 68 - 0
BansheeEngine/Include/BsGUIDropDownList.h

@@ -0,0 +1,68 @@
+#pragma once
+
+#include "BsPrerequisites.h"
+#include "BsGUIElement.h"
+#include "BsImageSprite.h"
+#include "boost/signal.hpp"
+
+namespace BansheeEngine
+{
+	class BS_EXPORT GUIDropDownList : public GUIElement
+	{
+	public:
+		static const CM::String& getGUITypeName();
+
+		static GUIDropDownList* create(GUIWidget& parent, const CM::Vector<CM::WString>::type& elements, const GUIElementStyle* style = nullptr);
+		static GUIDropDownList* create(GUIWidget& parent, const CM::Vector<CM::WString>::type& elements, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style = nullptr);
+	protected:
+		~GUIDropDownList();
+
+		/**
+		 * @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();
+
+		/**
+		 * @copydoc GUIElement::updateBounds()
+		 */
+		virtual void updateClippedBounds();
+
+		virtual CM::UINT32 _getOptimalWidth() const;
+		virtual CM::UINT32 _getOptimalHeight() const;
+
+		virtual CM::UINT32 _getRenderElementDepth(CM::UINT32 renderElementIdx) const;
+	private:
+		ImageSprite* mImageSprite;
+		TextSprite* mTextSprite;
+		CM::UINT32 mNumImageRenderElements;
+		CM::UINT32 mSelectedIdx;
+
+		IMAGE_SPRITE_DESC mImageDesc;
+		CM::Vector<CM::WString>::type mElements;
+
+		GUIDropDownList(GUIWidget& parent, const GUIElementStyle* style, const CM::Vector<CM::WString>::type& elements, const GUILayoutOptions& layoutOptions);
+
+		virtual bool mouseEvent(const GUIMouseEvent& ev);
+	};
+}

+ 150 - 1
BansheeEngine/Source/BsEngineGUI.cpp

@@ -67,6 +67,22 @@ namespace BansheeEngine
 	const String EngineGUI::ScrollBarHandleVertHoverTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\ScrollBarVertHandleHover.psd";
 	const String EngineGUI::ScrollBarHandleVertActiveTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\ScrollBarVertHandleActive.psd";
 
+	const String EngineGUI::DropDownBtnNormalTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownNormal.psd";
+	const String EngineGUI::DropDownBtnHoverTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownHover.psd";
+
+	const String EngineGUI::DropDownBoxBgTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownBoxBg.psd";
+	const String EngineGUI::DropDownBoxEntryNormalTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownButtonNormal.psd";
+	const String EngineGUI::DropDownBoxEntryHoverTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownButtonHover.psd";
+
+	const String EngineGUI::DropDownBoxBtnUpNormalTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownBoxBtnUpNormal.psd";
+	const String EngineGUI::DropDownBoxBtnUpHoverTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownBoxBtnUpHover.psd";
+
+	const String EngineGUI::DropDownBoxBtnDownNormalTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownBoxBtnDownNormal.psd";
+	const String EngineGUI::DropDownBoxBtnDownHoverTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownBoxBtnDownHover.psd";
+
+	const String EngineGUI::DropDownBoxBtnUpBgTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownBoxBtnUpBg.psd";
+	const String EngineGUI::DropDownBoxBtnDownBgTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\DropDownBoxBtnDownBg.psd";
+
 	const String EngineGUI::ScrollBarBgTex = "..\\..\\..\\..\\Data\\Editor\\Skin\\ScrollBarBg.psd";
 
 	EngineGUI::EngineGUI()
@@ -378,6 +394,139 @@ namespace BansheeEngine
 		horzScrollBarStyle.height = 8;
 
 		mSkin.setStyle("ScrollBarHorz", horzScrollBarStyle);
-	}
 
+		/************************************************************************/
+		/* 								DROP DOWN BOX                      		*/
+		/************************************************************************/
+
+		// DropDown button
+		HTexture dropDownListNormal = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBtnNormalTex));
+		HTexture dropDownListHover = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBtnHoverTex));
+
+		GUIElementStyle dropDownListStyle;
+		dropDownListStyle.normal.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownListNormal));
+		dropDownListStyle.hover.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownListHover));
+		dropDownListStyle.active.texture = dropDownListStyle.hover.texture;
+		dropDownListStyle.fixedHeight = true;
+		dropDownListStyle.fixedWidth = false;
+		dropDownListStyle.height = 13;
+		dropDownListStyle.width = 30;
+		dropDownListStyle.border.left = 1;
+		dropDownListStyle.border.right = 10;
+		dropDownListStyle.border.top = 1;
+		dropDownListStyle.border.bottom = 1;
+		dropDownListStyle.font = font;
+		dropDownListStyle.fontSize = DefaultFontSize;
+		dropDownListStyle.textHorzAlign = THA_Left;
+		dropDownListStyle.textVertAlign = TVA_Top;
+
+		mSkin.setStyle("DropDownList", dropDownListStyle);
+
+		// DropDown scroll up button
+		HTexture dropDownBtnScrollUpNormal = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxBtnUpNormalTex));
+		HTexture dropDownBtnScrollUpHover = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxBtnUpHoverTex));
+
+		GUIElementStyle dropDownScrollUpBtnStyle;
+		dropDownScrollUpBtnStyle.normal.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownBtnScrollUpNormal));
+		dropDownScrollUpBtnStyle.hover.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownBtnScrollUpHover));
+		dropDownScrollUpBtnStyle.active.texture = dropDownScrollUpBtnStyle.hover.texture;
+		dropDownScrollUpBtnStyle.fixedHeight = true;
+		dropDownScrollUpBtnStyle.fixedWidth = false;
+		dropDownScrollUpBtnStyle.height = 7;
+		dropDownScrollUpBtnStyle.width = 30;
+		dropDownScrollUpBtnStyle.border.left = 1;
+		dropDownScrollUpBtnStyle.border.right = 1;
+		dropDownScrollUpBtnStyle.border.top = 1;
+		dropDownScrollUpBtnStyle.border.bottom = 1;
+
+		mSkin.setStyle("DropDownScrollUpBtn", dropDownScrollUpBtnStyle);
+
+		// DropDown scroll up button background
+		HTexture dropDownBtnScrollUpBg = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxBtnUpBgTex));
+
+		GUIElementStyle dropDownScrollUpBtnBgStyle;
+		dropDownScrollUpBtnBgStyle.normal.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownBtnScrollUpBg));
+		dropDownScrollUpBtnBgStyle.fixedHeight = true;
+		dropDownScrollUpBtnBgStyle.fixedWidth = false;
+		dropDownScrollUpBtnBgStyle.height = 7;
+		dropDownScrollUpBtnBgStyle.width = 30;
+		dropDownScrollUpBtnBgStyle.border.left = 1;
+		dropDownScrollUpBtnBgStyle.border.right = 1;
+		dropDownScrollUpBtnBgStyle.border.top = 1;
+		dropDownScrollUpBtnBgStyle.border.bottom = 1;
+
+		mSkin.setStyle("DropDownScrollUpBtnBg", dropDownScrollUpBtnBgStyle);
+
+		// DropDown scroll down button
+		HTexture dropDownBtnScrollDownNormal = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxBtnDownNormalTex));
+		HTexture dropDownBtnScrollDownHover = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxBtnDownHoverTex));
+
+		GUIElementStyle dropDownScrollDownBtnStyle;
+		dropDownScrollDownBtnStyle.normal.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownBtnScrollDownNormal));
+		dropDownScrollDownBtnStyle.hover.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownBtnScrollDownHover));
+		dropDownScrollDownBtnStyle.active.texture = dropDownScrollDownBtnStyle.hover.texture;
+		dropDownScrollDownBtnStyle.fixedHeight = true;
+		dropDownScrollDownBtnStyle.fixedWidth = false;
+		dropDownScrollDownBtnStyle.height = 7;
+		dropDownScrollDownBtnStyle.width = 30;
+		dropDownScrollDownBtnStyle.border.left = 1;
+		dropDownScrollDownBtnStyle.border.right = 1;
+		dropDownScrollDownBtnStyle.border.top = 1;
+		dropDownScrollDownBtnStyle.border.bottom = 1;
+		
+		mSkin.setStyle("DropDownScrollDownBtn", dropDownScrollDownBtnStyle);
+
+		// DropDown scroll down button background
+		HTexture dropDownBtnScrollDownBg = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxBtnDownBgTex));
+
+		GUIElementStyle dropDownScrollDownBtnBgStyle;
+		dropDownScrollDownBtnBgStyle.normal.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownBtnScrollDownBg));
+		dropDownScrollDownBtnBgStyle.fixedHeight = true;
+		dropDownScrollDownBtnBgStyle.fixedWidth = false;
+		dropDownScrollDownBtnBgStyle.height = 7;
+		dropDownScrollDownBtnBgStyle.width = 30;
+		dropDownScrollDownBtnBgStyle.border.left = 1;
+		dropDownScrollDownBtnBgStyle.border.right = 1;
+		dropDownScrollDownBtnBgStyle.border.top = 1;
+		dropDownScrollDownBtnBgStyle.border.bottom = 1;
+
+		mSkin.setStyle("DropDownScrollDownBtnBg", dropDownScrollDownBtnBgStyle);
+		
+		// DropDown entry button
+		HTexture dropDownEntryBtnNormal = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxEntryNormalTex));
+		HTexture dropDownEntryBtnHover = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxEntryHoverTex));
+
+		GUIElementStyle dropDownEntryBtnStyle;
+		dropDownEntryBtnStyle.normal.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownEntryBtnNormal));
+		dropDownEntryBtnStyle.hover.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownEntryBtnHover));
+		dropDownEntryBtnStyle.active.texture = dropDownEntryBtnStyle.hover.texture;
+		dropDownEntryBtnStyle.fixedHeight = true;
+		dropDownEntryBtnStyle.fixedWidth = false;
+		dropDownEntryBtnStyle.height = 14;
+		dropDownEntryBtnStyle.width = 30;
+		dropDownEntryBtnStyle.border.left = 1;
+		dropDownEntryBtnStyle.border.right = 1;
+		dropDownEntryBtnStyle.border.top = 1;
+		dropDownEntryBtnStyle.border.bottom = 1;
+
+		mSkin.setStyle("DropDownEntryBtn", dropDownEntryBtnStyle);
+
+		// DropDown box frame
+		HTexture dropDownBoxBgTex = static_resource_cast<Texture>(Importer::instance().import(FileSystem::getCurrentPath() + "\\" + DropDownBoxBgTex));
+
+		GUIElementStyle dropDownBoxStyle;
+		dropDownBoxStyle.normal.texture = cm_shared_ptr<SpriteTexture, PoolAlloc>(std::cref(dropDownBoxBgTex));
+		dropDownBoxStyle.hover.texture = dropDownEntryBtnStyle.normal.texture;
+		dropDownBoxStyle.active.texture = dropDownEntryBtnStyle.hover.texture;
+		dropDownBoxStyle.fixedHeight = false;
+		dropDownBoxStyle.fixedWidth = false;
+		dropDownBoxStyle.height = 14;
+		dropDownBoxStyle.width = 30;
+		dropDownBoxStyle.border.left = 1;
+		dropDownBoxStyle.border.right = 1;
+		dropDownBoxStyle.border.top = 1;
+		dropDownBoxStyle.border.bottom = 1;
+
+		mSkin.setStyle("DropDownBox", dropDownBoxStyle);
+	}
 }

+ 206 - 0
BansheeEngine/Source/BsGUIDropDownList.cpp

@@ -0,0 +1,206 @@
+#include "BsGUIDropDownList.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& GUIDropDownList::getGUITypeName()
+	{
+		static String name = "DropDownList";
+		return name;
+	}
+
+	GUIDropDownList::GUIDropDownList(GUIWidget& parent, const GUIElementStyle* style, const Vector<WString>::type& elements, const GUILayoutOptions& layoutOptions)
+		:GUIElement(parent, style, layoutOptions), mElements(elements), mNumImageRenderElements(0), mSelectedIdx(0)
+	{
+		mImageSprite = cm_new<ImageSprite, PoolAlloc>();
+		mTextSprite = cm_new<TextSprite, PoolAlloc>();
+
+		mImageDesc.texture = mStyle->normal.texture;
+
+		if(mImageDesc.texture != nullptr)
+		{
+			mImageDesc.width = mImageDesc.texture->getTexture()->getWidth();
+			mImageDesc.height = mImageDesc.texture->getTexture()->getHeight();
+		}
+
+		mImageDesc.borderLeft = mStyle->border.left;
+		mImageDesc.borderRight = mStyle->border.right;
+		mImageDesc.borderTop = mStyle->border.top;
+		mImageDesc.borderBottom = mStyle->border.bottom;
+	}
+
+	GUIDropDownList::~GUIDropDownList()
+	{
+		cm_delete<PoolAlloc>(mTextSprite);
+		cm_delete<PoolAlloc>(mImageSprite);
+	}
+
+	GUIDropDownList* GUIDropDownList::create(GUIWidget& parent, const Vector<WString>::type& elements, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIDropDownList, PoolAlloc>()) GUIDropDownList(parent, style, elements, getDefaultLayoutOptions(style));
+	}
+
+	GUIDropDownList* GUIDropDownList::create(GUIWidget& parent, const Vector<WString>::type& elements, const GUILayoutOptions& layoutOptions, const GUIElementStyle* style)
+	{
+		if(style == nullptr)
+		{
+			const GUISkin* skin = parent.getSkin();
+			style = skin->getStyle(getGUITypeName());
+		}
+
+		return new (cm_alloc<GUIDropDownList, PoolAlloc>()) GUIDropDownList(parent, style, elements, layoutOptions);
+	}
+
+	UINT32 GUIDropDownList::getNumRenderElements() const
+	{
+		UINT32 numElements = mImageSprite->getNumRenderElements();
+		numElements += mTextSprite->getNumRenderElements();
+
+		return numElements;
+	}
+
+	const HMaterial& GUIDropDownList::getMaterial(UINT32 renderElementIdx) const
+	{
+		if(renderElementIdx >= mNumImageRenderElements)
+			return mTextSprite->getMaterial(mNumImageRenderElements - renderElementIdx);
+		else
+			return mImageSprite->getMaterial(renderElementIdx);
+	}
+
+	UINT32 GUIDropDownList::getNumQuads(UINT32 renderElementIdx) const
+	{
+		UINT32 numQuads = 0;
+		if(renderElementIdx >= mNumImageRenderElements)
+			numQuads = mTextSprite->getNumQuads(mNumImageRenderElements - renderElementIdx);
+		else
+			numQuads = mImageSprite->getNumQuads(renderElementIdx);
+
+		return numQuads;
+	}
+
+	void GUIDropDownList::updateRenderElementsInternal()
+	{		
+		mImageDesc.width = mWidth;
+		mImageDesc.height = mHeight;
+
+		mImageSprite->update(mImageDesc);
+		mNumImageRenderElements = mImageSprite->getNumRenderElements();
+
+		TEXT_SPRITE_DESC textDesc;
+		textDesc.text = mElements[mSelectedIdx];
+		textDesc.font = mStyle->font;
+		textDesc.fontSize = mStyle->fontSize;
+
+		Rect textBounds = getContentBounds();
+
+		textDesc.width = textBounds.width;
+		textDesc.height = textBounds.height;
+		textDesc.horzAlign = mStyle->textHorzAlign;
+		textDesc.vertAlign = mStyle->textVertAlign;
+
+		mTextSprite->update(textDesc);
+
+		GUIElement::updateRenderElementsInternal();
+	}
+
+	void GUIDropDownList::updateClippedBounds()
+	{
+		mClippedBounds = mImageSprite->getBounds(mOffset, mClipRect);
+	}
+
+	UINT32 GUIDropDownList::_getOptimalWidth() const
+	{
+		if(mImageDesc.texture != nullptr)
+		{
+			return mImageDesc.texture->getTexture()->getWidth();
+		}
+
+		return 0;
+	}
+
+	UINT32 GUIDropDownList::_getOptimalHeight() const
+	{
+		if(mImageDesc.texture != nullptr)
+		{
+			return mImageDesc.texture->getTexture()->getHeight();
+		}
+
+		return 0;
+	}
+
+	UINT32 GUIDropDownList::_getRenderElementDepth(UINT32 renderElementIdx) const
+	{
+		if(renderElementIdx >= mNumImageRenderElements)
+			return _getDepth();
+		else
+			return _getDepth() + 1;
+	}
+
+	void GUIDropDownList::fillBuffer(UINT8* vertices, UINT8* uv, UINT32* indices, UINT32 startingQuad, UINT32 maxNumQuads, 
+		UINT32 vertexStride, UINT32 indexStride, UINT32 renderElementIdx) const
+	{
+		if(renderElementIdx >= mNumImageRenderElements)
+		{
+			Rect textBounds = getContentBounds();
+			Int2 offset(textBounds.x, textBounds.y);
+			Rect textClipRect = getContentClipRect();
+
+			mTextSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
+				vertexStride, indexStride, mNumImageRenderElements - renderElementIdx, offset, textClipRect);
+		}
+		else
+		{
+			mImageSprite->fillBuffer(vertices, uv, indices, startingQuad, maxNumQuads, 
+				vertexStride, indexStride, renderElementIdx, mOffset, mClipRect);
+		}
+	}
+
+	bool GUIDropDownList::mouseEvent(const GUIMouseEvent& ev)
+	{
+		if(ev.getType() == GUIMouseEventType::MouseOver)
+		{
+			mImageDesc.texture = mStyle->hover.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseOut)
+		{
+			mImageDesc.texture = mStyle->normal.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseDown)
+		{
+			mImageDesc.texture = mStyle->active.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+		else if(ev.getType() == GUIMouseEventType::MouseUp)
+		{
+			mImageDesc.texture = mStyle->hover.texture;
+			markContentAsDirty();
+
+			return true;
+		}
+
+		return false;
+	}
+}

+ 9 - 0
CamelotClient/Source/CmTestTextSprite.cpp

@@ -7,6 +7,7 @@
 #include "CmFont.h"
 #include "CmMaterial.h"
 #include "BsGUILabel.h"
+#include "BsGUIDropDownList.h"
 #include "BsGUISkin.h"
 #include "BsOverlayManager.h"
 #include "BsSpriteTexture.h"
@@ -14,6 +15,7 @@
 #include "BsGUITexture.h"
 #include "BsGUIArea.h"
 #include "BsGUILayout.h"
+#include "BsGUISpace.h"
 #include "BsGUIViewport.h"
 #include "BsCamera.h"
 #include "CmInput.h"
@@ -42,6 +44,13 @@ namespace CamelotFramework
 		area->getLayout().addElement(GUITexture::create(*this, GUILayoutOptions::fixed(800, 600), spriteTex));
 		mLabel = GUILabel::create(*this, L"");
 		area->getLayout().addElement(mLabel);
+
+		Vector<WString>::type dropDownElements;
+		dropDownElements.push_back(L"Element #1");
+		dropDownElements.push_back(L"Element #2");
+		dropDownElements.push_back(L"Element #3");
+		area->getLayout().addElement(GUIDropDownList::create(*this, dropDownElements, GUILayoutOptions::fixed(50, 13)));
+		area->getLayout().addFlexibleSpace();
 	}
 
 	void TestTextSprite::update()

+ 12 - 0
DropDown.txt

@@ -0,0 +1,12 @@
+DropDownList
+ - 2 states
+   - Closed - Pretty much a normal button with a drop down arrow
+   - Open - Creates a new GUIArea in the current widget
+        - The area is always sized so it doesn't go outside the widget
+        - Area is full of GUIButtons with callbacks set up so that the GUIArea gets destroyed when selection is made
+        - If GUIButtons don't fully fit in the area then top and bottom display arrow buttons you may press to scroll through them
+             - Arrows change pages, not element-by-element
+
+
+IMMEDIATE:
+ - Add up/down drop down arrows (need Textures)

+ 3 - 0
Notes.txt

@@ -20,6 +20,9 @@ Reminders:
 	   until I get the result. But I'd rather apply the result once render thread is finished.
   - GUI currently doesn't batch elements belonging to different GUIWidgets because each of them has its own transform. Implement some form of instancing for DX11 and GL
     so this isn't required. GUIManager already has the ability to properly group meshes, all that is needed is a shader.
+  - When specifying GUIElement layout using (for example) GUILayoutOptions::expandableX then it would be useful if I didn't have to provide the Y height, and instead make it use 
+    the default value for that GUIElement type. For most elements I will only be changing width, and height will remain default (labels, buttons, toggles, drop down lists, etc.) 
+	so this would be helpful in a way I wouldn't need to look up actual element height in EngineGUI.
 
 Potential optimizations:
  - bulkPixelConversion is EXTREMELY poorly unoptimized. Each pixel it calls a separate method that does redudant operations every pixel.