Browse Source

Initial pass to rework and cleanup the main UI interface
Implements interface buttons that react to input type and visually display keybinds
Updates the T3D icon and splash screen

Areloch 5 years ago
parent
commit
bc27125e90
100 changed files with 2380 additions and 703 deletions
  1. 466 18
      Engine/source/gui/controls/guiGameListMenuCtrl.cpp
  2. 110 2
      Engine/source/gui/controls/guiGameListMenuCtrl.h
  3. 14 0
      Engine/source/gui/controls/guiGameListOptionsCtrl.cpp
  4. 12 1
      Engine/source/gui/controls/guiGameListOptionsCtrl.h
  5. 33 0
      Engine/source/gui/controls/guiTextListCtrl.cpp
  6. 2 0
      Engine/source/gui/controls/guiTextListCtrl.h
  7. 1 1
      Engine/source/gui/core/guiCanvas.cpp
  8. 1 3
      Templates/BaseGame/game/core/clientServer/Core_ClientServer.cs
  9. BIN
      Templates/BaseGame/game/data/splash.png
  10. BIN
      Templates/BaseGame/game/data/torque.png
  11. 12 5
      Templates/BaseGame/game/data/ui/UI.cs
  12. 90 165
      Templates/BaseGame/game/data/ui/guis/chooseLevelDlg.cs
  13. 95 155
      Templates/BaseGame/game/data/ui/guis/chooseLevelDlg.gui
  14. 319 0
      Templates/BaseGame/game/data/ui/guis/guiGamepadButton.cs
  15. 239 0
      Templates/BaseGame/game/data/ui/guis/guiGamepadButton.gui
  16. 23 1
      Templates/BaseGame/game/data/ui/guis/joinServerMenu.cs
  17. 125 63
      Templates/BaseGame/game/data/ui/guis/joinServerMenu.gui
  18. 77 16
      Templates/BaseGame/game/data/ui/guis/mainMenu.cs
  19. 27 175
      Templates/BaseGame/game/data/ui/guis/mainMenu.gui
  20. 110 0
      Templates/BaseGame/game/data/ui/guis/messageBoxDlg.gui
  21. 15 0
      Templates/BaseGame/game/data/ui/guis/optionsDlg.gui
  22. 246 89
      Templates/BaseGame/game/data/ui/guis/optionsMenu.cs
  23. 363 9
      Templates/BaseGame/game/data/ui/guis/optionsMenu.gui
  24. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Controller_Disconnected.png
  25. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_0.png
  26. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_1.png
  27. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_10.png
  28. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_11.png
  29. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_12.png
  30. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_2.png
  31. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_3.png
  32. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_4.png
  33. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_5.png
  34. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_6.png
  35. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_7.png
  36. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_8.png
  37. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_9.png
  38. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_A.png
  39. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Alt.png
  40. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Down.png
  41. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Left.png
  42. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Right.png
  43. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Up.png
  44. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Asterisk.png
  45. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_B.png
  46. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Backspace.png
  47. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Backspace_Alt.png
  48. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Bracket_Left.png
  49. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Bracket_Right.png
  50. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_C.png
  51. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Caps_Lock.png
  52. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Command.png
  53. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Ctrl.png
  54. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_D.png
  55. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Del.png
  56. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_E.png
  57. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_End.png
  58. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Enter.png
  59. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Enter_Alt.png
  60. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Enter_Tall.png
  61. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Esc.png
  62. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F.png
  63. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F1.png
  64. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F10.png
  65. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F11.png
  66. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F12.png
  67. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F2.png
  68. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F3.png
  69. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F4.png
  70. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F5.png
  71. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F6.png
  72. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F7.png
  73. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F8.png
  74. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F9.png
  75. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_G.png
  76. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_H.png
  77. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Home.png
  78. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_I.png
  79. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Insert.png
  80. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_J.png
  81. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_K.png
  82. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_L.png
  83. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_M.png
  84. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mark_Left.png
  85. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mark_Right.png
  86. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Minus.png
  87. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Left.png
  88. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Middle.png
  89. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Right.png
  90. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Simple.png
  91. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_N.png
  92. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Num_Lock.png
  93. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_O.png
  94. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_P.png
  95. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Page_Down.png
  96. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Page_Up.png
  97. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Plus.png
  98. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Plus_Tall.png
  99. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Print_Screen.png
  100. BIN
      Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Q.png

+ 466 - 18
Engine/source/gui/controls/guiGameListMenuCtrl.cpp

@@ -25,6 +25,9 @@
 #include "console/consoleTypes.h"
 #include "console/consoleTypes.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
 #include "gfx/gfxDrawUtil.h"
 #include "gfx/gfxDrawUtil.h"
+#include "gui/containers/guiScrollCtrl.h"
+#include "sim\actionMap.h"
+#include "core\strings\stringUnit.h"
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // GuiGameListMenuCtrl
 // GuiGameListMenuCtrl
@@ -33,7 +36,8 @@
 GuiGameListMenuCtrl::GuiGameListMenuCtrl()
 GuiGameListMenuCtrl::GuiGameListMenuCtrl()
  : mSelected(NO_ROW),
  : mSelected(NO_ROW),
    mDebugRender(false),
    mDebugRender(false),
-   mHighlighted(NO_ROW)
+   mHighlighted(NO_ROW),
+   mCallbackOnInputs(false)
 {
 {
    VECTOR_SET_ASSOCIATION(mRows);
    VECTOR_SET_ASSOCIATION(mRows);
 
 
@@ -93,7 +97,7 @@ void GuiGameListMenuCtrl::onRender(Point2I offset, const RectI &updateRect)
       U32 buttonTextureIndex;
       U32 buttonTextureIndex;
       S32 iconIndex = (*row)->mIconIndex;
       S32 iconIndex = (*row)->mIconIndex;
       bool useHighlightIcon = (*row)->mUseHighlightIcon;
       bool useHighlightIcon = (*row)->mUseHighlightIcon;
-      if (! (*row)->mEnabled)
+      if (!(*row)->mEnabled)
       {
       {
          buttonTextureIndex = Profile::TEX_DISABLED;
          buttonTextureIndex = Profile::TEX_DISABLED;
          fontColor = profile->mFontColorNA;
          fontColor = profile->mFontColorNA;
@@ -127,7 +131,7 @@ void GuiGameListMenuCtrl::onRender(Point2I offset, const RectI &updateRect)
       drawUtil->drawBitmapStretchSR(profile->mTextureObject, RectI(currentOffset, rowExtent), profile->getBitmapArrayRect(buttonTextureIndex));
       drawUtil->drawBitmapStretchSR(profile->mTextureObject, RectI(currentOffset, rowExtent), profile->getBitmapArrayRect(buttonTextureIndex));
 
 
       // render the row icon if it has one
       // render the row icon if it has one
-      if ((iconIndex != NO_ICON) && profileHasIcons && (! profile->getBitmapArrayRect((U32)iconIndex).extent.isZero()))
+      if ((iconIndex != NO_ICON) && profileHasIcons && (!profile->getBitmapArrayRect((U32)iconIndex).extent.isZero()))
       {
       {
          iconIndex += Profile::TEX_FIRST_ICON;
          iconIndex += Profile::TEX_FIRST_ICON;
          drawUtil->clearBitmapModulation();
          drawUtil->clearBitmapModulation();
@@ -137,6 +141,11 @@ void GuiGameListMenuCtrl::onRender(Point2I offset, const RectI &updateRect)
       // render the row text
       // render the row text
       drawUtil->setBitmapModulation(fontColor);
       drawUtil->setBitmapModulation(fontColor);
       renderJustifiedText(currentOffset + textOffset, textExtent, (*row)->mLabel);
       renderJustifiedText(currentOffset + textOffset, textExtent, (*row)->mLabel);
+
+      if ((*row)->mMode == Row::Mode::OptionList)
+      {
+         onRenderOptionList((*row), currentOffset);
+      }
    }
    }
 
 
    if (mDebugRender)
    if (mDebugRender)
@@ -147,6 +156,92 @@ void GuiGameListMenuCtrl::onRender(Point2I offset, const RectI &updateRect)
    renderChildControls(offset, updateRect);
    renderChildControls(offset, updateRect);
 }
 }
 
 
+void GuiGameListMenuCtrl::onRenderOptionList(Row* row, Point2I currentOffset)
+{
+   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
+
+   F32 xScale = (float)getWidth() / profile->getRowWidth();
+
+   S32 rowHeight = profile->getRowHeight();
+
+   bool profileHasArrows = profile->hasArrows();
+   Point2I arrowExtent;
+   S32 arrowOffsetY(0);
+   if (profileHasArrows)
+   {
+      arrowExtent = profile->getArrowExtent();
+
+      // icon is centered vertically
+      arrowOffsetY = (rowHeight - arrowExtent.y) >> 1;
+   }
+
+   GFXDrawUtil* drawer = GFX->getDrawUtil();
+
+   Point2I arrowOffset;
+   S32 columnSplit = profile->mColumnSplit * xScale;
+
+   S32 iconIndex;
+   bool hasOptions = (row->mOptions.size() > 0) && row->mSelectedOption > -1;
+   if (hasOptions)
+   {
+      bool isRowSelected = (getSelected() != NO_ROW) && (row == mRows[getSelected()]);
+      bool isRowHighlighted = (getHighlighted() != NO_ROW) ? ((row == mRows[getHighlighted()]) && (row->mEnabled)) : false;
+      if (profileHasArrows)
+      {
+         // render the left arrow
+         bool arrowOnL = (isRowSelected || isRowHighlighted) && (row->mWrapOptions || (row->mSelectedOption > 0));
+         iconIndex = (arrowOnL) ? Profile::TEX_L_ARROW_ON : Profile::TEX_L_ARROW_OFF;
+         arrowOffset.x = currentOffset.x + columnSplit;
+         arrowOffset.y = currentOffset.y + arrowOffsetY;
+
+         drawer->clearBitmapModulation();
+         drawer->drawBitmapStretchSR(profile->mTextureObject, RectI(arrowOffset, arrowExtent), profile->getBitmapArrayRect((U32)iconIndex));
+
+         // render the right arrow
+         bool arrowOnR = (isRowSelected || isRowHighlighted) && (row->mWrapOptions || (row->mSelectedOption < row->mOptions.size() - 1));
+         iconIndex = (arrowOnR) ? Profile::TEX_R_ARROW_ON : Profile::TEX_R_ARROW_OFF;
+         arrowOffset.x = currentOffset.x + (profile->mHitAreaLowerRight.x - profile->mRightPad) * xScale - arrowExtent.x;
+         arrowOffset.y = currentOffset.y + arrowOffsetY;
+
+         drawer->clearBitmapModulation();
+         drawer->drawBitmapStretchSR(profile->mTextureObject, RectI(arrowOffset, arrowExtent), profile->getBitmapArrayRect((U32)iconIndex));
+      }
+
+      // get the appropriate font color
+      ColorI fontColor;
+      if (!row->mEnabled)
+      {
+         fontColor = profile->mFontColorNA;
+      }
+      else if (isRowSelected)
+      {
+         fontColor = profile->mFontColorSEL;
+      }
+      else if (isRowHighlighted)
+      {
+         fontColor = profile->mFontColorHL;
+      }
+      else
+      {
+         fontColor = profile->mFontColor;
+      }
+
+      // calculate text to be at the center between the arrows
+      GFont* font = profile->mFont;
+      StringTableEntry text = row->mOptions[row->mSelectedOption];
+      S32 textWidth = font->getStrWidth(text);
+      S32 columnWidth = profile->mHitAreaLowerRight.x * xScale - profile->mRightPad - columnSplit;
+      S32 columnCenter = columnSplit + (columnWidth >> 1);
+      S32 textStartX = columnCenter - (textWidth >> 1);
+      Point2I textOffset(textStartX, 0);
+
+      // render the option text itself
+      Point2I textExtent(columnWidth, rowHeight);
+      drawer->setBitmapModulation(fontColor);
+      renderJustifiedText(currentOffset + textOffset, textExtent, text);
+   }
+}
+
 void GuiGameListMenuCtrl::onDebugRender(Point2I offset)
 void GuiGameListMenuCtrl::onDebugRender(Point2I offset)
 {
 {
    GuiGameListMenuProfile * profile = (GuiGameListMenuProfile *) mProfile;
    GuiGameListMenuProfile * profile = (GuiGameListMenuProfile *) mProfile;
@@ -197,13 +292,13 @@ void GuiGameListMenuCtrl::onDebugRender(Point2I offset)
    }
    }
 }
 }
 
 
-void GuiGameListMenuCtrl::addRow(const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled)
+void GuiGameListMenuCtrl::addRow(const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, S32 mode)
 {
 {
    Row * row = new Row();
    Row * row = new Row();
-   addRow(row, label, callback, icon, yPad, useHighlightIcon, enabled);
+   addRow(row, label, callback, icon, yPad, useHighlightIcon, enabled, mode);
 }
 }
 
 
-void GuiGameListMenuCtrl::addRow(Row * row, const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled)
+void GuiGameListMenuCtrl::addRow(Row * row, const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, S32 mode)
 {
 {
    row->mLabel = StringTable->insert(label, true);
    row->mLabel = StringTable->insert(label, true);
    row->mScriptCallback = (dStrlen(callback) > 0) ? StringTable->insert(callback, true) : NULL;
    row->mScriptCallback = (dStrlen(callback) > 0) ? StringTable->insert(callback, true) : NULL;
@@ -211,6 +306,7 @@ void GuiGameListMenuCtrl::addRow(Row * row, const char* label, const char* callb
    row->mHeightPad = yPad;
    row->mHeightPad = yPad;
    row->mUseHighlightIcon = useHighlightIcon;
    row->mUseHighlightIcon = useHighlightIcon;
    row->mEnabled = enabled;
    row->mEnabled = enabled;
+   row->mMode = (Row::Mode)mode;
 
 
    mRows.push_back(row);
    mRows.push_back(row);
 
 
@@ -222,6 +318,24 @@ void GuiGameListMenuCtrl::addRow(Row * row, const char* label, const char* callb
    }
    }
 }
 }
 
 
+void GuiGameListMenuCtrl::addRow(const char* label, const char* optionsList, bool wrapOptions, const char* callback, S32 icon, S32 yPad, bool enabled)
+{
+   static StringTableEntry DELIM = StringTable->insert("\t", true);
+   Row* row = new Row();
+   Vector<StringTableEntry> options(__FILE__, __LINE__);
+   S32 count = StringUnit::getUnitCount(optionsList, DELIM);
+   for (S32 i = 0; i < count; ++i)
+   {
+      const char* option = StringUnit::getUnit(optionsList, i, DELIM);
+      options.push_back(StringTable->insert(option, true));
+   }
+   row->mOptions = options;
+   bool hasOptions = row->mOptions.size() > 0;
+   row->mSelectedOption = (hasOptions) ? 0 : NO_OPTION;
+   row->mWrapOptions = wrapOptions;
+   addRow(row, label, callback, icon, yPad, true, (hasOptions) ? enabled : false, Row::Mode::OptionList);
+}
+
 Point2I  GuiGameListMenuCtrl::getMinExtent() const
 Point2I  GuiGameListMenuCtrl::getMinExtent() const
 {
 {
    Point2I parentMin = Parent::getMinExtent();
    Point2I parentMin = Parent::getMinExtent();
@@ -280,12 +394,12 @@ bool GuiGameListMenuCtrl::onWake()
    if( !hasValidProfile() )
    if( !hasValidProfile() )
       return false;
       return false;
       
       
-   if( mRows.empty() )
+   /*if( mRows.empty() )
    {
    {
       Con::errorf( "GuiGameListMenuCtrl: %s can't be woken up without any rows. Please use \"addRow\" to add at least one row to the control before pushing it to the canvas.",
       Con::errorf( "GuiGameListMenuCtrl: %s can't be woken up without any rows. Please use \"addRow\" to add at least one row to the control before pushing it to the canvas.",
          getName() );
          getName() );
       return false;
       return false;
-   }
+   }*/
 
 
    enforceConstraints();
    enforceConstraints();
 
 
@@ -349,7 +463,15 @@ void GuiGameListMenuCtrl::onMouseUp(const GuiEvent &event)
    S32 hitRow = getRow(event.mousePoint);
    S32 hitRow = getRow(event.mousePoint);
    if ((hitRow != NO_ROW) && isRowEnabled(hitRow) && (hitRow == getSelected()))
    if ((hitRow != NO_ROW) && isRowEnabled(hitRow) && (hitRow == getSelected()))
    {
    {
-      activateRow();
+      if (mRows[hitRow]->mMode == Row::Mode::Default)
+      {
+         activateRow();
+      }
+      else if (mRows[hitRow]->mMode == Row::Mode::OptionList)
+      {
+         S32 xPos = globalToLocalCoord(event.mousePoint).x;
+         clickOption((Row*)mRows[getSelected()], xPos);
+      }
    }
    }
 }
 }
 
 
@@ -425,6 +547,13 @@ void GuiGameListMenuCtrl::setSelected(S32 index)
    }
    }
 
 
    mSelected = mClamp(index, 0, mRows.size() - 1);
    mSelected = mClamp(index, 0, mRows.size() - 1);
+
+   //If we're childed to a scroll container, make sure us changing rows has our new position visible
+   GuiScrollCtrl* scroll = dynamic_cast<GuiScrollCtrl*>(getParent());
+   if (scroll)
+   {
+      scroll->scrollRectVisible(getRowBounds(mSelected));
+   }
 }
 }
 
 
 bool GuiGameListMenuCtrl::isRowEnabled(S32 index) const
 bool GuiGameListMenuCtrl::isRowEnabled(S32 index) const
@@ -470,6 +599,63 @@ void GuiGameListMenuCtrl::selectFirstEnabledRow()
    }
    }
 }
 }
 
 
