瀏覽代碼

Git didn't properly actually commit new files.

JeffR 3 年之前
父節點
當前提交
938e4930ae
共有 72 個文件被更改,包括 2054 次插入0 次删除
  1. 1121 0
      Engine/source/gui/controls/guiGameSettingsCtrl.cpp
  2. 313 0
      Engine/source/gui/controls/guiGameSettingsCtrl.h
  3. 4 0
      Templates/BaseGame/game/data/UI/guis/NetGraphGui.asset.taml
  4. 二進制
      Templates/BaseGame/game/data/UI/images/Torque_3D_logo.png
  5. 二進制
      Templates/BaseGame/game/data/UI/images/Torque_3D_logo_alt.png
  6. 二進制
      Templates/BaseGame/game/data/UI/images/Torque_3D_logo_shortcut.png
  7. 二進制
      Templates/BaseGame/game/data/UI/images/Torque_3D_logo_w.png
  8. 二進制
      Templates/BaseGame/game/data/UI/images/backgrounddark.png
  9. 3 0
      Templates/BaseGame/game/data/UI/images/backgrounddark_image.asset.taml
  10. 二進制
      Templates/BaseGame/game/data/UI/images/clearbtn_d.png
  11. 3 0
      Templates/BaseGame/game/data/UI/images/clearbtn_d_image.asset.taml
  12. 二進制
      Templates/BaseGame/game/data/UI/images/clearbtn_h.png
  13. 3 0
      Templates/BaseGame/game/data/UI/images/clearbtn_h_image.asset.taml
  14. 二進制
      Templates/BaseGame/game/data/UI/images/clearbtn_n.png
  15. 3 0
      Templates/BaseGame/game/data/UI/images/clearbtn_n_image.asset.taml
  16. 二進制
      Templates/BaseGame/game/data/UI/images/collapsetoolbar_d.png
  17. 3 0
      Templates/BaseGame/game/data/UI/images/collapsetoolbar_d_image.asset.taml
  18. 二進制
      Templates/BaseGame/game/data/UI/images/collapsetoolbar_h.png
  19. 3 0
      Templates/BaseGame/game/data/UI/images/collapsetoolbar_h_image.asset.taml
  20. 二進制
      Templates/BaseGame/game/data/UI/images/collapsetoolbar_n.png
  21. 3 0
      Templates/BaseGame/game/data/UI/images/collapsetoolbar_n_image.asset.taml
  22. 二進制
      Templates/BaseGame/game/data/UI/images/dropdownbuttonarrow.png
  23. 3 0
      Templates/BaseGame/game/data/UI/images/dropdownbuttonarrow_image.asset.taml
  24. 二進制
      Templates/BaseGame/game/data/UI/images/dropdowntextEdit.png
  25. 3 0
      Templates/BaseGame/game/data/UI/images/dropdowntextEdit_image.asset.taml
  26. 二進制
      Templates/BaseGame/game/data/UI/images/expandtoolbar_d.png
  27. 3 0
      Templates/BaseGame/game/data/UI/images/expandtoolbar_d_image.asset.taml
  28. 二進制
      Templates/BaseGame/game/data/UI/images/expandtoolbar_h.png
  29. 3 0
      Templates/BaseGame/game/data/UI/images/expandtoolbar_h_image.asset.taml
  30. 二進制
      Templates/BaseGame/game/data/UI/images/expandtoolbar_n.png
  31. 3 0
      Templates/BaseGame/game/data/UI/images/expandtoolbar_n_image.asset.taml
  32. 二進制
      Templates/BaseGame/game/data/UI/images/groupborder.png
  33. 3 0
      Templates/BaseGame/game/data/UI/images/groupborder_image.asset.taml
  34. 二進制
      Templates/BaseGame/game/data/UI/images/inactiveoverlay.png
  35. 3 0
      Templates/BaseGame/game/data/UI/images/inactiveoverlay_image.asset.taml
  36. 二進制
      Templates/BaseGame/game/data/UI/images/menubutton.png
  37. 3 0
      Templates/BaseGame/game/data/UI/images/menubutton_image.asset.taml
  38. 二進制
      Templates/BaseGame/game/data/UI/images/nextOption_n.png
  39. 8 0
      Templates/BaseGame/game/data/UI/images/nextOption_n_image.asset.taml
  40. 二進制
      Templates/BaseGame/game/data/UI/images/nextbutton_d.png
  41. 3 0
      Templates/BaseGame/game/data/UI/images/nextbutton_d_image.asset.taml
  42. 二進制
      Templates/BaseGame/game/data/UI/images/nextbutton_h.png
  43. 3 0
      Templates/BaseGame/game/data/UI/images/nextbutton_h_image.asset.taml
  44. 二進制
      Templates/BaseGame/game/data/UI/images/nextbutton_n.png
  45. 3 0
      Templates/BaseGame/game/data/UI/images/nextbutton_n_image.asset.taml
  46. 二進制
      Templates/BaseGame/game/data/UI/images/nopreview.png
  47. 3 0
      Templates/BaseGame/game/data/UI/images/nopreview_image.asset.taml
  48. 二進制
      Templates/BaseGame/game/data/UI/images/previousOption_n.png
  49. 8 0
      Templates/BaseGame/game/data/UI/images/previousOption_n_image.asset.taml
  50. 二進制
      Templates/BaseGame/game/data/UI/images/previousbutton_d.png
  51. 3 0
      Templates/BaseGame/game/data/UI/images/previousbutton_d_image.asset.taml
  52. 二進制
      Templates/BaseGame/game/data/UI/images/previousbutton_h.png
  53. 3 0
      Templates/BaseGame/game/data/UI/images/previousbutton_h_image.asset.taml
  54. 二進制
      Templates/BaseGame/game/data/UI/images/previousbutton_n.png
  55. 3 0
      Templates/BaseGame/game/data/UI/images/previousbutton_n_image.asset.taml
  56. 二進制
      Templates/BaseGame/game/data/UI/images/selectorbutton.png
  57. 3 0
      Templates/BaseGame/game/data/UI/images/selectorbutton_image.asset.taml
  58. 二進制
      Templates/BaseGame/game/data/UI/images/selectorbuttonblank.png
  59. 3 0
      Templates/BaseGame/game/data/UI/images/selectorbuttonblank_image.asset.taml
  60. 二進制
      Templates/BaseGame/game/data/UI/images/selectorbuttondark.png
  61. 3 0
      Templates/BaseGame/game/data/UI/images/selectorbuttondark_image.asset.taml
  62. 二進制
      Templates/BaseGame/game/data/UI/images/selectorbuttonhighlightonly.png
  63. 3 0
      Templates/BaseGame/game/data/UI/images/selectorbuttonhighlightonly_image.asset.taml
  64. 二進制
      Templates/BaseGame/game/data/UI/images/separatorh.png
  65. 3 0
      Templates/BaseGame/game/data/UI/images/separatorh_image.asset.taml
  66. 二進制
      Templates/BaseGame/game/data/UI/images/separatorv.png
  67. 3 0
      Templates/BaseGame/game/data/UI/images/separatorv_image.asset.taml
  68. 二進制
      Templates/BaseGame/game/data/UI/images/sliderwbox.png
  69. 3 0
      Templates/BaseGame/game/data/UI/images/sliderwbox_image.asset.taml
  70. 二進制
      Templates/BaseGame/game/data/UI/images/tabborder.png
  71. 3 0
      Templates/BaseGame/game/data/UI/images/tabborder_image.asset.taml
  72. 510 0
      Templates/BaseGame/game/data/UI/scripts/menuInputHandling.tscript

+ 1121 - 0
Engine/source/gui/controls/guiGameSettingsCtrl.cpp

