Przeglądaj źródła

Added GuiDropDownCtrl!

This code add the new GuiDropDownCtrl to replace the older GuiPopUpCtrl. It is a combination of the GuiButtonCtrl and GuiListBoxCtrl with all their features. This code also adds IDs and individual item active state to the GuiListBoxCtrl.
Peter Robinson 4 lat temu
rodzic
commit
91ec96ad8f

+ 3 - 0
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj

@@ -612,6 +612,7 @@
     <ClCompile Include="..\..\source\graphics\TextureDictionary.cc" />
     <ClCompile Include="..\..\source\graphics\TextureHandle.cc" />
     <ClCompile Include="..\..\source\graphics\TextureManager.cc" />
+    <ClCompile Include="..\..\source\gui\buttons\guiDropDownCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiChainCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiExpandCtrl.cc" />
     <ClCompile Include="..\..\source\gui\containers\guiFrameCtrl.cc" />
@@ -1148,6 +1149,8 @@
     <ClInclude Include="..\..\source\graphics\TextureObject.h" />
     <ClInclude Include="..\..\source\gui\buttons\guiButtonCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\buttons\guiCheckBoxCtrl_ScriptBinding.h" />
+    <ClInclude Include="..\..\source\gui\buttons\guiDropDownCtrl.h" />
+    <ClInclude Include="..\..\source\gui\buttons\guiDropDownCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiChainCtrl.h" />
     <ClInclude Include="..\..\source\gui\containers\guiChainCtrl_ScriptBinding.h" />
     <ClInclude Include="..\..\source\gui\containers\guiDragAndDropCtrl_ScriptBinding.h" />

+ 9 - 0
engine/compilers/VisualStudio 2017/Torque 2D.vcxproj.filters

@@ -1489,6 +1489,9 @@
     <ClCompile Include="..\..\source\gui\containers\guiFrameCtrl.cc">
       <Filter>gui\containers</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\source\gui\buttons\guiDropDownCtrl.cc">
+      <Filter>gui\buttons</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\source\audio\audio.h">
@@ -3355,6 +3358,12 @@
     <ClInclude Include="..\..\source\gui\guiProgressCtrl_ScriptBinding.h">
       <Filter>gui</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\source\gui\buttons\guiDropDownCtrl.h">
+      <Filter>gui\buttons</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\source\gui\buttons\guiDropDownCtrl_ScriptBinding.h">
+      <Filter>gui\buttons</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="Torque 2D.rc" />

+ 1 - 1
engine/source/graphics/gColor.cc

@@ -163,7 +163,7 @@ StockColorItem StockColorTable[] =
     StockColorItem( "PapayaWhip", 255, 239, 213 ),
     StockColorItem( "PeachPuff", 255, 218, 185 ),
     StockColorItem( "Peru", 205, 133, 63 ),
-    StockColorItem( "Pink", 55, 192, 203 ),
+    StockColorItem( "Pink", 255, 192, 203 ),
     StockColorItem( "Plum", 221, 160, 221 ),
     StockColorItem( "PowderBlue", 176, 224, 230 ),
     StockColorItem( "Purple", 128, 0, 128 ),

+ 7 - 7
engine/source/gui/buttons/guiButtonCtrl.h

@@ -56,15 +56,15 @@ public:
 	void acceleratorKeyPress(U32 index);
 	void acceleratorKeyRelease(U32 index);
 
-	void onTouchDown(const GuiEvent &);
-	void onTouchUp(const GuiEvent &);
-	void onRightMouseUp(const GuiEvent &);
+	virtual void onTouchDown(const GuiEvent &);
+	virtual void onTouchUp(const GuiEvent &);
+	virtual void onRightMouseUp(const GuiEvent &);
 
-	void onTouchEnter(const GuiEvent &);
-	void onTouchLeave(const GuiEvent &);
+	virtual void onTouchEnter(const GuiEvent &);
+	virtual void onTouchLeave(const GuiEvent &);
 
-	bool onKeyDown(const GuiEvent &event);
-	bool onKeyUp(const GuiEvent &event);
+	virtual bool onKeyDown(const GuiEvent &event);
+	virtual bool onKeyUp(const GuiEvent &event);
 
 	virtual void setScriptValue(const char *value);
 	virtual const char *getScriptValue();

+ 388 - 0
engine/source/gui/buttons/guiDropDownCtrl.cc