+bool GuiGameListMenuCtrl::onInputEvent(const InputEventInfo& event)
+{
+   if (mCallbackOnInputs)
+   {
+      char deviceString[32];
+      if (!ActionMap::getDeviceName(event.deviceType, event.deviceInst, deviceString))
+         return false;
+
+      if (event.action == SI_MAKE || event.action == SI_BREAK)
+      {
+         bool isModifier = false;
+
+         switch (event.objInst)
+         {
+            case KEY_LCONTROL:
+            case KEY_RCONTROL:
+            case KEY_LALT:
+            case KEY_RALT:
+            case KEY_LSHIFT:
+            case KEY_RSHIFT:
+            case KEY_MAC_LOPT:
+            case KEY_MAC_ROPT:
+               isModifier = true;
+         }
+
+         if ((event.objType == SI_KEY) && isModifier)
+         {
+            char keyString[32];
+            if (!ActionMap::getKeyString(event.objInst, keyString))
+               return false;
+
+            onInputEvent_callback(deviceString, keyString, event.action);
+         }
+         else
+         {
+            const char* actionString = ActionMap::buildActionString(&event);
+            onInputEvent_callback(deviceString, actionString, event.action);
+         }
+      }
+      else if (event.objType == SI_AXIS || event.objType == SI_INT || event.objType == SI_FLOAT)
+      {
+         F32 fValue = event.fValue;
+         if (event.objType == SI_INT)
+            fValue = (F32)event.iValue;
+
+         if (!ActionMap::getDeviceName(event.deviceType, event.deviceInst, deviceString))
+            return false;
+
+         const char* actionString = ActionMap::buildActionString(&event);
+
+         onAxisEvent_callback(deviceString, actionString, fValue);
+      }
+   }
+
+   return false;
+}
+
 bool GuiGameListMenuCtrl::onKeyDown(const GuiEvent &event)
 bool GuiGameListMenuCtrl::onKeyDown(const GuiEvent &event)
 {
 {
    switch (event.keyCode)
    switch (event.keyCode)
@@ -528,6 +714,18 @@ bool GuiGameListMenuCtrl::onGamepadAxisDown(const GuiEvent &event)
    return true;
    return true;
 }
 }
 
 
+bool GuiGameListMenuCtrl::onGamepadAxisLeft(const GuiEvent& event)
+{
+   changeOption(-1);
+   return true;
+}
+
+bool GuiGameListMenuCtrl::onGamepadAxisRight(const GuiEvent& event)
+{
+   changeOption(1);
+   return true;
+}
+
 void GuiGameListMenuCtrl::doScriptCommand(StringTableEntry command)
 void GuiGameListMenuCtrl::doScriptCommand(StringTableEntry command)
 {
 {
    if (command && command[0])
    if (command && command[0])
@@ -589,10 +787,179 @@ void GuiGameListMenuCtrl::setRowLabel(S32 rowIndex, const char * label)
    mRows[rowIndex]->mLabel = StringTable->insert(label, true);
    mRows[rowIndex]->mLabel = StringTable->insert(label, true);
 }
 }
 
 
+void GuiGameListMenuCtrl::clearRows()
+{
+   mRows.clear();
+}
+
+RectI GuiGameListMenuCtrl::getRowBounds(S32 rowIndex)
+{
+   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
+
+   F32 xScale = (float)getWidth() / profile->getRowWidth();
+   S32 rowHeight = profile->getRowHeight();
+
+   Point2I currentOffset = Point2I::Zero;
+   Point2I extent = getExtent();
+   Point2I rowExtent(extent.x, rowHeight);
+
+   for (U32 i = 1; i <= rowIndex; i++)
+   {
+      //the top row can't pad, so we'll ignore it
+      GuiGameListMenuCtrl::Row* row = mRows[i];
+
+      // rows other than the first can have padding above them
+      currentOffset.y += row->mHeightPad;
+      currentOffset.y += rowHeight;
+   }
+
+   return RectI(currentOffset, rowExtent);
+}
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // Console stuff (GuiGameListMenuCtrl)
 // Console stuff (GuiGameListMenuCtrl)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
+StringTableEntry GuiGameListMenuCtrl::getCurrentOption(S32 rowIndex) const
+{
+   if (isValidRowIndex(rowIndex))
+   {
+      Row* row = (Row*)mRows[rowIndex];
+      if (row->mSelectedOption != NO_OPTION)
+      {
+         return row->mOptions[row->mSelectedOption];
+      }
+   }
+   return StringTable->insert("", false);
+}
+
+bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption)
+{
+   if (!isValidRowIndex(rowIndex))
+   {
+      return false;
+   }
+
+   Row* row = (Row*)mRows[rowIndex];
+
+   for (Vector<StringTableEntry>::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption)
+   {
+      if (dStrcmp(*anOption, theOption) == 0)
+      {
+         S32 newIndex = anOption - row->mOptions.begin();
+         row->mSelectedOption = newIndex;
+         return true;
+      }
+   }
+
+   return false;
+}
+
+void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList)
+{
+   static StringTableEntry DELIM = StringTable->insert("\t", true);
+
+   if (!isValidRowIndex(rowIndex))
+   {
+      return;
+   }
+
+   Row* row = (Row*)mRows[rowIndex];
+
+   S32 count = StringUnit::getUnitCount(optionsList, DELIM);
+   row->mOptions.setSize(count);
+   for (S32 i = 0; i < count; ++i)
+   {
+      const char* option = StringUnit::getUnit(optionsList, i, DELIM);
+      row->mOptions[i] = StringTable->insert(option, true);
+   }
+
+   if (row->mSelectedOption >= row->mOptions.size())
+   {
+      row->mSelectedOption = row->mOptions.size() - 1;
+   }
+}
+
+void GuiGameListMenuCtrl::clickOption(Row* row, S32 xPos)
+{
+   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
+   if (!profile->hasArrows())
+   {
+      return;
+   }
+
+   F32 xScale = (float)getWidth() / profile->getRowWidth();
+
+   S32 bitmapArrowWidth = mProfile->getBitmapArrayRect(Profile::TEX_FIRST_ARROW).extent.x;
+
+   S32 leftArrowX1 = profile->mColumnSplit * xScale;
+   S32 leftArrowX2 = leftArrowX1 + bitmapArrowWidth;
+
+   S32 rightArrowX2 = (profile->mHitAreaLowerRight.x - profile->mRightPad) * xScale;
+   S32 rightArrowX1 = rightArrowX2 - bitmapArrowWidth;
+
+   if ((leftArrowX1 <= xPos) && (xPos <= leftArrowX2))
+   {
+      changeOption(row, -1);
+   }
+   else if ((rightArrowX1 <= xPos) && (xPos <= rightArrowX2))
+   {
+      changeOption(row, 1);
+   }
+}
+
+void GuiGameListMenuCtrl::changeOption(S32 delta)
+{
+   if (getSelected() != NO_ROW)
+   {
+      Row* row = (Row*)mRows[getSelected()];
+      changeOption(row, delta);
+   }
+}
+
+void GuiGameListMenuCtrl::changeOption(Row* row, S32 delta)
+{
+   S32 optionCount = row->mOptions.size();
+
+   S32 newSelection = row->mSelectedOption + delta;
+   if (optionCount == 0)
+   {
+      newSelection = NO_OPTION;
+   }
+   else if (!row->mWrapOptions)
+   {
+      newSelection = mClamp(newSelection, 0, optionCount - 1);
+   }
+   else if (newSelection < 0)
+   {
+      newSelection = optionCount - 1;
+   }
+   else if (newSelection >= optionCount)
+   {
+      newSelection = 0;
+   }
+   row->mSelectedOption = newSelection;
+
+   static StringTableEntry LEFT = StringTable->insert("LEFT", true);
+   static StringTableEntry RIGHT = StringTable->insert("RIGHT", true);
+
+   if (row->mScriptCallback != NULL)
+   {
+      setThisControl();
+      StringTableEntry direction = NULL;
+      if (delta < 0)
+      {
+         direction = LEFT;
+      }
+      else if (delta > 0)
+      {
+         direction = RIGHT;
+      }
+      if ((direction != NULL) && (Con::isFunction(row->mScriptCallback)))
+      {
+         Con::executef(row->mScriptCallback, direction);
+      }
+   }
+}
 IMPLEMENT_CONOBJECT(GuiGameListMenuCtrl);
 IMPLEMENT_CONOBJECT(GuiGameListMenuCtrl);
 
 
 ConsoleDocClass( GuiGameListMenuCtrl,
 ConsoleDocClass( GuiGameListMenuCtrl,
@@ -622,6 +989,20 @@ ConsoleDocClass( GuiGameListMenuCtrl,
 IMPLEMENT_CALLBACK( GuiGameListMenuCtrl, onChange, void, (), (),
 IMPLEMENT_CALLBACK( GuiGameListMenuCtrl, onChange, void, (), (),
    "Called when the selected row changes." );
    "Called when the selected row changes." );
 
 
+IMPLEMENT_CALLBACK(GuiGameListMenuCtrl, 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(GuiGameListMenuCtrl, 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 GuiGameListMenuCtrl::initPersistFields()
 void GuiGameListMenuCtrl::initPersistFields()
 {
 {
    addField("debugRender", TypeBool, Offset(mDebugRender, GuiGameListMenuCtrl),
    addField("debugRender", TypeBool, Offset(mDebugRender, GuiGameListMenuCtrl),
@@ -639,21 +1020,25 @@ void GuiGameListMenuCtrl::initPersistFields()
    addField("callbackOnY", TypeString, Offset(mCallbackOnY, GuiGameListMenuCtrl),
    addField("callbackOnY", TypeString, Offset(mCallbackOnY, GuiGameListMenuCtrl),
       "Script callback when the 'Y' button is pressed. 'Y' inputs are Keyboard: Y; Gamepad: Y" );
       "Script callback when the 'Y' button is pressed. 'Y' inputs are Keyboard: Y; Gamepad: Y" );
 
 
+   addField("callbackOnInputs", TypeBool, Offset(mCallbackOnInputs, GuiGameListMenuCtrl),
+      "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.");
+
    Parent::initPersistFields();
    Parent::initPersistFields();
 }
 }
 
 
 DefineEngineMethod( GuiGameListMenuCtrl, addRow, void,
 DefineEngineMethod( GuiGameListMenuCtrl, addRow, void,
-   ( const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled ),
-   ( -1, 0, true, true ),
+   ( const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, int mode ),
+   ( -1, 0, true, true, 0 ),
    "Add a row to the list control.\n\n"
    "Add a row to the list control.\n\n"
    "@param label The text to display on the row as a label.\n"
    "@param label The text to display on the row as a label.\n"
    "@param callback Name of a script function to use as a callback when this row is activated.\n"
    "@param callback Name of a script function to use as a callback when this row is activated.\n"
    "@param icon [optional] Index of the icon to use as a marker.\n"
    "@param icon [optional] Index of the icon to use as a marker.\n"
    "@param yPad [optional] An extra amount of height padding before the row. Does nothing on the first row.\n"
    "@param yPad [optional] An extra amount of height padding before the row. Does nothing on the first row.\n"
    "@param useHighlightIcon [optional] Does this row use the highlight icon?.\n"
    "@param useHighlightIcon [optional] Does this row use the highlight icon?.\n"
-   "@param enabled [optional] If this row is initially enabled." )
+   "@param enabled [optional] If this row is initially enabled.\n"
+   "@param mode [optional] What option mode the row is in. 0 = Default, 1 = OptionList, 2 == Keybind")
 {
 {
-   object->addRow( label, callback, icon, yPad, useHighlightIcon, enabled );
+   object->addRow( label, callback, icon, yPad, useHighlightIcon, enabled, mode);
 }
 }
 
 
 DefineEngineMethod( GuiGameListMenuCtrl, isRowEnabled, bool, ( S32 row ),,
 DefineEngineMethod( GuiGameListMenuCtrl, isRowEnabled, bool, ( S32 row ),,
@@ -715,16 +1100,65 @@ DefineEngineMethod( GuiGameListMenuCtrl, getSelectedRow, S32, (),,
    return object->getSelected();
    return object->getSelected();
 }
 }
 
 
+DefineEngineMethod(GuiGameListMenuCtrl, clearRows, void, (), ,
+   "Gets the index of the currently selected row.\n\n"
+   "@return Index of the selected row.")
+{
+   return object->clearRows();
+}
+
+DefineEngineMethod(GuiGameListMenuCtrl, addOptionRow, void,
+   (const char* label, const char* options, bool wrapOptions, const char* callback, S32 icon, S32 yPad, bool enabled),
+   (-1, 0, true),
+   "Add a row to the list control.\n\n"
+   "@param label The text to display on the row 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 row is activated.\n"
+   "@param icon [optional] Index of the icon to use as a marker.\n"
+   "@param yPad [optional] An extra amount of height padding before the row. Does nothing on the first row.\n"
+   "@param enabled [optional] If this row is initially enabled.")
+{
+   object->addRow(label, options, wrapOptions, callback, icon, yPad, enabled);
+}
+
+DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOption, const char*, (S32 row), ,
+   "Gets the text for the currently selected option of the given row.\n\n"
+   "@param row Index of the row to get the option from.\n"
+   "@return A string representing the text currently displayed as the selected option on the given row. If there is no such displayed text then the empty string is returned.")
+{
+   return object->getCurrentOption(row);
+}
+
+DefineEngineMethod(GuiGameListMenuCtrl, selectOption, bool, (S32 row, const char* option), ,
+   "Set the row's current option to the one specified\n\n"
+   "@param row Index of the row to set an option on.\n"
+   "@param option The option to be made active.\n"
+   "@return True if the row contained the option and was set, false otherwise.")
+{
+   return object->selectOption(row, option);
+}
+
+DefineEngineMethod(GuiGameListMenuCtrl, setOptions, void, (S32 row, const char* optionsList), ,
+   "Sets the list of options on the given row.\n\n"
+   "@param row Index of the row to set options on."
+   "@param optionsList A tab separated list of options for the control.")
+{
+   object->setOptions(row, optionsList);
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // GuiGameListMenuProfile
 // GuiGameListMenuProfile
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 
 
 GuiGameListMenuProfile::GuiGameListMenuProfile()
 GuiGameListMenuProfile::GuiGameListMenuProfile()
-: mHitAreaUpperLeft(0, 0),
-  mHitAreaLowerRight(0, 0),
-  mIconOffset(0, 0),
-  mRowSize(0, 0),
-  mRowScale(1.0f, 1.0f)
+   : mHitAreaUpperLeft(0, 0),
+   mHitAreaLowerRight(0, 0),
+   mIconOffset(0, 0),
+   mRowSize(0, 0),
+   mRowScale(1.0f, 1.0f),
+   mColumnSplit(0),
+   mRightPad(0)
 {
 {
 }
 }
 
 
@@ -775,6 +1209,12 @@ void GuiGameListMenuProfile::enforceConstraints()
    Point2I rowTexExtent = getBitmapArrayRect(TEX_NORMAL).extent;
    Point2I rowTexExtent = getBitmapArrayRect(TEX_NORMAL).extent;
    mRowScale.x = (float) getRowWidth() / rowTexExtent.x;
    mRowScale.x = (float) getRowWidth() / rowTexExtent.x;
    mRowScale.y = (float) getRowHeight() / rowTexExtent.y;
    mRowScale.y = (float) getRowHeight() / rowTexExtent.y;
+
+   if (mHitAreaUpperLeft.x > mColumnSplit || mColumnSplit > mHitAreaLowerRight.x)
+      Con::errorf("GuiGameListOptionsProfile: You can't create %s with a ColumnSplit outside the hit area. You set the split to %d. Please change the ColumnSplit to be in the range [%d, %d].",
+         getName(), mColumnSplit, mHitAreaUpperLeft.x, mHitAreaLowerRight.x);
+
+   mColumnSplit = mClamp(mColumnSplit, mHitAreaUpperLeft.x, mHitAreaLowerRight.x);
 }
 }
 
 
 Point2I GuiGameListMenuProfile::getIconExtent()
 Point2I GuiGameListMenuProfile::getIconExtent()
@@ -827,6 +1267,8 @@ ConsoleDocClass( GuiGameListMenuProfile,
    "   hitAreaLowerRight = \"190 18\";\n"
    "   hitAreaLowerRight = \"190 18\";\n"
    "   iconOffset = \"10 2\";\n"
    "   iconOffset = \"10 2\";\n"
    "   rowSize = \"200 20\";\n"
    "   rowSize = \"200 20\";\n"
+   "   columnSplit = \"100\";\n"
+   "   rightPad = \"4\";\n"
    "   //Properties not specific to this control have been omitted from this example.\n"
    "   //Properties not specific to this control have been omitted from this example.\n"
    "};\n"
    "};\n"
    "@endtsexample\n\n"
    "@endtsexample\n\n"
@@ -848,6 +1290,12 @@ void GuiGameListMenuProfile::initPersistFields()
    addField( "rowSize", TypePoint2I, Offset(mRowSize, GuiGameListMenuProfile),
    addField( "rowSize", TypePoint2I, Offset(mRowSize, GuiGameListMenuProfile),
       "The base size (\"width height\") of a row" );
       "The base size (\"width height\") of a row" );
 
 
+   addField("columnSplit", TypeS32, Offset(mColumnSplit, GuiGameListMenuProfile),
+      "Padding between the leftmost edge of the control, and the row's left arrow.");
+
+   addField("rightPad", TypeS32, Offset(mRightPad, GuiGameListMenuProfile),
+      "Padding between the rightmost edge of the control and the row's right arrow.");
+
    Parent::initPersistFields();
    Parent::initPersistFields();
 
 
    removeField("tab");
    removeField("tab");

+ 110 - 2
Engine/source/gui/controls/guiGameListMenuCtrl.h

@@ -47,6 +47,26 @@ protected:
       bool mUseHighlightIcon;             ///< Toggle the use of the highlight icon
       bool mUseHighlightIcon;             ///< Toggle the use of the highlight icon
       bool mEnabled;                      ///< If this row is enabled or not (grayed out)
       bool mEnabled;                      ///< If this row is enabled or not (grayed out)
 
 
+      enum Mode
+      {
+         Default = 0,
+         OptionList,
+         Keybind
+      };
+
+      Mode mMode;
+
+      //List options
+      Vector<StringTableEntry>   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
+
+      Row() : mLabel(StringTable->EmptyString()), mScriptCallback(StringTable->EmptyString()), mIconIndex(-1), mHeightPad(0), mUseHighlightIcon(false), mEnabled(true),
+         mSelectedOption(0), mWrapOptions(false), mMode(Mode::Default)
+      {
+         VECTOR_SET_ASSOCIATION(mOptions);
+      }
+
       virtual ~Row() {}
       virtual ~Row() {}
    };
    };
 
 
@@ -99,7 +119,43 @@ public:
    /// means no icon will be shown on this row.
    /// means no icon will be shown on this row.
    /// \param yPad [optional] An extra amount of height padding before the row.
    /// \param yPad [optional] An extra amount of height padding before the row.
    /// \param enabled [optional] If this row is initially enabled. Default true.
    /// \param enabled [optional] If this row is initially enabled. Default true.
-   virtual void addRow(const char* label, const char* callback, S32 icon = -1, S32 yPad = 0, bool useHighlightIcon = true, bool enabled = true);
+   virtual void addRow(const char* label, const char* callback, S32 icon = -1, S32 yPad = 0, bool useHighlightIcon = true, bool enabled = true, S32 mode = 0);
+
+   /// Adds a row to the control.
+   ///
+   /// \param label The text to display on the row 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 row is activated. Default NULL means no callback.
+   /// \param icon [optional] Index of the icon to use as a marker. Default -1
+   /// means no icon will be shown on this row.
+   /// \param yPad [optional] An extra amount of height padding before the row.
+   /// \param enabled [optional] If this row is initially enabled. Default true.
+   void addRow(const char* label, const char* optionsList, bool wrapOptions, const char* callback, S32 icon, S32 yPad, bool enabled);
+
+   /// Gets the text for the currently selected option of the given row.
+   ///
+   /// \param rowIndex Index of the row to get the option from.
+   /// \return A string representing the text currently displayed as the selected
+   /// option on the given row. If there is no such displayed text then the empty
+   /// string is returned.
+   StringTableEntry getCurrentOption(S32 rowIndex) const;
+
+   /// Attempts to set the given row to the specified selected option. The option
+   /// will only be set if the option exists in the control.
+   ///
+   /// \param rowIndex Index of the row to set an option on.
+   /// \param option The option to be made active.
+   /// \return True if the row contained the option and was set, false otherwise.
+   bool selectOption(S32 rowIndex, StringTableEntry option);
+
+   /// Sets the list of options on the given row.
+   ///
+   /// \param rowIndex Index of the row to set options on.
+   /// \param optionsList A tab separated list of options for the control.
+   void setOptions(S32 rowIndex, const char* optionsList);
 
 
    /// Activates the current row. The script callback of  the current row will
    /// Activates the current row. The script callback of  the current row will
    /// be called (if it has one).
    /// be called (if it has one).
@@ -115,6 +171,8 @@ public:
 
 
    void onRender(Point2I offset, const RectI &updateRect);
    void onRender(Point2I offset, const RectI &updateRect);
 
 
+   void onRenderOptionList(Row* row, Point2I currentOffset);
+
    /// Callback when the object is registered with the sim.
    /// Callback when the object is registered with the sim.
    ///
    ///
    /// \return True if the profile was successfully added, false otherwise.
    /// \return True if the profile was successfully added, false otherwise.
@@ -158,6 +216,8 @@ public:
    /// \param event A reference to the event that triggered the callback.
    /// \param event A reference to the event that triggered the callback.
    void onMouseUp(const GuiEvent &event);
    void onMouseUp(const GuiEvent &event);
 
 
+   virtual bool onInputEvent(const InputEventInfo& event);
+
    /// Callback when the gamepad axis is activated.
    /// Callback when the gamepad axis is activated.
    ///
    ///
    /// \param event A reference to the event that triggered the callback.
    /// \param event A reference to the event that triggered the callback.
@@ -168,6 +228,20 @@ public:
    /// \param event A reference to the event that triggered the callback.
    /// \param event A reference to the event that triggered the callback.
    virtual bool onGamepadAxisDown(const GuiEvent & event);
    virtual bool onGamepadAxisDown(const GuiEvent & event);
 
 
+   /// Callback when the gamepad axis is activated.
+   ///
+   /// \param event A reference to the event that triggered the callback.
+   virtual bool onGamepadAxisLeft(const GuiEvent& event);
+
+   /// Callback when the gamepad axis is activated.
+   ///
+   /// \param event A reference to the event that triggered the callback.
+   virtual bool onGamepadAxisRight(const GuiEvent& event);
+
+   void clearRows();
+
+   RectI getRowBounds(S32 rowIndex);
+
    DECLARE_CONOBJECT(GuiGameListMenuCtrl);
    DECLARE_CONOBJECT(GuiGameListMenuCtrl);
    DECLARE_CATEGORY( "Gui Game" );
    DECLARE_CATEGORY( "Gui Game" );
    DECLARE_DESCRIPTION( "Base class for cross platform menu controls that are gamepad friendly." );
    DECLARE_DESCRIPTION( "Base class for cross platform menu controls that are gamepad friendly." );
@@ -177,6 +251,7 @@ public:
 
 
    static const S32 NO_ROW          = -1; ///< Indicates a query result of no row found.
    static const S32 NO_ROW          = -1; ///< Indicates a query result of no row found.
    static const S32 NO_ICON         = -1; ///< Indicates a row has no extra icon available
    static const S32 NO_ICON         = -1; ///< Indicates a row has no extra icon available
+   static const S32 NO_OPTION = -1; ///< Indicates there is no option
 
 
 protected:
 protected:
    /// Adds a row to the control.
    /// Adds a row to the control.
@@ -189,7 +264,7 @@ protected:
    /// means no icon will be shown on this row.
    /// means no icon will be shown on this row.
    /// \param yPad [optional] An extra amount of height padding before the row.
    /// \param yPad [optional] An extra amount of height padding before the row.
    /// \param enabled [optional] If this row is initially enabled. Default true.
    /// \param enabled [optional] If this row is initially enabled. Default true.
-   virtual void addRow(Row * row, const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled);
+   virtual void addRow(Row * row, const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, S32 mode = 0);
 
 
    /// Determines if the given index is a valid row index. Any index pointing at
    /// Determines if the given index is a valid row index. Any index pointing at
    /// an existing row is valid.
    /// an existing row is valid.
@@ -224,6 +299,10 @@ protected:
    /// @name Callbacks
    /// @name Callbacks
    /// @{
    /// @{
    DECLARE_CALLBACK( void, onChange, () );
    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.
    /// Evaluates some script. If the command is empty then nothing is evaluated.
@@ -239,6 +318,30 @@ protected:
    bool              mDebugRender;  ///< Determines when to show debug render lines
    bool              mDebugRender;  ///< Determines when to show debug render lines
    Vector<Row *>     mRows;         ///< Holds data wrappers on all the rows we have
    Vector<Row *>     mRows;         ///< Holds data wrappers on all the rows we have
 
 
+private:
+   /// Performs a click on the current option row. 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 row.
+   ///
+   /// \param row The row to perform the click on.
+   /// \param xPos The x position of the the click, relative to the control.
+   void clickOption(Row* row, S32 xPos);
+
+   /// Changes the option on the currently selected row. If there is no row
+   /// selected, this method does nothing.
+   ///
+   /// \param delta The amount to change the option selection by. Typically this
+   /// will be 1 or -1.
+   void changeOption(S32 delta);
+
+   /// Changes the option on the given row.
+   ///
+   /// \param row The row to change the option on.
+   /// \param delta The amount to change the option selection by. Typically this
+   /// will be 1 or -1.
+   void changeOption(Row* row, S32 delta);
+
 private:
 private:
    /// Recalculates the height of this control based on the stored row height and
    /// Recalculates the height of this control based on the stored row height and
    /// and padding on the rows.
    /// and padding on the rows.
@@ -260,6 +363,8 @@ private:
 
 
    S32      mSelected;     ///< index of the currently selected row
    S32      mSelected;     ///< index of the currently selected row
    S32      mHighlighted;  ///< index of the currently highlighted row
    S32      mHighlighted;  ///< index of the currently highlighted row
+
+   bool     mCallbackOnInputs;
 };
 };
 
 
 /// \class GuiGameListMenuProfile
 /// \class GuiGameListMenuProfile
@@ -325,6 +430,9 @@ public:
    Point2I  mIconOffset;         ///< Offset for a row's extra icon
    Point2I  mIconOffset;         ///< Offset for a row's extra icon
    Point2I  mRowSize;            ///< The base size of a row
    Point2I  mRowSize;            ///< The base size of a row
 
 
+   S32   mColumnSplit;  ///< Absolute position of the split between columns
+   S32   mRightPad;     ///< Extra padding between the right arrow and the hit area
+
    GuiGameListMenuProfile();
    GuiGameListMenuProfile();
 
 
    DECLARE_CONOBJECT(GuiGameListMenuProfile);
    DECLARE_CONOBJECT(GuiGameListMenuProfile);

+ 14 - 0
Engine/source/gui/controls/guiGameListOptionsCtrl.cpp

@@ -419,6 +419,11 @@ bool GuiGameListOptionsCtrl::selectOption(S32 rowIndex, const char * theOption)
    return false;
    return false;
 }
 }
 
 
+void GuiGameListOptionsCtrl::clearRows()
+{
+   mRows.clear();
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // Console stuff (GuiGameListOptionsCtrl)
 // Console stuff (GuiGameListOptionsCtrl)
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -484,6 +489,15 @@ DefineEngineMethod( GuiGameListOptionsCtrl, setOptions, void, ( S32 row, const c
    object->setOptions( row, optionsList );
    object->setOptions( row, optionsList );
 }
 }
 
 
+DefineEngineMethod(GuiGameListOptionsCtrl, clearOptions, void, (), ,
+   "Sets the list of options on the given row.\n\n"
+   "@param row Index of the row to set options on."
+   "@param optionsList A tab separated list of options for the control.")
+{
+   object->clearRows();
+}
+
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // GuiGameListOptionsProfile
 // GuiGameListOptionsProfile
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 12 - 1
Engine/source/gui/controls/guiGameListOptionsCtrl.h

@@ -41,7 +41,16 @@ protected:
       S32                        mSelectedOption;  ///< Index into mOptions pointing at the selected option
       S32                        mSelectedOption;  ///< Index into mOptions pointing at the selected option
       bool                       mWrapOptions;     ///< Determines if options should "wrap around" at the ends
       bool                       mWrapOptions;     ///< Determines if options should "wrap around" at the ends
 
 
-      Row() : mSelectedOption(0), mWrapOptions(false)
+      enum Mode
+      {
+         Default = 0,
+         OptionsList,
+         Keybind
+      };
+
+      Mode mMode;
+
+      Row() : mSelectedOption(0), mWrapOptions(false), mMode(Mode::Default)
       {
       {
          VECTOR_SET_ASSOCIATION( mOptions );
          VECTOR_SET_ASSOCIATION( mOptions );
       }
       }
@@ -111,6 +120,8 @@ public:
    /// \param event A reference to the event that triggered the callback.
    /// \param event A reference to the event that triggered the callback.
    virtual bool onGamepadAxisRight(const GuiEvent &event);
    virtual bool onGamepadAxisRight(const GuiEvent &event);
 
 
+   virtual void clearRows();
+
    GuiGameListOptionsCtrl();
    GuiGameListOptionsCtrl();
    ~GuiGameListOptionsCtrl();
    ~GuiGameListOptionsCtrl();
 
 

+ 33 - 0
Engine/source/gui/controls/guiTextListCtrl.cpp

@@ -516,6 +516,39 @@ bool GuiTextListCtrl::onKeyDown( const GuiEvent &event )
 
 
 }
 }
 
 