@@ -0,0 +1,1121 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 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 "guiGameSettingsCtrl.h"
+
+#include "console/consoleTypes.h"
+#include "console/engineAPI.h"
+#include "gfx/gfxDrawUtil.h"
+#include "gui/containers/guiScrollCtrl.h"
+#include "core/strings/stringUnit.h"
+#include "gui/core/guiDefaultControlRender.h"
+
+//-----------------------------------------------------------------------------
+// GuiGameSettingsCtrl
+//-----------------------------------------------------------------------------
+
+GuiGameSettingsCtrl::GuiGameSettingsCtrl() :
+   mLabel(StringTable->EmptyString()),
+   mScriptCallback(StringTable->EmptyString()),
+   mTooltip(StringTable->EmptyString()),
+   mEnabled(true),
+   mSelected(false),
+   mSelectedOption(0),
+   mWrapOptions(false),
+   mMode(Mode::Default),
+   mValue(0),
+   mStepSize(1),
+   mRange(Point2F(0, 1)),
+   mCallbackOnInputs(false),
+   mConsumeKeyInputEvents(false),
+   mArrowSize(30),
+   mColumnSplit(250),
+   mRightPad(20)
+{
+   VECTOR_SET_ASSOCIATION(mOptions);
+
+   // initialize the control callbacks
+   mCallbackOnA = StringTable->EmptyString();
+   mCallbackOnB = mCallbackOnA;
+   mCallbackOnX = mCallbackOnA;
+   mCallbackOnY = mCallbackOnA;
+
+   INIT_ASSET(KeybindBitmap);
+   INIT_ASSET(PreviousBitmap);
+   INIT_ASSET(NextBitmap);
+}
+
+GuiGameSettingsCtrl::~GuiGameSettingsCtrl()
+{
+   mOptions.clear();
+}
+
+void GuiGameSettingsCtrl::onMouseMove(const GuiEvent& event)
+{
+   //check if we're inside an arrow/slider/etc and kick a highlight action
+   Parent::onMouseMove(event);
+}
+
+void GuiGameSettingsCtrl::onMouseUp(const GuiEvent& event)
+{
+   Parent::onMouseUp(event);
+
+   if (isEnabled())
+   {
+      if (mMode == Mode::Default)
+      {
+         activate();
+      }
+      else if (mMode == Mode::OptionList)
+      {
+         S32 xPos = globalToLocalCoord(event.mousePoint).x;
+         clickOption(xPos);
+      }
+      else if (mMode == Mode::Slider)
+      {
+         S32 xPos = globalToLocalCoord(event.mousePoint).x;
+         clickSlider(xPos);
+      }
+      else if (mMode == Mode::Keybind)
+      {
+         S32 xPos = globalToLocalCoord(event.mousePoint).x;
+         clickKeybind(xPos);
+      }
+   }
+}
+
+void GuiGameSettingsCtrl::onRender(Point2I offset, const RectI &updateRect)
+{
+   GFXDrawUtil* drawUtil = GFX->getDrawUtil();
+
+   F32 xScale = (float) getWidth();
+
+   S32 height = getHeight();
+
+   Point2I currentOffset = offset;
+   Point2I extent = getExtent();
+   Point2I textOffset(mProfile->mTextOffset.x * xScale, mProfile->mTextOffset.y);
+   Point2I textExtent(mColumnSplit, height);
+   Point2I iconExtent, iconOffset(0.0f, 0.0f);
+
+   bool highlight = mHighlighted;
+   bool depressed = mDepressed;
+
+   ColorI fontColor = mActive ? (highlight ? mProfile->mFontColorHL : mProfile->mFontColor) : mProfile->mFontColorNA;
+   ColorI fillColor = mActive ? (highlight ? mProfile->mFillColorHL : mProfile->mFillColor) : mProfile->mFillColorNA;
+   ColorI borderColor = mActive ? (highlight ? mProfile->mBorderColorHL : mProfile->mBorderColor) : mProfile->mBorderColorNA;
+
+   RectI boundsRect(offset, getExtent());
+
+   if (!mHasTheme)
+   {
+      if (mProfile->mBorder != 0)
+         renderFilledBorder(boundsRect, borderColor, fillColor, mProfile->mBorderThickness);
+      else
+         GFX->getDrawUtil()->drawRectFill(boundsRect, fillColor);
+   }
+   else
+   {
+      S32 indexMultiplier = 1;
+
+      if (!mActive)
+         indexMultiplier = 4;
+      else if (mDepressed || mStateOn)
+         indexMultiplier = 2;
+      else if (mHighlighted)
+         indexMultiplier = 3;
+
+      renderSizableBitmapBordersFilled(boundsRect, indexMultiplier, mProfile);
+   }
+
+   // render the text
+   drawUtil->setBitmapModulation(fontColor);
+   renderJustifiedText(currentOffset + textOffset, textExtent, mLabel);
+
+   if (mMode == Mode::OptionList)
+   {
+      onRenderListOption(currentOffset);
+   }
+   else if (mMode == Mode::Slider)
+   {
+      onRenderSliderOption(currentOffset);
+   }
+   else if (mMode == Mode::Keybind)
+   {
+      onRenderKeybindOption(currentOffset);
+   }
+
+   renderChildControls(offset, updateRect);
+}
+
+void GuiGameSettingsCtrl::onRenderListOption(Point2I currentOffset)
+{
+   F32 xScale = (float)getWidth();
+
+   S32 height = getHeight();
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   Point2I arrowOffset;
+
+   S32 arrowOffsetY = 0;
+
+   bool hasOptions = (mOptions.size() > 0) && mSelectedOption > -1;
+   if (hasOptions)
+   {
+      if (mPreviousBitmapAsset.notNull())
+      {
+         // render the left arrow
+         bool arrowOnL = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption > 0));
+         arrowOffset.x = currentOffset.x + mColumnSplit;
+         arrowOffset.y = currentOffset.y + arrowOffsetY;
+
+         drawer->clearBitmapModulation();
+         drawer->drawBitmapStretch(mPreviousBitmap, RectI(arrowOffset, Point2I(mArrowSize, mArrowSize)), GFXBitmapFlip_None, GFXTextureFilterLinear, false);
+      }
+      else
+      {
+         // render the left arrow
+         bool arrowOnL = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption > 0));
+         arrowOffset.x = currentOffset.x + mColumnSplit;
+         arrowOffset.y = currentOffset.y + height/2;
+
+         drawer->clearBitmapModulation();
+
+         drawer->drawLine(arrowOffset, Point2I(arrowOffset.x + mArrowSize, currentOffset.y), ColorI::WHITE);
+         drawer->drawLine(arrowOffset, Point2I(arrowOffset.x + mArrowSize, currentOffset.y + height), ColorI::WHITE);
+      }
+
+      if (mNextBitmapAsset.notNull())
+      {
+         // render the right arrow
+         bool arrowOnR = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption < mOptions.size() - 1));
+         arrowOffset.x = currentOffset.x + getWidth() - mRightPad - mArrowSize;
+         arrowOffset.y = currentOffset.y + arrowOffsetY;
+
+         drawer->clearBitmapModulation();
+         drawer->drawBitmapStretch(mNextBitmap, RectI(arrowOffset, Point2I(mArrowSize, mArrowSize)), GFXBitmapFlip_None, GFXTextureFilterLinear, false);
+      }
+      else
+      {
+         // render the left arrow
+         bool arrowOnL = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption > 0));
+         arrowOffset.x = currentOffset.x + getWidth() - mRightPad;
+         arrowOffset.y = currentOffset.y + height / 2;
+
+         drawer->clearBitmapModulation();
+
+         drawer->drawLine(arrowOffset, Point2I(arrowOffset.x - mArrowSize, currentOffset.y), ColorI::WHITE);
+         drawer->drawLine(arrowOffset, Point2I(arrowOffset.x - mArrowSize, currentOffset.y + height), ColorI::WHITE);
+      }
+
+      // get the appropriate font color
+      ColorI fontColor;
+      if (!mEnabled)
+      {
+         fontColor = mProfile->mFontColorNA;
+      }
+      else if (isSelected())
+      {
+         fontColor = mProfile->mFontColorSEL;
+      }
+      else if (isHighlighted())
+      {
+         fontColor = mProfile->mFontColorHL;
+      }
+      else
+      {
+         fontColor = mProfile->mFontColor;
+      }
+
+      // calculate text to be at the center between the arrows
+      GFont* font = mProfile->mFont;
+      StringTableEntry text = mOptions[mSelectedOption].mDisplayText;
+      S32 textWidth = font->getStrWidth(text);
+      S32 columnWidth = xScale - mRightPad - mColumnSplit;
+      S32 columnCenter = mColumnSplit + (columnWidth >> 1);
+      S32 textStartX = columnCenter - (textWidth >> 1);
+      Point2I textOffset(textStartX, 0);
+
+      // render the option text itself
+      Point2I textExtent(columnWidth, height);
+      drawer->setBitmapModulation(fontColor);
+      renderJustifiedText(currentOffset + Point2I(mColumnSplit, 0), textExtent, text);
+   }
+}
+
+void GuiGameSettingsCtrl::onRenderSliderOption(Point2I currentOffset)
+{
+   F32 xScale = (float)getWidth();
+
+   S32 height = getHeight();
+
+   S32 arrowOffsetY = 0;
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   Point2I arrowOffset;
+   S32 columnSplit = mColumnSplit;
+
+   
+
+   /*if (mPreviousBitmapAsset.notNull())
+   {
+      // render the left arrow
+      bool arrowOnL = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption > 0));
+      arrowOffset.x = currentOffset.x + columnSplit;
+      arrowOffset.y = currentOffset.y + arrowOffsetY;
+
+      drawer->clearBitmapModulation();
+      drawer->drawBitmapStretch(mPreviousBitmap, RectI(arrowOffset, Point2I(mArrowSize, mArrowSize)), GFXBitmapFlip_None, GFXTextureFilterLinear, false);
+   }
+   else
+   {
+      // render the left arrow
+      bool arrowOnL = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption > 0));
+      arrowOffset.x = currentOffset.x + mColumnSplit;
+      arrowOffset.y = currentOffset.y + height / 2;
+
+      drawer->clearBitmapModulation();
+
+      drawer->drawLine(arrowOffset, Point2I(arrowOffset.x + mArrowSize, currentOffset.y), ColorI::WHITE);
+      drawer->drawLine(arrowOffset, Point2I(arrowOffset.x + mArrowSize, currentOffset.y + height), ColorI::WHITE);
+   }
+
+   if (mNextBitmapAsset.notNull())
+   {
+      // render the right arrow
+      bool arrowOnR = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption < mOptions.size() - 1));
+      arrowOffset.x = currentOffset.x + mRightPad * xScale - mArrowSize;
+      arrowOffset.y = currentOffset.y + arrowOffsetY;
+
+      drawer->clearBitmapModulation();
+      drawer->drawBitmapStretch(mNextBitmap, RectI(arrowOffset, Point2I(mArrowSize, mArrowSize)), GFXBitmapFlip_None, GFXTextureFilterLinear, false);
+   }
+   else
+   {
+      // render the left arrow
+      bool arrowOnL = (isSelected() || isHighlighted()) && (mWrapOptions || (mSelectedOption > 0));
+      arrowOffset.x = currentOffset.x + getWidth() - mRightPad;
+      arrowOffset.y = currentOffset.y + height / 2;
+
+      drawer->clearBitmapModulation();
+
+      drawer->drawLine(arrowOffset, Point2I(arrowOffset.x - mArrowSize, currentOffset.y), ColorI::WHITE);
+      drawer->drawLine(arrowOffset, Point2I(arrowOffset.x - mArrowSize, currentOffset.y + height), ColorI::WHITE);
+   }*/
+
+   //Draw the slider bar
+
+   RectI sliderRect;
+
+   S32 sliderOffset = 5;
+
+   RectI optionRect;
+
+   sliderRect.point.x = currentOffset.x + columnSplit + mArrowSize;
+   sliderRect.point.y = currentOffset.y + sliderOffset;
+
+   sliderRect.extent.x = (currentOffset.x + getWidth() - mRightPad - mArrowSize) - sliderRect.point.x;
+   sliderRect.extent.y = height - sliderOffset*2;
+
+   optionRect = sliderRect;
+
+   S32 textWidth = sliderRect.extent.x * 0.3;
+   sliderRect.extent.x -= textWidth;
+
+   //Now adjust the bar to match-to our value
+
+   S32 barStart = sliderRect.point.x;
+   S32 barEnd = sliderRect.point.x + sliderRect.extent.x;
+
+   S32 xPosFill = (((mValue - mRange.x) * (barEnd - barStart)) / (mRange.y - mRange.x)) + barStart;
+
+   RectI fillRect = sliderRect;
+   fillRect.extent.x = xPosFill - sliderRect.point.x;
+
+   ColorI barColor;
+   ColorI barOutlineColor;
+   if (isSelected())
+   {
+      barColor = mProfile->mFontColor;
+      barOutlineColor = mProfile->mFontColorSEL;
+   }
+   else
+   {
+      barColor = mProfile->mFontColor;
+      barOutlineColor = mProfile->mFontColorHL;
+   }
+
+   drawer->drawRectFill(fillRect, barColor);
+
+   drawer->drawRect(sliderRect, barOutlineColor);
+
+   // get the appropriate font color
+   ColorI fontColor;
+   if (!mEnabled)
+   {
+      fontColor = mProfile->mFontColorNA;
+   }
+   else if (isSelected())
+   {
+      fontColor = mProfile->mFontColorSEL;
+   }
+   else if (isHighlighted())
+   {
+      fontColor = mProfile->mFontColorHL;
+   }
+   else
+   {
+      fontColor = mProfile->mFontColor;
+   }
+
+   // calculate text to be at the center between the arrows
+   GFont* font = mProfile->mFont;
+
+   char stringVal[32];
+   dSprintf(stringVal, 32, "%f", mValue);
+
+   S32 stringWidth = font->getStrWidth(stringVal);
+   Point2I textOffset(sliderRect.point.x + sliderRect.extent.x, 0);
+
+   // render the option text itself
+   Point2I textExtent(textWidth, height);
+
+   RectI textRect = optionRect;
+   textRect.point.x = sliderRect.point.x + sliderRect.extent.x;
+   textRect.extent.x = optionRect.extent.x * 0.3;
+
+   drawer->setBitmapModulation(fontColor);
+   renderJustifiedText(textRect.point, textRect.extent, stringVal);
+
+   //drawer->drawRectFill(textRect, ColorI::RED);
+}
+
+void GuiGameSettingsCtrl::onRenderKeybindOption(Point2I currentOffset)
+{
+   F32 xScale = (float)getWidth();
+   S32 columnSplit = mColumnSplit;
+
+   S32 height = getHeight();
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+   //drawer->drawBitmap(mBitmap, )
+
+   Point2I button;
+   button.x = currentOffset.x + columnSplit + (columnSplit / 2.5)/* + (optionWidth / 2)*/;
+   button.y = currentOffset.y;
+
+   Point2I buttonSize;
+   buttonSize.x = height;
+   buttonSize.y = height;
+
+   if (mKeybindBitmapAsset.notNull())
+   {
+      RectI rect(button, buttonSize);
+      drawer->clearBitmapModulation();
+      drawer->drawBitmapStretch(mKeybindBitmap, rect, GFXBitmapFlip_None, GFXTextureFilterLinear, false);
+   }
+
+   //drawer->drawRectFill(button, ColorI::BLUE);
+}
+
+void GuiGameSettingsCtrl::set(const char* label, const char* callback, bool useHighlightIcon, bool enabled, S32 mode, const char* tooltip)
+{
+   mScriptCallback = (dStrlen(callback) > 0) ? StringTable->insert(callback, true) : NULL;
+   mEnabled = enabled;
+   mMode = (Mode)mode;
+   mTooltip = StringTable->insert(tooltip);
+   mLabel = StringTable->insert(label, true);
+}
+
+void GuiGameSettingsCtrl::setListSetting(const char* label, const char* optionsList, bool wrapOptions, const char* callback, bool enabled, const char* tooltip, const char* defaultValue)
+{
+   static StringTableEntry DELIM = StringTable->insert("\t", true);
+
+   Vector<OptionEntry> options(__FILE__, __LINE__);
+
+   S32 defaultOption = 0;
+
+   S32 count = StringUnit::getUnitCount(optionsList, DELIM);
+   for (S32 i = 0; i < count; ++i)
+   {
+      OptionEntry e;
+      const char* option = StringUnit::getUnit(optionsList, i, DELIM);
+      e.mDisplayText = StringTable->insert(option, true);
+      e.mKeyString = e.mDisplayText;
+      options.push_back(e);
+
+      if (String::compare(option, defaultValue) == 0)
+         defaultOption = options.size() - 1;
+   }
+   mOptions = options;
+   bool hasOptions = mOptions.size() > 0;
+   mSelectedOption = (hasOptions) ? defaultOption : NO_OPTION;
+   mWrapOptions = wrapOptions;
+   set(label, callback, true, (hasOptions) ? enabled : false, Mode::OptionList, tooltip);
+}
+
+void GuiGameSettingsCtrl::setSliderSetting(const char* label, F32 defaultValue, F32 increments, Point2F range, const char* callback, bool enabled, const char* tooltip)
+{
+   static StringTableEntry DELIM = StringTable->insert("\t", true);
+
+   mValue = defaultValue;
+   mStepSize = increments;
+   mRange = range;
+
+   set(label, callback, true, enabled, Mode::Slider, tooltip);
+}
+
+void GuiGameSettingsCtrl::setKeybindSetting(const char* label, const char* bitmapName, const char* callback, bool enabled, const char* tooltip)
+{
+   static StringTableEntry DELIM = StringTable->insert("\t", true);
+
+   _setKeybindBitmap(StringTable->insert(bitmapName));
+
+   //if(mBitmap != StringTable->EmptyString())
+   //   mBitmapTex.set(mBitmap, &GFXDefaultGUIProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));
+
+   set(label, callback, true, enabled, Mode::Keybind, tooltip);
+}
+
+bool GuiGameSettingsCtrl::onAdd()
+{
+   if( !Parent::onAdd() )
+      return false;
+      
+   return true;
+}
+
+bool GuiGameSettingsCtrl::onWake()
+{
+   if( !Parent::onWake() )
+      return false;
+
+   return true;
+}
+void GuiGameSettingsCtrl::activate()
+{
+   if(isSelected() && isEnabled() && (mScriptCallback != StringTable->EmptyString()))
+   {
+      setThisControl();
+      if (Con::isFunction(mScriptCallback))
+      {
+         Con::executef(mScriptCallback);
+      }
+   }
+}
+
+void GuiGameSettingsCtrl::setSelected()
+{
+   if (!isEnabled())
+      return;
+
+   mSelected = true;
+}
+
+bool GuiGameSettingsCtrl::isEnabled() const
+{
+   return mEnabled;
+}
+
+void GuiGameSettingsCtrl::setEnabled(bool enabled)
+{
+   mEnabled = enabled;
+}
+
+void GuiGameSettingsCtrl::doScriptCommand(StringTableEntry command)
+{
+   if (command && command[0])
+   {
+      setThisControl();
+      Con::evaluate(command, false, __FILE__);
+   }
+}
+
+void GuiGameSettingsCtrl::setThisControl()
+{
+   smThisControl = this;
+}
+
+StringTableEntry GuiGameSettingsCtrl::getLabel() const
+{
+   return mLabel;
+}
+
+void GuiGameSettingsCtrl::setLabel( const char * label)
+{
+   mLabel = StringTable->insert(label, true);
+}
+
+void GuiGameSettingsCtrl::clear()
+{
+   mOptions.clear();
+}
+
+//-----------------------------------------------------------------------------
+// Console stuff (GuiGameSettingsCtrl)
+//-----------------------------------------------------------------------------
+
+StringTableEntry GuiGameSettingsCtrl::getCurrentOption() const
+{
+   if (mSelectedOption != NO_OPTION && !mOptions.empty())
+   {
+      return mOptions[mSelectedOption].mDisplayText;
+   }
+
+   return StringTable->insert("", false);
+}
+
+StringTableEntry GuiGameSettingsCtrl::getCurrentOptionKey() const
+{
+   if (mSelectedOption != NO_OPTION)
+   {
+      return mOptions[mSelectedOption].mKeyString;
+   }
+
+   return StringTable->insert("", false);
+}
+
+S32 GuiGameSettingsCtrl::getCurrentOptionIndex() const
+{
+   if (mSelectedOption != NO_OPTION)
+   {
+      return mSelectedOption;
+   }
+
+   return S32(-1);
+}
+
+bool GuiGameSettingsCtrl::selectOption(const char* theOption)
+{
+   for (Vector<OptionEntry>::iterator anOption = mOptions.begin(); anOption < mOptions.end(); ++anOption)
+   {
+      if (String::compare((*anOption).mDisplayText, theOption) == 0)
+      {
+         S32 newIndex = anOption - mOptions.begin();
+         mSelectedOption = newIndex;
+         return true;
+      }
+   }
+
+   return false;
+}
+
+bool GuiGameSettingsCtrl::selectOptionByKey(const char* optionKey)
+{
+   for (Vector<OptionEntry>::iterator anOption = mOptions.begin(); anOption < mOptions.end(); ++anOption)
+   {
+      if (String::compare((*anOption).mKeyString, optionKey) == 0)
+      {
+         S32 newIndex = anOption - mOptions.begin();
+         mSelectedOption = newIndex;
+         return true;
+      }
+   }
+
+   return false;
+}
+
+bool GuiGameSettingsCtrl::selectOptionByIndex(S32 optionIndex)
+{
+   if (optionIndex < mOptions.size() && optionIndex >= 0)
+   {
+      mSelectedOption = optionIndex;
+      return true;
+   }
+
+   return false;
+}
+
+void GuiGameSettingsCtrl::setOptions(const char* optionsList)
+{
+   static StringTableEntry DELIM = StringTable->insert("\t", true);
+
+   S32 count = StringUnit::getUnitCount(optionsList, DELIM);
+   mOptions.setSize(count);
+   for (S32 i = 0; i < count; ++i)
+   {
+      const char* option = StringUnit::getUnit(optionsList, i, DELIM);
+      OptionEntry e;
+      e.mDisplayText = StringTable->insert(option, true);
+      e.mKeyString = e.mDisplayText;
+      mOptions[i] = e;
+   }
+
+   if (mSelectedOption >= mOptions.size())
+   {
+      mSelectedOption = mOptions.size() - 1;
+   }
+}
+
+void GuiGameSettingsCtrl::addOption(const char* displayText, const char* keyText)
+{
+   OptionEntry e;
+   e.mDisplayText = StringTable->insert(displayText, true);
+   e.mKeyString = (keyText[0] == '\0') ? e.mDisplayText : StringTable->insert(keyText, true);
+
+   mOptions.push_back(e);
+}
+
+void GuiGameSettingsCtrl::clickOption(S32 xPos)
+{
+   F32 xScale = (float)getWidth();
+
+   S32 leftArrowX1 = mColumnSplit;
+   S32 leftArrowX2 = leftArrowX1 + mArrowSize;
+
+   S32 rightArrowX2 = getWidth() - mRightPad;
+   S32 rightArrowX1 = rightArrowX2 - mArrowSize;
+
+   if ((leftArrowX1 <= xPos) && (xPos <= leftArrowX2))
+   {
+      changeOption(-1);
+   }
+   else if ((rightArrowX1 <= xPos) && (xPos <= rightArrowX2))
+   {
+      changeOption(1);
+   }
+}
+
+void GuiGameSettingsCtrl::changeOption(S32 delta)
+{
+   S32 optionCount = mOptions.size();
+
+   S32 newSelection = mSelectedOption + delta;
+   if (optionCount == 0)
+   {
+      newSelection = NO_OPTION;
+   }
+   else if (!mWrapOptions)
+   {
+      newSelection = mClamp(newSelection, 0, optionCount - 1);
+   }
+   else if (newSelection < 0)
+   {
+      newSelection = optionCount - 1;
+   }
+   else if (newSelection >= optionCount)
+   {
+      newSelection = 0;
+   }
+   mSelectedOption = newSelection;
+
+   if (mMode == GuiGameSettingsCtrl::Slider)
+   {
+      mValue += mStepSize * delta;
+
+      mValue = mRound(mValue / mStepSize) * mStepSize;
+
+      if (mValue < mRange.x)
+         mValue = mRange.x;
+      if (mValue > mRange.y)
+         mValue = mRange.y;
+   }
+
+   static StringTableEntry LEFT = StringTable->insert("LEFT", true);
+   static StringTableEntry RIGHT = StringTable->insert("RIGHT", true);
+
+   onChange_callback();
+
+   if (mScriptCallback != NULL && (mSelectedOption != NO_OPTION && mMode != GuiGameSettingsCtrl::Slider))
+   {
+      setThisControl();
+      StringTableEntry direction = NULL;
+      if (delta < 0)
+      {
+         direction = LEFT;
+      }
+      else if (delta > 0)
+      {
+         direction = RIGHT;
+      }
+      if ((direction != NULL) && (Con::isFunction(mScriptCallback)))
+      {
+         Con::executef(mScriptCallback, direction);
+      }
+   }
+}
+IMPLEMENT_CONOBJECT(GuiGameSettingsCtrl);
+
+void GuiGameSettingsCtrl::clickSlider(S32 xPos)
+{
+   F32 xScale = (float)getWidth();
+
+   S32 leftArrowX1 = mColumnSplit;
+   S32 leftArrowX2 = leftArrowX1 + mArrowSize;
+
+   S32 rightArrowX2 = getWidth() - mRightPad;
+   S32 rightArrowX1 = rightArrowX2 - mArrowSize;
+
+   S32 sliderWidth = rightArrowX1 - leftArrowX2;
+   sliderWidth *= 0.6; //remove the number text spacing
+
+   /*if ((leftArrowX1 <= xPos) && (xPos <= leftArrowX2))
+   {
+      mValue -= mStepSize;
+
+      mValue = mRound(mValue / mStepSize) * mStepSize;
+
+      if (mValue < mRange.x)
+         mValue = mRange.x;
+
+   }
+   else if ((rightArrowX1 <= xPos) && (xPos <= rightArrowX2))
+   {
+      //F32 snap = mValue % mStepSize;
+      //mValue.y -= snap;
+
+      mValue += mStepSize;
+
+      mValue = mRound(mValue / mStepSize) * mStepSize;
+
+      if (mValue > mRange.y)
+         mValue = mRange.y;
+   }
+   else
+   {*/
+      //see if we clicked on the sliderbar itself
+      S32 barStart = leftArrowX2;
+      S32 barEnd = barStart + sliderWidth;
+
+      if (xPos >= barStart && xPos <= barEnd)
+      {
+         //find the position
+         F32 newValue = (((xPos - barStart) * (mRange.y - mRange.x)) / (barEnd - barStart)) + mRange.x;
+
+         newValue = mRound(newValue / mStepSize) * mStepSize;
+
+         mValue = newValue;
+      }
+   //}
+
+   onChange_callback();
+}
+
+void GuiGameSettingsCtrl::clickKeybind(S32 xPos)
+{
+   S32 columnSplit = mColumnSplit;
+
+   S32 height = getHeight();
+
+   Point2I button;
+   button.x = columnSplit + (columnSplit / 2.5)/* + (optionWidth / 2)*/;
+   button.y = 0;
+
+   Point2I buttonSize;
+   buttonSize.x = height;
+   buttonSize.y = height;
+
+   RectI rect(button, buttonSize);
+
+   onChange_callback();
+
+   if (rect.pointInRect(Point2I(xPos, getHeight()/2)))
+   {
+      if (mScriptCallback != StringTable->EmptyString())
+      {
+         Con::executef(mScriptCallback, this);
+      }
+   }
+}
+
+F32 GuiGameSettingsCtrl::getValue()
+{
+   return mValue;
+}
+
+void GuiGameSettingsCtrl::setValue(F32 value)
+{
+   mValue = value;
+}
+
+const char* GuiGameSettingsCtrl::getTooltip()
+{
+   return mTooltip;
+}
+
+ConsoleDocClass( GuiGameSettingsCtrl,
+   "@brief A base class for cross platform menu controls that are gamepad friendly.\n\n"
+
+   "This class is used to build row-based menu GUIs that can be easily navigated "
+   "using the keyboard, mouse or gamepad. The desired row can be selected using "
+   "the mouse, or by navigating using the Up and Down buttons.\n\n"
+
+   "@tsexample\n\n"
+   "new GuiGameSettingsCtrl()\n"
+   "{\n"
+   "   debugRender = \"0\";\n"
+   "   callbackOnA = \"applyOptions();\";\n"
+   "   callbackOnB = \"Canvas.setContent(MainMenuGui);\";\n"
+   "   callbackOnX = \"\";\n"
+   "   callbackOnY = \"revertOptions();\";\n"
+   "   //Properties not specific to this control have been omitted from this example.\n"
+   "};\n"
+   "@endtsexample\n\n"
+
+   "@see GuiGameSettingsProfile\n\n"
+
+   "@ingroup GuiGame"
+);
+
+IMPLEMENT_CALLBACK( GuiGameSettingsCtrl, onChange, void, (), (),
+   "Called when the setting's value changes." );
+
+IMPLEMENT_CALLBACK(GuiGameSettingsCtrl, onInputEvent, void, (const char* device, const char* action, bool state),
+   (device, action, state),
+   "@brief Callback that occurs when an input is triggered on this control\n\n"
+   "@param device The device type triggering the input, such as keyboard, mouse, etc\n"
+   "@param action The actual event occuring, such as a key or button\n"
+   "@param state True if the action is being pressed, false if it is being release\n\n");
+
+IMPLEMENT_CALLBACK(GuiGameSettingsCtrl, onAxisEvent, void, (const char* device, const char* action, F32 axisValue),
+   (device, action, axisValue),
+   "@brief Callback that occurs when an axis event is triggered on this control\n\n"
+   "@param device The device type triggering the input, such as mouse, joystick, gamepad, etc\n"
+   "@param action The ActionMap code for the axis\n"
+   "@param axisValue The current value of the axis\n\n");
+
+void GuiGameSettingsCtrl::initPersistFields()
+{
+   INITPERSISTFIELD_IMAGEASSET(KeybindBitmap, GuiGameSettingsCtrl, "Bitmap used to display the bound key for this keybind option.");
+   INITPERSISTFIELD_IMAGEASSET(PreviousBitmap, GuiGameSettingsCtrl, "Bitmap used for the previous button when in list mode.");
+   INITPERSISTFIELD_IMAGEASSET(NextBitmap, GuiGameSettingsCtrl, "Bitmap used for the next button when in list mode.");
+
+   addField("arrowSize", TypeS32, Offset(mArrowSize, GuiGameSettingsCtrl),
+      "Size of the arrow buttons' extents");
+
+   addField("columnSplit", TypeS32, Offset(mColumnSplit, GuiGameSettingsCtrl),
+      "Position of the split between the leftside label and the rightside setting parts");
+
+   addField("rightPad", TypeS32, Offset(mRightPad, GuiGameSettingsCtrl),
+      "Padding between the rightmost edge of the control and right arrow.");
+
+   addField("callbackOnA", TypeString, Offset(mCallbackOnA, GuiGameSettingsCtrl),
+      "Script callback when the 'A' button is pressed. 'A' inputs are Keyboard: A, Return, Space; Gamepad: A, Start" );
+
+   addField("callbackOnB", TypeString, Offset(mCallbackOnB, GuiGameSettingsCtrl),
+      "Script callback when the 'B' button is pressed. 'B' inputs are Keyboard: B, Esc, Backspace, Delete; Gamepad: B, Back" );
+
+   addField("callbackOnX", TypeString, Offset(mCallbackOnX, GuiGameSettingsCtrl),
+      "Script callback when the 'X' button is pressed. 'X' inputs are Keyboard: X; Gamepad: X" );
+
+   addField("callbackOnY", TypeString, Offset(mCallbackOnY, GuiGameSettingsCtrl),
+      "Script callback when the 'Y' button is pressed. 'Y' inputs are Keyboard: Y; Gamepad: Y" );
+
+   addField("callbackOnInputs", TypeBool, Offset(mCallbackOnInputs, GuiGameSettingsCtrl),
+      "Script callback when any inputs are detected, even if they aren't the regular 4 face buttons. Useful for secondary/speciality handling of menu navigation.");
+
+   addField("consumeKeyInputEvents", TypeBool, Offset(mConsumeKeyInputEvents, GuiGameSettingsCtrl),
+      "When callbackOnInputs is active, this indicates if the input event should be consumed, or allowed 'through' to let other things respond to the event as well.");
+   
+
+   Parent::initPersistFields();
+}
+
+DefineEngineMethod( GuiGameSettingsCtrl, isEnabled, bool, (),,
+   "Determines if the control is enabled or disabled.\n\n"
+   "@return True if the control is enabled. False if the control is not enabled." )
+{
+   return object->isEnabled();
+}
+
+DefineEngineMethod( GuiGameSettingsCtrl, setEnabled, void, ( bool enabled ),,
+   "Sets the control's enabled status according to the given parameters.\n\n"
+   "@param enabled Indicate true to enable the control or false to disable it." )
+{
+   object->setEnabled( enabled );
+}
+
+DefineEngineMethod( GuiGameSettingsCtrl, activate, void, (),,
+   "Activates the control. The script callback of the control will be called (if it has one)." )
+{
+   object->activate();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, getLabel, const char *, (),,
+   "Gets the label displayed.\n\n"
+   "@return The label." )
+{
+   return object->getLabel();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, setLabel, void, ( const char* label ),,
+   "Sets the label.\n\n"
+   "@param label Text to set as the label.\n" )
+{
+   object->setLabel(label );
+}
+
+DefineEngineMethod( GuiGameSettingsCtrl, setSelected, void, (),,
+   "Sets the control as selected. Can only select enabled controls." )
+{
+   object->setSelected();
+}
+
+DefineEngineMethod( GuiGameSettingsCtrl, getSelected, bool, (),,
+   "Gets if the control is currently selected.\n\n"
+   "@return if the control is selected." )
+{
+   return object->isSelected();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, clear, void, (), ,
+   "Clears the current options.\n\n")
+{
+   return object->clear();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, getMode, S32, (), ,
+   "Gets this control's options mode.\n\n")
+{
+   GuiGameSettingsCtrl::Mode mode = object->getMode();
+   if (mode == GuiGameSettingsCtrl::Mode::OptionList)
+      return 0;
+   else if (mode == GuiGameSettingsCtrl::Mode::Slider)
+      return 1;
+   else if (mode == GuiGameSettingsCtrl::Mode::Keybind)
+      return 2;
+   else
+      return -1;
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, setListSetting, void,
+   (const char* label, const char* options, bool wrapOptions, const char* callback, bool enabled, const char* tooltip, const char* defaultValue),
+   (true, "", ""),
+   "Sets this setting to a list.\n\n"
+   "@param label The text to display  as a label.\n"
+   "@param options A tab separated list of options.\n"
+   "@param wrapOptions Specify true to allow options to wrap at each end or false to prevent wrapping.\n"
+   "@param callback Name of a script function to use as a callback when this control is activated.\n"
+   "@param enabled [optional] If this control is initially enabled.")
+{
+   object->setListSetting(label, options, wrapOptions, callback, enabled, tooltip, defaultValue);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, setSliderSetting, void,
+(const char* label, F32 defaultValue, F32 increment, Point2F range, const char* callback, bool enabled, const char* tooltip),
+(true, ""),
+"Sets this setting to a slider.\n\n"
+"@param label The text to display as a label.\n"
+"@param options A tab separated list of options.\n"
+"@param wrapOptions Specify true to allow options to wrap at each end or false to prevent wrapping.\n"
+"@param callback Name of a script function to use as a callback when this control is activated.\n"
+"@param enabled [optional] If this control is initially enabled.")
+{
+   object->setSliderSetting(label, defaultValue, increment, range, callback, enabled, tooltip);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, setKeybindSetting, void,
+(const char* label, const char* bitmapName, const char* callback, bool enabled, const char* tooltip),
+(true, ""),
+"Sets this setting to a keybind.\n\n"
+"@param label The text to display as a label.\n"
+"@param options A tab separated list of options.\n"
+"@param wrapOptions Specify true to allow options to wrap at each end or false to prevent wrapping.\n"
+"@param callback Name of a script function to use as a callback when this control is activated.\n"
+"@param enabled [optional] If this control is initially enabled.")
+{
+   object->setKeybindSetting(label, bitmapName, callback, enabled, tooltip);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, getCurrentOption, const char*, (), ,
+   "Gets the text for the currently selected option .\n\n"
+   "@return A string representing the text currently displayed as the selected option. If there is no such displayed text then the empty string is returned.")
+{
+   return object->getCurrentOption();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, getCurrentOptionKey, const char*, (), ,
+   "Gets the key string for the currently selected option.\n\n"
+   "@return The key (or id) that was assigned to the selected option. If there is no selected option then the empty string is returned.")
+{
+   return object->getCurrentOptionKey();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, getCurrentOptionIndex, S32, (), ,
+   "Gets the index into the option list for the currently selected option.\n\n"
+   "@return The index of the selected option. If there is no selected option then -1 is returned.")
+{
+   return object->getCurrentOptionIndex();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, selectOption, bool, (const char* option), ,
+   "Set the control's current option to the one specified\n\n"
+   "@param option The option to be made active.\n"
+   "@return True if the control contained the option and was set, false otherwise.")
+{
+   return object->selectOption(option);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, selectOptionByKey, bool, (const char* optionKey), ,
+   "Set the control's current option to the one with the specified key.\n\n"
+   "@param optionKey The key string that was assigned to the option to be made active.\n"
+   "@return True if the control contained the key and the option and was set, false otherwise.")
+{
+   return object->selectOptionByKey(optionKey);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, selectOptionByIndex, bool, (S32 optionIndex), ,
+   "Set the control's current option to the one at the specified index.\n\n"
+   "@param optionIndex The index of the option to be made active.\n"
+   "@return True if the index was valid and the option and was set, false otherwise.")
+{
+   return object->selectOptionByIndex(optionIndex);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, setOptions, void, (const char* optionsList), ,
+   "Sets the list of options on the given control.\n\n"
+   "@param optionsList A tab separated list of options for the control.")
+{
+   object->setOptions(optionsList);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, addOption, void, (const char* displayText, const char* keyText), (""),
+   "Adds an option to the list of options on the given control.\n\n"
+   "@param displayText The text to display for this option.\n"
+   "@param keyText [Optional] The id string to associate with this value. "
+   "If unset, the id will be the same as the display text.\n")
+{
+   object->addOption(displayText, keyText);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, getValue, F32, (), ,
+   "Sets the list of options on the given control.\n\n"
+   "@param optionsList A tab separated list of options for the control.")
+{
+   return object->getValue();
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, setValue, void, (F32 value), ,
+   "Sets the list of options on the given control.\n\n"
+   "@param optionsList A tab separated list of options for the control.")
+{
+   object->setValue(value);
+}
+
+DefineEngineMethod(GuiGameSettingsCtrl, getTooltip, const char*, (), ,
+   "Sets the list of options on the given control.\n\n"
+   "@param optionsList A tab separated list of options for the control.")
+{
+   return object->getTooltip();
+}