@@ -0,0 +1,388 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#include "gui/buttons/GuiDropDownCtrl.h"
+#include "gui/guiCanvas.h"
+
+#include "GuiDropDownCtrl_ScriptBinding.h"
+
+#pragma region GuiDropDownBGCtrl
+GuiDropDownBGCtrl::GuiDropDownBGCtrl(GuiDropDownCtrl *ctrl)
+{
+	mDropDownCtrl = ctrl;
+	mBounds.point.set(0, 0);
+	setField("profile", "GuiDefaultProfile");
+}
+
+void GuiDropDownBGCtrl::onTouchUp(const GuiEvent &event)
+{
+	mDropDownCtrl->closeDropDown();
+}
+#pragma endregion
+
+#pragma region GuiDropDownListBoxCtrl
+GuiDropDownListBoxCtrl::GuiDropDownListBoxCtrl(GuiDropDownCtrl *ctrl)
+{
+	mDropDownCtrl = ctrl;
+	mBounds.point.set(0, 0);
+	caller = ctrl;
+}
+void GuiDropDownListBoxCtrl::addSelection(LBItem *item, S32 index)
+{
+	Parent::addSelection(item, index);
+
+	mDropDownCtrl->closeDropDown();
+}
+#pragma endregion
+
+IMPLEMENT_CONOBJECT(GuiDropDownCtrl);
+
+GuiDropDownCtrl::GuiDropDownCtrl()
+{
+	mMaxHeight = 300;
+	mBounds.extent.set(140, 24);
+	mIsOpen = false;
+	mActive = true;
+	mText = StringTable->insert("none");
+
+	setField("profile", "GuiDropDownProfile");
+
+	mBackground = new GuiDropDownBGCtrl(this);
+	AssertFatal(mBackground, "GuiDropDownCtrl: Failed to initialize GuiDropDownBGCtrl!");
+	mBackgroundProfile = mBackground->mProfile;
+	mBackgroundProfile->incRefCount();
+
+	mListBox = new GuiDropDownListBoxCtrl(this);
+	AssertFatal(mListBox, "GuiDropDownCtrl: Failed to initialize GuiDropDownListBoxCtrl!");
+	mListBox->setField("profile", "GuiListBoxProfile");
+	mListBoxProfile = mListBox->mProfile;
+	mListBoxProfile->incRefCount();
+	mListBox->setField("FitParentWidth", "1");
+	mListBox->setField("AllowMultipleSelections", "0");
+
+	mScroll = new GuiScrollCtrl();
+	AssertFatal(mScroll, "GuiDropDownCtrl: Failed to initialize GuiScrollCtrl!");
+	mScroll->setField("profile", "GuiScrollProfile");
+	mScrollProfile = mScroll->mProfile;
+	mScrollProfile->incRefCount();
+
+	mScroll->setField("thumbProfile", "GuiScrollThumbProfile");
+	mThumbProfile = mScroll->mThumbProfile;
+	mThumbProfile->incRefCount();
+
+	mScroll->setField("arrowProfile", "GuiScrollArrowProfile");
+	mArrowProfile = mScroll->mArrowProfile;
+	mArrowProfile->incRefCount();
+
+	mScroll->setField("trackProfile", "GuiScrollTrackProfile");
+	mTrackProfile = mScroll->mTrackProfile;
+	mTrackProfile->incRefCount();
+
+	mScroll->setField("hScrollBar", "AlwaysOff");
+	mScroll->setField("vScrollBar", "Dynamic");
+	mScroll->setField("constantThumbHeight", "0");
+	mUseConstantHeightThumb = false;
+	mScroll->setField("scrollBarThickness", "12");
+	mScrollBarThickness = 12;
+	mScroll->setField("showArrowButtons", "0");
+	mShowArrowButtons = false;
+	
+	mScroll->addObject(mListBox);
+	mBackground->addObject(mScroll);
+}
+
+void GuiDropDownCtrl::initPersistFields()
+{
+   Parent::initPersistFields();
+   addField("maxHeight", TypeBool, Offset(mMaxHeight, GuiDropDownCtrl));
+   addField("scrollProfile", TypeGuiProfile, Offset(mScrollProfile, GuiDropDownCtrl));
+   addField("thumbProfile", TypeGuiProfile, Offset(mThumbProfile, GuiDropDownCtrl));
+   addField("arrowProfile", TypeGuiProfile, Offset(mArrowProfile, GuiDropDownCtrl));
+   addField("trackProfile", TypeGuiProfile, Offset(mTrackProfile, GuiDropDownCtrl));
+   addField("listBoxProfile", TypeGuiProfile, Offset(mListBoxProfile, GuiDropDownCtrl));
+   addField("backgroundProfile", TypeGuiProfile, Offset(mBackgroundProfile, GuiDropDownCtrl));
+   addField("constantThumbHeight", TypeBool, Offset(mUseConstantHeightThumb, GuiDropDownCtrl));
+   addField("showArrowButtons", TypeBool, Offset(mShowArrowButtons, GuiDropDownCtrl));
+   addField("scrollBarThickness", TypeS32, Offset(mScrollBarThickness, GuiDropDownCtrl));
+}
+
+void GuiDropDownCtrl::onTouchUp(const GuiEvent &event)
+{
+	if (!mActive)
+		return;
+
+	Parent::onTouchUp(event);
+
+	mouseUnlock();
+
+	if (!mIsOpen)
+	{
+		openDropDown();
+	}
+	else
+	{
+		closeDropDown();
+	}
+}
+
+GuiControlState GuiDropDownCtrl::getCurrentState()
+{
+	if (!mActive)
+		return GuiControlState::DisabledState;
+	else if (mDepressed || mIsOpen)
+		return GuiControlState::SelectedState;
+	else if (mMouseOver)
+		return GuiControlState::HighlightState;
+	else
+		return GuiControlState::NormalState;
+}
+
+void GuiDropDownCtrl::onRender(Point2I offset, const RectI& updateRect)
+{
+	GuiControlState currentState = getCurrentState();
+	RectI ctrlRect = applyMargins(offset, mBounds.extent, currentState, mProfile);
+
+	renderUniversalRect(ctrlRect, mProfile, currentState, getFillColor(currentState), true);
+
+	//Get the content area
+	dglSetBitmapModulation(mProfile->getFontColor(currentState));
+	RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, mProfile);
+	RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
+
+	//Render the triangle
+	if(mProfile->usesDefaultRendering(currentState))
+	{
+		RectI drawArea = RectI(contentRect.point.x + contentRect.extent.x - contentRect.extent.y, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
+		renderTriangleIcon(drawArea, ColorI(mProfile->getFontColor(currentState)), false, 8);
+		contentRect.extent.x -= contentRect.extent.y;
+	}
+
+	//Render the text
+	S32 index = mListBox->getSelectedItem();
+	if (index == -1)
+	{
+		renderText(contentRect.point, contentRect.extent, mText, mProfile);
+	}
+	else
+	{
+		if (mListBox->getItemHasColor(index))
+		{
+			//Draw the bullet
+			RectI drawArea = RectI(contentRect.point.x, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
+			renderColorBullet(drawArea, ColorI(mListBox->getItemColor(index)), 5);
+
+			contentRect.point.x += contentRect.extent.y;
+			contentRect.extent.x -= contentRect.extent.y;
+		}
+		renderText(contentRect.point, contentRect.extent, mListBox->getItemText(index), mProfile);
+	}
+}
+
+void GuiDropDownCtrl::openDropDown()
+{
+	if (mIsOpen)
+		return;
+
+	GuiCanvas *root = getRoot();
+	AssertFatal(root, "GuiDropDownCtrl::openDropDown: Unable to optain the Canvas!");
+	mBackground->mBounds.extent = root->mBounds.extent;
+
+	//Update all pass through values
+	mBackground->setControlProfile(mBackgroundProfile);
+	mListBox->setControlProfile(mListBoxProfile);
+	mScroll->setControlProfile(mScrollProfile);
+	mScroll->setControlThumbProfile(mThumbProfile);
+	mScroll->setControlArrowProfile(mArrowProfile);
+	mScroll->setControlTrackProfile(mTrackProfile);
+	mScroll->mUseConstantHeightThumb = mUseConstantHeightThumb;
+	mScroll->mScrollBarThickness = mScrollBarThickness;
+	mScroll->mShowArrowButtons = mShowArrowButtons;
+
+	//Set the size of the scroll control.
+	S32 width = mClamp(mListBox->mBounds.extent.x, mBounds.extent.x, mBounds.extent.x * 2);
+	S32 height = mClamp(mListBox->mBounds.extent.y, 10, mMaxHeight);
+
+	Point2I pos = localToGlobalCoord(Point2I(0,0));
+
+	//Is there enough space below?
+	if ((height + pos.y + mBounds.extent.y) <= root->mBounds.extent.y)
+	{
+		pos.y += mBounds.extent.y;
+	}
+	else if (height <= pos.y) //Is there enough space above?
+	{
+		pos.y -= height;
+	}
+	else if (pos.y < (root->mBounds.extent.y - (pos.y + mBounds.extent.y))) //Is there more space below?
+	{
+		pos.y += mBounds.extent.y;
+		height = root->mBounds.extent.y - pos.y;
+	}
+	else //There must be more space above
+	{
+		height = pos.y;
+		pos.y = 0;
+	}
+
+	mScroll->resize(pos, Point2I(width, height));
+
+	root->pushDialogControl(mBackground, 99);
+
+	mIsOpen = true;
+
+	if (isMethod("onOpen"))
+		Con::executef(this, 1, "onOpen");
+}
+
+void GuiDropDownCtrl::closeDropDown()
+{
+	if(!mIsOpen)
+		return;
+
+	getRoot()->popDialogControl(mBackground);
+
+	mIsOpen = false;
+
+	if (isMethod("onClose"))
+		Con::executef(this, 1, "onClose");
+}
+
+bool GuiDropDownCtrl::onWake()
+{
+	if (!Parent::onWake())
+		return false;
+
+	if (mBackgroundProfile != NULL)
+		mBackgroundProfile->incRefCount();
+
+	if (mListBoxProfile != NULL)
+		mListBoxProfile->incRefCount();
+
+	if (mScrollProfile != NULL)
+		mScrollProfile->incRefCount();
+
+	if (mThumbProfile != NULL)
+		mThumbProfile->incRefCount();
+
+	if (mTrackProfile != NULL)
+		mTrackProfile->incRefCount();
+
+	if (mArrowProfile != NULL)
+		mArrowProfile->incRefCount();
+
+	return true;
+}
+
+void GuiDropDownCtrl::onSleep()
+{
+	Parent::onSleep();
+
+	if (mBackgroundProfile != NULL)
+		mBackgroundProfile->decRefCount();
+
+	if (mListBoxProfile != NULL)
+		mListBoxProfile->decRefCount();
+
+	if (mScrollProfile != NULL)
+		mScrollProfile->decRefCount();
+
+	if (mThumbProfile != NULL)
+		mThumbProfile->decRefCount();
+
+	if (mTrackProfile != NULL)
+		mTrackProfile->decRefCount();
+
+	if (mArrowProfile != NULL)
+		mArrowProfile->decRefCount();
+}
+
+void GuiDropDownCtrl::setControlBackgroundProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiDropDownCtrl::setControlBackgroundProfile: invalid background profile");
+	if (prof == mBackgroundProfile)
+		return;
+	if (mAwake)
+		mBackgroundProfile->decRefCount();
+	mBackgroundProfile = prof;
+	if (mAwake)
+		mBackgroundProfile->incRefCount();
+}
+
+void GuiDropDownCtrl::setControlListBoxProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiDropDownCtrl::setControlListBoxProfile: invalid list box profile");
+	if (prof == mListBoxProfile)
+		return;
+	if (mAwake)
+		mListBoxProfile->decRefCount();
+	mListBoxProfile = prof;
+	if (mAwake)
+		mListBoxProfile->incRefCount();
+}
+
+void GuiDropDownCtrl::setControlScrollProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiDropDownCtrl::setControlScrollProfile: invalid scroll profile");
+	if (prof == mScrollProfile)
+		return;
+	if (mAwake)
+		mScrollProfile->decRefCount();
+	mScrollProfile = prof;
+	if (mAwake)
+		mScrollProfile->incRefCount();
+}
+
+void GuiDropDownCtrl::setControlThumbProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiDropDownCtrl::setControlThumbProfile: invalid thumb profile");
+	if (prof == mThumbProfile)
+		return;
+	if (mAwake)
+		mThumbProfile->decRefCount();
+	mThumbProfile = prof;
+	if (mAwake)
+		mThumbProfile->incRefCount();
+}
+
+void GuiDropDownCtrl::setControlTrackProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiDropDownCtrl::setControlTrackProfile: invalid track profile");
+	if (prof == mTrackProfile)
+		return;
+	if (mAwake)
+		mTrackProfile->decRefCount();
+	mTrackProfile = prof;
+	if (mAwake)
+		mTrackProfile->incRefCount();
+}
+
+void GuiDropDownCtrl::setControlArrowProfile(GuiControlProfile* prof)
+{
+	AssertFatal(prof, "GuiDropDownCtrl::setControlArrowProfile: invalid arrow profile");
+	if (prof == mArrowProfile)
+		return;
+	if (mAwake)
+		mArrowProfile->decRefCount();
+	mArrowProfile = prof;
+	if (mAwake)
+		mArrowProfile->incRefCount();
+}