+bool GuiTextListCtrl::onGamepadAxisUp(const GuiEvent& event)
+{
+   if (mSelectedCell.y < (mList.size() - 1))
+   {
+      S32 yDelta = 0;
+
+      mSelectedCell.y++;
+      yDelta = mCellSize.y;
+
+      GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl*>(getParent());
+      if (parent)
+         parent->scrollDelta(0, yDelta);
+   }
+   return true;
+}
+
+bool GuiTextListCtrl::onGamepadAxisDown(const GuiEvent& event)
+{
+   if (mSelectedCell.y > 0)
+   {
+      S32 yDelta = 0;
+
+      mSelectedCell.y--;
+      yDelta = -mCellSize.y;
+
+      GuiScrollCtrl* parent = dynamic_cast<GuiScrollCtrl*>(getParent());
+      if (parent)
+         parent->scrollDelta(0, yDelta);
+   }
+
+   return true;
+}
+
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
 // Console Methods
 // Console Methods
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 2 - 0
Engine/source/gui/controls/guiTextListCtrl.h

@@ -104,6 +104,8 @@ class GuiTextListCtrl : public GuiArrayCtrl
    const char *getSelectedText();
    const char *getSelectedText();
 
 
    bool onKeyDown(const GuiEvent &event);
    bool onKeyDown(const GuiEvent &event);
+   bool onGamepadAxisUp(const GuiEvent& event);
+   bool onGamepadAxisDown(const GuiEvent& event);
 
 
    virtual void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
    virtual void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
 
 

+ 1 - 1
Engine/source/gui/core/guiCanvas.cpp

@@ -1082,7 +1082,7 @@ bool GuiCanvas::processGamepadEvent(InputEventInfo &inputEvent)
          case SI_YAXIS:
          case SI_YAXIS:
          case XI_THUMBLY:
          case XI_THUMBLY:
          case XI_THUMBRY:
          case XI_THUMBRY:
-            if (negative)
+            if (!negative)
             {
             {
                return mFirstResponder->onGamepadAxisDown(mLastEvent);
                return mFirstResponder->onGamepadAxisDown(mLastEvent);
             }
             }

+ 1 - 3
Templates/BaseGame/game/core/clientServer/Core_ClientServer.cs

@@ -64,9 +64,7 @@ function StartGame( %mission, %hostingType )
 {
 {
    if( %mission $= "" )
    if( %mission $= "" )
    {
    {
-      %id = CL_levelList.getSelectedId();
-      %mission = getField(CL_levelList.getRowTextById(%id), 1);
-      //error("Cannot start a level with no level selected!");
+      %mission = $selectedLevelFile;
    }
    }
 
 
    if (%hostingType !$= "")
    if (%hostingType !$= "")

BIN
Templates/BaseGame/game/data/splash.png


BIN
Templates/BaseGame/game/data/torque.png


+ 12 - 5
Templates/BaseGame/game/data/ui/UI.cs

@@ -14,7 +14,6 @@
 
 
 function UI::onCreate( %this )
 function UI::onCreate( %this )
 {
 {
-   %bool = true;
 }
 }
 
 
 function UI::onDestroy( %this )
 function UI::onDestroy( %this )
@@ -36,9 +35,14 @@ function UI::initClient(%this)
    //Profiles
    //Profiles
    exec("./scripts/profiles.cs");
    exec("./scripts/profiles.cs");
    
    
+   exec("./scripts/menu.keybinds.cs");
+   
    //Now gui files
    //Now gui files
-   exec("./guis/mainMenu.gui");
+   exec("./guis/guiGamepadButton.cs");
+   exec("./guis/guiGamepadButton.gui");
+   
    exec("./guis/mainMenu.cs");
    exec("./guis/mainMenu.cs");
+   exec("./guis/mainMenu.gui");
    
    
    exec("./guis/chooseLevelDlg.gui");
    exec("./guis/chooseLevelDlg.gui");
    exec("./guis/chooseLevelDlg.cs");
    exec("./guis/chooseLevelDlg.cs");
@@ -48,8 +52,8 @@ function UI::initClient(%this)
    
    
    exec("./guis/loadingGui.gui");
    exec("./guis/loadingGui.gui");
    
    
-   exec("./guis/optionsMenu.gui");
    exec("./guis/optionsMenu.cs");
    exec("./guis/optionsMenu.cs");
+   exec("./guis/optionsMenu.gui");
    
    
    exec("./guis/pauseMenu.gui");
    exec("./guis/pauseMenu.gui");
    exec("./guis/pauseMenu.cs");
    exec("./guis/pauseMenu.cs");
@@ -73,8 +77,7 @@ function UI::initClient(%this)
    exec("./guis/startupGui.cs");
    exec("./guis/startupGui.cs");
    
    
    // Load Editor Dialogs
    // Load Editor Dialogs
-   exec("./guis/messageBoxOk.gui");
-   exec("./guis/messageBoxYesNo.gui");
+   exec("./guis/messageBoxDlg.gui");
    
    
    //Load scripts
    //Load scripts
    exec("./scripts/optionsList.cs");
    exec("./scripts/optionsList.cs");
@@ -89,9 +92,13 @@ function UI::initClient(%this)
    exec("./guis/menuGraphics.gui");
    exec("./guis/menuGraphics.gui");
    exec("./guis/menuGraphics.cs");
    exec("./guis/menuGraphics.cs");
    
    
+   //exec("./scripts/menu.keybinds.cs");
+   
    //exec("./scripts/GuiTreeViewCtrl.cs");
    //exec("./scripts/GuiTreeViewCtrl.cs");
    
    
    loadStartup();
    loadStartup();
+   
+   //menuMoveMap.push();
 }
 }
 
 
 function UI::onCreateClientConnection(%this){}
 function UI::onCreateClientConnection(%this){}

+ 90 - 165
Templates/BaseGame/game/data/ui/guis/chooseLevelDlg.cs