+ 313 - 0
Engine/source/gui/controls/guiGameSettingsCtrl.h

@@ -0,0 +1,313 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 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 _GuiGameSettingsCtrl_H_
+#define _GuiGameSettingsCtrl_H_
+
+#include "gui/buttons/guiButtonCtrl.h"
+#include "T3D/assets/ImageAsset.h"
+
+/// \class GuiGameSettingsCtrl
+/// A base class for cross platform menu controls that are gamepad friendly.
+class GuiGameSettingsCtrl : public GuiButtonCtrl
+{
+public:
+   typedef GuiButtonCtrl Parent;
+
+   enum Mode
+   {
+      Default = 0,
+      OptionList,
+      Slider,
+      Keybind,
+      Text
+   };
+
+protected:
+
+   /// \struct OptionEntry
+   /// Display text and ID key for each entry in an option.
+   struct OptionEntry
+   {
+      StringTableEntry mDisplayText;   ///< The text that is displayed for the option
+      StringTableEntry mKeyString;     ///< Key value that is associated with this option
+      OptionEntry() : mDisplayText(StringTable->EmptyString()), mKeyString(StringTable->EmptyString()) {}
+      virtual ~OptionEntry() {}
+   };
+
+
+   StringTableEntry mLabel;            ///< Text to display in the control as a label
+   StringTableEntry mScriptCallback;   ///< Script callback when control is activated
+   StringTableEntry mTooltip;          ///< A descriptive tooltip message for what the control is
+
+   Mode mMode;
+
+   //List options
+   Vector<OptionEntry>        mOptions;         ///< Collection of options available to display
+   S32                        mSelectedOption;  ///< Index into mOptions pointing at the selected option
+   bool                       mWrapOptions;     ///< Determines if options should "wrap around" at the ends
+
+   //Slider option
+   F32                        mValue;           ///< When working as a slider, this contains the value
+   F32                        mStepSize;        ///< When working as a slider, this is the increment levels in the range
+   Point2F                    mRange;           ///< When working as a slider, this sets our min/max range
+
+   //Keybind option
+   DECLARE_IMAGEASSET(GuiGameSettingsCtrl, KeybindBitmap, changeBitmap, GFXDefaultGUIProfile);
+   DECLARE_ASSET_SETGET(GuiGameSettingsCtrl, KeybindBitmap);
+
+   DECLARE_IMAGEASSET(GuiGameSettingsCtrl, PreviousBitmap, changeBitmap, GFXDefaultGUIProfile);
+   DECLARE_ASSET_SETGET(GuiGameSettingsCtrl, PreviousBitmap);
+
+   DECLARE_IMAGEASSET(GuiGameSettingsCtrl, NextBitmap, changeBitmap, GFXDefaultGUIProfile);
+   DECLARE_ASSET_SETGET(GuiGameSettingsCtrl, NextBitmap);
+
+   S32 mArrowSize;
+   S32 mColumnSplit; //Padding between the leftmost edge of the control, and the left side of the 'option'.
+   S32 mRightPad;
+
+   bool mEnabled;
+   bool mSelected;
+
+public:
+   void changeBitmap() {}
+
+   /// Sets the control as selected . Only controls that are enabled can be selected. 
+   virtual void setSelected();
+
+   /// Determines if the specified control is enabled or disabled.
+   ///
+   /// \return True if the specified control is enabled. False if the control is not
+   /// enabled
+   virtual bool isEnabled() const;
+
+   /// Sets a control's enabled status according to the given parameters.
+   ///
+   /// \param enabled Indicate true to enable the control or false to disable it.
+   virtual void setEnabled(bool enabled);
+
+   /// Gets the label displayed on the control.
+   ///
+   /// \return The label for the control.
+   virtual StringTableEntry getLabel() const;
+
+   /// Sets the label on the control.
+   ///
+   /// \param label Text to set as the label.
+   virtual void setLabel(const char * label);
+
+   /// Sets the control to a List setting.
+   ///
+   /// \param label The text to display on the control as a label.
+   /// \param optionsList A tab separated list of options for the control.
+   /// \param wrapOptions Specify true to allow options to wrap at the ends or
+   /// false to prevent wrapping.
+   /// \param callback [optional] Name of a script function to use as a callback
+   /// when this control is activated. Default NULL means no callback.
+   /// \param enabled [optional] If this control is initially enabled. Default true.
+   void setListSetting(const char* label, const char* optionsList, bool wrapOptions, const char* callback,bool enabled, const char* tooltip = "", const char* defaultValue = "");
+
+   /// Sets the control to a Slider setting
+   ///
+   /// \param label The text to display on the control as a label.
+   /// \param defaultValue A float indicating the slider's default value
+   /// \param increments A float indicating the incremental values the slider snaps along between it's range
+   /// \param range A Point2F that indicates the minimum and maximum value range
+   /// \param callback [optional] Name of a script function to use as a callback
+   /// when this control is activated. Default NULL means no callback.
+   /// \param enabled [optional] If this control is initially enabled. Default true.
+   void setSliderSetting(const char* label, F32 defaultValue, F32 increments, Point2F range, const char* callback, bool enabled, const char* tooltip = "");
+
+   /// Sets the control to a Keybind setting
+   ///
+   /// \param label The text to display on the control as a label.
+   /// \param bitmapAssetId The assetId for the button display image
+   /// \param range A Point2F that indicates the minimum and maximum value range
+   /// \param callback [optional] Name of a script function to use as a callback
+   /// when this control is activated. Default NULL means no callback.
+   /// \param enabled [optional] If this control is initially enabled. Default true.
+   void setKeybindSetting(const char* label, const char* bitmapAssetId, const char* callback, bool enabled, const char* tooltip);
+
+   /// Gets the text for the currently selected option of the control.
+   ///
+   /// \return A string representing the text currently displayed as the selected
+   /// option on the control. If there is no such displayed text then the empty
+   /// string is returned.
+   StringTableEntry getCurrentOption() const;
+
+   /// Gets the key string for the currently selected option of the control
+   ///
+   /// \return The key (or id) that was assigned to the selected option on the
+   ///  control. If there is no selected option then the empty string is returned.
+   StringTableEntry getCurrentOptionKey() const;
+
+   /// Gets the index into the option list for the currently selected option of the control.
+   ///
+   /// \return The index of the selected option on the control. If there is no
+   /// selected option then -1 is returned.
+   S32 getCurrentOptionIndex() const;
+
+   /// Attempts to set the control to the specified selected option. The option
+   /// will only be set if the option exists in the control.
+   ///
+   /// \param option The option to be made active.
+   /// \return True if the control contained the option and was set, false otherwise.
+   bool selectOption(const char* option);
+
+   /// Attempts to set the control to the option with the specified key. The
+   /// option will only be set if the key exists in the control.
+   ///
+   /// \param optionKey The key string that was assigned to the option to be made active.
+   /// \return True if the control contained the key and the option and was set, false otherwise.
+   bool selectOptionByKey(const char* optionKey);
+
+   /// Attempts to set the control to the option at the specified index. The option
+   /// will only be set if the index is valid.
+   ///
+   /// \param optionIndex The index of the option to be made active.
+   /// \return True if the index was valid and the option and was set, false otherwise.
+   bool selectOptionByIndex(S32 optionIndex);
+
+   /// Sets the list of options on the control.
+   ///
+   /// \param optionsList A tab separated list of options for the control.
+   void setOptions(const char* optionsList);
+
+   /// Adds an option to the list of options on the control.
+   ///
+   /// \param displayText The text to display for this option.
+   /// \param keyText The id string to associate with this value. If NULL the
+   ///  id will be the same as the display text.
+   void addOption(const char* displayText, const char* keyText);
+
+   /// Activates the control. The script callback of the control will
+   /// be called (if it has one).
+   virtual void activate();
+
+   /// Gets the value
+   ///
+   F32 getValue();
+
+   /// Sets the value
+   ///
+   /// \param value The new value to be set.
+   void setValue(F32 value);
+
+   Mode getMode() { return mMode; }
+
+   /// Gets the tooltip
+   const char* getTooltip();
+
+   GuiGameSettingsCtrl();
+   ~GuiGameSettingsCtrl();
+
+   void onRender(Point2I offset, const RectI &updateRect);
+
+   void onRenderListOption(Point2I currentOffset);
+   void onRenderSliderOption(Point2I currentOffset);
+
+   void onRenderKeybindOption(Point2I currentOffset);
+
+   /// Callback when the object is registered with the sim.
+   ///
+   /// \return True if the profile was successfully added, false otherwise.
+   bool onAdd();
+
+   /// Callback when the control wakes up.
+   bool onWake();
+
+   void clear();
+
+   virtual void onMouseMove(const GuiEvent& event);
+   virtual void onMouseUp(const GuiEvent& event);
+
+   DECLARE_CONOBJECT(GuiGameSettingsCtrl);
+   DECLARE_CATEGORY( "Gui Game" );
+   DECLARE_DESCRIPTION( "Base class for cross platform menu controls that are gamepad friendly." );
+
+   /// Initializes fields accessible through the console.
+   static void initPersistFields();
+
+   static const S32 NO_OPTION = -1; ///< Indicates there is no option
+
+protected:
+   /// Sets up the option
+   ///
+   /// \param label The text to display on the control as a label.
+   /// \param callback Name of a script function to use as a callback when this
+   /// control is activated.
+   /// \param enabled [optional] If this control is initially enabled. Default true.
+   virtual void set(const char* label, const char* callback, bool useHighlightIcon = true, bool enabled = true, S32 mode = 0, const char* tooltip = "");
+
+   /// Sets the script variable $ThisControl to reflect this control.
+   virtual void setThisControl();
+
+   /// @name Callbacks
+   /// @{
+   DECLARE_CALLBACK( void, onChange, () );
+
+   DECLARE_CALLBACK(void, onInputEvent,  (const char* device, const char* action, bool state));
+
+   DECLARE_CALLBACK(void, onAxisEvent, (const char* device, const char* action, F32 axisValue));
+   /// @}
+
+   /// Evaluates some script. If the command is empty then nothing is evaluated.
+   ///
+   /// \param command The script to evaluate.
+   void doScriptCommand(StringTableEntry command);
+
+   StringTableEntry  mCallbackOnA;  ///< Script callback when the 'A' button is pressed
+   StringTableEntry  mCallbackOnB;  ///< Script callback when the 'B' button is pressed
+   StringTableEntry  mCallbackOnX;  ///< Script callback when the 'X' button is pressed
+   StringTableEntry  mCallbackOnY;  ///< Script callback when the 'Y' button is pressed
+
+private:
+   /// Performs a click on the current option. The x position is used to
+   /// determine if the left or right arrow were clicked. If one was clicked, the
+   /// option will be changed. If neither was clicked, the option is unaffected.
+   /// This method should only be called when there is an actively selected control.
+   ///
+   /// \param xPos The x position of the the click, relative to the control.
+   void clickOption(S32 xPos);
+
+   /// Changes the option on the currently selected control.
+   ///
+   /// \param delta The amount to change the option selection by. Typically this
+   /// will be 1 or -1.
+   void changeOption(S32 delta);
+
+   /// Performs a click on the current slider control. The x position is used to
+   /// determine if the left or right arrow were clicked, or if it landed somewhere on the sliderbar.
+   /// If one was clicked, the option will be changed. If neither was clicked, the option is unaffected.
+   /// This method should only be called when there is an actively selected control.
+   ///
+   /// \param xPos The x position of the the click, relative to the control.
+   void clickSlider(S32 xPos);
+
+   void clickKeybind(S32 xPos);
+
+private:
+   bool     mCallbackOnInputs;
+   bool     mConsumeKeyInputEvents;
+};
+
+#endif