+ 111 - 0
engine/source/gui/buttons/guiDropDownCtrl.h

@@ -0,0 +1,111 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+#ifndef _GUIDROPDOWNCTRL_H_
+#define _GUIDROPDOWNCTRL_H_
+
+#ifndef _GUICONTROL_H_
+#include "gui/guiControl.h"
+#endif
+#ifndef _GUIBUTTONCTRL_H_
+#include "gui/buttons/guiButtonCtrl.h"
+#endif
+#ifndef _GUISCROLLCTRL_H_
+#include "gui/containers/guiScrollCtrl.h"
+#endif
+#ifndef _GUILISTBOXCTRL_H_
+#include "gui/guiListBoxCtrl.h"
+#endif
+class GuiDropDownCtrl;
+
+class GuiDropDownBGCtrl : public GuiControl
+{
+protected:
+	GuiDropDownCtrl *mDropDownCtrl;
+public:
+	GuiDropDownBGCtrl(GuiDropDownCtrl *ctrl);
+	void onTouchUp(const GuiEvent &event);
+};
+
+class GuiDropDownListBoxCtrl : public GuiListBoxCtrl
+{
+private:
+	typedef GuiListBoxCtrl Parent;
+
+protected:
+	GuiDropDownCtrl *mDropDownCtrl;
+public:
+	GuiDropDownListBoxCtrl(GuiDropDownCtrl *ctrl);
+	void addSelection(LBItem *item, S32 index);
+};
+
+class GuiDropDownCtrl : public GuiButtonCtrl
+{
+private:
+   typedef GuiButtonCtrl Parent;
+
+   S32 mMaxHeight;
+   bool mIsOpen;
+
+   GuiDropDownBGCtrl *mBackground;
+   GuiDropDownListBoxCtrl *mListBox;
+   GuiScrollCtrl *mScroll;
+
+   GuiControlProfile *mBackgroundProfile; //Used to render the background when the drop down is open
+   GuiControlProfile *mListBoxProfile; //Used to render the list box items
+   GuiControlProfile *mScrollProfile; //Used to render the scroll content area
+   GuiControlProfile *mThumbProfile; //Used to render the thumb and arrow buttons
+   GuiControlProfile *mTrackProfile; //Used to render the tracks
+   GuiControlProfile *mArrowProfile; //Used to render the arrow buttons
+
+   S32 mScrollBarThickness;
+   bool mShowArrowButtons;
+   bool mUseConstantHeightThumb;
+
+protected:
+
+public:
+   GuiDropDownCtrl();
+   static void initPersistFields();
+
+   virtual void onTouchUp(const GuiEvent &event);
+   GuiControlState getCurrentState();
+   void onRender(Point2I offset, const RectI &updateRect);
+
+   void openDropDown();
+   void closeDropDown();
+
+   bool onWake();
+   void onSleep();
+   void setControlBackgroundProfile(GuiControlProfile* prof);
+   void setControlListBoxProfile(GuiControlProfile* prof);
+   void setControlScrollProfile(GuiControlProfile* prof);
+   void setControlThumbProfile(GuiControlProfile* prof);
+   void setControlTrackProfile(GuiControlProfile* prof);
+   void setControlArrowProfile(GuiControlProfile* prof);
+
+   inline GuiListBoxCtrl* getList() { return mListBox; }
+
+   DECLARE_CONOBJECT(GuiDropDownCtrl);
+};
+
+#endif

+ 423 - 0
engine/source/gui/buttons/guiDropDownCtrl_ScriptBinding.h