@@ -23,13 +23,15 @@
 //----------------------------------------
 //----------------------------------------
 function ChooseLevelDlg::onWake( %this )
 function ChooseLevelDlg::onWake( %this )
 {
 {
-   CL_levelList.clear();
-   ChooseLevelWindow->SmallPreviews.clear();
+   if(!isObject(LevelListEntries))
+      new ArrayObject(LevelListEntries){};
+      
+   LevelList.clearRows();
+   LevelListEntries.empty();
    
    
-   %this->CurrentPreview.visible = false;
-   %this->levelName.visible = false;
-   %this->LevelDescriptionLabel.visible = false;
-   %this->LevelDescription.visible = false;
+   ChooseLevelWindow->CurrentPreview.setBitmap("data/ui/images/no-preview");
+   ChooseLevelWindow->LevelDescriptionLabel.visible = false;
+   ChooseLevelWindow->LevelDescription.visible = false;
    
    
    %assetQuery = new AssetQuery();
    %assetQuery = new AssetQuery();
    AssetDatabase.findAssetType(%assetQuery, "LevelAsset");
    AssetDatabase.findAssetType(%assetQuery, "LevelAsset");
@@ -76,13 +78,22 @@ function ChooseLevelDlg::onWake( %this )
       %this.addMissionFile( "tools/levels/DefaultEditorLevel.mis" );
       %this.addMissionFile( "tools/levels/DefaultEditorLevel.mis" );
    }
    }
 
 
-   // Sort our list
-   CL_levelList.sort(0);
-
-   // Set the first row as the selected row
-   CL_levelList.setSelectedRow(0);
-
-   for (%i = 0; %i < CL_levelList.rowCount(); %i++)
+   for(%i=0; %i < LevelListEntries.count(); %i++)
+   {
+      %levelEntry = LevelListEntries.getKey(%i);
+      
+      LevelList.addRow(getField(%levelEntry, 0), "", -1, -30);
+   }
+   
+   LevelList.setSelected(0);
+   LevelList.onChange();
+   
+   if(!$pref::HostMultiPlayer)
+      LevelSelectTitle.setText("SINGLE PLAYER");
+   else
+      LevelSelectTitle.setText("CREATE SERVER");
+   
+   /*for (%i = 0; %i < LevelList.rowCount(); %i++)
    {
    {
       %preview = new GuiButtonCtrl() {
       %preview = new GuiButtonCtrl() {
          profile = "GuiMenuButtonProfile";
          profile = "GuiMenuButtonProfile";
@@ -127,67 +138,31 @@ function ChooseLevelDlg::onWake( %this )
       %desc = getField(CL_levelList.getRowText(%i), 2);
       %desc = getField(CL_levelList.getRowText(%i), 2);
 
 
       %preview.levelDesc = %desc;
       %preview.levelDesc = %desc;
-   }
-
-   ChooseLevelWindow->SmallPreviews.firstVisible = -1;
-   ChooseLevelWindow->SmallPreviews.lastVisible = -1;
-
-   if (ChooseLevelWindow->SmallPreviews.getCount() > 0)
-   {
-      ChooseLevelWindow->SmallPreviews.firstVisible = 0;
-
-      if (ChooseLevelWindow->SmallPreviews.getCount() < 6)
-         ChooseLevelWindow->SmallPreviews.lastVisible = ChooseLevelWindow->SmallPreviews.getCount() - 1;
-      else
-         ChooseLevelWindow->SmallPreviews.lastVisible = 4;
-   }
-
-   if (ChooseLevelWindow->SmallPreviews.getCount() > 0)
-      ChooseLevelWindow.previewSelected(ChooseLevelWindow->SmallPreviews.getObject(0));
-
-   // If we have 5 or less previews then hide our next/previous buttons
-   // and resize to fill their positions
-   if (ChooseLevelWindow->SmallPreviews.getCount() < 6)
-   {
-      ChooseLevelWindow->PreviousSmallPreviews.setVisible(false);
-      ChooseLevelWindow->NextSmallPreviews.setVisible(false);
-
-      %previewPos = ChooseLevelWindow->SmallPreviews.getPosition();
-      %previousPos = ChooseLevelWindow->PreviousSmallPreviews.getPosition();
-
-      %previewPosX = getWord(%previousPos, 0);
-      %previewPosY = getWord(%previewPos,  1);
-
-      ChooseLevelWindow->SmallPreviews.setPosition(%previewPosX, %previewPosY);
-
-      ChooseLevelWindow->SmallPreviews.colSpacing = 10;//((getWord(NextSmallPreviews.getPosition(), 0)+11)-getWord(PreviousSmallPreviews.getPosition(), 0))/4;
-      ChooseLevelWindow->SmallPreviews.refresh();
-   }
-
-   /*if (ChooseLevelWindow->SmallPreviews.getCount() <= 1)
-   {
-      // Hide the small previews
-      ChooseLevelWindow->SmallPreviews.setVisible(false);
-
-      // Shrink the ChooseLevelWindow so that we don't have a large blank space
-      %extentX = getWord(ChooseLevelWindow.getExtent(), 0);
-      %extentY = getWord(ChooseLevelWindow->SmallPreviews.getPosition(), 1);
+   }*/
+}
 
 
-      ChooseLevelWIndow.setExtent(%extentX, %extentY);
-   }
-   else
-   {
-      // Make sure the small previews are visible
-      ChooseLevelWindow->SmallPreviews.setVisible(true);
+function ChooseLevelButtonHolder::onWake(%this)
+{
+   %this.refresh();
+}
 
 
-      %extentX = getWord(ChooseLevelWindow.getExtent(), 0);
-      
-      %extentY = getWord(ChooseLevelWindow->SmallPreviews.getPosition(), 1);
-      %extentY = %extentY + getWord(ChooseLevelWindow->SmallPreviews.getExtent(), 1);
-      %extentY = %extentY + 9;
+function ChooseLevelButtonHolder::refresh(%this)
+{
+   ChooseLevelButtonHolder.add(GamepadButtonsGui);
+   
+   GamepadButtonsGui.clearButtons();
+   
+   GamepadButtonsGui.setButton(2, "A", "Enter", "Start Level", "ChooseLevelDlg.beginLevel();");
+   GamepadButtonsGui.setButton(3, "B", "Esc", "Back", "ChooseLevelDlg.backOut();");
+   
+   GamepadButtonsGui.refreshButtons();
+}
 
 
-      //ChooseLevelWIndow.setExtent(%extentX, %extentY);
-   //}*/
+function ChooseLevelDlg::onSleep( %this )
+{
+   // This is set from the outside, only stays true for a single wake/sleep
+   // cycle.
+   %this.launchInEditor = false;
 }
 }
 
 
 function ChooseLevelDlg::addMissionFile( %this, %file )
 function ChooseLevelDlg::addMissionFile( %this, %file )
@@ -213,7 +188,7 @@ function ChooseLevelDlg::addMissionFile( %this, %file )
       %LevelInfoObject.delete();
       %LevelInfoObject.delete();
    }
    }
 
 
-   CL_levelList.addRow( CL_levelList.rowCount(), %levelName TAB %file TAB %levelDesc TAB %levelPreview );
+   LevelListEntries.add( %levelName TAB %file TAB %levelDesc TAB %levelPreview );
 }
 }
 
 
 function ChooseLevelDlg::addLevelAsset( %this, %levelAsset )
 function ChooseLevelDlg::addLevelAsset( %this, %levelAsset )
@@ -245,113 +220,57 @@ function ChooseLevelDlg::addLevelAsset( %this, %levelAsset )
    %levelDesc = %levelAsset.description;
    %levelDesc = %levelAsset.description;
    %levelPreview = %levelAsset.levelPreviewImage;
    %levelPreview = %levelAsset.levelPreviewImage;
    
    
-   CL_levelList.addRow( CL_levelList.rowCount(), %levelName TAB %file TAB %levelDesc TAB %levelPreview );
+   LevelListEntries.add( %levelName TAB %file TAB %levelDesc TAB %levelPreview );
 }
 }
 
 
-function ChooseLevelDlg::onSleep( %this )
+function LevelList::onChange(%this)
 {
 {
-   // This is set from the outside, only stays true for a single wake/sleep
-   // cycle.
-   %this.launchInEditor = false;
-}
-
-function ChooseLevelWindow::previewSelected(%this, %preview)
-{
-   // Set the selected level
-   if (isObject(%preview) && %preview.levelIndex !$= "")
-      CL_levelList.setSelectedRow(%preview.levelIndex);
-   else
-      CL_levelList.setSelectedRow(-1);
-
-   // Set the large preview image
-   if (isObject(%preview) && %preview.bitmap !$= "")
-   {
-      %this->CurrentPreview.visible = true;
-      %this->CurrentPreview.setBitmap(%preview.bitmap);
-   }
-   else
-   {
-      %this->CurrentPreview.visible = false;
-   }
-
-   // Set the current level name
-   if (isObject(%preview) && %preview.levelName !$= "")
-   {
-      %this->LevelName.visible = true;
-      %this->LevelName.setText(%preview.levelName);
-   }
+   %index = %this.getSelectedRow();
+   
+   %levelEntry = LevelListEntries.getKey(%index);
+   
+   // Get the name
+   ChooseLevelWindow->LevelName.text = getField(%levelEntry, 0);
+   
+   // Get the level file
+   $selectedLevelFile = getField(%levelEntry, 1);
+   
+   // Find the preview image
+   %levelPreview = getField(%levelEntry, 3);
+   
+   // Test against all of the different image formats
+   // This should probably be moved into an engine function
+   if (isFile(%levelPreview @ ".png") ||
+       isFile(%levelPreview @ ".jpg") ||
+       isFile(%levelPreview @ ".bmp") ||
+       isFile(%levelPreview @ ".gif") ||
+       isFile(%levelPreview @ ".jng") ||
+       isFile(%levelPreview @ ".mng") ||
+       isFile(%levelPreview @ ".tga"))
+      ChooseLevelWindow->CurrentPreview.setBitmap(%previewFile);
    else
    else
-   {
-      %this->LevelName.visible = false;
-   }
+      ChooseLevelWindow->CurrentPreview.setBitmap("data/ui/images/no-preview");
 
 
-   // Set the current level description
-   if (isObject(%preview) && %preview.levelDesc !$= "")
+   // Get the description
+   %levelDesc = getField(%levelEntry, 2);
+   
+   if(%levelDesc !$= "")
    {
    {
-      %this->LevelDescription.visible = true;
-      %this->LevelDescriptionLabel.visible = true;
-      %this->LevelDescription.setText(%preview.levelDesc);
+      ChooseLevelWindow->LevelDescriptionLabel.setVisible(true);
+      ChooseLevelWindow->LevelDescription.setVisible(true);
+      ChooseLevelWindow->LevelDescription.setText(%levelDesc);
    }
    }
    else
    else
    {
    {
-      %this->LevelDescription.visible = false;
-      %this->LevelDescriptionLabel.visible = false;
-   }
-}
-
-function ChooseLevelWindow::previousPreviews(%this)
-{
-   %prevHiddenIdx = %this->SmallPreviews.firstVisible - 1;
-
-   if (%prevHiddenIdx < 0)
-      return;
-
-   %lastVisibleIdx = %this->SmallPreviews.lastVisible;
-
-   if (%lastVisibleIdx >= %this->SmallPreviews.getCount())
-      return;
-
-   %prevHiddenObj  = %this->SmallPreviews.getObject(%prevHiddenIdx);
-   %lastVisibleObj = %this->SmallPreviews.getObject(%lastVisibleIdx);
-
-   if (isObject(%prevHiddenObj) && isObject(%lastVisibleObj))
-   {
-      %this->SmallPreviews.firstVisible--;
-      %this->SmallPreviews.lastVisible--;
-
-      %prevHiddenObj.setVisible(true);
-      %lastVisibleObj.setVisible(false);
-   }
-}
-
-function ChooseLevelWindow::nextPreviews(%this)
-{
-   %firstVisibleIdx = %this->SmallPreviews.firstVisible;
-
-   if (%firstVisibleIdx < 0)
-      return;
-
-   %firstHiddenIdx = %this->SmallPreviews.lastVisible + 1;
-
-   if (%firstHiddenIdx >= %this->SmallPreviews.getCount())
-      return;
-
-   %firstVisibleObj = %this->SmallPreviews.getObject(%firstVisibleIdx);
-   %firstHiddenObj  = %this->SmallPreviews.getObject(%firstHiddenIdx);
-
-   if (isObject(%firstVisibleObj) && isObject(%firstHiddenObj))
-   {
-      %this->SmallPreviews.firstVisible++;
-      %this->SmallPreviews.lastVisible++;
-
-      %firstVisibleObj.setVisible(false);
-      %firstHiddenObj.setVisible(true);
+      ChooseLevelWindow->LevelDescriptionLabel.setVisible(false);
+      ChooseLevelWindow->LevelDescription.setVisible(false);
    }
    }
+   
 }
 }
 
 
 // Do this onMouseUp not via Command which occurs onMouseDown so we do
 // Do this onMouseUp not via Command which occurs onMouseDown so we do
 // not have a lingering mouseUp event lingering in the ether.
 // not have a lingering mouseUp event lingering in the ether.
-function ChooseLevelDlgGoBtn::onMouseUp( %this )
+function ChooseLevelDlg::beginLevel(%this)
 {
 {
    // So we can't fire the button when loading is in progress.
    // So we can't fire the button when loading is in progress.
    if ( isObject( ServerGroup ) )
    if ( isObject( ServerGroup ) )
@@ -370,3 +289,9 @@ function ChooseLevelDlgGoBtn::onMouseUp( %this )
    }
    }
 }
 }
 
 
+function ChooseLevelDlg::backOut(%this)
+{
+   Canvas.popDialog(ChooseLevelDlg);
+   if(isObject(ChooseLevelDlg.returnGui) && ChooseLevelDlg.returnGui.isMethod("onReturnTo"))    
+      ChooseLevelDlg.returnGui.onReturnTo();  
+}

+ 95 - 155
Templates/BaseGame/game/data/ui/guis/chooseLevelDlg.gui