+ 4 - 0
Templates/BaseGame/game/data/UI/guis/NetGraphGui.asset.taml

@@ -0,0 +1,4 @@
+<GUIAsset
+    AssetName="NetGraphGui"
+    GUIFile="@assetFile=netGraphGui.gui"
+    VersionId="1"/>

二進制
Templates/BaseGame/game/data/UI/images/Torque_3D_logo.png


二進制
Templates/BaseGame/game/data/UI/images/Torque_3D_logo_alt.png


二進制
Templates/BaseGame/game/data/UI/images/Torque_3D_logo_shortcut.png


二進制
Templates/BaseGame/game/data/UI/images/Torque_3D_logo_w.png


二進制
Templates/BaseGame/game/data/UI/images/backgrounddark.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/backgrounddark_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="backgrounddark_image"
+    imageFile="@assetFile=backgrounddark.png"/>

二進制
Templates/BaseGame/game/data/UI/images/clearbtn_d.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/clearbtn_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="clearbtn_d_image"
+    imageFile="@assetFile=clearbtn_d.png"/>

二進制
Templates/BaseGame/game/data/UI/images/clearbtn_h.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/clearbtn_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="clearbtn_h_image"
+    imageFile="@assetFile=clearbtn_h.png"/>

二進制
Templates/BaseGame/game/data/UI/images/clearbtn_n.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/clearbtn_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="clearbtn_n_image"
+    imageFile="@assetFile=clearbtn_n.png"/>