@@ -0,0 +1,423 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+ConsoleMethodGroupBeginWithDocs(GuiDropDownCtrl, GuiControl)
+
+/*! Opens the drop down. Does nothing if the drop down is already open.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, openDropDown, ConsoleVoid, 2, 2, "()")
+{
+	object->openDropDown();
+}
+
+/*! Closes the drop down. Does nothing if the drop down is already closed.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, closeDropDown, ConsoleVoid, 2, 2, "()")
+{
+	object->closeDropDown();
+}
+
+/*! Removes all items from the listbox.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, clearItems, ConsoleVoid, 2, 2, "()")
+{
+	object->getList()->clearItems();
+}
+
+/*! Unselects any items that have been selected.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, clearSelection, ConsoleVoid, 2, 2, "()")
+{
+	object->getList()->clearSelection();
+}
+
+/*! Sets an item to selected or unselected using an index.
+	@param index The zero-based index of the item that should be selected.
+	@param isSelected If true, the item is selected. If false, it is unselected. If omitted, will default to true.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setSelected, ConsoleVoid, 3, 4, "(S32 index, [bool isSelected])")
+{
+	bool value = true;
+	if (argc == 4)
+		value = dAtob(argv[3]);
+
+	if (value == true)
+		object->getList()->addSelection(dAtoi(argv[2]));
+	else
+		object->getList()->removeSelection(dAtoi(argv[2]));
+}
+
+/*! Sets an item's ID using an index.
+	@param index The zero-based index of the item that should have the ID.
+	@param ID An interger value that numerically represents this item.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setItemID, ConsoleVoid, 4, 4, "(int index, int ID)")
+{
+	if (argc != 4)
+	{
+		Con::warnf("GuiDropDownCtrl::setItemID() - Invalid number of parameters! Should be (index, ID).");
+	}
+	else
+	{
+		object->getList()->setItemID(dAtoi(argv[2]), dAtoi(argv[3]));
+	}
+}
+
+/*! Returns an item's ID using an index.
+	@param index The zero-based index of the item with the needed ID.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, getItemID, ConsoleInt, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiDropDownCtrl::getItemID() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		return object->getList()->getItemID(dAtoi(argv[2]));
+	}
+	return 0;
+}
+
+/*! Finds the first item with the given ID.
+	@param ID The item ID to search for.
+	@return The first matching item index or -1 if no item is found.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, findItemID, ConsoleInt, 3, 3, "(int ID)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiDropDownCtrl::findItemID() - Invalid number of parameters! Should be (ID).");
+		return -1;
+	}
+
+	return object->getList()->findItemID(dAtoi(argv[2]));
+}
+
+/*! Sets an item active using an index.
+	@param index The zero-based index of the item that should be active.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setItemActive, ConsoleVoid, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiDropDownCtrl::setItemActive() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		object->getList()->setItemActive(dAtoi(argv[2]));
+	}
+}
+
+/*! Disables an item using an index.
+	@param index The zero-based index of the item that should be inactive.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setItemInactive, ConsoleVoid, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiDropDownCtrl::setItemInactive() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		object->getList()->setItemInactive(dAtoi(argv[2]));
+	}
+}
+
+/*! Returns if an item is active or not using an index.
+	@param index The zero-based index of the item.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, getItemActive, ConsoleBool, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiDropDownCtrl::getItemActive() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		return object->getList()->getItemActive(dAtoi(argv[2]));
+	}
+	return true;
+}
+
+/*! Returns the number of items in the list.
+	@return The number of items.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, getItemCount, ConsoleInt, 2, 2, "()")
+{
+	return object->getList()->getItemCount();
+}
+
+/*! Returns the index of the selected item.
+	@return The index of the selected item or -1 if no item is selected.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, getSelectedItem, ConsoleInt, 2, 2, "()")
+{
+	return object->getList()->getSelectedItem();
+}
+
+/*! Finds all items with the given text.
+	@param itemText The text to search for.
+	@param caseSensitive If true, a case-sensitive search will be performed.
+	@return A space-delimited list of matching item indexes or -1 if no items are found.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, findItemText, ConsoleInt, 3, 4, "(string itemText, bool caseSensitive)")
+{
+	bool bCaseSensitive = false;
+
+	if (argc == 4)
+		bCaseSensitive = dAtob(argv[3]);
+
+	return object->getList()->findItemText(argv[2], bCaseSensitive);
+}
+
+/*! Selects the item at the given index.
+	@param index The zero-based index of the item that should be selected. Passing a -1 clears the selection.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setCurSel, ConsoleVoid, 3, 3, "(S32 index)")
+{
+	object->getList()->setCurSel(dAtoi(argv[2]));
+}
+
+/*! Adds an item to the end of the list with an optional color bullet.
+	@param text The text of the new item.
+	@param color The optional color of a color bullet that will appear to the left of the text. Values range between 0 and 255.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, addItem, ConsoleVoid, 3, 4, "(string text, [color red / green / blue / [alpha]])")
+{
+	if (argc == 3)
+	{
+		object->getList()->addItem(argv[2]);
+	}
+	else if (argc == 4)
+	{
+		const U32 colorCount = Utility::mGetStringElementCount(argv[3]);
+		if (colorCount != 4 && colorCount != 3)
+		{
+			Con::warnf("GuiDropDownCtrl::addItem() - Invalid color! Colors require three or four values (red / green / blue / [alpha])!");
+			object->getList()->addItem(argv[2]);
+			return;
+		}
+
+		F32 red, green, blue, alpha;
+
+		red = dAtof(Utility::mGetStringElement(argv[3], 0));
+		green = dAtof(Utility::mGetStringElement(argv[3], 1));
+		blue = dAtof(Utility::mGetStringElement(argv[3], 2));
+		alpha = colorCount > 3 ? dAtof(Utility::mGetStringElement(argv[3], 3)) : 255;
+
+		object->getList()->addItemWithColor(argv[2], ColorI(red, green, blue, alpha));
+	}
+	else
+	{
+		Con::warnf("GuiDropDownCtrl::addItem() - Invalid number of parameters!");
+	}
+}
+
+/*! Adds an item to the end of the list with an ID.
+	@param text The text of the new item.
+	@param ID The ID to assign to the item.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, addItemWithID, ConsoleVoid, 4, 4, "(string text, int ID")
+{
+	if (argc == 4)
+	{
+		object->getList()->addItemWithID(argv[2], dAtoi(argv[3]));
+	}
+	else
+	{
+		Con::warnf("GuiDropDownCtrl::addItemWithID() - Invalid number of parameters! Should be (text, ID).");
+	}
+}
+
+/*! Sets the color of the color bullet at the given index.
+	@param index The zero-based index of the item that should have a color bullet.
+	@param color The color of a color bullet that will appear to the left of the text. Values range between 0 and 255.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setItemColor, ConsoleVoid, 4, 4, "(S32 index, color red / green / blue / [alpha])")
+{
+	if (argc == 4)
+	{
+		const U32 colorCount = Utility::mGetStringElementCount(argv[3]);
+		if (colorCount != 4 && colorCount != 3)
+		{
+			Con::warnf("GuiDropDownCtrl::setItemColor() - Invalid color! Colors require three or four values (red / green / blue / [alpha])!");
+			return;
+		}
+
+		F32 red, green, blue, alpha;
+
+		red = dAtof(Utility::mGetStringElement(argv[3], 0));
+		green = dAtof(Utility::mGetStringElement(argv[3], 1));
+		blue = dAtof(Utility::mGetStringElement(argv[3], 2));
+		alpha = colorCount > 3 ? dAtof(Utility::mGetStringElement(argv[3], 3)) : 255;
+
+		object->getList()->setItemColor(dAtoi(argv[2]), ColorI(red, green, blue, alpha));
+	}
+	else
+	{
+		Con::warnf("GuiDropDownCtrl::setItemColor() - Invalid number of parameters!");
+	}
+}
+
+/*! Clears the color of the color bullet at the given index.
+	@param index The zero-based index of the item's color bullet.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, clearItemColor, ConsoleVoid, 3, 3, "(S32 index)")
+{
+	object->getList()->clearItemColor(dAtoi(argv[2]));
+}
+
+/*! Clears the color bullets on all items.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, clearAllColors, ConsoleVoid, 2, 2, "()")
+{
+	object->getList()->clearAllColors();
+}
+
+/*! Inserts an item into the list at the specified index.
+	@param index The zero-based index of the new location of the item.
+	@param text The text of the new item.
+	@return Returns the index assigned or -1 on error.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, insertItem, ConsoleVoid, 4, 4, "(S32 index, string text)")
+{
+	object->getList()->insertItem(dAtoi(argv[2]), argv[3]);
+}
+
+/*! Removes the item at the given index.
+	@param index The zero-based index of the item to delete.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, deleteItem, ConsoleVoid, 3, 3, "(S32 index)")
+{
+	object->getList()->deleteItem(dAtoi(argv[2]));
+}
+
+/*! Returns the text of the given item index.
+	@param index The zero-based index of the item to inspect.
+	@return The text of the inspected item.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, getItemText, ConsoleString, 3, 3, "(S32 index)")
+{
+	return object->getList()->getItemText(dAtoi(argv[2]));
+}
+
+/*! Sets the text of the item at the given item index.
+	@param index The zero-based index of the item that will be updated.
+	@param text The text value to update with.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setItemText, ConsoleVoid, 4, 4, "(S32 index, string text)")
+{
+	object->getList()->setItemText(dAtoi(argv[2]), argv[3]);
+}
+
+/*! Sets the currently used BackgroundProfile for the GuiControl
+	@param p The BackgroundProfile applies to the the entire screen when the list opens.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setBackgroundProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlBackgroundProfile(profile);
+}
+
+/*! Sets the currently used ListBoxProfile for the GuiControl
+	@param p The ListBoxProfile is applied to each item in the drop down.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setListBoxProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlListBoxProfile(profile);
+}
+
+/*! Sets the currently used ScrollProfile for the GuiControl
+	@param p The ScrollProfile is applied the to scrollable area.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setScrollProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlScrollProfile(profile);
+}
+
+/*! Sets the currently used ThumbProfile for the GuiControl
+	@param p The ThumbProfile is applied to the thumb of the scrollbar.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setThumbProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlThumbProfile(profile);
+}
+
+/*! Sets the currently used TrackProfile for the GuiControl
+	@param p The TrackProfile is applied to the track area used by the scroll thumb.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setTrackProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlTrackProfile(profile);
+}
+
+/*! Sets the currently used ArrowProfile for the GuiControl
+	@param p The ArrowProfile is applied to the arrow buttons of the scrollbar if you turn them on.
+	@return No return value
+*/
+ConsoleMethodWithDocs(GuiDropDownCtrl, setArrowProfile, ConsoleVoid, 3, 3, (GuiControlProfile p))
+{
+	GuiControlProfile* profile;
+
+	if (Sim::findObject(argv[2], profile))
+		object->setControlArrowProfile(profile);
+}
+
+ConsoleMethodGroupEndWithDocs(GuiDropDownCtrl)

+ 1 - 2
engine/source/gui/buttons/guiRadioCtrl.cc