@@ -1,7 +1,7 @@
 //--- OBJECT WRITE BEGIN ---
 //--- OBJECT WRITE BEGIN ---
 %guiContent = new GuiControl(ChooseLevelDlg) {
 %guiContent = new GuiControl(ChooseLevelDlg) {
    position = "0 0";
    position = "0 0";
-   extent = "1280 1024";
+   extent = "1024 768";
    minExtent = "8 8";
    minExtent = "8 8";
    horizSizing = "width";
    horizSizing = "width";
    vertSizing = "height";
    vertSizing = "height";
@@ -13,16 +13,16 @@
    isContainer = "1";
    isContainer = "1";
    canSave = "1";
    canSave = "1";
    canSaveDynamicFields = "1";
    canSaveDynamicFields = "1";
-      enabled = "1";
+      Enabled = "1";
       launchInEditor = "0";
       launchInEditor = "0";
       returnGui = "MainMenuGui";
       returnGui = "MainMenuGui";
 
 
    new GuiControl(ChooseLevelWindow) {
    new GuiControl(ChooseLevelWindow) {
-      position = "80 36";
-      extent = "770 616";
+      position = "48 56";
+      extent = "928 655";
       minExtent = "8 2";
       minExtent = "8 2";
-      horizSizing = "right";
-      vertSizing = "bottom";
+      horizSizing = "center";
+      vertSizing = "center";
       profile = "GuiDefaultProfile";
       profile = "GuiDefaultProfile";
       visible = "1";
       visible = "1";
       active = "1";
       active = "1";
@@ -32,29 +32,51 @@
       canSave = "1";
       canSave = "1";
       canSaveDynamicFields = "0";
       canSaveDynamicFields = "0";
 
 
+      new GuiTextCtrl(LevelSelectTitle) {
+         text = "CHOOSE LEVEL";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "22 10";
+         extent = "307 28";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "MenuHeaderText";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
       new GuiBitmapCtrl() {
       new GuiBitmapCtrl() {
          bitmap = "data/ui/images/no-preview";
          bitmap = "data/ui/images/no-preview";
          color = "255 255 255 255";
          color = "255 255 255 255";
          wrap = "0";
          wrap = "0";
-         position = "369 31";
+         position = "513 71";
          extent = "400 300";
          extent = "400 300";
          minExtent = "8 2";
          minExtent = "8 2";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
          profile = "GuiDefaultProfile";
          profile = "GuiDefaultProfile";
-         visible = "0";
+         visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
          internalName = "CurrentPreview";
          internalName = "CurrentPreview";
-         hidden = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "1";
          canSaveDynamicFields = "1";
-            enabled = "1";
+            Enabled = "1";
       };
       };
       new GuiTextCtrl() {
       new GuiTextCtrl() {
-         text = "Empty Room";
+         text = "EmptyLevel";
          maxLength = "255";
          maxLength = "255";
          margin = "0 0 0 0";
          margin = "0 0 0 0";
          padding = "0 0 0 0";
          padding = "0 0 0 0";
@@ -62,19 +84,18 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "370 335";
-         extent = "90 18";
+         position = "514 375";
+         extent = "398 27";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
-         profile = "GuiMenuButtonProfile";
-         visible = "0";
+         profile = "MenuHeaderText";
+         visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
-         internalName = "levelName";
-         hidden = "1";
+         internalName = "LevelName";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
@@ -87,19 +108,18 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "370 354";
+         position = "522 410";
          extent = "91 18";
          extent = "91 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
-         profile = "GuiMenuButtonProfile";
-         visible = "0";
+         profile = "MenuSubHeaderText";
+         visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
          internalName = "LevelDescriptionLabel";
          internalName = "LevelDescriptionLabel";
-         hidden = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
@@ -107,9 +127,10 @@
          lineSpacing = "2";
          lineSpacing = "2";
          allowColorChars = "0";
          allowColorChars = "0";
          maxChars = "-1";
          maxChars = "-1";
+         text = "This is placeholder text";
          useURLMouseCursor = "0";
          useURLMouseCursor = "0";
-         position = "370 380";
-         extent = "165 14";
+         position = "522 436";
+         extent = "391 14";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
@@ -123,150 +144,69 @@
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
-      new GuiBitmapButtonCtrl() {
-         bitmap = "data/ui/images/previous-button";
-         bitmapMode = "Stretched";
-         autoFitExtents = "0";
-         useModifiers = "0";
-         useStates = "1";
-         masked = "0";
-         groupNum = "-1";
-         buttonType = "PushButton";
-         useMouseEvents = "0";
-         position = "2 -1";
-         extent = "368 33";
-         minExtent = "8 2";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiDefaultProfile";
-         visible = "0";
-         active = "1";
-         command = "ChooseLevelWindow.previousPreviews();";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "0";
-         internalName = "PreviousSmallPreviews";
-         hidden = "1";
-         canSave = "1";
-         canSaveDynamicFields = "1";
-            enabled = "1";
-            wrap = "0";
-      };
-      new GuiBitmapButtonCtrl() {
-         bitmap = "data/ui/images/next-button";
-         bitmapMode = "Stretched";
-         autoFitExtents = "0";
-         useModifiers = "0";
-         useStates = "1";
-         masked = "0";
-         groupNum = "-1";
-         buttonType = "PushButton";
-         useMouseEvents = "0";
-         position = "-3 549";
-         extent = "374 33";
-         minExtent = "8 2";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiDefaultProfile";
-         visible = "0";
-         active = "1";
-         command = "ChooseLevelWindow.nextPreviews();";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "0";
-         internalName = "NextSmallPreviews";
-         hidden = "1";
-         canSave = "1";
-         canSaveDynamicFields = "1";
-            enabled = "1";
-            wrap = "0";
-      };
-      new GuiTextListCtrl(CL_levelList) {
-         columns = "0";
-         fitParentWidth = "1";
-         clipColumnText = "0";
-         position = "-7 1";
-         extent = "80 30";
-         minExtent = "8 8";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiTextArrayProfile";
-         visible = "0";
-         active = "1";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "1";
-         hidden = "1";
-         canSave = "1";
-         canSaveDynamicFields = "0";
-      };
-      new GuiDynamicCtrlArrayControl() {
-         colCount = "1";
-         colSize = "368";
-         rowCount = "14";
-         rowSize = "35";
-         rowSpacing = "0";
-         colSpacing = "10";
-         frozen = "0";
-         autoCellSize = "1";
-         fillRowFirst = "0";
-         dynamicSize = "0";
+      new GuiScrollCtrl() {
+         willFirstRespond = "1";
+         hScrollBar = "dynamic";
+         vScrollBar = "dynamic";
+         lockHorizScroll = "0";
+         lockVertScroll = "0";
+         constantThumbHeight = "0";
+         childMargin = "0 0";
+         mouseWheelScrollSpeed = "-1";
+         margin = "0 0 0 0";
          padding = "0 0 0 0";
          padding = "0 0 0 0";
-         position = "2 33";
-         extent = "368 516";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "0 40";
+         extent = "450 580";
          minExtent = "8 2";
          minExtent = "8 2";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
-         profile = "GuiDefaultProfile";
+         profile = "GuiMenuScrollProfile";
          visible = "1";
          visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "1";
          isContainer = "1";
-         internalName = "SmallPreviews";
-         canSave = "1";
-         canSaveDynamicFields = "0";
-      };
-      new GuiButtonCtrl(ChooseLevelDlgGoBtn) {
-         text = "Start Level";
-         groupNum = "-1";
-         buttonType = "PushButton";
-         useMouseEvents = "1";
-         position = "371 583";
-         extent = "399 33";
-         minExtent = "8 8";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiMenuButtonProfile";
-         visible = "1";
-         active = "1";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "0";
-         canSave = "1";
-         canSaveDynamicFields = "0";
-      };
-      new GuiButtonCtrl(ChooseLevelDlgBackBtn) {
-         text = "Return to Menu";
-         groupNum = "-1";
-         buttonType = "PushButton";
-         useMouseEvents = "1";
-         position = "0 583";
-         extent = "371 33";
-         minExtent = "8 8";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiMenuButtonProfile";
-         visible = "1";
-         active = "1";
-         command = "Canvas.popDialog(ChooseLevelDlg);\n\nif(isObject(ChooseLevelDlg.returnGui) && ChooseLevelDlg.returnGui.isMethod(\"onReturnTo\"))    ChooseLevelDlg.returnGui.onReturnTo();";
-         accelerator = "escape";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "0";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
+
+         new GuiGameListMenuCtrl(LevelList) {
+            debugRender = "0";
+            callbackOnInputs = "1";
+            position = "1 1";
+            extent = "450 580";
+            minExtent = "8 2";
+            horizSizing = "right";
+            vertSizing = "bottom";
+            profile = "DefaultListMenuProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "GuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "0";
+            class = "UIMenuButtonList";
+            canSave = "1";
+            canSaveDynamicFields = "0";
+         };
       };
       };
    };
    };
+   new GuiControl(ChooseLevelButtonHolder) {
+      position = "189 652";
+      extent = "646 130";
+      minExtent = "8 2";
+      horizSizing = "center";
+      vertSizing = "top";
+      profile = "GuiDefaultProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+   };
 };
 };
 //--- OBJECT WRITE END ---
 //--- OBJECT WRITE END ---

+ 319 - 0
Templates/BaseGame/game/data/ui/guis/guiGamepadButton.cs

@@ -0,0 +1,319 @@
+//------------------------------------------------------------------------------
+// global vars
+//------------------------------------------------------------------------------
+
+$BUTTON_A         =  0;
+$BUTTON_B         =  1;
+$BUTTON_X         =  2;
+$BUTTON_Y         =  3;
+$BUTTON_BACK      =  4;
+$BUTTON_START     =  5;
+$BUTTON_LTRIGGER  =  6;
+$BUTTON_RTRIGGER  =  7;
+$BUTTON_LSHOULDER =  8;
+$BUTTON_RSHOULDER =  9;
+$BUTTON_LSTICK    =  10;
+$BUTTON_RSTICK    =  11;
+
+//------------------------------------------------------------------------------
+// GamepadButtonsGui methods
+//------------------------------------------------------------------------------
+
+/// Callback when this control wakes up. All buttons are set to invisible and
+/// disabled.
+function GamepadButtonsGui::onWake(%this)
+{
+   GamepadButtonsGui.controllerName = "K&M";
+}
+
+function GamepadButtonsGui::initMenuButtons(%this)
+{
+   %buttonExt = %this.extent.x / 4 SPC %this.extent.y / 2;
+   
+   for(%i=0; %i < 9; %i++)
+   {
+      %btn = new GuiIconButtonCtrl()
+      {
+         iconLocation = "Left";
+         sizeIconToButton = true;
+         makeIconSquare = true;
+         textLocation = "Right";
+         extent = %buttonExt;
+         profile="GuiMenuButtonProfile";
+         gamepadButton = "";
+         keyboardButton = "";
+      };
+   
+      GamepadButtonsGui.addGuiControl(%btn); 
+   } 
+   
+   GamepadButtonsGui.refresh();
+}
+
+/// Sets the command and text for the specified button. If %text and %command
+/// are left empty, the button will be disabled and hidden.
+/// Note: This command is not executed when the A button is pressed. That
+/// command is executed directly from the GuiGameList___Ctrl. This command is
+/// for the graphical hint and to allow a mouse equivalent.
+///
+/// \param %button (constant) The button to set. See: $BUTTON_A, _B, _X, _Y
+/// \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.
+function GamepadButtonsGui::setButton(%this, %buttonIdx, %gamepadButton, %keyboardButton, %text, %command, %gamepadOnly)
+{
+   if(%buttonIdx >= GamepadButtonsGui.getCount())
+      return;
+      
+   %btn = GamepadButtonsGui.getObject(%buttonIdx);
+   
+   %set = (! ((%text $= "") && (%command $= "")));
+   %btn.setText(%text);
+   %btn.setActive(%set);
+   %btn.setVisible(%set);
+   
+   %btn.gamepadButton = %gamepadButton;
+   %btn.keyboardButton = %keyboardButton;
+   
+   if(%gamepadOnly $= "")
+      %gamepadOnly = false;
+      
+   %btn.gamepadOnly = %gamepadOnly;
+
+   %btn.Command = %command;
+}
+
+function GamepadButtonsGui::checkGamepad(%this)
+{
+   %controllerName = SDLInputManager::JoystickNameForIndex(0);
+   
+   GamepadButtonsGui.controllerName = %controllerName;
+}
+   
+function GamepadButtonsGui::clearButtons(%this)
+{
+   for(%i=0; %i < GamepadButtonsGui.getCount(); %i++)
+   {
+      %btn = GamepadButtonsGui.getObject(%i);
+      
+      %btn.setBitmap("");
+      %btn.text = "";
+      %btn.command = "";
+   }
+}
+
+function GamepadButtonsGui::refreshButtons(%this)
+{
+   //Set up our basic buttons
+   for(%i=0; %i < GamepadButtonsGui.getCount(); %i++)
+   {
+      %btn = GamepadButtonsGui.getObject(%i);
+      
+      %set = (! ((%btn.text $= "") && (%btn.command $= "")));
+      
+      //Special-case of where we're in keyboard+mouse mode, but the menubutton is gamepad only mode, so we early out
+      if(%btn.gamepadOnly && GamepadButtonsGui.controllerName $= "K&M")
+         %set = false;
+         
+      %btn.setActive(%set);
+      %btn.setVisible(%set);
+      
+      if(!%btn.isActive())
+         continue;
+      
+      if(GamepadButtonsGui.controllerName !$= "K&M")
+      {
+         if(%btn.gamepadButton !$= "")
+         {
+            %path = "";
+            if(GamepadButtonsGui.controllerName $= "PS4 Controller")
+            { 
+               %path = "data/ui/images/inputs/PS4/PS4_";
+               
+               if(%btn.gamepadButton $= "A")
+                  %path = %path @ "Cross";
+               else if(%btn.gamepadButton $= "B")
+                  %path = %path @ "Circle";
+               else if(%btn.gamepadButton $= "X")
+                  %path = %path @ "Square";
+               else if(%btn.gamepadButton $= "Y")
+                  %path = %path @ "Triangle";
+               else if(%btn.gamepadButton $= "LB")
+                  %path = %path @ "L1";
+               else if(%btn.gamepadButton $= "LT")
+                  %path = %path @ "L2";
+               else if(%btn.gamepadButton $= "RB")
+                  %path = %path @ "R1";
+               else if(%btn.gamepadButton $= "RT")
+                  %path = %path @ "R2";
+               else      
+                  continue;
+            }
+            else if(GamepadButtonsGui.controllerName $= "Nintendo Switch Pro Controller")
+            {
+               %path = "data/ui/images/inputs/Switch/Switch_";
+               
+               if(%btn.gamepadButton $= "A")
+                  %path = %path @ "B";
+               else if(%btn.gamepadButton $= "B")
+                  %path = %path @ "A";
+               else if(%btn.gamepadButton $= "X")
+                  %path = %path @ "Y";
+               else if(%btn.gamepadButton $= "Y")
+                  %path = %path @ "X";
+               else if(%btn.gamepadButton $= "LB")
+                  %path = %path @ "LB";
+               else if(%btn.gamepadButton $= "LT")
+                  %path = %path @ "LT";
+               else if(%btn.gamepadButton $= "RB")
+                  %path = %path @ "RB";
+               else if(%btn.gamepadButton $= "RT")
+                  %path = %path @ "RT";
+               else      
+                  continue;
+            }
+            else if(GamepadButtonsGui.controllerName !$= "")
+            {
+               %path = "data/ui/images/inputs/Xbox/Xbox_";
+               
+               %path = %path @ %btn.gamepadButton;
+            }
+         } 
+      }
+      else
+      {
+         if(%btn.keyboardButton !$= "")
+         {
+            %path = "data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_" @ %btn.keyboardButton;
+         }
+      }
+      
+      %btn.setBitmap(%path);
+   }
+   
+   return true;
+}
+
+function GamepadButtonsGui::processInputs(%this, %device, %action)
+{
+   //check to see if our status has changed
+   %changed = false;
+   
+   %oldDevice = GamepadButtonsGui.controllerName;
+   
+   if(startsWith(%device, "Keyboard"))
+   {
+      if(GamepadButtonsGui.controllerName !$= %device)
+         %changed = true;
+         
+      GamepadButtonsGui.controllerName = "K&M";
+      Canvas.showCursor();
+   }
+   else if(startsWith(%device, "Mouse"))
+   {
+      if(startsWith(%action, "button"))
+      {
+         if(GamepadButtonsGui.controllerName !$= %device)
+            %changed = true;
+            
+         GamepadButtonsGui.controllerName = "K&M";
+         Canvas.showCursor();
+      }
+   }
+   else
+   {
+      if(GamepadButtonsGui.checkGamepad())
+      {
+         Canvas.hideCursor();
+      }
+      
+      if(GamepadButtonsGui.controllerName !$= %device)
+         %changed = true;
+   }
+   
+   if(%changed)
+      GamepadButtonsGui.refreshButtons();
+      
+   //Now process the input for the button accelerator, if applicable
+   //Set up our basic buttons
+   for(%i=0; %i < GamepadButtonsGui.getCount(); %i++)
+   {
+      %btn = GamepadButtonsGui.getObject(%i);
+      
+      if(!%btn.isActive())
+         continue;
+      
+      if(GamepadButtonsGui.controllerName !$= "K&M")
+      {
+         if(%action $= "btn_r")
+            %action = "RB";
+         else if(%action $= "btn_l")
+            %action = "LB";
+            
+         if(%btn.gamepadButton $= %action)
+         {
+            eval(%btn.command);
+         }
+      }
+      else
+      {
+         if(%action $= "return")
+            %action = "enter";
+         else if(%action $= "escape")
+            %action = "esc";
+            
+         if(%btn.keyboardButton $= %action)
+         {
+            eval(%btn.command);
+         }
+      }
+   }
+}
+
+function GamepadButtonsGui::processAxisEvent(%this, %device, %action, %axisVal)
+{
+   %changed = false;
+   
+   %oldDevice = GamepadButtonsGui.controllerName;
+   
+   if(startsWith(%device, "Mouse"))
+   {
+      if(startsWith(%action, "button"))
+      {
+         if(GamepadButtonsGui.controllerName !$= %device)
+            %changed = true;
+            
+         GamepadButtonsGui.controllerName = "K&M";
+         Canvas.showCursor();
+      }
+   }
+   else
+   {
+      if(GamepadButtonsGui.checkGamepad())
+      {
+         Canvas.hideCursor();
+      }
+      
+      if(GamepadButtonsGui.controllerName !$= %device)
+         %changed = true;
+   }
+   
+   if(%changed)
+      GamepadButtonsGui.refreshButtons();
+}
+//
+//
+function onSDLDeviceConnected(%sdlIndex, %deviceName, %deviceType)
+{
+   /*if(GamepadButtonsGui.checkGamepad())
+   {
+      GamepadButtonsGui.hidden = false;  
+   }*/
+}
+
+function onSDLDeviceDisconnected(%sdlIndex)
+{
+   /*if(!GamepadButtonsGui.checkGamepad())
+   {
+      GamepadButtonsGui.hidden = true;
+   }*/   
+}

+ 239 - 0
Templates/BaseGame/game/data/ui/guis/guiGamepadButton.gui

@@ -0,0 +1,239 @@
+//--- OBJECT WRITE BEGIN ---
+new GuiControl(GamepadButtonsGuiCtrl) {
+   position = "0 0";
+   extent = "646 130";
+   minExtent = "8 2";
+   horizSizing = "right";
+   vertSizing = "bottom";
+   profile = "GamepadDefaultProfile";
+   visible = "1";
+   active = "1";
+   tooltipProfile = "GuiToolTipProfile";
+   hovertime = "1000";
+   isContainer = "1";
+   canSave = "1";
+   canSaveDynamicFields = "1";
+   
+   new GuiDynamicCtrlArrayControl(GamepadButtonsGui) {
+      position = "0 0";
+      extent = "640 100";
+      minExtent = "8 2";
+      horizSizing = "right";
+      vertSizing = "bottom";
+      profile = "GamepadDefaultProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "1";
+      colSize = "155";
+      rowSize = "45";
+      rowSpacing = 5;
+      colSpacing = 5;
+      frozen = true;
+
+      /*new GuiBitmapCtrl(ButtonBImg) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "left";
+         VertSizing = "relative";
+         position = "416 16";
+         Extent = "32 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         bitmap = "data/ui/images/Inputs/Xbox/Xbox_B";
+         wrap = "0";
+      };
+      new GuiTextCtrl(ButtonBLabel) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadButtonTextRight";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "248 16";
+         Extent = "160 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button B Label";
+         maxLength = "1024";
+      };
+      new GuiButtonBaseCtrl(ButtonBButton) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "248 16";
+         Extent = "200 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button";
+         groupNum = "-1";
+         buttonType = "PushButton";
+         useMouseEvents = "0";
+      };
+      new GuiBitmapCtrl(ButtonAImg) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "left";
+         VertSizing = "relative";
+         position = "400 64";
+         Extent = "32 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         bitmap = "data/ui/images/Inputs/Xbox/Xbox_A";
+         wrap = "0";
+      };
+      new GuiTextCtrl(ButtonALabel) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadButtonTextRight";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "232 64";
+         Extent = "160 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button B Label";
+         maxLength = "1024";
+      };
+      new GuiButtonBaseCtrl(ButtonAButton) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "232 64";
+         Extent = "200 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button";
+         groupNum = "-1";
+         buttonType = "PushButton";
+         useMouseEvents = "0";
+      };
+      new GuiBitmapCtrl(ButtonXImg) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "right";
+         VertSizing = "relative";
+         position = "32 64";
+         Extent = "32 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         bitmap = "data/ui/images/Inputs/Xbox/Xbox_X";
+         wrap = "0";
+      };
+      new GuiTextCtrl(ButtonXLabel) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadButtonTextLeft";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "72 64";
+         Extent = "160 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button X Label";
+         maxLength = "1024";
+      };
+      new GuiButtonBaseCtrl(ButtonXButton) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "32 64";
+         Extent = "200 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button";
+         groupNum = "-1";
+         buttonType = "PushButton";
+         useMouseEvents = "0";
+      };
+      new GuiBitmapCtrl(ButtonYImg) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "right";
+         VertSizing = "relative";
+         position = "16 16";
+         Extent = "32 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         bitmap = "data/ui/images/Inputs/Xbox/Xbox_Y";
+         wrap = "0";
+      };
+      new GuiTextCtrl(ButtonYLabel) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadButtonTextLeft";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "55 16";
+         Extent = "164 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button Y Label";
+         maxLength = "1024";
+      };
+      new GuiButtonBaseCtrl(ButtonYButton) {
+         canSaveDynamicFields = "0";
+         Enabled = "1";
+         isContainer = "0";
+         Profile = "GamepadDefaultProfile";
+         HorizSizing = "relative";
+         VertSizing = "relative";
+         position = "16 16";
+         Extent = "208 32";
+         MinExtent = "8 2";
+         canSave = "1";
+         Visible = "1";
+         hovertime = "1000";
+         text = "Button";
+         groupNum = "-1";
+         buttonType = "PushButton";
+         useMouseEvents = "0";
+      };*/
+   };
+};
+//--- OBJECT WRITE END ---

+ 23 - 1
Templates/BaseGame/game/data/ui/guis/joinServerMenu.cs

@@ -6,6 +6,26 @@ function JoinServerMenu::onWake()
    JoinServerJoinBtn.setActive(JS_serverList.rowCount() > 0);
    JoinServerJoinBtn.setActive(JS_serverList.rowCount() > 0);
 }   
 }   
 
 
+function JoinServerButtonHolder::onWake(%this)
+{
+   %this.refresh();
+}
+
+function JoinServerButtonHolder::refresh(%this)
+{
+   JoinServerButtonHolder.add(GamepadButtonsGui);
+   
+   GamepadButtonsGui.clearButtons();
+   
+   GamepadButtonsGui.setButton(1, "A", "", "Query LAN", "JoinServerMenu.queryLan();");
+   GamepadButtonsGui.setButton(2, "X", "", "Query Internet", "JoinServerMenu.query();");
+   GamepadButtonsGui.setButton(3, "B", "", "Refresh", "JoinServerMenu.refresh();");
+   GamepadButtonsGui.setButton(6, "Start", "Enter", "Join", "JoinServerMenu.join();");
+   GamepadButtonsGui.setButton(7, "B", "Esc", "Back", "JoinServerMenu.backOut();");
+   
+   GamepadButtonsGui.refreshButtons();
+}
+
 //----------------------------------------
 //----------------------------------------
 function JoinServerMenu::query(%this)
 function JoinServerMenu::query(%this)
 {
 {
@@ -77,11 +97,13 @@ function JoinServerMenu::refreshSelectedServer( %this )
 }
 }
 
 
 //----------------------------------------
 //----------------------------------------
-function JoinServerMenu::exit(%this)
+function JoinServerMenu::backOut(%this)
 {
 {
    cancelServerQuery();
    cancelServerQuery();
    
    
    Canvas.popDialog(JoinServerMenu);
    Canvas.popDialog(JoinServerMenu);
+   if(isObject(JoinServerMenu.returnGui) && JoinServerMenu.returnGui.isMethod("onReturnTo"))    
+      JoinServerMenu.returnGui.onReturnTo();  
 }
 }
 
 
 //----------------------------------------
 //----------------------------------------

+ 125 - 63
Templates/BaseGame/game/data/ui/guis/joinServerMenu.gui

@@ -15,11 +15,11 @@
    canSaveDynamicFields = "1";
    canSaveDynamicFields = "1";
 
 
    new GuiControl(JoinServerWindow) {
    new GuiControl(JoinServerWindow) {
-      position = "80 36";
-      extent = "800 616";
+      position = "45 56";
+      extent = "928 655";
       minExtent = "8 2";
       minExtent = "8 2";
-      horizSizing = "right";
-      vertSizing = "bottom";
+      horizSizing = "center";
+      vertSizing = "center";
       profile = "GuiDefaultProfile";
       profile = "GuiDefaultProfile";
       visible = "1";
       visible = "1";
       active = "1";
       active = "1";
@@ -29,21 +29,39 @@
       canSave = "1";
       canSave = "1";
       canSaveDynamicFields = "0";
       canSaveDynamicFields = "0";
 
 
-      new GuiTextCtrl(JS_status) {
-         text = "No servers found.";
-         maxLength = "255";
+      new GuiBitmapCtrl() {
+         bitmap = "data/ui/images/hudfill.png";
+         color = "255 255 255 255";
+         wrap = "0";
+         position = "0 0";
+         extent = "928 655";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiDefaultProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiTextCtrl() {
+         text = "JOIN SERVER";
+         maxLength = "1024";
          margin = "0 0 0 0";
          margin = "0 0 0 0";
          padding = "0 0 0 0";
          padding = "0 0 0 0";
          anchorTop = "1";
          anchorTop = "1";
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "277 31";
-         extent = "148 18";
-         minExtent = "8 8";
+         position = "22 10";
+         extent = "207 28";
+         minExtent = "8 2";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
-         profile = "GuiMenuButtonProfile";
+         profile = "MenuHeaderText";
          visible = "1";
          visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
@@ -52,54 +70,28 @@
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
-      new GuiScrollCtrl() {
-         willFirstRespond = "1";
-         hScrollBar = "dynamic";
-         vScrollBar = "alwaysOn";
-         lockHorizScroll = "0";
-         lockVertScroll = "0";
-         constantThumbHeight = "0";
-         childMargin = "0 0";
-         mouseWheelScrollSpeed = "-1";
+      new GuiTextCtrl() {
+         text = "Player Name:";
+         maxLength = "255";
          margin = "0 0 0 0";
          margin = "0 0 0 0";
          padding = "0 0 0 0";
          padding = "0 0 0 0";
          anchorTop = "1";
          anchorTop = "1";
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "10 80";
-         extent = "780 461";
+         position = "12 47";
+         extent = "109 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
-         profile = "GuiMenuScrollProfile";
+         profile = "MenuSubHeaderText";
          visible = "1";
          visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
-         isContainer = "1";
+         isContainer = "0";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
-
-         new GuiTextListCtrl(JS_serverList) {
-            columns = "0 200 270 335 400";
-            fitParentWidth = "1";
-            clipColumnText = "0";
-            position = "1 1";
-            extent = "762 8";
-            minExtent = "8 8";
-            horizSizing = "right";
-            vertSizing = "bottom";
-            profile = "GuiTextArrayProfile";
-            visible = "1";
-            active = "1";
-            altCommand = "JoinServerDlg.join();";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "1";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
       };
       };
       new GuiTextEditCtrl() {
       new GuiTextEditCtrl() {
          historySize = "0";
          historySize = "0";
@@ -114,7 +106,7 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "116 31";
+         position = "124 47";
          extent = "144 18";
          extent = "144 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
@@ -129,8 +121,8 @@
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
-      new GuiTextCtrl() {
-         text = "Player Name:";
+      new GuiTextCtrl(JS_status) {
+         text = "No servers found.";
          maxLength = "255";
          maxLength = "255";
          margin = "0 0 0 0";
          margin = "0 0 0 0";
          padding = "0 0 0 0";
          padding = "0 0 0 0";
@@ -138,17 +130,17 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "12 31";
-         extent = "98 18";
+         position = "277 47";
+         extent = "148 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
-         profile = "GuiMenuButtonProfile";
+         profile = "MenuSubHeaderText";
          visible = "1";
          visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
-         isContainer = "0";
+         isContainer = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
@@ -161,7 +153,7 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "269 59";
+         position = "269 67";
          extent = "36 18";
          extent = "36 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
@@ -184,7 +176,7 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "335 59";
+         position = "335 67";
          extent = "38 18";
          extent = "38 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
@@ -207,7 +199,7 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "412 59";
+         position = "412 67";
          extent = "28 18";
          extent = "28 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
@@ -230,7 +222,7 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "212 59";
+         position = "212 67";
          extent = "20 18";
          extent = "20 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
@@ -253,7 +245,7 @@
          anchorBottom = "0";
          anchorBottom = "0";
          anchorLeft = "1";
          anchorLeft = "1";
          anchorRight = "0";
          anchorRight = "0";
-         position = "12 59";
+         position = "12 67";
          extent = "63 18";
          extent = "63 18";
          minExtent = "8 8";
          minExtent = "8 8";
          horizSizing = "right";
          horizSizing = "right";
@@ -267,9 +259,59 @@
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
+      new GuiScrollCtrl() {
+         willFirstRespond = "1";
+         hScrollBar = "dynamic";
+         vScrollBar = "dynamic";
+         lockHorizScroll = "0";
+         lockVertScroll = "0";
+         constantThumbHeight = "0";
+         childMargin = "0 0";
+         mouseWheelScrollSpeed = "-1";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "19 98";
+         extent = "890 501";
+         minExtent = "8 8";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMenuScrollProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+
+         new GuiTextListCtrl(JS_serverList) {
+            columns = "0 200 270 335 400";
+            fitParentWidth = "1";
+            clipColumnText = "0";
+            rowHeightPadding = "2";
+            position = "1 1";
+            extent = "765 8";
+            minExtent = "8 8";
+            horizSizing = "right";
+            vertSizing = "bottom";
+            profile = "GuiTextArrayProfile";
+            visible = "1";
+            active = "1";
+            altCommand = "JoinServerDlg.join();";
+            tooltipProfile = "GuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "1";
+            canSave = "1";
+            canSaveDynamicFields = "0";
+         };
+      };
       new GuiControl(JS_queryStatus) {
       new GuiControl(JS_queryStatus) {
-         position = "10 541";
-         extent = "778 35";
+         position = "16 615";
+         extent = "900 35";
          minExtent = "8 2";
          minExtent = "8 2";
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
@@ -360,13 +402,14 @@
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
          profile = "GuiMenuButtonProfile";
          profile = "GuiMenuButtonProfile";
-         visible = "1";
+         visible = "0";
          active = "1";
          active = "1";
          command = "Canvas.popDialog(JoinServerMenu);\n\nif(isObject(JoinServerMenu.returnGui) && JoinServerMenu.returnGui.isMethod(\"onReturnTo\"))    JoinServerMenu.returnGui.onReturnTo();";
          command = "Canvas.popDialog(JoinServerMenu);\n\nif(isObject(JoinServerMenu.returnGui) && JoinServerMenu.returnGui.isMethod(\"onReturnTo\"))    JoinServerMenu.returnGui.onReturnTo();";
          accelerator = "escape";
          accelerator = "escape";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         hidden = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
@@ -381,12 +424,13 @@
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
          profile = "GuiMenuButtonProfile";
          profile = "GuiMenuButtonProfile";
-         visible = "1";
+         visible = "0";
          active = "1";
          active = "1";
          command = "JoinServerMenu.queryLan();";
          command = "JoinServerMenu.queryLan();";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         hidden = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
@@ -401,12 +445,13 @@
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
          profile = "GuiMenuButtonProfile";
          profile = "GuiMenuButtonProfile";
-         visible = "1";
+         visible = "0";
          active = "1";
          active = "1";
          command = "JoinServerMenu.query();";
          command = "JoinServerMenu.query();";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         hidden = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
@@ -421,12 +466,13 @@
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
          profile = "GuiMenuButtonProfile";
          profile = "GuiMenuButtonProfile";
-         visible = "1";
+         visible = "0";
          active = "1";
          active = "1";
          command = "JoinServerMenu.refresh();";
          command = "JoinServerMenu.refresh();";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         hidden = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
@@ -441,15 +487,31 @@
          horizSizing = "right";
          horizSizing = "right";
          vertSizing = "bottom";
          vertSizing = "bottom";
          profile = "GuiMenuButtonProfile";
          profile = "GuiMenuButtonProfile";
-         visible = "1";
+         visible = "0";
          active = "0";
          active = "0";
          command = "JoinServerMenu.join();";
          command = "JoinServerMenu.join();";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         hidden = "1";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
    };
    };
+   new GuiControl(JoinServerButtonHolder) {
+      position = "189 652";
+      extent = "646 130";
+      minExtent = "8 2";
+      horizSizing = "center";
+      vertSizing = "top";
+      profile = "GuiDefaultProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+   };
 };
 };
 //--- OBJECT WRITE END ---
 //--- OBJECT WRITE END ---

+ 77 - 16
Templates/BaseGame/game/data/ui/guis/mainMenu.cs

@@ -1,41 +1,102 @@
+function MainMenuGui::onAdd(%this)
+{
+   GamepadButtonsGui.initMenuButtons();
+}
+
 function MainMenuGui::onWake(%this)
 function MainMenuGui::onWake(%this)
 {
 {
-   if (isFunction("getWebDeployment") &&
-       getWebDeployment() &&
-       isObject(%this-->ExitButton))
-      %this-->ExitButton.setVisible(false);
-      
-   MainMenuButtonContainer.hidden = false;
+   MainMenuButtonList.hidden = false; 
+}
+
+function MainMenuGui::onSleep(%this)
+{
+   menuMoveMap.pop();
+}
+
+function MainMenuButtonHolder::onWake(%this)
+{
+   %this.refresh();
+}
+
+function MainMenuButtonHolder::refresh(%this)
+{
+   %this.add(GamepadButtonsGui);
+   
+   GamepadButtonsGui.clearButtons();
+   
+   //GamepadButtonsGui.setButton(2, "A", "Select", "Go", "echo(\"FART\");");
+   //GamepadButtonsGui.setButton(3, "B", "Esc", "Back", "");
+   
+   GamepadButtonsGui.refreshButtons();
+}
+
+function MainMenuButtonList::onAdd(%this)
+{
+   MainMenuButtonList.addRow("Single Player", "openSinglePlayerMenu", 0);
+   MainMenuButtonList.addRow("Create Server", "openMultiPlayerMenu", 4, -15);
+   MainMenuButtonList.addRow("Join Server", "openJoinServerMenu", 4, -15);
+   MainMenuButtonList.addRow("Options", "openOptionsMenu", 6, -15);
+   MainMenuButtonList.addRow("Open World Editor", "openWorldEditorBtn", 6, -15);
+   MainMenuButtonList.addRow("Open GUI Editor", "openGUIEditorBtn", 6, -15);
+   MainMenuButtonList.addRow("Exit Game", "quit", 8, -15);
 }
 }
 
 
-function MainMenuGui::openSinglePlayerMenu(%this)
+function UIMenuButtonList::onInputEvent(%this, %device, %action, %state)
+{
+   if(%state)
+      GamepadButtonsGui.processInputs(%device, %action);
+}
+
+function UIMenuButtonList::onAxisEvent(%this, %device, %action, %axisVal)
+{
+   GamepadButtonsGui.processAxisEvent(%device, %action);
+}
+
+function openSinglePlayerMenu()
 {
 {
    $pref::HostMultiPlayer=false;
    $pref::HostMultiPlayer=false;
    Canvas.pushDialog(ChooseLevelDlg);
    Canvas.pushDialog(ChooseLevelDlg);
-   ChooseLevelDlg.returnGui = %this; 
-   MainMenuButtonContainer.hidden = true; 
+   ChooseLevelDlg.returnGui = MainMenuGui; 
+   MainMenuButtonList.hidden = true; 
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo");
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo");
 }
 }
 
 
-function MainMenuGui::openMultiPlayerMenu(%this)
+function openMultiPlayerMenu()
 {
 {
    $pref::HostMultiPlayer=true;
    $pref::HostMultiPlayer=true;
    Canvas.pushDialog(ChooseLevelDlg);
    Canvas.pushDialog(ChooseLevelDlg);
-   ChooseLevelDlg.returnGui = %this; 
-   MainMenuButtonContainer.hidden = true; 
+   ChooseLevelDlg.returnGui = MainMenuGui; 
+   MainMenuButtonList.hidden = true; 
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo");
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo");
 }
 }
 
 
-function MainMenuGui::openOptionsMenu(%this)
+function openJoinServerMenu()
+{
+   Canvas.pushDialog(JoinServerMenu);
+   JoinServerMenu.returnGui = MainMenuGui; 
+   MainMenuButtonList.hidden = true; 
+}
+
+function openOptionsMenu()
 {
 {
    Canvas.pushDialog(OptionsMenu);
    Canvas.pushDialog(OptionsMenu);
-   OptionsMenu.returnGui = %this; 
-   MainMenuButtonContainer.hidden = true; 
+   OptionsMenu.returnGui = MainMenuGui; 
+   MainMenuButtonList.hidden = true; 
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo");
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo");
 }
 }
 
 
+function openWorldEditorBtn()
+{
+   fastLoadWorldEdit(1);
+}
+
+function openGUIEditorBtn()
+{
+   fastLoadGUIEdit(1);
+}
+
 function MainMenuGui::onReturnTo(%this)
 function MainMenuGui::onReturnTo(%this)
 {
 {
-   MainMenuButtonContainer.hidden = false;
+   MainMenuButtonList.hidden = false;
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo-shortcut");
    MainMenuAppLogo.setBitmap("data/ui/images/Torque-3D-logo-shortcut");
 }
 }

+ 27 - 175
Templates/BaseGame/game/data/ui/guis/mainMenu.gui

@@ -2,7 +2,7 @@ exec( "tools/gui/profiles.ed.cs" );
 
 
 //--- OBJECT WRITE BEGIN ---
 //--- OBJECT WRITE BEGIN ---
 %guiContent = new GuiChunkedBitmapCtrl(MainMenuGui) {
 %guiContent = new GuiChunkedBitmapCtrl(MainMenuGui) {
-   bitmap = "data/ui/images/BackgroundImage.png";
+   bitmap = "data/ui/images/background-dark.png";
    useVariable = "0";
    useVariable = "0";
    tile = "0";
    tile = "0";
    position = "0 0";
    position = "0 0";
@@ -20,9 +20,10 @@ exec( "tools/gui/profiles.ed.cs" );
    canSaveDynamicFields = "1";
    canSaveDynamicFields = "1";
       Enabled = "1";
       Enabled = "1";
       isDecoy = "0";
       isDecoy = "0";
+      navigationIndex = "-1";
 
 
    new GuiBitmapButtonCtrl(MainMenuAppLogo) {
    new GuiBitmapButtonCtrl(MainMenuAppLogo) {
-      bitmap = "data/ui/images/Torque-3D-logo-shortcut";
+      bitmap = "data/ui/images/Torque-3D-logo";
       bitmapMode = "Stretched";
       bitmapMode = "Stretched";
       autoFitExtents = "0";
       autoFitExtents = "0";
       useModifiers = "0";
       useModifiers = "0";
@@ -45,13 +46,33 @@ exec( "tools/gui/profiles.ed.cs" );
       isContainer = "0";
       isContainer = "0";
       canSave = "1";
       canSave = "1";
       canSaveDynamicFields = "1";
       canSaveDynamicFields = "1";
+         navigationIndex = "-1";
    };
    };
-   new GuiControl(MainMenuButtonContainer) {
-      position = "20 193";
-      extent = "442 381";
+   new GuiGameListMenuCtrl(MainMenuButtonList) {
+      class = "UIMenuButtonList";
+      debugRender = "0";
+      callbackOnA = "MainMenuButtonList.activateRow();";
+      callbackOnInputs = "1";
+      position = "292 103";
+      extent = "439 561";
       minExtent = "8 2";
       minExtent = "8 2";
-      horizSizing = "right";
+      horizSizing = "center";
       vertSizing = "center";
       vertSizing = "center";
+      profile = "DefaultListMenuProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "0";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+   };
+   new GuiControl(MainMenuButtonHolder) {
+      position = "190 652";
+      extent = "646 130";
+      minExtent = "8 2";
+      horizSizing = "center";
+      vertSizing = "top";
       profile = "GuiDefaultProfile";
       profile = "GuiDefaultProfile";
       visible = "1";
       visible = "1";
       active = "1";
       active = "1";
@@ -60,175 +81,6 @@ exec( "tools/gui/profiles.ed.cs" );
       isContainer = "1";
       isContainer = "1";
       canSave = "1";
       canSave = "1";
       canSaveDynamicFields = "0";
       canSaveDynamicFields = "0";
-
-      new GuiDynamicCtrlArrayControl() {
-         colCount = "1";
-         colSize = "442";
-         rowCount = "9";
-         rowSize = "40";
-         rowSpacing = "0";
-         colSpacing = "0";
-         frozen = "0";
-         autoCellSize = "1";
-         fillRowFirst = "0";
-         dynamicSize = "0";
-         padding = "0 0 0 0";
-         position = "0 0";
-         extent = "442 381";
-         minExtent = "8 2";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiDefaultProfile";
-         visible = "1";
-         active = "1";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "1";
-         canSave = "1";
-         canSaveDynamicFields = "0";
-
-         new GuiButtonCtrl() {
-            text = "Singleplayer";
-            groupNum = "-1";
-            buttonType = "PushButton";
-            useMouseEvents = "1";
-            position = "0 0";
-            extent = "442 40";
-            minExtent = "8 8";
-            horizSizing = "relative";
-            vertSizing = "bottom";
-            profile = "GuiMenuButtonProfile";
-            visible = "1";
-            active = "1";
-            command = "MainMenuGui.openSinglePlayerMenu();";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "0";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
-         new GuiButtonCtrl() {
-            text = "Create Server";
-            groupNum = "-1";
-            buttonType = "PushButton";
-            useMouseEvents = "0";
-            position = "0 40";
-            extent = "442 40";
-            minExtent = "8 8";
-            horizSizing = "relative";
-            vertSizing = "bottom";
-            profile = "GuiMenuButtonProfile";
-            visible = "1";
-            active = "1";
-            command = "MainMenuGui.openMultiPlayerMenu();";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "0";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
-         new GuiButtonCtrl() {
-            text = "Join Server";
-            groupNum = "-1";
-            buttonType = "PushButton";
-            useMouseEvents = "0";
-            position = "0 80";
-            extent = "442 40";
-            minExtent = "8 8";
-            horizSizing = "relative";
-            vertSizing = "bottom";
-            profile = "GuiMenuButtonProfile";
-            visible = "1";
-            active = "1";
-            command = "Canvas.pushDialog(JoinServerMenu);";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "0";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
-         new GuiButtonCtrl() {
-            text = "Options";
-            groupNum = "-1";
-            buttonType = "PushButton";
-            useMouseEvents = "0";
-            position = "0 120";
-            extent = "442 40";
-            minExtent = "8 8";
-            horizSizing = "relative";
-            vertSizing = "bottom";
-            profile = "GuiMenuButtonProfile";
-            visible = "1";
-            active = "1";
-            command = "MainMenuGui.openOptionsMenu();";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "0";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
-         new GuiButtonCtrl() {
-            text = "Launch World Editor";
-            groupNum = "-1";
-            buttonType = "PushButton";
-            useMouseEvents = "0";
-            position = "0 160";
-            extent = "442 40";
-            minExtent = "8 8";
-            horizSizing = "relative";
-            vertSizing = "bottom";
-            profile = "GuiMenuButtonProfile";
-            visible = "1";
-            active = "1";
-            command = "fastLoadWorldEdit(1);";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "0";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
-         new GuiButtonCtrl() {
-            text = "Launch GUI Editor";
-            groupNum = "-1";
-            buttonType = "PushButton";
-            useMouseEvents = "0";
-            position = "0 200";
-            extent = "442 40";
-            minExtent = "8 8";
-            horizSizing = "relative";
-            vertSizing = "bottom";
-            profile = "GuiMenuButtonProfile";
-            visible = "1";
-            active = "1";
-            command = "fastLoadGUIEdit(1);";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "0";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
-         new GuiButtonCtrl() {
-            text = "Exit";
-            groupNum = "-1";
-            buttonType = "PushButton";
-            useMouseEvents = "0";
-            position = "0 240";
-            extent = "442 40";
-            minExtent = "8 8";
-            horizSizing = "relative";
-            vertSizing = "bottom";
-            profile = "GuiMenuButtonProfile";
-            visible = "1";
-            active = "1";
-            command = "quit();";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "0";
-            internalName = "ExitButton";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-         };
-      };
    };
    };
 };
 };
 //--- OBJECT WRITE END ---
 //--- OBJECT WRITE END ---

+ 110 - 0
Templates/BaseGame/game/data/ui/guis/messageBoxDlg.gui

@@ -0,0 +1,110 @@
+//--- OBJECT WRITE BEGIN ---
+%guiContent = new GuiControl(MessageBoxDlg) {
+   position = "0 0";
+   extent = "1024 768";
+   minExtent = "8 8";
+   horizSizing = "width";
+   vertSizing = "height";
+   profile = "GuiOverlayProfile";
+   visible = "1";
+   active = "1";
+   tooltipProfile = "GuiToolTipProfile";
+   hovertime = "1000";
+   isContainer = "1";
+   canSave = "1";
+   canSaveDynamicFields = "1";
+      helpTag = "0";
+
+   new GuiControl(MessageBoxCtrl) {
+      position = "192 197";
+      extent = "641 381";
+      minExtent = "8 2";
+      horizSizing = "center";
+      vertSizing = "center";
+      profile = "GuiDefaultProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+
+      new GuiBitmapCtrl() {
+         bitmap = "data/ui/images/hudfill.png";
+         color = "255 255 255 255";
+         wrap = "0";
+         position = "0 0";
+         extent = "1156 704";
+         minExtent = "8 2";
+         horizSizing = "width";
+         vertSizing = "height";
+         profile = "GuiDefaultProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiTextCtrl(MessageBoxTitleText) {
+         text = "OPTIONS";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "32 10";
+         extent = "577 28";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "MenuHeaderText";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiMLTextCtrl(MessageBoxText) {
+         lineSpacing = "2";
+         allowColorChars = "0";
+         maxChars = "-1";
+         useURLMouseCursor = "0";
+         position = "81 83";
+         extent = "481 14";
+         minExtent = "8 8";
+         horizSizing = "center";
+         vertSizing = "center";
+         profile = "MenuMLSubHeaderText";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiControl(MessageBoxButtonHolder) {
+         position = "0 237";
+         extent = "641 130";
+         minExtent = "8 2";
+         horizSizing = "center";
+         vertSizing = "top";
+         profile = "GuiDefaultProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+   };
+};
+//--- OBJECT WRITE END ---

+ 15 - 0
Templates/BaseGame/game/data/ui/guis/optionsDlg.gui

@@ -1413,5 +1413,20 @@
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
    };
    };
+   new GuiControl(OptionsButtonHolder) {
+      position = "190 652";
+      extent = "646 130";
+      minExtent = "8 2";
+      horizSizing = "center";
+      vertSizing = "top";
+      profile = "GuiDefaultProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+   };
 };
 };
 //--- OBJECT WRITE END ---
 //--- OBJECT WRITE END ---

+ 246 - 89
Templates/BaseGame/game/data/ui/guis/optionsMenu.cs

@@ -46,112 +46,260 @@
 //headbob
 //headbob
 //FOV
 //FOV
 
 
+function OptionsMenuSettingsList::onAdd(%this)
+{
+   %yesNoList = "No\tYes";
+   %onOffList = "Off\tOn";
+   %highMedLow = "Low\tMedium\tHigh";
+   %anisoFilter = "Off\t4\t8\t16";
+   OptionsMenuSettingsList.addOptionRow("Shadow Quality", "High\tMedium\tLow\tNone", false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Soft Shadow Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Mesh Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Texture Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Terrain Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Decal Lifetime", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Ground Cover Density", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Shader Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Anisotropic Filtering", %anisoFilter, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Anti-Aliasing", "4\t2\t1\tOff", false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Refresh Rate", "75\t60\t30", false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Parallax", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Water Reflections", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("SSAO", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Depth of Field", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Vignette", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Light Rays", %onOffList, false, "", -1, -30);
+}
+
 function OptionsMenu::onWake(%this)
 function OptionsMenu::onWake(%this)
 {
 {
-    OptionsMain.hidden = false;
-    ControlsMenu.hidden = true;
-    GraphicsMenu.hidden = true;
-    AudioMenu.hidden = true;
-    CameraMenu.hidden = true;
-    ScreenBrightnessMenu.hidden = true;
-    
-    OptionsOKButton.hidden = false;
-    OptionsCancelButton.hidden = false;
-    OptionsDefaultsButton.hidden = false;
-    
-    OptionsMenu.tamlReader = new Taml();
-    
-    OptionsSettingStack.clear();
+   MainMenuButtonList.hidden = true;
    
    
-   %array = OptionsSettingStack;
-   %array.clear();
-   
-   %keyboardMenuBtn = new GuiButtonCtrl(){
-      text = "Keyboard and Mouse";
-      profile = GuiMenuButtonProfile;
-      extent = %array.extent.x SPC "35";
-      command="ControlsMenu::loadSettings();";
-   };
+   %this.pageTabIndex = 0;
+   %tab = %this.getTab();
+   %tab.performClick();
+}
+
+function OptionsButtonHolder::onWake(%this)
+{
+   %this.refresh();
+}
+
+function OptionsButtonHolder::refresh(%this)
+{
+   OptionsButtonHolder.add(GamepadButtonsGui);
    
    
-   %controllerMenuBtn = new GuiButtonCtrl(){
-      text = "Controller";
-      profile = GuiMenuButtonProfile;
-      extent = %array.extent.x SPC "35";
-      command="DisplayMenu::loadSettings();";
-   };
+   GamepadButtonsGui.clearButtons();
    
    
-   %displayMenuBtn = new GuiButtonCtrl(){
-      text = "Display";
-      profile = GuiMenuButtonProfile;
-      extent = %array.extent.x SPC "35";
-      command="DisplayMenu::loadSettings();";
-   };
+   GamepadButtonsGui.setButton(0, "LB", "", "Prev Tab", "OptionsMenu.prevTab();", true);
+   GamepadButtonsGui.setButton(1, "RB", "", "Next Tab", "OptionsMenu.nextTab();", true);
+   GamepadButtonsGui.setButton(2, "Start", "Enter", "Apply", "OptionsMenu.apply();");
+   GamepadButtonsGui.setButton(3, "B", "Esc", "Back", "OptionsMenu.backOut();");
+   GamepadButtonsGui.setButton(7, "Back", "R", "Reset", "OptionsMenu.backOut();");
    
    
-   %graphicsMenuBtn = new GuiButtonCtrl(){
-      text = "Graphics";
-      profile = GuiMenuButtonProfile;
-      extent = %array.extent.x SPC "35";
-      command="GraphicsMenu::loadSettings();";
-   };
+   GamepadButtonsGui.refreshButtons();
+}
+
+function OptionsMenuSettingsList::onChange(%this)
+{
+   return;
    
    
-   %audioMenuBtn = new GuiButtonCtrl(){
-      text = "Audio";
-      profile = GuiMenuButtonProfile;
-      extent = %array.extent.x SPC "35";
-      command="AudioMenu::loadSettings();";
-   };
+   OptionsMenuSettingsList.clearOptions();
+
+   %currentRowText = %this.getRowLabel(%this.getSelectedRow());
    
    
-   %gameplayMenuBtn = new GuiButtonCtrl(){
-      text = "Gameplay";
-      profile = GuiMenuButtonProfile;
-      extent = %array.extent.x SPC "35";
-      command="GameplayMenu::loadSettings();";
-   };
+   if(%currentRowText $= "Display")
+   {
+      OptionsMenuList.populateDisplaySettingsList();
+   }
+   else if(%currentRowText $= "Graphics")
+   {
+      OptionsMenuList.populateGraphicsSettingsList();
+   }
+   else if(%currentRowText $= "Audio")
+   {
+      OptionsMenuList.populateAudioSettingsList();
+   }
+   else if(%currentRowText $= "Keyboard + Mouse")
+   {
+      OptionsMenuList.populateKeyboardMouseSettingsList();
+   }
+   else if(%currentRowText $= "Gamepad")
+   {
+      OptionsMenuList.populateGamepadSettingsList();
+   }
+}
+
+function OptionsMenu::prevTab(%this)
+{
+   %this.pageTabIndex--;
+   if(%this.pageTabIndex < 0)
+      %this.pageTabIndex = 4;
+      
+   %tabBtn = %this.getTab();
+   %tabBtn.performClick();
+}
+
+function OptionsMenu::nextTab(%this)
+{
+   %this.pageTabIndex++;
+   if(%this.pageTabIndex > 4)
+      %this.pageTabIndex = 0;
+      
+   %tabBtn = %this.getTab();
+   %tabBtn.performClick();
+}
+
+function OptionsMenu::getTab(%this)
+{
+   if(%this.pageTabIndex == 0)
+      return %this-->DisplayButton;
+   else if(%this.pageTabIndex == 1)
+      return %this-->GraphicsButton;
+   else if(%this.pageTabIndex == 2)
+      return %this-->AudioButton;
+   else if(%this.pageTabIndex == 3)
+      return %this-->KBMButton;
+   else if(%this.pageTabIndex == 4)
+      return %this-->GamepadButton;
+   else 
+      return %this-->DisplayButton;
+}
+
+function OptionsMenu::populateDisplaySettingsList(%this)
+{
+   %this.pageTabIndex = 0;
+   OptionsMenuSettingsList.clearRows();
    
    
-   %array.add(%keyboardMenuBtn);
-   //%array.add(%controllerMenuBtn);
-   %array.add(%displayMenuBtn);
-   %array.add(%graphicsMenuBtn);
-   %array.add(%audioMenuBtn);
-   //%array.add(%gameplayMenuBtn);
+   %resolutionList = getScreenResolutionList();
+   //OptionsMenuSettingsList.addOptionsRow("Resolution", %yesNoList, false, "", 0, -15);
+   OptionsMenuSettingsList.addOptionRow("Resolution", %resolutionList, false, "screenResolutionOptionChanged", -1, -30);
+}
+
+function _makePrettyResString( %resString, %giveAspectRation )
+{
+   %width = getWord( %resString, $WORD::RES_X );
+   %height = getWord( %resString, $WORD::RES_Y );
    
    
-   //We programmatically set up our settings here so we can do some prepwork on the fields/controls
-   //Presets
-   /*OptionsMenu.addSettingOption(%array, "Preset", "High", ShadowQualityList, $pref::Video::Resolution);
+   %aspect = %width / %height;
+   %aspect = mRound( %aspect * 100 ) * 0.01;            
    
    
-   //AA
-   OptionsMenu.addSettingOption(%array, "AntiAliasing", "FXAA 4x", ShadowQualityList, $pref::Video::Resolution);
+   switch$( %aspect )
+   {
+      case "1.33":
+         %aspect = "4:3";
+      case "1.78":
+         %aspect = "16:9";
+      default:
+         %aspect = "";
+   }
    
    
-   //Lighting
-   OptionsMenu.addSettingOption(%array, "Shadow Quality", "High", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Shadow Caching", "On", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Soft Shadows", "High", ShadowQualityList, $pref::Video::Resolution);
+   %outRes = %width @ " x " @ %height;
+   if ( %giveAspectRation && %aspect !$= "" )
+      %outRes = %outRes @ "  (" @ %aspect @ ")";
+      
+   return %outRes;   
+}
+
+function getScreenResolutionList()
+{
+   %returnsList = "";
    
    
-   //Models and Textures
-   OptionsMenu.addSettingOption(%array, "Level of Detail", "High", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Texture Quality", "High", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Material Quality", "High", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Terrain Detail", "High", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Decal Lifetime", "High", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Ground Clutter Density", "High", ShadowQualityList, $pref::Video::Resolution);
+   %resCount = Canvas.getModeCount();
+   for (%i = 0; %i < %resCount; %i++)
+   {
+      %testResString = Canvas.getMode( %i );
+      %testRes = _makePrettyResString( %testResString );
+      
+      //sanitize
+      %found = false;
+      %retCount = getTokenCount(%returnsList, "\t");
+      for (%x = 0; %x < %retCount; %x++)
+      {
+         %existingEntry = getToken(%returnsList, "\t", %x);
+         if(%existingEntry $= %testRes)
+         {
+            %found = true;
+            break;  
+         }
+      }
+      
+      if(%found)
+         continue;
+                     
+      if(%i != 0)
+         %returnsList = %returnsList @ "\t" @ %testRes;
+      else
+         %returnsList = %testRes;
+   }
    
    
-   //Effects
-   OptionsMenu.addSettingOption(%array, "HDR", "On", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Parallax", "On", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Ambient Occlusion", "On", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Light Rays", "On", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Depth of Field", "On", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Vignetting", "On", ShadowQualityList, $pref::Video::Resolution);
-   OptionsMenu.addSettingOption(%array, "Water Reflections", "On", ShadowQualityList, $pref::Video::Resolution);
+   return %returnsList;
+}
+
+function screenResolutionOptionChanged()
+{
+   echo("Resolution Changed to: " @ OptionsMenuSettingsList.getCurrentOption(0));
+}
+
+function OptionsMenu::populateGraphicsSettingsList(%this)
+{
+   %this.pageTabIndex = 1;
+   OptionsMenuSettingsList.clearRows();
    
    
-   OptionsMenu.addSettingOption(%array, "Anisotropic Filtering", "16x", ShadowQualityList, $pref::Video::Resolution);*/
+   %yesNoList = "No\tYes";
+   %onOffList = "Off\tOn";
+   %highMedLow = "Low\tMedium\tHigh";
+   %anisoFilter = "Off\t4\t8\t16";
+   OptionsMenuSettingsList.addOptionRow("Shadow Quality", "High\tMedium\tLow\tNone", false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Soft Shadow Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Mesh Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Texture Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Terrain Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Decal Lifetime", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Ground Cover Density", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Shader Quality", %highMedLow, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Anisotropic Filtering", %anisoFilter, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Anti-Aliasing", "4\t2\t1\tOff", false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Refresh Rate", "75\t60\t30", false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Parallax", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Water Reflections", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("SSAO", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Depth of Field", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Vignette", %onOffList, false, "", -1, -30);
+   OptionsMenuSettingsList.addOptionRow("Light Rays", %onOffList, false, "", -1, -30);
+}
+
+function OptionsMenu::populateAudioSettingsList(%this)
+{
+   %this.pageTabIndex = 2;
+   OptionsMenuSettingsList.clearRows();
    
    
-   if(!isObject(GraphicsSettingsCache))
-   {
-      new ArrayObject(GraphicsSettingsCache){};
-   }
+   %yesNoList = "Yes\tNo";
+   OptionsMenuSettingsList.addOptionRow("Audio Device", %yesNoList, false, "", -1, -15);
+}
+
+function OptionsMenu::populateKeyboardMouseSettingsList(%this)
+{
+   %this.pageTabIndex = 3;
+   OptionsMenuSettingsList.clearRows();
    
    
-   GraphicsSettingsCache.empty();
+   OptionsMenuSettingsList.addOptionRow("Forward", "W", false, "", -1, -15);
+}
+
+function OptionsMenu::populateGamepadSettingsList(%this)
+{
+   %this.pageTabIndex = 4;
+   OptionsMenuSettingsList.clearRows();
+}
+
+function OptionsMenuList::activateRow(%this)
+{
+   OptionsMenuSettingsList.setFirstResponder();
+}
+
+function OptionsMenuList::backOut(%this)
+{
+   OptionsMenuList.setFirstResponder();
 }
 }
 
 
 function OptionsMenuOKButton::onClick(%this)
 function OptionsMenuOKButton::onClick(%this)
@@ -161,6 +309,15 @@ function OptionsMenuOKButton::onClick(%this)
     OptionsMenu.backOut();
     OptionsMenu.backOut();
 }
 }
 
 
+//
+//
+function OptionsMenuSettingsList::backOut(%this)
+{
+   OptionsMenuList.setFirstResponder();
+}
+//
+//
+
 function OptionsMenuCancelButton::onClick(%this)
 function OptionsMenuCancelButton::onClick(%this)
 {
 {
     //we don't save, so just back out of the menu 
     //we don't save, so just back out of the menu 

+ 363 - 9
Templates/BaseGame/game/data/ui/guis/optionsMenu.gui

@@ -13,23 +13,23 @@
    isContainer = "1";
    isContainer = "1";
    canSave = "1";
    canSave = "1";
    canSaveDynamicFields = "1";
    canSaveDynamicFields = "1";
-      returnGui = "MainMenuGui";
-      tamlReader = "20077";
+      tamlReader = "20088";
       tile = "0";
       tile = "0";
       useVariable = "0";
       useVariable = "0";
 
 
    new GuiControl() {
    new GuiControl() {
-      position = "86 70";
+      position = "89 75";
       extent = "846 618";
       extent = "846 618";
       minExtent = "8 2";
       minExtent = "8 2";
       horizSizing = "center";
       horizSizing = "center";
       vertSizing = "center";
       vertSizing = "center";
       profile = "GuiDefaultProfile";
       profile = "GuiDefaultProfile";
-      visible = "1";
+      visible = "0";
       active = "1";
       active = "1";
       tooltipProfile = "GuiToolTipProfile";
       tooltipProfile = "GuiToolTipProfile";
       hovertime = "1000";
       hovertime = "1000";
       isContainer = "1";
       isContainer = "1";
+      hidden = "1";
       canSave = "1";
       canSave = "1";
       canSaveDynamicFields = "0";
       canSaveDynamicFields = "0";
 
 
@@ -128,7 +128,7 @@
          minExtent = "8 2";
          minExtent = "8 2";
          horizSizing = "width";
          horizSizing = "width";
          vertSizing = "height";
          vertSizing = "height";
-         profile = "GuiScrollProfile";
+         profile = "GuiMenuScrollProfile";
          visible = "1";
          visible = "1";
          active = "1";
          active = "1";
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
@@ -148,7 +148,7 @@
             changeChildSizeToFit = "1";
             changeChildSizeToFit = "1";
             changeChildPosition = "1";
             changeChildPosition = "1";
             position = "1 1";
             position = "1 1";
-            extent = "846 210";
+            extent = "846 140";
             minExtent = "16 16";
             minExtent = "16 16";
             horizSizing = "width";
             horizSizing = "width";
             vertSizing = "bottom";
             vertSizing = "bottom";
@@ -160,6 +160,87 @@
             isContainer = "1";
             isContainer = "1";
             canSave = "1";
             canSave = "1";
             canSaveDynamicFields = "0";
             canSaveDynamicFields = "0";
+
+            new GuiButtonCtrl() {
+               text = "Keyboard and Mouse";
+               groupNum = "-1";
+               buttonType = "PushButton";
+               useMouseEvents = "0";
+               position = "0 0";
+               extent = "846 35";
+               minExtent = "8 2";
+               horizSizing = "right";
+               vertSizing = "bottom";
+               profile = "GuiMenuButtonProfile";
+               visible = "1";
+               active = "1";
+               command = "ControlsMenu::loadSettings();";
+               tooltipProfile = "GuiToolTipProfile";
+               hovertime = "1000";
+               isContainer = "0";
+               canSave = "1";
+               canSaveDynamicFields = "0";
+            };
+            new GuiButtonCtrl() {
+               text = "Display";
+               groupNum = "-1";
+               buttonType = "PushButton";
+               useMouseEvents = "0";
+               position = "0 35";
+               extent = "846 35";
+               minExtent = "8 2";
+               horizSizing = "right";
+               vertSizing = "bottom";
+               profile = "GuiMenuButtonProfile";
+               visible = "1";
+               active = "1";
+               command = "DisplayMenu::loadSettings();";
+               tooltipProfile = "GuiToolTipProfile";
+               hovertime = "1000";
+               isContainer = "0";
+               canSave = "1";
+               canSaveDynamicFields = "0";
+            };
+            new GuiButtonCtrl() {
+               text = "Graphics";
+               groupNum = "-1";
+               buttonType = "PushButton";
+               useMouseEvents = "0";
+               position = "0 70";
+               extent = "846 35";
+               minExtent = "8 2";
+               horizSizing = "right";
+               vertSizing = "bottom";
+               profile = "GuiMenuButtonProfile";
+               visible = "1";
+               active = "1";
+               command = "GraphicsMenu::loadSettings();";
+               tooltipProfile = "GuiToolTipProfile";
+               hovertime = "1000";
+               isContainer = "0";
+               canSave = "1";
+               canSaveDynamicFields = "0";
+            };
+            new GuiButtonCtrl() {
+               text = "Audio";
+               groupNum = "-1";
+               buttonType = "PushButton";
+               useMouseEvents = "0";
+               position = "0 105";
+               extent = "846 35";
+               minExtent = "8 2";
+               horizSizing = "right";
+               vertSizing = "bottom";
+               profile = "GuiMenuButtonProfile";
+               visible = "1";
+               active = "1";
+               command = "AudioMenu::loadSettings();";
+               tooltipProfile = "GuiToolTipProfile";
+               hovertime = "1000";
+               isContainer = "0";
+               canSave = "1";
+               canSaveDynamicFields = "0";
+            };
          };
          };
       };
       };
       new GuiMLTextCtrl() {
       new GuiMLTextCtrl() {
@@ -183,7 +264,6 @@
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
       new GuiButtonCtrl() {
       new GuiButtonCtrl() {
-         class="OptionsMenuOKButton";
          text = "OK";
          text = "OK";
          groupNum = "-1";
          groupNum = "-1";
          buttonType = "PushButton";
          buttonType = "PushButton";
@@ -199,11 +279,11 @@
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         class = "OptionsMenuOKButton";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
       new GuiButtonCtrl() {
       new GuiButtonCtrl() {
-         class="OptionsMenuDefaultsButton";
          text = "Defaults";
          text = "Defaults";
          groupNum = "-1";
          groupNum = "-1";
          buttonType = "PushButton";
          buttonType = "PushButton";
@@ -219,11 +299,11 @@
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         class = "OptionsMenuDefaultsButton";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
       new GuiButtonCtrl() {
       new GuiButtonCtrl() {
-         class="OptionsMenuCancelButton";
          text = "Cancel";
          text = "Cancel";
          groupNum = "-1";
          groupNum = "-1";
          buttonType = "PushButton";
          buttonType = "PushButton";
@@ -239,9 +319,283 @@
          tooltipProfile = "GuiToolTipProfile";
          tooltipProfile = "GuiToolTipProfile";
          hovertime = "1000";
          hovertime = "1000";
          isContainer = "0";
          isContainer = "0";
+         class = "OptionsMenuCancelButton";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+   };
+   new GuiControl() {
+      position = "48 56";
+      extent = "928 655";
+      minExtent = "8 2";
+      horizSizing = "center";
+      vertSizing = "center";
+      profile = "GuiDefaultProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+
+      new GuiTextCtrl() {
+         text = "OPTIONS";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "22 10";
+         extent = "120 28";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "MenuHeaderText";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiBitmapBarCtrl() {
+         percent = "100";
+         vertical = "0";
+         flipClip = "0";
+         bitmap = "data/ui/images/hudfill.png";
+         color = "255 255 255 255";
+         position = "0 40";
+         extent = "846 618";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiDefaultProfile";
+         visible = "0";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         hidden = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiButtonCtrl() {
+         text = "Display";
+         groupNum = "1";
+         buttonType = "RadioButton";
+         useMouseEvents = "0";
+         position = "114 49";
+         extent = "140 32";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMenuButtonProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+         internalName = "DisplayButton";
+         command="OptionsMenu.populateDisplaySettingsList();";
+      };
+      new GuiButtonCtrl() {
+         text = "Graphics";
+         groupNum = "1";
+         buttonType = "RadioButton";
+         useMouseEvents = "0";
+         position = "258 49";
+         extent = "140 32";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMenuButtonProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+         internalName = "GraphicsButton";
+         command="OptionsMenu.populateGraphicsSettingsList();";
+      };
+      new GuiButtonCtrl() {
+         text = "Audio";
+         groupNum = "1";
+         buttonType = "RadioButton";
+         useMouseEvents = "0";
+         position = "402 49";
+         extent = "140 32";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMenuButtonProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+         internalName = "AudioButton";
+         command="OptionsMenu.populateAudioSettingsList();";
+      };
+      new GuiButtonCtrl() {
+         text = "Keyboard + Mouse";
+         groupNum = "1";
+         buttonType = "RadioButton";
+         useMouseEvents = "0";
+         position = "547 49";
+         extent = "140 32";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMenuButtonProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+         internalName = "KBMButton";
+         command="OptionsMenu.populateKeyboardMouseSettingsList();";
+      };
+      new GuiButtonCtrl() {
+         text = "Gamepad";
+         groupNum = "1";
+         buttonType = "RadioButton";
+         useMouseEvents = "0";
+         position = "691 49";
+         extent = "140 32";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMenuButtonProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+         internalName = "GamepadButton";
+         command="OptionsMenu.populateGamepadSettingsList();";
+      };
+      new GuiScrollCtrl() {
+         willFirstRespond = "1";
+         hScrollBar = "alwaysOff";
+         vScrollBar = "dynamic";
+         lockHorizScroll = "0";
+         lockVertScroll = "0";
+         constantThumbHeight = "0";
+         childMargin = "0 0";
+         mouseWheelScrollSpeed = "-1";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "1 83";
+         extent = "622 573";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMenuScrollProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+
+         new GuiGameListMenuCtrl(OptionsMenuSettingsList) {
+            class = "UIMenuButtonList";
+            debugRender = "0";
+            callbackOnA = "OptionsMenuSettingsList.activateRow();";
+            callbackOnB = "OptionsMenuSettingsList.backOut();";
+            callbackOnInputs = "1";
+            position = "1 1";
+            extent = "621 141";
+            minExtent = "8 2";
+            horizSizing = "width";
+            vertSizing = "bottom";
+            profile = "DefaultListMenuProfile";
+            visible = "1";
+            active = "1";
+            tooltipProfile = "GuiToolTipProfile";
+            hovertime = "1000";
+            isContainer = "0";
+            canSave = "1";
+            canSaveDynamicFields = "0";
+         };
+      };
+      new GuiTextCtrl(OptionName) {
+         text = "Option";
+         maxLength = "1024";
+         margin = "0 0 0 0";
+         padding = "0 0 0 0";
+         anchorTop = "1";
+         anchorBottom = "0";
+         anchorLeft = "1";
+         anchorRight = "0";
+         position = "635 94";
+         extent = "293 17";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "MenuSubHeaderText";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "1";
+         canSave = "1";
+         canSaveDynamicFields = "0";
+      };
+      new GuiMLTextCtrl(OptionDescription) {
+         lineSpacing = "2";
+         allowColorChars = "0";
+         maxChars = "-1";
+         text = "This is a placeholder text for an option.";
+         useURLMouseCursor = "0";
+         position = "635 126";
+         extent = "293 14";
+         minExtent = "8 2";
+         horizSizing = "right";
+         vertSizing = "bottom";
+         profile = "GuiMLWhiteTextProfile";
+         visible = "1";
+         active = "1";
+         tooltipProfile = "GuiToolTipProfile";
+         hovertime = "1000";
+         isContainer = "0";
          canSave = "1";
          canSave = "1";
          canSaveDynamicFields = "0";
          canSaveDynamicFields = "0";
       };
       };
    };
    };
+   new GuiControl(OptionsButtonHolder) {
+      position = "189 652";
+      extent = "646 130";
+      minExtent = "8 2";
+      horizSizing = "center";
+      vertSizing = "top";
+      profile = "GuiDefaultProfile";
+      visible = "1";
+      active = "1";
+      tooltipProfile = "GuiToolTipProfile";
+      hovertime = "1000";
+      isContainer = "1";
+      canSave = "1";
+      canSaveDynamicFields = "0";
+   };
 };
 };
 //--- OBJECT WRITE END ---
 //--- OBJECT WRITE END ---

BIN
Templates/BaseGame/game/data/ui/images/Inputs/Controller_Disconnected.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_0.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_1.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_10.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_11.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_12.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_2.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_3.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_4.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_5.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_6.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_7.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_8.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_9.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_A.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Alt.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Down.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Left.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Right.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Arrow_Up.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Asterisk.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_B.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Backspace.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Backspace_Alt.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Bracket_Left.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Bracket_Right.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_C.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Caps_Lock.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Command.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Ctrl.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_D.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Del.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_E.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_End.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Enter.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Enter_Alt.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Enter_Tall.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Esc.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F1.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F10.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F11.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F12.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F2.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F3.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F4.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F5.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F6.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F7.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F8.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_F9.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_G.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_H.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Home.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_I.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Insert.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_J.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_K.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_L.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_M.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mark_Left.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mark_Right.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Minus.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Left.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Middle.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Right.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Mouse_Simple.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_N.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Num_Lock.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_O.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_P.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Page_Down.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Page_Up.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Plus.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Plus_Tall.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Print_Screen.png


BIN
Templates/BaseGame/game/data/ui/images/Inputs/Keyboard & Mouse/Keyboard_Black_Q.png


Some files were not shown because too many files changed in this diff