二進制
Templates/BaseGame/game/data/UI/images/collapsetoolbar_d.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/collapsetoolbar_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="collapsetoolbar_d_image"
+    imageFile="@assetFile=collapsetoolbar_d.png"/>

二進制
Templates/BaseGame/game/data/UI/images/collapsetoolbar_h.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/collapsetoolbar_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="collapsetoolbar_h_image"
+    imageFile="@assetFile=collapsetoolbar_h.png"/>

二進制
Templates/BaseGame/game/data/UI/images/collapsetoolbar_n.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/collapsetoolbar_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="collapsetoolbar_n_image"
+    imageFile="@assetFile=collapsetoolbar_n.png"/>

二進制
Templates/BaseGame/game/data/UI/images/dropdownbuttonarrow.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/dropdownbuttonarrow_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="dropdownbuttonarrow_image"
+    imageFile="@assetFile=dropdownbuttonarrow.png"/>

二進制
Templates/BaseGame/game/data/UI/images/dropdowntextEdit.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/dropdowntextEdit_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="dropdowntextEdit_image"
+    imageFile="@assetFile=dropdowntextEdit.png"/>

二進制
Templates/BaseGame/game/data/UI/images/expandtoolbar_d.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/expandtoolbar_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="expandtoolbar_d_image"
+    imageFile="@assetFile=expandtoolbar_d.png"/>