@@ -45,8 +45,7 @@ void GuiRadioCtrl::renderInnerControl(RectI &boxRect, const GuiControlState curr
 {
 	U8 stateIndex = currentState;
 
-	if ((mProfile->mImageAsset != NULL && mProfile->mImageAsset->isAssetValid() && mProfile->mImageAsset->getFrameCount() > stateIndex) 
-		|| (mProfile->mBitmapName != NULL && mProfile->constructBitmapArray() > stateIndex))
+	if (mProfile->usesAssetRendering(currentState) || mProfile->usesBitmapRendering(currentState))
 	{
 		renderUniversalRect(boxRect, mProfile, currentState);
 	}

+ 2 - 2
engine/source/gui/containers/guiScrollCtrl.h

@@ -38,14 +38,12 @@ protected:
    // arrow length and that horizontal and vertical scroll bars have the
    // same thickness
 
-	S32 mScrollBarThickness;        // determined by the width of the vertical page bmp
 	S32 mScrollBarDragTolerance;    // maximal distance from scrollbar at which a scrollbar drag is still valid
 
 	bool mHBarEnabled;				//True if the children extent is greater than the content area.
 	bool mVBarEnabled;
 	bool mHasHScrollBar;			//The final word on if the bar should be shown. Adjusted internally.
 	bool mHasVScrollBar;
-	bool mShowArrowButtons;			//True if the arrow buttons should appear
 
 	Point2I mChildExt;				//The furthest reaches of the child controls.
 	Point2I mContentExt;			//The content area length and width in pixels.
@@ -103,6 +101,8 @@ public:
 
    bool mUseConstantHeightThumb;
    Point2I mScrollOffset;			//The offset of the children
+   S32 mScrollBarThickness;        // determined by the width of the vertical page bmp
+   bool mShowArrowButtons;			//True if the arrow buttons should appear
 
    Region findHitRegion(const Point2I &);
 

+ 54 - 0
engine/source/gui/guiDefaultControlRender.cc

@@ -353,3 +353,57 @@ void renderStretchedImageAsset(RectI &bounds, U8 frame, GuiControlProfile *profi
 	}
 }
 
+//Renders a color bullet at or one pixel smaller than maxSize.
+//It shrinks the given box until it is less than or equal to the 
+//maxSize in the x direction.
+void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize)
+{
+	if (bounds.extent.x > maxSize)
+	{
+		S32 delta = mCeil((bounds.extent.x - maxSize) / 2);
+		bounds.inset(delta, delta);
+	}
+	if (!bounds.isValidRect())
+	{
+		return;
+	}
+	dglDrawRectFill(bounds, ColorI(0, 0, 0, 100));
+	bounds.inset(1, 1);
+	if (!bounds.isValidRect())
+	{
+		return;
+	}
+	dglDrawRectFill(bounds, color);
+}
+
+void renderTriangleIcon(RectI &bounds, ColorI &color, bool pointsUp, S32 maxSize)
+{
+	if (bounds.extent.x > maxSize)
+	{
+		S32 delta = mCeil((bounds.extent.x - maxSize) / 2);
+		bounds.inset(delta, delta);
+	}
+	if (!bounds.isValidRect())
+	{
+		return;
+	}
+
+	if (pointsUp)
+	{
+		dglDrawTriangleFill(
+			Point2I(bounds.point.x, bounds.point.y + bounds.extent.y),
+			Point2I(bounds.point.x + bounds.extent.x, bounds.point.y + bounds.extent.y),
+			Point2I(bounds.point.x + (bounds.extent.x / 2), bounds.point.y),
+			color
+		);
+	}
+	else
+	{
+		dglDrawTriangleFill(
+			bounds.point,
+			Point2I(bounds.point.x + (bounds.extent.x / 2), bounds.point.y + bounds.extent.y),
+			Point2I(bounds.point.x + bounds.extent.x, bounds.point.y),
+			color
+		);
+	}
+}

+ 2 - 0
engine/source/gui/guiDefaultControlRender.h

@@ -39,5 +39,7 @@ void renderSizableBorderedTexture(RectI &bounds, TextureHandle &texture, RectI &
 void renderFixedBitmapBordersFilled(RectI &bounds, S32 baseMultiplier, GuiControlProfile *profile);
 void renderStretchedBitmap(RectI &bounds, U8 frame, GuiControlProfile *profile);
 void renderStretchedImageAsset(RectI &bounds, U8 frame, GuiControlProfile *profile);
+void renderColorBullet(RectI &bounds, ColorI &color, S32 maxSize);
+void renderTriangleIcon(RectI &bounds, ColorI &color, bool pointsUp, S32 maxSize);
 
 #endif

+ 145 - 72
engine/source/gui/guiListBoxCtrl.cc

@@ -36,6 +36,7 @@ GuiListBoxCtrl::GuiListBoxCtrl()
    mLastClickItem = NULL;
    mIsContainer = false;
    mActive = true;
+   caller = this;
 
    setField("profile", "GuiListBoxProfile");
 }
@@ -117,7 +118,7 @@ void GuiListBoxCtrl::removeSelection( LBItem *item, S32 index )
       {
          mSelectedItems.erase( &mSelectedItems[i] );
          item->isSelected = false;
-         Con::executef(this, 3, "onUnSelect", Con::getIntArg( index ), item->itemText);
+         Con::executef(caller, 3, "onUnSelect", Con::getIntArg( index ), item->itemText, item->ID);
          return;
       }
    }
@@ -163,8 +164,8 @@ void GuiListBoxCtrl::addSelection( LBItem *item, S32 index )
    item->isSelected = true;
    mSelectedItems.push_front( item );
 
-   if(isMethod("onSelect"))
-		Con::executef(this, 3, "onSelect", Con::getIntArg( index ), item->itemText);
+   if(caller->isMethod("onSelect"))
+		Con::executef(caller, 3, "onSelect", Con::getIntArg( index ), item->itemText, item->ID);
 
 }
 
@@ -297,6 +298,13 @@ S32 GuiListBoxCtrl::addItemWithColor( StringTableEntry text, ColorF color, void
    return insertItemWithColor( mItems.size(), text, color, itemData );
 }
 
+S32	GuiListBoxCtrl::addItemWithID(StringTableEntry text, S32 ID, void *itemData)
+{
+	S32 index = insertItem( mItems.size(), text, itemData);
+	setItemID(index, ID);
+	return index;
+}
+
 void GuiListBoxCtrl::setItemColor( S32 index, ColorF color )
 {
    if ((index >= mItems.size()) || index < 0)
@@ -332,45 +340,110 @@ void GuiListBoxCtrl::clearAllColors()
 		(*i)->hasColor = false;
 }
 
-S32 GuiListBoxCtrl::insertItem( S32 index, StringTableEntry text, void *itemData )
+ColorF GuiListBoxCtrl::getItemColor(S32 index)
 {
-   // If the index is greater than our list size, insert it at the end
-   if( index >= mItems.size() )
-      index = mItems.size();
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::getItemColor - invalid index");
+		return ColorF(0,0,0,0);
+	}
 
-   // Sanity checking
-   if( !text )
-   {
-      Con::warnf("GuiListBoxCtrl::insertItem - cannot add NULL string" );
-      return -1;
-   }
+	LBItem* item = mItems[index];
+	return item->color;
+}
 
-   LBItem *newItem = new LBItem;
-   if( !newItem )
-   {
-      Con::warnf("GuiListBoxCtrl::insertItem - error allocating item memory!" );
-      return -1;
-   }
+bool GuiListBoxCtrl::getItemHasColor(S32 index)
+{
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::getItemHasColor - invalid index");
+		return false;
+	}
 
-   // Assign item data
-   newItem->itemText    = StringTable->insert(text);
-   newItem->itemData    = itemData;
-   newItem->isSelected  = false;
-   newItem->hasColor    = false;
+	LBItem* item = mItems[index];
+	return item->hasColor;
+}
 
-   // Add to list
-   mItems.insert(index);
-   mItems[index] = newItem;
+void GuiListBoxCtrl::setItemID(S32 index, S32 ID)
+{
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemID - invalid index");
+		return;
+	}
 
-   // Resize our list to fit our items
-   updateSize();
+	LBItem* item = mItems[index];
+	item->ID = ID;
+}
 
-   // Return our index in list (last)
-   return index;
+S32 GuiListBoxCtrl::getItemID(S32 index)
+{
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemID - invalid index");
+		return 0;
+	}
 
+	LBItem* item = mItems[index];
+	return item->ID;
 }
 