二進制
Templates/BaseGame/game/data/UI/images/expandtoolbar_h.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/expandtoolbar_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="expandtoolbar_h_image"
+    imageFile="@assetFile=expandtoolbar_h.png"/>

二進制
Templates/BaseGame/game/data/UI/images/expandtoolbar_n.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/expandtoolbar_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="expandtoolbar_n_image"
+    imageFile="@assetFile=expandtoolbar_n.png"/>

二進制
Templates/BaseGame/game/data/UI/images/groupborder.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/groupborder_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="groupborder_image"
+    imageFile="@assetFile=groupborder.png"/>

二進制
Templates/BaseGame/game/data/UI/images/inactiveoverlay.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/inactiveoverlay_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="inactiveoverlay_image"
+    imageFile="@assetFile=inactiveoverlay.png"/>

二進制
Templates/BaseGame/game/data/UI/images/menubutton.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/menubutton_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="menubutton_image"
+    imageFile="@assetFile=menubutton.png"/>

二進制
Templates/BaseGame/game/data/UI/images/nextOption_n.png


+ 8 - 0
Templates/BaseGame/game/data/UI/images/nextOption_n_image.asset.taml

@@ -0,0 +1,8 @@
+<ImageAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="nextOption_n_image"
+    imageFile="@assetFile=nextOption_n.png"
+    UseMips="true"
+    isHDRImage="false"
+    imageType="GUI" />

二進制
Templates/BaseGame/game/data/UI/images/nextbutton_d.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/nextbutton_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="nextbutton_d_image"
+    imageFile="@assetFile=nextbutton_d.png"/>

二進制
Templates/BaseGame/game/data/UI/images/nextbutton_h.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/nextbutton_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="nextbutton_h_image"
+    imageFile="@assetFile=nextbutton_h.png"/>

二進制
Templates/BaseGame/game/data/UI/images/nextbutton_n.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/nextbutton_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="nextbutton_n_image"
+    imageFile="@assetFile=nextbutton_n.png"/>

二進制
Templates/BaseGame/game/data/UI/images/nopreview.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/nopreview_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="nopreview_image"
+    imageFile="@assetFile=nopreview.png"/>

二進制
Templates/BaseGame/game/data/UI/images/previousOption_n.png


+ 8 - 0
Templates/BaseGame/game/data/UI/images/previousOption_n_image.asset.taml

@@ -0,0 +1,8 @@
+<ImageAsset
+    canSave="true"
+    canSaveDynamicFields="true"
+    AssetName="previousOption_n_image"
+    imageFile="@assetFile=previousOption_n.png"
+    UseMips="true"
+    isHDRImage="false"
+    imageType="GUI" />

二進制
Templates/BaseGame/game/data/UI/images/previousbutton_d.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/previousbutton_d_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="previousbutton_d_image"
+    imageFile="@assetFile=previousbutton_d.png"/>

二進制
Templates/BaseGame/game/data/UI/images/previousbutton_h.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/previousbutton_h_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="previousbutton_h_image"
+    imageFile="@assetFile=previousbutton_h.png"/>

二進制
Templates/BaseGame/game/data/UI/images/previousbutton_n.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/previousbutton_n_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="previousbutton_n_image"
+    imageFile="@assetFile=previousbutton_n.png"/>

二進制
Templates/BaseGame/game/data/UI/images/selectorbutton.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/selectorbutton_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="selectorbutton_image"
+    imageFile="@assetFile=selectorbutton.png"/>

二進制
Templates/BaseGame/game/data/UI/images/selectorbuttonblank.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/selectorbuttonblank_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="selectorbuttonblank_image"
+    imageFile="@assetFile=selectorbuttonblank.png"/>

二進制
Templates/BaseGame/game/data/UI/images/selectorbuttondark.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/selectorbuttondark_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="selectorbuttondark_image"
+    imageFile="@assetFile=selectorbuttondark.png"/>

二進制
Templates/BaseGame/game/data/UI/images/selectorbuttonhighlightonly.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/selectorbuttonhighlightonly_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="selectorbuttonhighlightonly_image"
+    imageFile="@assetFile=selectorbuttonhighlightonly.png"/>

二進制
Templates/BaseGame/game/data/UI/images/separatorh.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/separatorh_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="separatorh_image"
+    imageFile="@assetFile=separatorh.png"/>

二進制
Templates/BaseGame/game/data/UI/images/separatorv.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/separatorv_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="separatorv_image"
+    imageFile="@assetFile=separatorv.png"/>

二進制
Templates/BaseGame/game/data/UI/images/sliderwbox.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/sliderwbox_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="sliderwbox_image"
+    imageFile="@assetFile=sliderwbox.png"/>

二進制
Templates/BaseGame/game/data/UI/images/tabborder.png


+ 3 - 0
Templates/BaseGame/game/data/UI/images/tabborder_image.asset.taml

@@ -0,0 +1,3 @@
+<ImageAsset
+    AssetName="tabborder_image"
+    imageFile="@assetFile=tabborder.png"/>

+ 510 - 0
Templates/BaseGame/game/data/UI/scripts/menuInputHandling.tscript