-S32 GuiListBoxCtrl::insertItemWithColor( S32 index, StringTableEntry text, ColorF color, void *itemData )
+S32 GuiListBoxCtrl::findItemID(S32 ID)
+{
+	// Check Items Exist.
+	if (mItems.empty())
+		return -1;
+
+	// Lookup the index of an item in our list, by the pointer to the item
+	for (S32 i = 0; i < mItems.size(); i++)
+	{
+		if (mItems[i]->ID == ID)
+		{
+			return i;
+		}
+	}
+
+	// Not Found!
+	return -1;
+}
+
+void GuiListBoxCtrl::setItemActive(S32 index)
+{
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemActive - invalid index");
+		return;
+	}
+
+	LBItem* item = mItems[index];
+	item->isActive = true;
+}
+
+void GuiListBoxCtrl::setItemInactive(S32 index)
+{
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemInactive - invalid index");
+		return;
+	}
+
+	LBItem* item = mItems[index];
+	item->isActive = false;
+}
+
+bool GuiListBoxCtrl::getItemActive(S32 index)
+{
+	if ((index >= mItems.size()) || index < 0)
+	{
+		Con::warnf("GuiListBoxCtrl::getItemActive - invalid index");
+		return true;
+	}
+
+	LBItem* item = mItems[index];
+	return item->isActive;
+}
+
+S32 GuiListBoxCtrl::insertItem( S32 index, StringTableEntry text, void *itemData )
 {
    // If the index is greater than our list size, insert it at the end
    if( index >= mItems.size() )
@@ -383,12 +456,6 @@ S32 GuiListBoxCtrl::insertItemWithColor( S32 index, StringTableEntry text, Color
       return -1;
    }
 
-   if( color == ColorF(-1, -1, -1) )
-   {
-      Con::warnf("GuiListBoxCtrl::insertItem - cannot add NULL color" );
-      return -1;
-   }
-
    LBItem *newItem = new LBItem;
    if( !newItem )
    {
@@ -397,11 +464,12 @@ S32 GuiListBoxCtrl::insertItemWithColor( S32 index, StringTableEntry text, Color
    }
 
    // Assign item data
-   newItem->itemText    = StringTable->insert(text);
-   newItem->itemData    = itemData;
-   newItem->isSelected  = false;
-   newItem->hasColor    = true;
-   newItem->color       = color;
+   newItem->itemText = StringTable->insert(text);
+   newItem->isSelected = false;
+   newItem->isActive = true;
+   newItem->ID = 0;
+   newItem->itemData = itemData;
+   newItem->hasColor = false;
 
    // Add to list
    mItems.insert(index);
@@ -412,7 +480,25 @@ S32 GuiListBoxCtrl::insertItemWithColor( S32 index, StringTableEntry text, Color
 
    // Return our index in list (last)
    return index;
+}
+
+S32 GuiListBoxCtrl::insertItemWithColor( S32 index, StringTableEntry text, ColorF color, void *itemData )
+{
+	if( color == ColorF(-1, -1, -1) )
+	{
+		Con::warnf("GuiListBoxCtrl::insertItem - cannot add NULL color" );
+			return -1;
+	}
 
+	index = insertItem(index, text, itemData);
+
+	if(index != -1)
+	{
+		setItemColor(index, color);
+	}
+
+	// Return our index in list (last)
+	return index;
 }
 
 void  GuiListBoxCtrl::deleteItem( S32 index )
@@ -564,7 +650,7 @@ void GuiListBoxCtrl::onRenderItem( RectI &itemRect, LBItem *item )
 	   cursorPt = root->getCursorPos();
    }
    GuiControlState currentState = GuiControlState::NormalState;
-   if (!mActive)
+   if (!mActive || !item->isActive)
 	   currentState = GuiControlState::DisabledState;
    else if (item->isSelected)
 	   currentState = GuiControlState::SelectedState;
@@ -584,11 +670,11 @@ void GuiListBoxCtrl::onRenderItem( RectI &itemRect, LBItem *item )
    RectI fillRect = applyBorders(ctrlRect.point, ctrlRect.extent, currentState, mProfile);
    RectI contentRect = applyPadding(fillRect.point, fillRect.extent, currentState, mProfile);
 
-   // Render color box if needed
+   // Render color bullet if needed
    if (item->hasColor)
    {
-	   RectI drawArea = RectI(contentRect.point.x + 1, contentRect.point.y + 1, contentRect.extent.y - 2, contentRect.extent.y - 2);
-	   drawBox(drawArea, ColorI(item->color));
+	   RectI drawArea = RectI(contentRect.point.x, contentRect.point.y, contentRect.extent.y, contentRect.extent.y);
+	   renderColorBullet(drawArea, ColorI(item->color), 5);
 
 	   contentRect.point.x += contentRect.extent.y;
 	   contentRect.extent.x -= contentRect.extent.y;
@@ -596,19 +682,6 @@ void GuiListBoxCtrl::onRenderItem( RectI &itemRect, LBItem *item )
 
    renderText(contentRect.point, contentRect.extent, item->itemText, mProfile);
 }
-
-void GuiListBoxCtrl::drawBox(RectI &box, ColorI &boxColor)
-{
-	const S32 max = 5;
-	if (box.extent.x > max)
-	{
-		S32 delta = mCeil((box.extent.x - max) / 2);
-		box.inset(delta, delta);
-	}
-	dglDrawRectFill(box, ColorI(0,0,0, 100));
-	box.inset(1, 1);
-	dglDrawRectFill(box, boxColor);
-}
 #pragma endregion
 
 #pragma region InputEvents
@@ -628,11 +701,11 @@ void GuiListBoxCtrl::onTouchDragged(const GuiEvent &event)
 	   return;
 
    LBItem *hitItem = mItems[itemHit];
-   if (hitItem == NULL)
+   if (hitItem == NULL || !hitItem->isActive)
 	   return;
 
-   if(isMethod("onTouchDragged"))
-      Con::executef(this, 3, "onTouchDragged", Con::getIntArg(itemHit), hitItem->itemText);
+   if(caller->isMethod("onTouchDragged"))
+      Con::executef(caller, 3, "onTouchDragged", Con::getIntArg(itemHit), hitItem->itemText, hitItem->ID);
 }
 
 void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
@@ -649,7 +722,7 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
       return;
 
    LBItem *hitItem = mItems[ itemHit ];
-   if ( hitItem == NULL )
+   if ( hitItem == NULL || !hitItem->isActive)
       return;
 
    // If we're not a multiple selection listbox, we simply select/unselect an item
@@ -666,12 +739,12 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
 
 		if( itemHit == selItem && event.mouseClickCount == 2)
 		{
-			if(isMethod("onDoubleClick") )
-				Con::executef( this, 3, "onDoubleClick", Con::getIntArg(itemHit), hitItem->itemText);
+			if(caller->isMethod("onDoubleClick") )
+				Con::executef(caller, 3, "onDoubleClick", Con::getIntArg(itemHit), hitItem->itemText, hitItem->ID);
 		}
-		else if (isMethod("onClick"))
+		else if (caller->isMethod("onClick"))
 		{
-			Con::executef(this, 3, "onClick", Con::getIntArg(itemHit), hitItem->itemText);
+			Con::executef(caller, 3, "onClick", Con::getIntArg(itemHit), hitItem->itemText, hitItem->ID);
 		}
 
       // Store the clicked item
@@ -715,12 +788,12 @@ void GuiListBoxCtrl::onTouchDown( const GuiEvent &event )
 
    if( hitItem == mLastClickItem && event.mouseClickCount == 2)
    {
-		if(isMethod("onDoubleClick") )
-			Con::executef( this, 3, "onDoubleClick", Con::getIntArg(itemHit), hitItem->itemText);
+		if(caller->isMethod("onDoubleClick") )
+			Con::executef(caller, 3, "onDoubleClick", Con::getIntArg(itemHit), hitItem->itemText, hitItem->ID);
 	}
-   else if (isMethod("onClick"))
+   else if (caller->isMethod("onClick"))
    {
-	   Con::executef(this, 3, "onClick", Con::getIntArg(itemHit), hitItem->itemText);
+	   Con::executef(caller, 3, "onClick", Con::getIntArg(itemHit), hitItem->itemText, hitItem->ID);
    }
 
    mLastClickItem = hitItem;

+ 16 - 2
engine/source/gui/guiListBoxCtrl.h

@@ -57,6 +57,8 @@ public:
    {
       StringTableEntry  itemText;
       bool              isSelected;
+	  bool				isActive;
+	  int				ID;
       void*             itemData;
       ColorF            color;
       bool              hasColor;
@@ -86,6 +88,7 @@ public:
 
    S32               addItem( StringTableEntry text, void *itemData = NULL );
    S32               addItemWithColor( StringTableEntry text, ColorF color = ColorF(-1, -1, -1), void *itemData = NULL);
+   S32				 addItemWithID(StringTableEntry text, S32 ID = 0, void *itemData = NULL);
    S32               insertItem( S32 index, StringTableEntry text, void *itemData = NULL );
    S32               insertItemWithColor( S32 index, StringTableEntry text, ColorF color = ColorF(-1, -1, -1), void *itemData = NULL);
    S32               findItemText( StringTableEntry text, bool caseSensitive = false );
@@ -93,13 +96,23 @@ public:
    void              setItemColor(S32 index, ColorF color);
    void              clearItemColor(S32 index);
    void				 clearAllColors();
+   ColorF			 getItemColor(S32 index);
+   bool				 getItemHasColor(S32 index);
+
+   void				 setItemID(S32 index, S32 ID);
+   S32				 getItemID(S32 index);
+   S32				 findItemID(S32 ID);
+
+   void				 setItemActive(S32 index);
+   void				 setItemInactive(S32 index);
+   bool				 getItemActive(S32 index);
 
    void              deleteItem( S32 index );
    void              clearItems();
    void              clearSelection();
    void              removeSelection( LBItem *item, S32 index );
    void              removeSelection( S32 index );
-   void              addSelection( LBItem *item, S32 index );
+   virtual void      addSelection( LBItem *item, S32 index );
    void              addSelection( S32 index );
    inline void       setMultipleSelection(bool allowMultipleSelect = true) { mMultipleSelections = allowMultipleSelect; };
    inline bool       getMultipleSelection() { return mMultipleSelections; };
@@ -113,11 +126,12 @@ public:
    // Rendering
    virtual void      onRender( Point2I offset, const RectI &updateRect );
    virtual void      onRenderItem( RectI &itemRect, LBItem *item );
-   void              drawBox( RectI &box, ColorI &boxColor );
 
    // Mouse Events
    virtual void      onTouchDown( const GuiEvent &event );
    virtual void      onTouchDragged(const GuiEvent &event);
+protected:
+	GuiControl		*caller;
 };
 
 #endif