@@ -0,0 +1,510 @@
+//==============================================================================
+// Menu Input Buttons
+// This file manages the Menu Input Buttons stuff
+// Any time you have a GUI button that should be clickable AND map to a key input
+// such as a gamepad button, or enter, etc, this stuff can be used
+//==============================================================================
+/*
+Gamepad input reference for 360 controller
+btn_a = A
+btn_b = B
+btn_x = X
+btn_y = Y
+btn_r = Right Bumper
+btn_l = Right Bumper
+upov = Dpad Up
+dpov = Dpad Down
+lpov = Dpad Left
+rpov = Dpad Right
+xaxis = Left Stick | + values = up, - values = down
+yaxis = Left Stick | + values = up, - values = down
+rxaxis = Right Stick | + values = up, - values = down
+ryaxis = Right Stick | + values = up, - values = down
+zaxis = Left Trigger
+rzaxis = Right Trigger
+btn_start = Start
+btn_back = Back/Select
+*/
+
+/// This is used with the main UI menu lists, when a non-axis input event is called
+/// such as pressing a button
+/// It is called from the engine
+function UIMenuButtonList::onInputEvent(%this, %device, %action, %state)
+{
+   if(%state)
+      $activeMenuButtonContainer.processInputs(%device, %action);
+}
+
+/// This is used with the main UI menu lists, when an axis input event is called
+/// such as moving a joystick
+/// It is called from the engine
+function UIMenuButtonList::onAxisEvent(%this, %device, %action, %axisVal)
+{
+   //Skip out of the value is too low as it could just be noise or miscalibrated defaults
+   if(%axisVal < 0.02)
+      return;
+      
+   $activeMenuButtonContainer.processAxisEvent(%device, %action);
+}
+
+/// Sets the command and text for the specified button. If %text and %command
+/// are left empty, the button will be disabled and hidden.
+///
+/// \param %gamepadButton (string) The button to set for when using gamepad input. See the input map reference comment at the top of the file
+/// \param %keyboardButton (string) The button to set for when using keyboard/mouse input.
+/// \param %text (string) The text to display next to the A button graphic.
+/// \param %command (string) The command executed when the A button is pressed.
+/// \param %gamepadOnly (bool) If true, will only show the button when working in the gamepad input mode
+function MenuInputButton::set(%this, %gamepadButton, %keyboardButton, %text, %command, %gamepadOnly)
+{
+   %set = (! ((%text $= "") && (%command $= "")));
+   %this.setText(%text);
+   %this.setActive(%set);
+   %this.setVisible(%set);
+   
+   %this.gamepadButton = %gamepadButton;
+   %this.keyboardButton = %keyboardButton;
+   
+   if(%gamepadOnly $= "")
+      %gamepadOnly = false;
+      
+   %this.gamepadOnly = %gamepadOnly;
+
+   %this.Command = %command;
+}
+
+/// Refreshes the specific button, updating it's visbility status and the displayed input image
+function MenuInputButton::refresh(%this)
+{
+   %set = (! ((%this.text $= "") && (%this.command $= "")));
+   
+   //Special-case of where we're in keyboard+mouse mode, but the menubutton is gamepad only mode, so we early out
+   if(%this.gamepadOnly && $activeControllerType !$= "gamepad")
+      %set = false;
+      
+   %this.setActive(%set);
+   %this.setVisible(%set);
+   
+   if(!%this.isActive())
+      return;
+   
+   if($activeControllerType $= "gamepad")
+   {
+      if(%this.gamepadButton !$= "")
+      {
+         %assetId = "";
+         if($activeControllerName $= "PS4 Controller")
+         { 
+            %assetId = "UI:PS4_";
+            
+            if(%this.gamepadButton $= "btn_a")
+               %assetId = %assetId @ "Cross";
+            else if(%this.gamepadButton $= "btn_b")
+               %assetId = %assetId @ "Circle";
+            else if(%this.gamepadButton $= "btn_x")
+               %assetId = %assetId @ "Square";
+            else if(%this.gamepadButton $= "btn_y")
+               %assetId = %assetId @ "Triangle";
+            else if(%this.gamepadButton $= "btn_l")
+               %assetId = %assetId @ "L1";
+            else if(%this.gamepadButton $= "zaxis")
+               %assetId = %assetId @ "L2";
+            else if(%this.gamepadButton $= "btn_r")
+               %assetId = %assetId @ "R1";
+            else if(%this.gamepadButton $= "rzaxis")
+               %assetId = %assetId @ "R2";
+            else if(%this.gamepadButton $= "btn_start")
+               %assetId = %assetId @ "Options";
+            else if(%this.gamepadButton $= "btn_back")
+               %assetId = %assetId @ "Share";
+         }
+         else if($activeControllerName $= "Nintendo Switch Pro Controller")
+         {
+            %assetId = "UI:Switch_";
+            
+            if(%this.gamepadButton $= "btn_a")
+               %assetId = %assetId @ "B";
+            else if(%this.gamepadButton $= "btn_b")
+               %assetId = %assetId @ "A";
+            else if(%this.gamepadButton $= "btn_x")
+               %assetId = %assetId @ "Y";
+            else if(%this.gamepadButton $= "btn_y")
+               %assetId = %assetId @ "X";
+            else if(%this.gamepadButton $= "btn_l")
+               %assetId = %assetId @ "LB";
+            else if(%this.gamepadButton $= "zaxis")
+               %assetId = %assetId @ "LT";
+            else if(%this.gamepadButton $= "btn_r")
+               %assetId = %assetId @ "RB";
+            else if(%this.gamepadButton $= "rzaxis")
+               %assetId = %assetId @ "RT";
+            else if(%this.gamepadButton $= "btn_start")
+               %assetId = %assetId @ "Plus";
+            else if(%this.gamepadButton $= "btn_back")
+               %assetId = %assetId @ "Minus";
+         }
+         else if($activeControllerName !$= "")
+         {
+            %assetId = "UI:Xbox_";
+            
+            if(%this.gamepadButton $= "btn_a")
+               %assetId = %assetId @ "A";
+            else if(%this.gamepadButton $= "btn_b")
+               %assetId = %assetId @ "B";
+            else if(%this.gamepadButton $= "btn_x")
+               %assetId = %assetId @ "X";
+            else if(%this.gamepadButton $= "btn_y")
+               %assetId = %assetId @ "Y";
+            else if(%this.gamepadButton $= "btn_l")
+               %assetId = %assetId @ "LB";
+            else if(%this.gamepadButton $= "zaxis")
+               %assetId = %assetId @ "LT";
+            else if(%this.gamepadButton $= "btn_r")
+               %assetId = %assetId @ "RB";
+            else if(%this.gamepadButton $= "rzaxis")
+               %assetId = %assetId @ "RT";
+            else if(%this.gamepadButton $= "btn_start")
+               %assetId = %assetId @ "Menu";
+            else if(%this.gamepadButton $= "btn_back")
+               %assetId = %assetId @ "Windows";
+         }
+      } 
+   }
+   else
+   {
+      if(%this.keyboardButton !$= "")
+      {
+         %assetId = "UI:Keyboard_Black_" @ %this.keyboardButton;
+      }
+   }
+   
+   %this.setBitmap(%assetId @ "_image");
+
+   return true;
+}
+
+/// Refreshes a menu input container, updating the buttons inside it
+function MenuInputButtonContainer::refresh(%this)
+{
+   %count = %this.getCount();
+   for(%i=0; %i < %count; %i++)
+   {
+      %btn = %this.getObject(%i);
+      
+      %btn.refresh();
+   }
+}
+
+/// Sets the given MenuInputButtonContainer as the active one. This directs input events
+/// to it's buttons, ensures it's visible, and auto-hides the old active container if it was set
+function MenuInputButtonContainer::setActive(%this)
+{
+   if(isObject($activeMenuButtonContainer))
+      $activeMenuButtonContainer.hidden = true;
+      
+   $activeMenuButtonContainer = %this;
+   $activeMenuButtonContainer.hidden = false;
+   $activeMenuButtonContainer.refresh();
+}
+
+/// Checks the input manager for if we have a gamepad active and gets it's name
+/// If we have one, also sets the active input type to gamepad
+function MenuInputButtonContainer::checkGamepad(%this)
+{
+   %controllerName = SDLInputManager::JoystickNameForIndex(0);
+   
+   $activeControllerName = %controllerName;
+   
+   if($activeControllerName $= "")
+      $activeControllerType = "K&M";
+   else
+      $activeControllerType = "gamepad";     
+}
+   
+/// This is called by the earlier inputs callback that comes from the menu list
+/// this allows us to first check what the input type is, and if the device is different
+/// (such as going from keyboard and mouse to gamepad) we can refresh the buttons to update
+/// the display
+/// Then we process the input to see if it matches to any of the button maps for our 
+/// MenuInputButtons. If we have a match, we execute it's command.
+function MenuInputButtonContainer::processInputs(%this, %device, %action)
+{
+   //check to see if our status has changed
+   %changed = false;
+   
+   %oldDevice = $activeControllerName;
+   
+   %deviceName = stripTrailingNumber(%device);
+   
+   if(%deviceName $= "keyboard" || %deviceName $= "mouse")
+   {
+      if($activeControllerName !$= "K&M")
+         %changed = true;
+         
+      $activeControllerName = "K&M";
+      $activeControllerType = "K&M";
+      Canvas.showCursor();
+   }
+   else
+   {
+      if(%this.checkGamepad())
+      {
+         Canvas.hideCursor();
+      }
+      
+      if($activeControllerType !$= %oldDevice)
+         %changed = true;
+   }
+   
+   if(%changed)
+      %this.refresh();
+      
+   //Now process the input for the button accelerator, if applicable
+   //Set up our basic buttons
+   for(%i=0; %i < %this.getCount(); %i++)
+   {
+      %btn = %this.getObject(%i);
+      
+      if(!%btn.isActive())
+         continue;
+      
+      if($activeControllerType !$= "K&M")
+      {
+         if(%btn.gamepadButton $= %action)
+         {
+            eval(%btn.command);
+         }
+      }
+      else
+      {
+         if(%btn.keyboardButton $= %action)
+         {
+            eval(%btn.command);
+         }
+      }
+   }
+}
+
+/// This is called by the earlier inputs callback that comes from the menu list
+/// this allows us to first check what the input type is, and if the device is different
+/// (such as going from keyboard and mouse to gamepad) we can refresh the buttons to update
+/// the display
+function MenuInputButtonContainer::processAxisEvent(%this, %device, %action, %axisVal)
+{
+   //check to see if our status has changed
+   %changed = false;
+   
+   %oldDevice = $activeControllerName;
+   
+   %deviceName = stripTrailingNumber(%device);
+   
+   if(%deviceName $= "mouse")
+   {
+      if($activeControllerName !$= "K&M")
+         %changed = true;
+         
+      $activeControllerName = "K&M";
+      $activeControllerType = "K&M";
+      Canvas.showCursor();
+   }
+   else
+   {
+      if(%this.checkGamepad())
+      {
+         Canvas.hideCursor();
+      }
+      
+      if($activeControllerType !$= %oldDevice)
+         %changed = true;
+   }
+   
+   if(%changed)
+      %this.refresh();
+}
+
+//
+//
+function onSDLDeviceConnected(%sdlIndex, %deviceName, %deviceType)
+{
+   /*if(GamepadButtonsGui.checkGamepad())
+   {
+      GamepadButtonsGui.hidden = false;  
+   }*/
+}
+
+function onSDLDeviceDisconnected(%sdlIndex)
+{
+   /*if(!GamepadButtonsGui.checkGamepad())
+   {
+      GamepadButtonsGui.hidden = true;
+   }*/   
+}
+
+//==============================================================================
+// Menu Input processing
+// These functions manage the Menu input processing in general
+// Whenever a MenuInputHandler consumes an input event, it'll process them here
+// This'll let the active menu list be navigated, as well as buttons be processed
+// and ultimately handled by the Input Buttons above
+//==============================================================================
+function MenuInputHandler::onAxisEvent(%this, %device, %action, %value)
+{
+   //this is to force a refresh of the menu
+   if(%value == 1 || %value == -1)
+      $activeMenuButtonContainer.processInputs(%device, %action);
+      
+   if(startsWith(%device, "mouse"))
+      return;   
+   
+   if((%action $= "upov" && %value > 0) || (%action $= "yaxis" && %value == -1))
+   {
+      $activeMenuList.navigateUp();
+   }
+   
+   if((%action $= "dpov" && %value > 0) || (%action $= "yaxis" && %value == 1))
+   {
+      $activeMenuList.navigateDown();
+   }
+   
+   //How we deal with the left and right navigation is dependant on the mode of the
+   //menu list
+   if($activeMenuListMode $= "Settings")
+   {
+      if((%action $= "lpov" && %value > 0) || (%action $= "xaxis" && %value == -1))
+      {
+         echo("Options menu nudged left!");
+         //$activeMenuList.navigateLeft();
+      }
+      
+      if((%action $= "rpov" && %value > 0) || (%action $= "xaxis" && %value == -1))
+      {
+         echo("Options menu nudged right!");
+         //$activeMenuList.navigateRight();
+      }
+   }
+   else
+   {
+      if((%action $= "lpov" && %value > 0) || (%action $= "xaxis" && %value == -1))
+      {
+         $activeMenuList.navigateLeft();
+      }
+      
+      if((%action $= "rpov" && %value > 0) || (%action $= "xaxis" && %value == -1))
+      {
+         $activeMenuList.navigateRight();
+      }
+   } 
+}
+
+function MenuInputHandler::onInputEvent(%this, %device, %action, %state)
+{
+   if(%action $= "upov" || %action $= "dpov" || %action $= "lpov" || %action $= "rpov")
+   {
+      %this.onAxisEvent(%device, %action, %state);
+      return;      
+   }
+   
+   if(%state)
+      $activeMenuButtonContainer.processInputs(%device, %action);
+}
+
+//==============================================================================
+// Menu List processing
+// These functions manage the navigation and activation of the Menu Lists
+//==============================================================================
+
+function MenuList::setAsActiveMenuList(%this, %startPosition, %menuMode)
+{
+   if(%startPosition $= "")
+      %startPosition = "0 0";
+      
+   if(%menuMode $= "")
+      %menuMode = "Menu";
+         
+   $activeMenuList = %this;
+   $activeMenuList.hidden = false; 
+   $activeMenuListPosition = %startPosition;
+   $activeMenuListMode = %menuMode;
+   
+   %this.refresh();
+}
+
+
+function MenuList::activate(%this)
+{
+   //check for a highlighted element
+   if($activeMenuListPosition.y > -1 && $activeMenuListPosition < $activeMenuList.getCount())
+   {
+      %btn = $activeMenuList.getObject($activeMenuListPosition.y);
+      %btn.performClick();
+   }
+}
+
+function MenuList::refresh(%this)
+{
+   %selectedObject = 0;
+   for(%i=0; %i < $activeMenuList.getCount(); %i++)
+   {
+      %btn = $activeMenuList.getObject(%i);
+      
+      %isSelected = %i == $activeMenuListPosition.y;
+      
+      %btn.setHighlighted(%isSelected);
+      
+      if(%isSelected)
+         %selectedObject = %i;
+   }
+   
+   if($activeMenuList.isMethod("onNavigate"))
+      $activeMenuList.onNavigate($activeMenuListPosition.y);
+   
+   %parent = $activeMenuList.getParent();
+   if(%parent.getClassName() $= "GuiScrollCtrl")
+   {
+      %parent.scrollToObject(%selectedObject);
+   }
+}
+
+function MenuList::navigateUp(%this)
+{
+   $activeMenuListPosition.y -= 1;
+   if($activeMenuListPosition.y < 0)
+      $activeMenuListPosition.y = 0;
+      
+   %this.refresh();
+}
+
+function MenuList::navigateDown(%this)
+{
+   $activeMenuListPosition.y += 1;
+   if($activeMenuListPosition.y >= $activeMenuList.getCount())
+      $activeMenuListPosition.y = $activeMenuList.getCount()-1;
+      
+   %this.refresh();
+}
+
+function MenuList::navigateLeft()
+{
+   echo("Menu list navigated left!"); 
+   
+   //Atm, we're only handling specific control types, namely options entries, but
+   //this could readily be expanded upon to handle grids like for inventory screens
+   //or the like
+    
+   %btn = $activeMenuList.getObject($activeMenuListPosition.y);
+   if(%btn.getClassName() $= "GuiGameSettingsCtrl" && %btn.isEnabled())
+   {
+      warnf("MenuList::navigateLeft() - actioned the option" @ %btn @ " to the left");
+   }
+}
+
+function MenuList::navigateRight()
+{
+   echo("Menu list navigated right!");  
+   
+   %btn = $activeMenuList.getObject($activeMenuListPosition.y);
+   if(%btn.getClassName() $= "GuiGameSettingsCtrl" && %btn.isEnabled())
+   {
+      warnf("MenuList::navigateLeft() - actioned the option" @ %btn @ " to the left");
+   }
+}