+ 128 - 28
engine/source/gui/guiListBoxCtrl_ScriptBinding.h

@@ -60,7 +60,7 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, clearSelection, ConsoleVoid, 2, 2, "()")
 	@param isSelected If true, the item is selected. If false, it is unselected. If omitted, will default to true.
 	@return No return value.
 */
-ConsoleMethodWithDocs(GuiListBoxCtrl, setSelected, ConsoleVoid, 3, 4, "(S32 index, [bool isSelected])")
+ConsoleMethodWithDocs(GuiListBoxCtrl, setSelected, ConsoleVoid, 3, 4, "(int index, [bool isSelected])")
 {
 	bool value = true;
 	if (argc == 4)
@@ -72,6 +72,104 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, setSelected, ConsoleVoid, 3, 4, "(S32 inde
 		object->removeSelection(dAtoi(argv[2]));
 }
 
+/*! Sets an item's ID using an index.
+	@param index The zero-based index of the item that should have the ID.
+	@param ID An interger value that numerically represents this item.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setItemID, ConsoleVoid, 4, 4, "(int index, int ID)")
+{
+	if(argc != 4)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemID() - Invalid number of parameters! Should be (index, ID).");
+	}
+	else
+	{
+		object->setItemID(dAtoi(argv[2]), dAtoi(argv[3]));
+	}
+}
+
+/*! Returns an item's ID using an index.
+	@param index The zero-based index of the item with the needed ID.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getItemID, ConsoleInt, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiListBoxCtrl::getItemID() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		return object->getItemID(dAtoi(argv[2]));
+	}
+	return 0;
+}
+
+/*! Finds the first item with the given ID.
+	@param ID The item ID to search for.
+	@return The first matching item index or -1 if no item is found.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, findItemID, ConsoleInt, 3, 3, "(int ID)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiListBoxCtrl::findItemID() - Invalid number of parameters! Should be (ID).");
+		return -1;
+	}
+	
+	return object->findItemID(dAtoi(argv[2]));
+}
+
+/*! Sets an item active using an index.
+	@param index The zero-based index of the item that should be active.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setItemActive, ConsoleVoid, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemActive() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		object->setItemActive(dAtoi(argv[2]));
+	}
+}
+
+/*! Disables an item using an index.
+	@param index The zero-based index of the item that should be inactive.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, setItemInactive, ConsoleVoid, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiListBoxCtrl::setItemInactive() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		object->setItemInactive(dAtoi(argv[2]));
+	}
+}
+
+/*! Returns if an item is active or not using an index.
+	@param index The zero-based index of the item.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, getItemActive, ConsoleBool, 3, 3, "(int index)")
+{
+	if (argc != 3)
+	{
+		Con::warnf("GuiListBoxCtrl::getItemActive() - Invalid number of parameters! Should be (index).");
+	}
+	else
+	{
+		return object->getItemActive(dAtoi(argv[2]));
+	}
+	return true;
+}
+
 /*! Returns the number of items in the list.
 	@return The number of items.
 */
@@ -89,7 +187,7 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, getSelCount, ConsoleInt, 2, 2, "()")
 }
 
 /*! Returns the index of the first selected item.
-	@return The index of the first selected item or -1 if the item does not belong to the listbox.
+	@return The index of the first selected item or -1 if no item is selected.
 */
 ConsoleMethodWithDocs(GuiListBoxCtrl, getSelectedItem, ConsoleInt, 2, 2, "()")
 {
@@ -163,9 +261,9 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, setCurSelRange, ConsoleVoid, 3, 4, "(S32 s
 		object->setCurSelRange(dAtoi(argv[2]), 999999);
 }
 
-/*! Adds an item to the end of the list with an optional color box.
+/*! Adds an item to the end of the list with an optional color bullet.
 	@param text The text of the new item.
-	@param color The optional color of a color box that will appear to the left of the text. Values range between 0 and 255.
+	@param color The optional color of a color bullet that will appear to the left of the text. Values range between 0 and 255.
 	@return No return value.
 */
 ConsoleMethodWithDocs(GuiListBoxCtrl, addItem, ConsoleVoid, 3, 4, "(string text, [color red / green / blue / [alpha]])")
@@ -180,6 +278,7 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, addItem, ConsoleVoid, 3, 4, "(string text,
 		if (colorCount != 4 && colorCount != 3)
 		{
 			Con::warnf("GuiListBoxCtrl::addItem() - Invalid color! Colors require three or four values (red / green / blue / [alpha])!");
+			object->addItem(argv[2]);
 			return;
 		}
 
@@ -188,15 +287,7 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, addItem, ConsoleVoid, 3, 4, "(string text,
 		red = dAtof(Utility::mGetStringElement(argv[3], 0));
 		green = dAtof(Utility::mGetStringElement(argv[3], 1));
 		blue = dAtof(Utility::mGetStringElement(argv[3], 2));
-
-		if (colorCount == 3)
-		{
-			alpha = 255;
-		}
-		else 
-		{
-			alpha = dAtof(Utility::mGetStringElement(argv[3], 3));
-		}
+		alpha = colorCount > 3 ? dAtof(Utility::mGetStringElement(argv[3], 3))  : 255;
 
 		object->addItemWithColor(argv[2], ColorI(red, green, blue, alpha));
 	}
@@ -206,9 +297,26 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, addItem, ConsoleVoid, 3, 4, "(string text,
 	}
 }
 
-/*! Sets the color of the color box at the given index.
-	@param index The zero-based index of the item that should have a color box.
-	@param color The color of a color box that will appear to the left of the text. Values range between 0 and 255.
+/*! Adds an item to the end of the list with an ID.
+	@param text The text of the new item.
+	@param ID The ID to assign to the item.
+	@return No return value.
+*/
+ConsoleMethodWithDocs(GuiListBoxCtrl, addItemWithID, ConsoleVoid, 4, 4, "(string text, int ID")
+{
+	if (argc == 4)
+	{
+		object->addItemWithID(argv[2], dAtoi(argv[3]));
+	}
+	else
+	{
+		Con::warnf("GuiListBoxCtrl::addItemWithID() - Invalid number of parameters! Should be (text, ID).");
+	}
+}
+
+/*! Sets the color of the color bullet at the given index.
+	@param index The zero-based index of the item that should have a color bullet.
+	@param color The color of a color bullet that will appear to the left of the text. Values range between 0 and 255.
 	@return No return value.
 */
 ConsoleMethodWithDocs(GuiListBoxCtrl, setItemColor, ConsoleVoid, 4, 4, "(S32 index, color red / green / blue / [alpha])")
@@ -227,15 +335,7 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, setItemColor, ConsoleVoid, 4, 4, "(S32 ind
 		red = dAtof(Utility::mGetStringElement(argv[3], 0));
 		green = dAtof(Utility::mGetStringElement(argv[3], 1));
 		blue = dAtof(Utility::mGetStringElement(argv[3], 2));
-
-		if (colorCount == 3)
-		{
-			alpha = 255;
-		}
-		else
-		{
-			alpha = dAtof(Utility::mGetStringElement(argv[3], 3));
-		}
+		alpha = colorCount > 3 ? dAtof(Utility::mGetStringElement(argv[3], 3)) : 255;
 
 		object->setItemColor(dAtoi(argv[2]), ColorI(red, green, blue, alpha));
 	}
@@ -245,8 +345,8 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, setItemColor, ConsoleVoid, 4, 4, "(S32 ind
 	}
 }
 
-/*! Clears the color of the color box at the given index.
-	@param index The zero-based index of the item's color box.
+/*! Clears the color of the color bullet at the given index.
+	@param index The zero-based index of the item's color bullet.
 	@return No return value.
 */
 ConsoleMethodWithDocs(GuiListBoxCtrl, clearItemColor, ConsoleVoid, 3, 3, "(S32 index)")
@@ -254,7 +354,7 @@ ConsoleMethodWithDocs(GuiListBoxCtrl, clearItemColor, ConsoleVoid, 3, 3, "(S32 i
 	object->clearItemColor(dAtoi(argv[2]));
 }
 
-/*! Clears the color boxes on all items.
+/*! Clears the color bullets on all items.
 	@return No return value.
 */
 ConsoleMethodWithDocs(GuiListBoxCtrl, clearAllColors, ConsoleVoid, 2, 2, "()")

+ 15 - 0
engine/source/gui/guiTypes.cc

@@ -844,6 +844,21 @@ const ColorI& GuiControlProfile::getFontColor(const GuiControlState state)
 	}
 }
 
+bool GuiControlProfile::usesAssetRendering(const GuiControlState state)
+{
+	return mImageAsset != NULL && mImageAsset->isAssetValid() && mImageAsset->getFrameCount() > state;
+}
+
+bool GuiControlProfile::usesBitmapRendering(const GuiControlState state)
+{
+	return !usesAssetRendering(state) && mBitmapName != NULL && constructBitmapArray() > state;
+}
+
+bool GuiControlProfile::usesDefaultRendering(const GuiControlState state)
+{
+	return !usesAssetRendering(state) && !usesBitmapRendering(state);
+}
+
 ConsoleType( GuiProfile, TypeGuiProfile, sizeof(GuiControlProfile*), "" )
 
 ConsoleSetType( TypeGuiProfile )

+ 3 - 0
engine/source/gui/guiTypes.h

@@ -293,6 +293,9 @@ public:
 
    const ColorI& getFillColor(const GuiControlState state); //Returns the fill color based on the state.
    const ColorI& getFontColor(const GuiControlState state); //Returns the font color based on the state.
+   bool usesAssetRendering(const GuiControlState state);
+   bool usesBitmapRendering(const GuiControlState state);
+   bool usesDefaultRendering(const GuiControlState state);
 
    GuiBorderProfile* getLeftBorder() { return mBorderLeft; }
    GuiBorderProfile* getRightBorder() { return mBorderRight; }

+ 6 - 15
toybox/Sandbox/1/gui/ToolboxDialog.gui.taml

@@ -57,11 +57,11 @@
 			text="Background Color:"
 			maxLength="255"
 			truncate="0" />
-		<GuiPopUpMenuCtrl
+		<GuiDropDownCtrl
 			Name="BackgroundColorSelectList"
 			canSaveDynamicFields="0"
 			isContainer="0"
-			Profile="GuiPopUpMenuProfile"
+			Profile="GuiDropDownProfile"
 			HorizSizing="relative"
 			VertSizing="relative"
 			Position="0 22"
@@ -74,11 +74,7 @@
 			toolTipProfile="GuiToolTipProfile"
 			toolTip="Selects the background color for the scene."
 			tooltipWidth="250"
-			maxLength="1024"
-			maxPopupHeight="200"
-			sbUsesNAColor="0"
-			reverseTextList="0"
-			bitmapBounds="16 16" />
+			scrollBarThickness="12" />
 
 		<!-- Resolution -->
 		<GuiControl
@@ -100,11 +96,11 @@
 			text="Resolution:"
 			maxLength="255"
 			truncate="0" />
-		<GuiPopUpMenuCtrl
+		<GuiDropDownCtrl
 			Name="ResolutionSelectList"
 			canSaveDynamicFields="0"
 			isContainer="0"
-			Profile="GuiPopUpMenuProfile"
+			Profile="GuiDropDownProfile"
 			HorizSizing="relative"
 			VertSizing="relative"
 			Position="0 78"
@@ -116,12 +112,7 @@
 			hovertime="1000"
 			toolTipProfile="GuiToolTipProfile"
 			toolTip="Selects the screen resolution for the window."
-			tooltipWidth="250"
-			maxLength="1024"
-			maxPopupHeight="200"
-			sbUsesNAColor="0"
-			reverseTextList="0"
-			bitmapBounds="16 16" />
+			tooltipWidth="250" />
 
 		<!-- Fullscreen Option -->
 		<GuiCheckBoxCtrl

+ 36 - 0
toybox/Sandbox/1/gui/guiProfiles.cs

@@ -776,3 +776,39 @@ if(!isObject(GuiProgressProfile)) new GuiControlProfile (GuiProgressProfile : Gu
    borderBottom = GuiProgressDarkBorderProfile;
    borderRight = GuiProgressDarkBorderProfile;
 };
+
+if (!isObject(GuiDropDownDarkBorderProfile)) new GuiBorderProfile (GuiDropDownDarkBorderProfile : GuiDarkBorderProfile)
+{
+	padding = 4;
+	paddingHL = 4;
+	paddingSL = 4;
+	paddingNA = 4;
+};
+
+if (!isObject(GuiDropDownBrightBorderProfile)) new GuiBorderProfile (GuiDropDownBrightBorderProfile : GuiBrightBorderProfile)
+{
+	padding = 4;
+	paddingHL = 4;
+	paddingSL = 4;
+	paddingNA = 4;
+};
+
+if(!isObject(GuiDropDownProfile)) new GuiControlProfile (GuiDropDownProfile : GuiDefaultProfile)
+{
+    // fill color
+    fillColor = AdjustColorValue($color3, -15);
+	fillColorHL = AdjustColorValue($color3, -8);
+	fillColorSL = $color4;
+	fillColorNA = SetColorAlpha($color3, 100);
+
+    fontColor = $color1;
+	fontColorHL = $color1;
+	fontColorSL = $color3;
+	fontColorNA = SetColorAlpha($color1, 100);
+	align = "left";
+
+	borderDefault = GuiDropDownBrightBorderProfile;
+	borderRight = GuiDropDownDarkBorderProfile;
+	borderBottom = GuiDropDownDarkBorderProfile;
+	category = "dropDown";
+};

+ 6 - 6
toybox/Sandbox/1/scripts/toolbox.cs

@@ -119,13 +119,13 @@ function initializeToolbox()
         %colorName = getStockColorName(%i);
 
         // Add to the list.
-        BackgroundColorSelectList.add( getStockColorName(%i), %i );
+		%colorName = getStockColorName(%i);
+        BackgroundColorSelectList.addItem( %colorName, getStockColorI(%colorName) );
 
         // Select the color if it's the default one.
         if ( %colorName $= $pref::Sandbox::defaultBackgroundColor )
             BackgroundColorSelectList.setSelected( %i );
     }
-    BackgroundColorSelectList.sort();
 
     ToyCategorySelectList.initialize();
 
@@ -165,7 +165,7 @@ function initializeToolbox()
             $sandboxResolutions[%outputIndex] = %width SPC %height SPC %bpp;
 
             // Add to the list.
-            ResolutionSelectList.add( %width @ "x" @ %height SPC "(" @ %bpp @ ")", %outputIndex );
+            ResolutionSelectList.addItem( %width @ "x" @ %height SPC "(" @ %bpp @ ")" );
 
             // Select the resolution if it's the default one.
             if ( %width == %activeWidth && %height == %activeHeight && %bpp == %activeBpp )
@@ -192,7 +192,7 @@ function toggleToolbox(%make)
 
     // Finish if the console is awake.
     //if ( ConsoleDialog.isAwake() )
-    //    return;       
+    //    return;
 
     // Is the toolbox awake?
     if ( ToolboxDialog.isAwake() )
@@ -218,7 +218,7 @@ function toggleToolbox(%make)
 function BackgroundColorSelectList::onSelect(%this)
 {
     // Fetch the index.
-    $activeBackgroundColor = %this.getSelected();
+    $activeBackgroundColor = %this.getSelectedItem();
 
     // Finish if the sandbox scene is not available.
     if ( !isObject(SandboxScene) )
@@ -238,7 +238,7 @@ function ResolutionSelectList::onSelect(%this)
         return;
 
     // Fetch the index.
-    %index = %this.getSelected();
+    %index = %this.getSelectedItem();
 
     // Fetch resolution.
     %resolution = $sandboxResolutions[%index];