Torque3D Documentation / _generateds / guiGameListMenuCtrl.cpp

guiGameListMenuCtrl.cpp

Engine/source/gui/controls/guiGameListMenuCtrl.cpp

More...

Public Functions

ConsoleDocClass(GuiGameListMenuCtrl , "@brief A base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> cross platform menu controls that are gamepad <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">friendly.\n\n</a>" "This class is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> build row-based menu GUIs that can be easily navigated " "using the keyboard, mouse or gamepad. The desired row can be selected using " "the mouse, or by navigating using the Up and Down <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">buttons.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguigamelistmenuctrl/">GuiGameListMenuCtrl</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " debugRender=\"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   callbackOnA = \"applyOptions();\";\n" "   callbackOnB = \"Canvas.setContent(MainMenuGui);\";\n" "   callbackOnX = \"\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   callbackOnY = \"revertOptions();\";\n" "   //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiGameListMenuProfile\n\n</a>" "@ingroup GuiGame" )
ConsoleDocClass(GuiGameListMenuProfile , "@brief A <a href="/coding/class/classguicontrolprofile/">GuiControlProfile</a> with additional fields specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiGameListMenuCtrl.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguigamelistmenuprofile/">GuiGameListMenuProfile</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   hitAreaUpperLeft = \"10 2\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   hitAreaLowerRight = \"190 18\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   iconOffset = \"10 2\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   rowSize = \"200 20\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   columnSplit = \"100\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   rightPad = \"4\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup GuiGame" )
DefineEngineMethod(GuiGameListMenuCtrl , activateRow , void , () , "Activates the current row. The script callback of the current row will be called (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it has one)." )
DefineEngineMethod(GuiGameListMenuCtrl , addKeybindRow , void , (const char *label, const char *bitmapName, const char *callback, S32 icon, S32 yPad, bool enabled, const char *tooltip) , (-1, 0, true, "") , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param options A tab separated list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">options.\n</a>" "@param wrapOptions Specify true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow options <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wrap at each end or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> prevent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">wrapping.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param enabled  If this row is initially enabled." )
DefineEngineMethod(GuiGameListMenuCtrl , addOptionRow , void , (const char *label, const char *options, bool wrapOptions, const char *callback, S32 icon, S32 yPad, bool enabled, const char *tooltip, const char *defaultValue) , (-1, 0, true, "", "") , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param options A tab separated list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">options.\n</a>" "@param wrapOptions Specify true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow options <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wrap at each end or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> prevent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">wrapping.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param enabled  If this row is initially enabled." )
DefineEngineMethod(GuiGameListMenuCtrl , addRow , void , (const char *label, const char *callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, int mode) , (-1, 0, true, true, 0) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param useHighlightIcon  Does this row use the highlight icon?.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param enabled  If this row is initially <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enabled.\n</a>" "@param <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a>  What option <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> the row is in. 0, 1 )
DefineEngineMethod(GuiGameListMenuCtrl , addSliderRow , void , (const char *label, F32 defaultValue, F32 increment, Point2F range, const char *callback, S32 icon, S32 yPad, bool enabled, const char *tooltip) , (-1, 0, true, "") , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param options A tab separated list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">options.\n</a>" "@param wrapOptions Specify true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow options <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wrap at each end or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> prevent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">wrapping.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param enabled  If this row is initially enabled." )
DefineEngineMethod(GuiGameListMenuCtrl , clearRows , void , () , "Gets the index of the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@return Index of the selected row." )
DefineEngineMethod(GuiGameListMenuCtrl , getCurrentOption , const char * , (S32 row) , "Gets the text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the currently selected option of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get the option <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@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." )
DefineEngineMethod(GuiGameListMenuCtrl , getRowCount , S32 , () , "Gets the number of rows on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@return (int) The number of rows on the control." )
DefineEngineMethod(GuiGameListMenuCtrl , getRowLabel , const char * , (S32 row) , "Gets the label displayed on the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get the label <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return The label <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the row." )
DefineEngineMethod(GuiGameListMenuCtrl , getSelectedRow , S32 , () , "Gets the index of the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@return Index of the selected row." )
DefineEngineMethod(GuiGameListMenuCtrl , getTooltip , const char * , (S32 row) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )
DefineEngineMethod(GuiGameListMenuCtrl , getValue , F32 , (S32 row) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )
DefineEngineMethod(GuiGameListMenuCtrl , isRowEnabled , bool , (S32 row) , "Determines <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the specified row is enabled or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n\n</a>" "@param row The row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the enabled status <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the specified row is enabled. False <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the row is not enabled or the given index was not valid." )
DefineEngineMethod(GuiGameListMenuCtrl , refresh , void , () , "Gets the index of the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@return Index of the selected row." )
DefineEngineMethod(GuiGameListMenuCtrl , removeRow , void , (S32 row) , "Removes the row at the provided index" )
DefineEngineMethod(GuiGameListMenuCtrl , selectOption , bool , (S32 row, const char *option) , "Set the row's current option <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the one <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">specified\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set an option <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n</a>" "@param option The option <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be made <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">active.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the row contained the option and was set, false otherwise." )
DefineEngineMethod(GuiGameListMenuCtrl , setOptions , void , (S32 row, const char *optionsList) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )
DefineEngineMethod(GuiGameListMenuCtrl , setRowEnabled , void , (S32 row, bool enabled) , "Sets <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row's enabled status according <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameters.\n\n</a>" "@param row The index <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">validity.\n</a>" "@param enabled Indicate true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> enable the row or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> disable it." )
DefineEngineMethod(GuiGameListMenuCtrl , setRowLabel , void , (S32 row, const char *label) , "Sets the label on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the label <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n</a>" "@param label Text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set as the label of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" )
DefineEngineMethod(GuiGameListMenuCtrl , setSelected , void , (S32 row) , "Sets the selected row. Only rows that are enabled can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selected.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set as selected." )
DefineEngineMethod(GuiGameListMenuCtrl , setValue , void , (S32 row, F32 value) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )
IMPLEMENT_CALLBACK(GuiGameListMenuCtrl , onAxisEvent , void , (const char *device, const char *action, F32 axisValue) , (device, action, axisValue) , "@brief <a href="/coding/file/sqliteobject_8cpp/#sqliteobject_8cpp_1a858cd1af41f1e4420d94dfe65b6a56a4">Callback</a> that occurs when an axis event is triggered on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control\n\n</a>" "@param device The device type triggering the input, such as mouse, joystick , gamepad , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">etc\n</a>" " @param action The <a href="/coding/class/classactionmap/">ActionMap</a> code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">axis\n</a>" " @param axisValue The current <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">axis\n\n</a>" )
IMPLEMENT_CALLBACK(GuiGameListMenuCtrl , onChange , void , () , () , "Called when the selected row changes." )
IMPLEMENT_CALLBACK(GuiGameListMenuCtrl , onInputEvent , void , (const char *device, const char *action, bool state) , (device, action, state) , "@brief <a href="/coding/file/sqliteobject_8cpp/#sqliteobject_8cpp_1a858cd1af41f1e4420d94dfe65b6a56a4">Callback</a> that occurs when an input is triggered on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control\n\n</a>" "@param device The device type triggering the input, such as keyboard, mouse , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">etc\n</a>" " @param action The actual event occuring, such as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> key or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">button\n</a>" " @param state True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the action is being pressed, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it is being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">release\n\n</a>" )

Detailed Description

Public Functions

ConsoleDocClass(GuiGameListMenuCtrl , "@brief A base class <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> cross platform menu controls that are gamepad <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">friendly.\n\n</a>" "This class is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> build row-based menu GUIs that can be easily navigated " "using the keyboard, mouse or gamepad. The desired row can be selected using " "the mouse, or by navigating using the Up and Down <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">buttons.\n\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguigamelistmenuctrl/">GuiGameListMenuCtrl</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " debugRender=\"0\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   callbackOnA = \"applyOptions();\";\n" "   callbackOnB = \"Canvas.setContent(MainMenuGui);\";\n" "   callbackOnX = \"\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   callbackOnY = \"revertOptions();\";\n" "   //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiGameListMenuProfile\n\n</a>" "@ingroup GuiGame" )

ConsoleDocClass(GuiGameListMenuProfile , "@brief A <a href="/coding/class/classguicontrolprofile/">GuiControlProfile</a> with additional fields specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">GuiGameListMenuCtrl.\n\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "<a href="/coding/file/tmm__on_8h/#tmm__on_8h_1a1ac41480eb2e4aadd52252ee550b630a">new</a> <a href="/coding/class/classguigamelistmenuprofile/">GuiGameListMenuProfile</a>()\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   hitAreaUpperLeft = \"10 2\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   hitAreaLowerRight = \"190 18\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   iconOffset = \"10 2\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   rowSize = \"200 20\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   columnSplit = \"100\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   rightPad = \"4\";\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "   //Properties not specific <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> this <a href="/coding/file/guieditctrl_8cpp/#guieditctrl_8cpp_1abb04e3738c4c5a96b3ade6fa47013a6c">control</a> have been omitted from this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">example.\n</a>" "};\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n\n</a>" "@ingroup GuiGame" )

DefineEngineMethod(GuiGameListMenuCtrl , activateRow , void , () , "Activates the current row. The script callback of the current row will be called (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it has one)." )

DefineEngineMethod(GuiGameListMenuCtrl , addKeybindRow , void , (const char *label, const char *bitmapName, const char *callback, S32 icon, S32 yPad, bool enabled, const char *tooltip) , (-1, 0, true, "") , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param options A tab separated list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">options.\n</a>" "@param wrapOptions Specify true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow options <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wrap at each end or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> prevent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">wrapping.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param enabled  If this row is initially enabled." )

DefineEngineMethod(GuiGameListMenuCtrl , addOptionRow , void , (const char *label, const char *options, bool wrapOptions, const char *callback, S32 icon, S32 yPad, bool enabled, const char *tooltip, const char *defaultValue) , (-1, 0, true, "", "") , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param options A tab separated list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">options.\n</a>" "@param wrapOptions Specify true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow options <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wrap at each end or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> prevent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">wrapping.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param enabled  If this row is initially enabled." )

DefineEngineMethod(GuiGameListMenuCtrl , addRow , void , (const char *label, const char *callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, int mode) , (-1, 0, true, true, 0) , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param useHighlightIcon  Does this row use the highlight icon?.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@param enabled  If this row is initially <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enabled.\n</a>" "@param <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a>  What option <a href="/coding/file/zipobject_8cpp/#zipobject_8cpp_1ac6c3dfb4c3a68f849f32cbfb21da4e77">mode</a> the row is in. 0, 1 )

DefineEngineMethod(GuiGameListMenuCtrl , addSliderRow , void , (const char *label, F32 defaultValue, F32 increment, Point2F range, const char *callback, S32 icon, S32 yPad, bool enabled, const char *tooltip) , (-1, 0, true, "") , "Add <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the list <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@param label The text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> display on the row as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">label.\n</a>" "@param options A tab separated list of <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">options.\n</a>" "@param wrapOptions Specify true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow options <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> wrap at each end or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> prevent <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">wrapping.\n</a>" "@param callback Name of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> script function <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> callback when this row is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">activated.\n</a>" "@param icon  Index of the icon <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> use as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">marker.\n</a>" "@param yPad  An extra amount of height padding before the row. Does nothing on the first <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" "@param enabled  If this row is initially enabled." )

DefineEngineMethod(GuiGameListMenuCtrl , clearRows , void , () , "Gets the index of the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@return Index of the selected row." )

DefineEngineMethod(GuiGameListMenuCtrl , getCurrentOption , const char * , (S32 row) , "Gets the text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the currently selected option of the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get the option <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">from.\n</a>" "@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." )

DefineEngineMethod(GuiGameListMenuCtrl , getRowCount , S32 , () , "Gets the number of rows on the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control.\n\n</a>" "@return (int) The number of rows on the control." )

DefineEngineMethod(GuiGameListMenuCtrl , getRowLabel , const char * , (S32 row) , "Gets the label displayed on the specified <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> get the label <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return The label <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the row." )

DefineEngineMethod(GuiGameListMenuCtrl , getSelectedRow , S32 , () , "Gets the index of the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@return Index of the selected row." )

DefineEngineMethod(GuiGameListMenuCtrl , getTooltip , const char * , (S32 row) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )

DefineEngineMethod(GuiGameListMenuCtrl , getValue , F32 , (S32 row) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )

DefineEngineMethod(GuiGameListMenuCtrl , isRowEnabled , bool , (S32 row) , "Determines <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the specified row is enabled or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n\n</a>" "@param row The row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the enabled status <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">of.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the specified row is enabled. False <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the row is not enabled or the given index was not valid." )

DefineEngineMethod(GuiGameListMenuCtrl , refresh , void , () , "Gets the index of the currently selected <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@return Index of the selected row." )

DefineEngineMethod(GuiGameListMenuCtrl , removeRow , void , (S32 row) , "Removes the row at the provided index" )

DefineEngineMethod(GuiGameListMenuCtrl , selectOption , bool , (S32 row, const char *option) , "Set the row's current option <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the one <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">specified\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set an option <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n</a>" "@param option The option <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be made <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">active.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the row contained the option and was set, false otherwise." )

DefineEngineMethod(GuiGameListMenuCtrl , setOptions , void , (S32 row, const char *optionsList) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )

DefineEngineMethod(GuiGameListMenuCtrl , setRowEnabled , void , (S32 row, bool enabled) , "Sets <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> row's enabled status according <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">parameters.\n\n</a>" "@param row The index <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> check <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">validity.\n</a>" "@param enabled Indicate true <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> enable the row or false <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> disable it." )

DefineEngineMethod(GuiGameListMenuCtrl , setRowLabel , void , (S32 row, const char *label) , "Sets the label on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the label <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">on.\n</a>" "@param label Text <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set as the label of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n</a>" )

DefineEngineMethod(GuiGameListMenuCtrl , setSelected , void , (S32 row) , "Sets the selected row. Only rows that are enabled can be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">selected.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set as selected." )

DefineEngineMethod(GuiGameListMenuCtrl , setValue , void , (S32 row, F32 value) , "Sets the list of options on the given <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">row.\n\n</a>" "@param row Index of the row <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set options on." "@param optionsList A tab separated list of options <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the control." )

IMPLEMENT_CALLBACK(GuiGameListMenuCtrl , onAxisEvent , void , (const char *device, const char *action, F32 axisValue) , (device, action, axisValue) , "@brief <a href="/coding/file/sqliteobject_8cpp/#sqliteobject_8cpp_1a858cd1af41f1e4420d94dfe65b6a56a4">Callback</a> that occurs when an axis event is triggered on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control\n\n</a>" "@param device The device type triggering the input, such as mouse, joystick , gamepad , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">etc\n</a>" " @param action The <a href="/coding/class/classactionmap/">ActionMap</a> code <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">axis\n</a>" " @param axisValue The current <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">axis\n\n</a>" )

IMPLEMENT_CALLBACK(GuiGameListMenuCtrl , onChange , void , () , () , "Called when the selected row changes." )

IMPLEMENT_CALLBACK(GuiGameListMenuCtrl , onInputEvent , void , (const char *device, const char *action, bool state) , (device, action, state) , "@brief <a href="/coding/file/sqliteobject_8cpp/#sqliteobject_8cpp_1a858cd1af41f1e4420d94dfe65b6a56a4">Callback</a> that occurs when an input is triggered on this <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">control\n\n</a>" "@param device The device type triggering the input, such as keyboard, mouse , <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">etc\n</a>" " @param action The actual event occuring, such as <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> key or <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">button\n</a>" " @param state True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the action is being pressed, false <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> it is being <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">release\n\n</a>" )

IMPLEMENT_CONOBJECT(GuiGameListMenuCtrl )

IMPLEMENT_CONOBJECT(GuiGameListMenuProfile )

   1
   2//-----------------------------------------------------------------------------
   3// Copyright (c) 2012 GarageGames, LLC
   4//
   5// Permission is hereby granted, free of charge, to any person obtaining a copy
   6// of this software and associated documentation files (the "Software"), to
   7// deal in the Software without restriction, including without limitation the
   8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
   9// sell copies of the Software, and to permit persons to whom the Software is
  10// furnished to do so, subject to the following conditions:
  11//
  12// The above copyright notice and this permission notice shall be included in
  13// all copies or substantial portions of the Software.
  14//
  15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21// IN THE SOFTWARE.
  22//-----------------------------------------------------------------------------
  23
  24#include "guiGameListMenuCtrl.h"
  25
  26#include "console/consoleTypes.h"
  27#include "console/engineAPI.h"
  28#include "gfx/gfxDrawUtil.h"
  29#include "gui/containers/guiScrollCtrl.h"
  30#include "sim/actionMap.h"
  31#include "core/strings/stringUnit.h"
  32
  33//-----------------------------------------------------------------------------
  34// GuiGameListMenuCtrl
  35//-----------------------------------------------------------------------------
  36
  37GuiGameListMenuCtrl::GuiGameListMenuCtrl()
  38 : mSelected(NO_ROW),
  39   mDebugRender(false),
  40   mHighlighted(NO_ROW),
  41   mCallbackOnInputs(false),
  42   mConsumeKeyInputEvents(false)
  43{
  44   VECTOR_SET_ASSOCIATION(mRows);
  45
  46   // initialize the control callbacks
  47   mCallbackOnA = StringTable->EmptyString();
  48   mCallbackOnB = mCallbackOnA;
  49   mCallbackOnX = mCallbackOnA;
  50   mCallbackOnY = mCallbackOnA;
  51}
  52
  53GuiGameListMenuCtrl::~GuiGameListMenuCtrl()
  54{
  55   for (S32 i = 0; i < mRows.size(); ++i)
  56   {
  57      delete mRows[i];
  58   }
  59}
  60
  61void GuiGameListMenuCtrl::onRender(Point2I offset, const RectI &updateRect)
  62{
  63   GuiGameListMenuProfile * profile = (GuiGameListMenuProfile *) mProfile;
  64
  65   GFXDrawUtil* drawUtil = GFX->getDrawUtil();
  66
  67   F32 xScale = (float) getWidth() / profile->getRowWidth();
  68
  69   bool profileHasIcons = profile->hasArrows();
  70
  71   S32 rowHeight = profile->getRowHeight();
  72
  73   Point2I currentOffset = offset;
  74   Point2I extent = getExtent();
  75   Point2I rowExtent(extent.x, rowHeight);
  76   Point2I textOffset(profile->mTextOffset.x * xScale, profile->mTextOffset.y);
  77   Point2I textExtent(extent.x - textOffset.x, rowHeight);
  78   Point2I iconExtent, iconOffset(0.0f, 0.0f);
  79   if (profileHasIcons)
  80   {
  81      iconExtent = profile->getIconExtent();
  82
  83      // icon is centered vertically plus any specified offset
  84      S32 iconOffsetY = (rowHeight - iconExtent.y) >> 1;
  85      iconOffsetY += profile->mIconOffset.y;
  86      iconOffset = Point2I(profile->mIconOffset.x * xScale, iconOffsetY);
  87   }
  88   for (Vector<Row *>::iterator row = mRows.begin(); row < mRows.end(); ++row)
  89   {
  90      if (row != mRows.begin())
  91      {
  92         // rows other than the first can have padding above them
  93         currentOffset.y += (*row)->mHeightPad;
  94         currentOffset.y += rowHeight;
  95      }
  96
  97      // select appropriate colors and textures
  98      ColorI fontColor;
  99      U32 buttonTextureIndex;
 100      S32 iconIndex = (*row)->mIconIndex;
 101      bool useHighlightIcon = (*row)->mUseHighlightIcon;
 102      if (!(*row)->mEnabled)
 103      {
 104         buttonTextureIndex = Profile::TEX_DISABLED;
 105         fontColor = profile->mFontColorNA;
 106      }
 107      else if (row == &mRows[mSelected])
 108      {
 109         if (iconIndex != NO_ICON)
 110         {
 111            iconIndex++;
 112         }
 113         buttonTextureIndex = Profile::TEX_SELECTED;
 114         fontColor = profile->mFontColorSEL;
 115      }
 116      else if ((mHighlighted != NO_ROW) && (row == &mRows[mHighlighted]))
 117      {
 118         if (iconIndex != NO_ICON && useHighlightIcon)
 119         {
 120            iconIndex++;
 121         }
 122         buttonTextureIndex = Profile::TEX_HIGHLIGHT;
 123         fontColor = profile->mFontColorHL;
 124      }
 125      else
 126      {
 127         buttonTextureIndex = Profile::TEX_NORMAL;
 128         fontColor = profile->mFontColor;
 129      }
 130
 131      // render the row bitmap
 132      drawUtil->clearBitmapModulation();
 133      drawUtil->drawBitmapStretchSR(profile->mTextureObject, RectI(currentOffset, rowExtent), profile->getBitmapArrayRect(buttonTextureIndex));
 134
 135      // render the row icon if it has one
 136      if ((iconIndex != NO_ICON) && profileHasIcons && (!profile->getBitmapArrayRect((U32)iconIndex).extent.isZero()))
 137      {
 138         iconIndex += Profile::TEX_FIRST_ICON;
 139         drawUtil->clearBitmapModulation();
 140         drawUtil->drawBitmapStretchSR(profile->mTextureObject, RectI(currentOffset + iconOffset, iconExtent), profile->getBitmapArrayRect(iconIndex));
 141      }
 142
 143      // render the row text
 144      drawUtil->setBitmapModulation(fontColor);
 145      renderJustifiedText(currentOffset + textOffset, textExtent, (*row)->mLabel);
 146
 147      if ((*row)->mMode == Row::Mode::OptionList)
 148      {
 149         onRenderListOption((*row), currentOffset);
 150      }
 151      else if ((*row)->mMode == Row::Mode::Slider)
 152      {
 153         onRenderSliderOption((*row), currentOffset);
 154      }
 155      else if ((*row)->mMode == Row::Mode::Keybind)
 156      {
 157         onRenderKeybindOption((*row), currentOffset);
 158      }
 159   }
 160
 161   if (mDebugRender)
 162   {
 163      onDebugRender(offset);
 164   }
 165
 166   renderChildControls(offset, updateRect);
 167}
 168
 169void GuiGameListMenuCtrl::onRenderListOption(Row* row, Point2I currentOffset)
 170{
 171   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
 172
 173   F32 xScale = (float)getWidth() / profile->getRowWidth();
 174
 175   S32 rowHeight = profile->getRowHeight();
 176
 177   bool profileHasArrows = profile->hasArrows();
 178   Point2I arrowExtent;
 179   S32 arrowOffsetY(0);
 180   if (profileHasArrows)
 181   {
 182      arrowExtent = profile->getArrowExtent();
 183
 184      // icon is centered vertically
 185      arrowOffsetY = (rowHeight - arrowExtent.y) >> 1;
 186   }
 187
 188   GFXDrawUtil* drawer = GFX->getDrawUtil();
 189
 190   Point2I arrowOffset;
 191   S32 columnSplit = profile->mColumnSplit * xScale;
 192
 193   S32 iconIndex;
 194   bool hasOptions = (row->mOptions.size() > 0) && row->mSelectedOption > -1;
 195   if (hasOptions)
 196   {
 197      bool isRowSelected = (getSelected() != NO_ROW) && (row == mRows[getSelected()]);
 198      bool isRowHighlighted = (getHighlighted() != NO_ROW) ? ((row == mRows[getHighlighted()]) && (row->mEnabled)) : false;
 199      if (profileHasArrows)
 200      {
 201         // render the left arrow
 202         bool arrowOnL = (isRowSelected || isRowHighlighted) && (row->mWrapOptions || (row->mSelectedOption > 0));
 203         iconIndex = (arrowOnL) ? Profile::TEX_L_ARROW_ON : Profile::TEX_L_ARROW_OFF;
 204         arrowOffset.x = currentOffset.x + columnSplit;
 205         arrowOffset.y = currentOffset.y + arrowOffsetY;
 206
 207         drawer->clearBitmapModulation();
 208         drawer->drawBitmapStretchSR(profile->mTextureObject, RectI(arrowOffset, arrowExtent), profile->getBitmapArrayRect((U32)iconIndex));
 209
 210         // render the right arrow
 211         bool arrowOnR = (isRowSelected || isRowHighlighted) && (row->mWrapOptions || (row->mSelectedOption < row->mOptions.size() - 1));
 212         iconIndex = (arrowOnR) ? Profile::TEX_R_ARROW_ON : Profile::TEX_R_ARROW_OFF;
 213         arrowOffset.x = currentOffset.x + (profile->mHitAreaLowerRight.x - profile->mRightPad) * xScale - arrowExtent.x;
 214         arrowOffset.y = currentOffset.y + arrowOffsetY;
 215
 216         drawer->clearBitmapModulation();
 217         drawer->drawBitmapStretchSR(profile->mTextureObject, RectI(arrowOffset, arrowExtent), profile->getBitmapArrayRect((U32)iconIndex));
 218      }
 219
 220      // get the appropriate font color
 221      ColorI fontColor;
 222      if (!row->mEnabled)
 223      {
 224         fontColor = profile->mFontColorNA;
 225      }
 226      else if (isRowSelected)
 227      {
 228         fontColor = profile->mFontColorSEL;
 229      }
 230      else if (isRowHighlighted)
 231      {
 232         fontColor = profile->mFontColorHL;
 233      }
 234      else
 235      {
 236         fontColor = profile->mFontColor;
 237      }
 238
 239      // calculate text to be at the center between the arrows
 240      GFont* font = profile->mFont;
 241      StringTableEntry text = row->mOptions[row->mSelectedOption];
 242      S32 textWidth = font->getStrWidth(text);
 243      S32 columnWidth = profile->mHitAreaLowerRight.x * xScale - profile->mRightPad - columnSplit;
 244      S32 columnCenter = columnSplit + (columnWidth >> 1);
 245      S32 textStartX = columnCenter - (textWidth >> 1);
 246      Point2I textOffset(textStartX, 0);
 247
 248      // render the option text itself
 249      Point2I textExtent(columnWidth, rowHeight);
 250      drawer->setBitmapModulation(fontColor);
 251      renderJustifiedText(currentOffset + textOffset, textExtent, text);
 252   }
 253}
 254
 255void GuiGameListMenuCtrl::onRenderSliderOption(Row* row, Point2I currentOffset)
 256{
 257   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
 258
 259   F32 xScale = (float)getWidth() / profile->getRowWidth();
 260
 261   S32 rowHeight = profile->getRowHeight();
 262
 263   bool profileHasArrows = profile->hasArrows();
 264   Point2I arrowExtent;
 265   S32 arrowOffsetY(0);
 266   if (profileHasArrows)
 267   {
 268      arrowExtent = profile->getArrowExtent();
 269
 270      // icon is centered vertically
 271      arrowOffsetY = (rowHeight - arrowExtent.y) >> 1;
 272   }
 273
 274   GFXDrawUtil* drawer = GFX->getDrawUtil();
 275
 276   Point2I arrowOffset;
 277   S32 columnSplit = profile->mColumnSplit * xScale;
 278
 279   S32 iconIndex;
 280
 281   bool isRowSelected = (getSelected() != NO_ROW) && (row == mRows[getSelected()]);
 282   bool isRowHighlighted = (getHighlighted() != NO_ROW) ? ((row == mRows[getHighlighted()]) && (row->mEnabled)) : false;
 283   /*if (profileHasArrows)
 284   {
 285      // render the left arrow
 286      bool arrowOnL = (isRowSelected || isRowHighlighted) && (row->mValue > row->mRange.x);
 287      iconIndex = (arrowOnL) ? Profile::TEX_L_ARROW_ON : Profile::TEX_L_ARROW_OFF;
 288      arrowOffset.x = currentOffset.x + columnSplit;
 289      arrowOffset.y = currentOffset.y + arrowOffsetY;
 290
 291      drawer->clearBitmapModulation();
 292      drawer->drawBitmapStretchSR(profile->mTextureObject, RectI(arrowOffset, arrowExtent), profile->getBitmapArrayRect((U32)iconIndex));
 293
 294      // render the right arrow
 295      bool arrowOnR = (isRowSelected || isRowHighlighted) && (row->mValue < row->mRange.y);
 296      iconIndex = (arrowOnR) ? Profile::TEX_R_ARROW_ON : Profile::TEX_R_ARROW_OFF;
 297      arrowOffset.x = currentOffset.x + (profile->mHitAreaLowerRight.x - profile->mRightPad) * xScale - arrowExtent.x;
 298      arrowOffset.y = currentOffset.y + arrowOffsetY;
 299
 300      drawer->clearBitmapModulation();
 301      drawer->drawBitmapStretchSR(profile->mTextureObject, RectI(arrowOffset, arrowExtent), profile->getBitmapArrayRect((U32)iconIndex));
 302   }*/
 303
 304   //Draw the slider bar
 305   if (row->mEnabled)
 306   {
 307      RectI sliderRect;
 308
 309      sliderRect.point.x = currentOffset.x + columnSplit + arrowExtent.x;
 310      sliderRect.point.y = currentOffset.y + arrowOffsetY;
 311
 312      sliderRect.extent.x = (currentOffset.x + (profile->mHitAreaLowerRight.x - profile->mRightPad) * xScale - arrowExtent.x) - sliderRect.point.x;
 313      sliderRect.extent.y = arrowExtent.y;
 314
 315      //Now adjust the bar to match-to our value
 316
 317      S32 barStart = sliderRect.point.x;
 318      S32 barEnd = sliderRect.point.x + sliderRect.extent.x;
 319
 320      S32 xPosFill = (((row->mValue - row->mRange.x) * (barEnd - barStart)) / (row->mRange.y - row->mRange.x)) + barStart;
 321
 322      RectI fillRect = sliderRect;
 323      fillRect.extent.x = xPosFill - sliderRect.point.x;
 324
 325      ColorI barColor;
 326      ColorI barOutlineColor;
 327      if (isRowSelected)
 328      {
 329         barColor = profile->mFillColor;
 330         barOutlineColor = profile->mFillColorSEL;
 331      }
 332      else
 333      {
 334         barColor = profile->mFillColor;
 335         barOutlineColor = profile->mFillColorHL;
 336      }
 337
 338      drawer->drawRectFill(fillRect, barColor);
 339
 340      drawer->drawRect(sliderRect, barOutlineColor);
 341   }
 342
 343   // get the appropriate font color
 344   ColorI fontColor;
 345   if (!row->mEnabled)
 346   {
 347      fontColor = profile->mFontColorNA;
 348   }
 349   else if (isRowSelected)
 350   {
 351      fontColor = profile->mFontColorSEL;
 352   }
 353   else if (isRowHighlighted)
 354   {
 355      fontColor = profile->mFontColorHL;
 356   }
 357   else
 358   {
 359      fontColor = profile->mFontColor;
 360   }
 361
 362   // calculate text to be at the center between the arrows
 363   GFont* font = profile->mFont;
 364
 365   ConsoleValue val;
 366   val.setFloatValue(row->mValue);
 367
 368   const char* stringVal = val.getStringValue();
 369
 370   S32 textWidth = font->getStrWidth(stringVal);
 371   S32 columnWidth = profile->mHitAreaLowerRight.x * xScale - profile->mRightPad - columnSplit;
 372   S32 columnCenter = columnSplit + (columnWidth >> 1);
 373   S32 textStartX = columnCenter - (textWidth >> 1);
 374   Point2I textOffset(textStartX, 0);
 375
 376   // render the option text itself
 377   Point2I textExtent(columnWidth, rowHeight);
 378   drawer->setBitmapModulation(fontColor);
 379   renderJustifiedText(currentOffset + textOffset, textExtent, stringVal);
 380}
 381
 382void GuiGameListMenuCtrl::onRenderKeybindOption(Row* row, Point2I currentOffset)
 383{
 384   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
 385   F32 xScale = (float)getWidth() / profile->getRowWidth();
 386   S32 columnSplit = profile->mColumnSplit * xScale;
 387
 388   S32 rowHeight = profile->getRowHeight();
 389
 390   S32 optionWidth = xScale - columnSplit;
 391
 392   GFXDrawUtil* drawer = GFX->getDrawUtil();
 393   //drawer->drawBitmap(row->mBitmap, )
 394
 395   Point2I button;
 396   button.x = currentOffset.x + columnSplit + (columnSplit / 2.5)/* + (optionWidth / 2)*/;
 397   button.y = currentOffset.y + (rowHeight / 4);
 398
 399   Point2I buttonSize;
 400   buttonSize.x = rowHeight / 2;
 401   buttonSize.y = rowHeight / 2;
 402
 403   if (row->mBitmapTex.isValid())
 404   {
 405      GFXTextureObject* texture = row->mBitmapTex;
 406      RectI rect(button, buttonSize);
 407      drawer->clearBitmapModulation();
 408      drawer->drawBitmapStretch(texture, rect, GFXBitmapFlip_None, GFXTextureFilterLinear, false);
 409   }
 410
 411   //drawer->drawRectFill(button, ColorI::BLUE);
 412}
 413
 414void GuiGameListMenuCtrl::onDebugRender(Point2I offset)
 415{
 416   GuiGameListMenuProfile * profile = (GuiGameListMenuProfile *) mProfile;
 417
 418   F32 xScale = (float) getWidth() / profile->getRowWidth();
 419
 420   ColorI controlBorderColor(200, 200, 200); // gray
 421   ColorI rowBorderColor(255, 127, 255); // magenta
 422   ColorI hitBorderColor(255, 0, 0); // red
 423   Point2I shrinker(-1, -1);
 424   Point2I extent = getExtent();
 425
 426   // render a border around the entire control
 427   RectI borderRect(offset, extent + shrinker);
 428   GFX->getDrawUtil()->drawRect(borderRect, controlBorderColor);
 429
 430   S32 rowHeight = profile->getRowHeight();
 431   Point2I currentOffset(offset);
 432   Point2I rowExtent(extent.x, rowHeight);
 433   rowExtent += shrinker;
 434   Point2I hitAreaExtent(profile->getHitAreaExtent());
 435   hitAreaExtent.x *= xScale;
 436   hitAreaExtent += shrinker;
 437   Point2I hitAreaOffset = profile->mHitAreaUpperLeft;
 438   hitAreaOffset.x *= xScale;
 439   Point2I upperLeft;
 440   for (Vector<Row *>::iterator row = mRows.begin(); row < mRows.end(); ++row)
 441   {
 442      // set the top of the current row
 443      if (row != mRows.begin())
 444      {
 445         // rows other than the first can have padding above them
 446         currentOffset.y += (*row)->mHeightPad;
 447         currentOffset.y += rowHeight;
 448      }
 449
 450      // draw the box around the whole row's extent
 451      upperLeft = currentOffset;
 452      borderRect.point = upperLeft;
 453      borderRect.extent = rowExtent;
 454      GFX->getDrawUtil()->drawRect(borderRect, rowBorderColor);
 455
 456      // draw the box around the hit area of the row
 457      upperLeft = currentOffset + hitAreaOffset;
 458      borderRect.point = upperLeft;
 459      borderRect.extent = hitAreaExtent;
 460      GFX->getDrawUtil()->drawRect(borderRect, hitBorderColor);
 461   }
 462}
 463
 464void GuiGameListMenuCtrl::addRow(const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, S32 mode, const char* tooltip)
 465{
 466   Row * row = new Row();
 467   addRow(row, label, callback, icon, yPad, useHighlightIcon, enabled, mode, tooltip);
 468}
 469
 470void GuiGameListMenuCtrl::addRow(Row * row, const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, S32 mode, const char* tooltip)
 471{
 472   row->mLabel = StringTable->insert(label, true);
 473   row->mScriptCallback = (dStrlen(callback) > 0) ? StringTable->insert(callback, true) : NULL;
 474   row->mIconIndex = (icon < 0) ? NO_ICON : icon;
 475   row->mHeightPad = yPad;
 476   row->mUseHighlightIcon = useHighlightIcon;
 477   row->mEnabled = enabled;
 478   row->mMode = (Row::Mode)mode;
 479   row->mTooltip = StringTable->insert(tooltip);
 480
 481   mRows.push_back(row);
 482
 483   updateHeight();
 484
 485   if (mSelected == NO_ROW)
 486   {
 487      selectFirstEnabledRow();
 488   }
 489}
 490
 491void GuiGameListMenuCtrl::addRow(const char* label, const char* optionsList, bool wrapOptions, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip, const char* defaultValue)
 492{
 493   static StringTableEntry DELIM = StringTable->insert("\t", true);
 494   Row* row = new Row();
 495   Vector<StringTableEntry> options(__FILE__, __LINE__);
 496
 497   S32 defaultOption = 0;
 498
 499   S32 count = StringUnit::getUnitCount(optionsList, DELIM);
 500   for (S32 i = 0; i < count; ++i)
 501   {
 502      const char* option = StringUnit::getUnit(optionsList, i, DELIM);
 503      options.push_back(StringTable->insert(option, true));
 504
 505      if (String::compare(option, defaultValue) == 0)
 506         defaultOption = options.size() - 1;
 507   }
 508   row->mOptions = options;
 509   bool hasOptions = row->mOptions.size() > 0;
 510   row->mSelectedOption = (hasOptions) ? defaultOption : NO_OPTION;
 511   row->mWrapOptions = wrapOptions;
 512   addRow(row, label, callback, icon, yPad, true, (hasOptions) ? enabled : false, Row::Mode::OptionList, tooltip);
 513}
 514
 515void GuiGameListMenuCtrl::addRow(const char* label, F32 defaultValue, F32 increments, Point2F range, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip)
 516{
 517   static StringTableEntry DELIM = StringTable->insert("\t", true);
 518   Row* row = new Row();
 519   row->mValue = defaultValue;
 520   row->mStepSize = increments;
 521   row->mRange = range;
 522
 523   addRow(row, label, callback, icon, yPad, true, enabled, Row::Mode::Slider, tooltip);
 524}
 525
 526void GuiGameListMenuCtrl::addRow(const char* label, const char* bitmapName, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip)
 527{
 528   static StringTableEntry DELIM = StringTable->insert("\t", true);
 529   Row* row = new Row();
 530   row->mBitmap = StringTable->insert(bitmapName);
 531
 532   if(row->mBitmap != StringTable->EmptyString())
 533      row->mBitmapTex.set(row->mBitmap, &GFXDefaultGUIProfile, avar("%s() - mTextureObject (line %d)", __FUNCTION__, __LINE__));
 534
 535   addRow(row, label, callback, icon, yPad, true, enabled, Row::Mode::Keybind, tooltip);
 536}
 537
 538void GuiGameListMenuCtrl::removeRow(const S32& row)
 539{
 540   if (row == -1 || row >= mRows.size())
 541      return;
 542
 543   mRows.erase(row);
 544}
 545
 546Point2I  GuiGameListMenuCtrl::getMinExtent() const
 547{
 548   Point2I parentMin = Parent::getMinExtent();
 549
 550   GuiGameListMenuProfile * profile = (GuiGameListMenuProfile *) mProfile;
 551
 552   S32 minHeight = 0;
 553   S32 rowHeight = profile->getRowHeight();
 554
 555   for (Vector<Row *>::const_iterator row = mRows.begin(); row < mRows.end(); ++row)
 556   {
 557      minHeight += rowHeight;
 558      if (row != mRows.begin())
 559      {
 560         minHeight += (*row)->mHeightPad;
 561      }
 562   }
 563
 564   if (minHeight > parentMin.y)
 565      parentMin.y = minHeight;
 566
 567   return parentMin;
 568}
 569
 570bool GuiGameListMenuCtrl::onAdd()
 571{
 572   if( !Parent::onAdd() )
 573      return false;
 574      
 575   // If we have a non-GuiGameListMenuProfile profile, try to
 576   // substitute it for DefaultListMenuProfile.
 577      
 578   if( !hasValidProfile() )
 579   {
 580      GuiGameListMenuProfile* profile;
 581      if( !Sim::findObject( "DefaultListMenuProfile", profile ) )
 582      {
 583         Con::errorf( "GuiGameListMenuCtrl: %s can't be created with a profile of type %s. Please create it with a profile of type GuiGameListMenuProfile.",
 584            getName(), mProfile->getClassName() );
 585         return false;
 586      }
 587      else
 588         Con::warnf( "GuiGameListMenuCtrl: substituted non-GuiGameListMenuProfile in %s for DefaultListMenuProfile", getName() );
 589         
 590      setControlProfile( profile );
 591   }
 592
 593   return true;
 594}
 595
 596bool GuiGameListMenuCtrl::onWake()
 597{
 598   if( !Parent::onWake() )
 599      return false;
 600      
 601   if( !hasValidProfile() )
 602      return false;
 603      
 604   /*if( mRows.empty() )
 605   {
 606      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.",
 607         getName() );
 608      return false;
 609   }*/
 610
 611   enforceConstraints();
 612
 613   selectFirstEnabledRow();
 614
 615   setFirstResponder();
 616
 617   mHighlighted = NO_ROW;
 618
 619   return true;
 620}
 621
 622bool GuiGameListMenuCtrl::hasValidProfile() const
 623{
 624   GuiGameListMenuProfile * profile = dynamic_cast<GuiGameListMenuProfile *>(mProfile);
 625   return profile;
 626}
 627
 628void GuiGameListMenuCtrl::enforceConstraints()
 629{
 630   if( hasValidProfile() )
 631   {
 632      ((GuiGameListMenuProfile *)mProfile)->enforceConstraints();
 633   }
 634   updateHeight();
 635}
 636
 637void GuiGameListMenuCtrl::updateHeight()
 638{
 639   S32 minHeight = getMinExtent().y;
 640   if (getHeight() < minHeight)
 641   {
 642      setHeight(minHeight);
 643   }
 644}
 645
 646void GuiGameListMenuCtrl::onMouseDown(const GuiEvent &event)
 647{
 648   S32 hitRow = getRow(event.mousePoint);
 649   if (hitRow != NO_ROW)
 650   {
 651      S32 delta = (mSelected != NO_ROW) ? (hitRow - mSelected) : (mSelected + 1);
 652      changeRow(delta);
 653   }
 654}
 655
 656void GuiGameListMenuCtrl::onMouseLeave(const GuiEvent &event)
 657{
 658   mHighlighted = NO_ROW;
 659}
 660
 661void GuiGameListMenuCtrl::onMouseMove(const GuiEvent &event)
 662{
 663   S32 hitRow = getRow(event.mousePoint);
 664   // allow mHighligetd to be set to NO_ROW so rows can be unhighlighted
 665   mHighlighted = hitRow;
 666}
 667
 668void GuiGameListMenuCtrl::onMouseUp(const GuiEvent &event)
 669{
 670   S32 hitRow = getRow(event.mousePoint);
 671   if ((hitRow != NO_ROW) && isRowEnabled(hitRow) && (hitRow == getSelected()))
 672   {
 673      if (mRows[hitRow]->mMode == Row::Mode::Default)
 674      {
 675         activateRow();
 676      }
 677      else if (mRows[hitRow]->mMode == Row::Mode::OptionList)
 678      {
 679         S32 xPos = globalToLocalCoord(event.mousePoint).x;
 680         clickOption((Row*)mRows[getSelected()], xPos);
 681      }
 682      else if (mRows[hitRow]->mMode == Row::Mode::Slider)
 683      {
 684         S32 xPos = globalToLocalCoord(event.mousePoint).x;
 685         clickSlider((Row*)mRows[getSelected()], xPos);
 686      }
 687      else if (mRows[hitRow]->mMode == Row::Mode::Keybind)
 688      {
 689         S32 xPos = globalToLocalCoord(event.mousePoint).x;
 690         clickKeybind((Row*)mRows[getSelected()], xPos);
 691      }
 692   }
 693}
 694
 695void GuiGameListMenuCtrl::activateRow()
 696{
 697   S32 row = getSelected();
 698   if ((row != NO_ROW) && isRowEnabled(row) && (mRows[row]->mScriptCallback != NULL))
 699   {
 700      setThisControl();
 701      if (Con::isFunction(mRows[row]->mScriptCallback))
 702      {
 703         Con::executef(mRows[row]->mScriptCallback);
 704      }
 705   }
 706}
 707
 708S32 GuiGameListMenuCtrl::getRow(Point2I globalPoint)
 709{
 710   Point2I localPoint = globalToLocalCoord(globalPoint);
 711   GuiGameListMenuProfile * profile = (GuiGameListMenuProfile *) mProfile;
 712
 713   F32 xScale = (float) getWidth() / profile->getRowWidth();
 714
 715   S32 rowHeight = profile->getRowHeight();
 716   Point2I currentOffset(0, 0);
 717   Point2I hitAreaUpperLeft = profile->mHitAreaUpperLeft;
 718   hitAreaUpperLeft.x *= xScale;
 719   Point2I hitAreaLowerRight = profile->mHitAreaLowerRight;
 720   hitAreaLowerRight.x *= xScale;
 721
 722   Point2I upperLeft, lowerRight;
 723   for (Vector<Row *>::iterator row = mRows.begin(); row < mRows.end(); ++row)
 724   {
 725      if (row != mRows.begin())
 726      {
 727         // rows other than the first can have padding above them
 728         currentOffset.y += (*row)->mHeightPad;
 729      }
 730
 731      upperLeft = currentOffset + hitAreaUpperLeft;
 732      lowerRight = currentOffset + hitAreaLowerRight;
 733
 734      if ((upperLeft.x <= localPoint.x) && (localPoint.x < lowerRight.x) &&
 735         (upperLeft.y <= localPoint.y) && (localPoint.y < lowerRight.y))
 736      {
 737         return row - mRows.begin();
 738      }
 739
 740      currentOffset.y += rowHeight;
 741   }
 742
 743   return NO_ROW;
 744}
 745
 746void GuiGameListMenuCtrl::setSelected(S32 index)
 747{
 748   if (index == NO_ROW)
 749   {
 750      // deselection
 751      mSelected = NO_ROW;
 752      return;
 753   }
 754
 755   if (! isValidRowIndex(index))
 756   {
 757      return;
 758   }
 759
 760   if (! isRowEnabled(index))
 761   {
 762      // row is disabled, it can't be selected
 763      return;
 764   }
 765
 766   mSelected = mClamp(index, 0, mRows.size() - 1);
 767
 768   //If we're childed to a scroll container, make sure us changing rows has our new position visible
 769   GuiScrollCtrl* scroll = dynamic_cast<GuiScrollCtrl*>(getParent());
 770   if (scroll)
 771   {
 772      scroll->scrollRectVisible(getRowBounds(mSelected));
 773   }
 774}
 775
 776bool GuiGameListMenuCtrl::isRowEnabled(S32 index) const
 777{
 778   if (! isValidRowIndex(index))
 779   {
 780      return false;
 781   }
 782
 783   return mRows[index]->mEnabled;
 784}
 785
 786void GuiGameListMenuCtrl::setRowEnabled(S32 index, bool enabled)
 787{
 788   if (! isValidRowIndex(index))
 789   {
 790      return;
 791   }
 792
 793   mRows[index]->mEnabled = enabled;
 794
 795   if (getSelected() == index)
 796   {
 797      selectFirstEnabledRow();
 798   }
 799}
 800
 801bool GuiGameListMenuCtrl::isValidRowIndex(S32 index) const
 802{
 803   return ((0 <= index) && (index < mRows.size()));
 804}
 805
 806void GuiGameListMenuCtrl::selectFirstEnabledRow()
 807{
 808   setSelected(NO_ROW);
 809   for (Vector<Row *>::iterator row = mRows.begin(); row < mRows.end(); ++row)
 810   {
 811      if ((*row)->mEnabled)
 812      {
 813         setSelected(row - mRows.begin());
 814         return;
 815      }
 816   }
 817}
 818
 819bool GuiGameListMenuCtrl::onInputEvent(const InputEventInfo& event)
 820{
 821   if (mCallbackOnInputs)
 822   {
 823      char deviceStr[32];
 824      if (!ActionMap::getDeviceName(event.deviceType, event.deviceInst, deviceStr))
 825         return false;
 826
 827      String deviceString = deviceStr;
 828
 829      if (event.action == SI_MAKE || event.action == SI_BREAK)
 830      {
 831         bool isModifier = false;
 832
 833         bool state = event.action == SI_MAKE;
 834
 835         switch (event.objInst)
 836         {
 837            case KEY_LCONTROL:
 838            case KEY_RCONTROL:
 839            case KEY_LALT:
 840            case KEY_RALT:
 841            case KEY_LSHIFT:
 842            case KEY_RSHIFT:
 843            case KEY_MAC_LOPT:
 844            case KEY_MAC_ROPT:
 845               isModifier = true;
 846         }
 847
 848         if ((event.objType == SI_KEY) && isModifier)
 849         {
 850            char keyString[32];
 851            if (!ActionMap::getKeyString(event.objInst, keyString))
 852               return false;
 853
 854            onInputEvent_callback(deviceString.c_str(), keyString, state);
 855
 856            if (mConsumeKeyInputEvents)
 857            {
 858               if(deviceString.startsWith("keyboard"))
 859                  return true;
 860            }
 861         }
 862         else
 863         {
 864            const char* actionString = ActionMap::buildActionString(&event);
 865            onInputEvent_callback(deviceString.c_str(), actionString, state);
 866
 867            if (mConsumeKeyInputEvents)
 868            {
 869               if (deviceString.startsWith("keyboard") || deviceString.startsWith("gamepad"))
 870                  return true;
 871            }
 872         }
 873      }
 874      else if (event.objType == SI_AXIS || event.objType == SI_INT || event.objType == SI_FLOAT)
 875      {
 876         F32 fValue = event.fValue;
 877         if (event.objType == SI_INT)
 878            fValue = (F32)event.iValue;
 879
 880         if (!ActionMap::getDeviceName(event.deviceType, event.deviceInst, deviceStr))
 881            return false;
 882
 883         const char* actionString = ActionMap::buildActionString(&event);
 884
 885         onAxisEvent_callback(deviceStr, actionString, fValue);
 886      }
 887   }
 888
 889   return false;
 890}
 891
 892bool GuiGameListMenuCtrl::onKeyDown(const GuiEvent &event)
 893{
 894   switch (event.keyCode)
 895   {
 896      case KEY_UP:
 897         changeRow(-1);
 898         return true;
 899
 900      case KEY_DOWN:
 901         changeRow(1);
 902         return true;
 903
 904      case KEY_LEFT:
 905         changeOption(-1);
 906         return true;
 907
 908      case KEY_RIGHT:
 909         changeOption(1);
 910         return true;
 911
 912      case KEY_A:
 913      case KEY_RETURN:
 914      case KEY_NUMPADENTER:
 915      case KEY_SPACE:
 916      case XI_A:
 917      case XI_START:
 918         doScriptCommand(mCallbackOnA);
 919         return true;
 920
 921      case KEY_B:
 922      case KEY_ESCAPE:
 923      case KEY_BACKSPACE:
 924      case KEY_DELETE:
 925      case XI_B:
 926      case XI_BACK:
 927         doScriptCommand(mCallbackOnB);
 928         return true;
 929
 930      case KEY_X:
 931      case XI_X:
 932         doScriptCommand(mCallbackOnX);
 933         return true;
 934
 935      case KEY_Y:
 936      case XI_Y:
 937         doScriptCommand(mCallbackOnY);
 938         return true;
 939      default:
 940         break;
 941   }
 942
 943   return Parent::onKeyDown(event);
 944}
 945
 946bool GuiGameListMenuCtrl::onGamepadAxisUp(const GuiEvent &event)
 947{
 948   changeRow(-1);
 949   return true;
 950}
 951
 952bool GuiGameListMenuCtrl::onGamepadAxisDown(const GuiEvent &event)
 953{
 954   changeRow(1);
 955   return true;
 956}
 957
 958bool GuiGameListMenuCtrl::onGamepadAxisLeft(const GuiEvent& event)
 959{
 960   changeOption(-1);
 961   return true;
 962}
 963
 964bool GuiGameListMenuCtrl::onGamepadAxisRight(const GuiEvent& event)
 965{
 966   changeOption(1);
 967   return true;
 968}
 969
 970void GuiGameListMenuCtrl::doScriptCommand(StringTableEntry command)
 971{
 972   if (command && command[0])
 973   {
 974      setThisControl();
 975      Con::evaluate(command, false, __FILE__);
 976   }
 977}
 978
 979void GuiGameListMenuCtrl::changeRow(S32 delta)
 980{
 981   S32 oldRowIndex = getSelected();
 982   S32 newRowIndex = oldRowIndex;
 983   do
 984   {
 985      newRowIndex += delta;
 986      if (newRowIndex >= mRows.size())
 987      {
 988         newRowIndex = 0;
 989      }
 990      else if (newRowIndex < 0)
 991      {
 992         newRowIndex = mRows.size() - 1;
 993      }
 994   }
 995   while ((! mRows[newRowIndex]->mEnabled) && (newRowIndex != oldRowIndex));
 996
 997   setSelected(newRowIndex);
 998
 999   // do the callback
1000   onChange_callback();
1001}
1002
1003void GuiGameListMenuCtrl::setThisControl()
1004{
1005   smThisControl = this;
1006}
1007
1008StringTableEntry GuiGameListMenuCtrl::getRowLabel(S32 rowIndex) const
1009{
1010   if (! isValidRowIndex(rowIndex))
1011   {
1012      // not a valid row index, don't do anything
1013      return StringTable->EmptyString();
1014   }
1015   return mRows[rowIndex]->mLabel;
1016}
1017
1018void GuiGameListMenuCtrl::setRowLabel(S32 rowIndex, const char * label)
1019{
1020   if (! isValidRowIndex(rowIndex))
1021   {
1022      // not a valid row index, don't do anything
1023      return;
1024   }
1025
1026   mRows[rowIndex]->mLabel = StringTable->insert(label, true);
1027}
1028
1029void GuiGameListMenuCtrl::clearRows()
1030{
1031   for (U32 i = 0; i < mRows.size(); i++)
1032   {
1033      if (mRows[i]->mBitmap != StringTable->EmptyString())
1034         mRows[i]->mBitmapTex = nullptr;
1035   }
1036
1037   mRows.clear();
1038   setSelected(-1);
1039   setHeight(mMinExtent.y);
1040}
1041
1042void GuiGameListMenuCtrl::refresh()
1043{
1044   enforceConstraints();
1045}
1046
1047RectI GuiGameListMenuCtrl::getRowBounds(S32 rowIndex)
1048{
1049   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
1050
1051   F32 xScale = (float)getWidth() / profile->getRowWidth();
1052   S32 rowHeight = profile->getRowHeight();
1053
1054   Point2I currentOffset = Point2I::Zero;
1055   Point2I extent = getExtent();
1056   Point2I rowExtent(extent.x, rowHeight);
1057
1058   for (U32 i = 1; i <= rowIndex; i++)
1059   {
1060      //the top row can't pad, so we'll ignore it
1061      GuiGameListMenuCtrl::Row* row = mRows[i];
1062
1063      // rows other than the first can have padding above them
1064      currentOffset.y += row->mHeightPad;
1065      currentOffset.y += rowHeight;
1066   }
1067
1068   return RectI(currentOffset, rowExtent);
1069}
1070//-----------------------------------------------------------------------------
1071// Console stuff (GuiGameListMenuCtrl)
1072//-----------------------------------------------------------------------------
1073
1074StringTableEntry GuiGameListMenuCtrl::getCurrentOption(S32 rowIndex) const
1075{
1076   if (isValidRowIndex(rowIndex))
1077   {
1078      Row* row = (Row*)mRows[rowIndex];
1079      if (row->mSelectedOption != NO_OPTION)
1080      {
1081         return row->mOptions[row->mSelectedOption];
1082      }
1083   }
1084   return StringTable->insert("", false);
1085}
1086
1087bool GuiGameListMenuCtrl::selectOption(S32 rowIndex, const char* theOption)
1088{
1089   if (!isValidRowIndex(rowIndex))
1090   {
1091      return false;
1092   }
1093
1094   Row* row = (Row*)mRows[rowIndex];
1095
1096   for (Vector<StringTableEntry>::iterator anOption = row->mOptions.begin(); anOption < row->mOptions.end(); ++anOption)
1097   {
1098      if (String::compare(*anOption, theOption) == 0)
1099      {
1100         S32 newIndex = anOption - row->mOptions.begin();
1101         row->mSelectedOption = newIndex;
1102         return true;
1103      }
1104   }
1105
1106   return false;
1107}
1108
1109void GuiGameListMenuCtrl::setOptions(S32 rowIndex, const char* optionsList)
1110{
1111   static StringTableEntry DELIM = StringTable->insert("\t", true);
1112
1113   if (!isValidRowIndex(rowIndex))
1114   {
1115      return;
1116   }
1117
1118   Row* row = (Row*)mRows[rowIndex];
1119
1120   S32 count = StringUnit::getUnitCount(optionsList, DELIM);
1121   row->mOptions.setSize(count);
1122   for (S32 i = 0; i < count; ++i)
1123   {
1124      const char* option = StringUnit::getUnit(optionsList, i, DELIM);
1125      row->mOptions[i] = StringTable->insert(option, true);
1126   }
1127
1128   if (row->mSelectedOption >= row->mOptions.size())
1129   {
1130      row->mSelectedOption = row->mOptions.size() - 1;
1131   }
1132}
1133
1134void GuiGameListMenuCtrl::clickOption(Row* row, S32 xPos)
1135{
1136   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
1137   if (!profile->hasArrows())
1138   {
1139      return;
1140   }
1141
1142   F32 xScale = (float)getWidth() / profile->getRowWidth();
1143
1144   S32 bitmapArrowWidth = mProfile->getBitmapArrayRect(Profile::TEX_FIRST_ARROW).extent.x;
1145
1146   S32 leftArrowX1 = profile->mColumnSplit * xScale;
1147   S32 leftArrowX2 = leftArrowX1 + bitmapArrowWidth;
1148
1149   S32 rightArrowX2 = (profile->mHitAreaLowerRight.x - profile->mRightPad) * xScale;
1150   S32 rightArrowX1 = rightArrowX2 - bitmapArrowWidth;
1151
1152   if ((leftArrowX1 <= xPos) && (xPos <= leftArrowX2))
1153   {
1154      changeOption(row, -1);
1155   }
1156   else if ((rightArrowX1 <= xPos) && (xPos <= rightArrowX2))
1157   {
1158      changeOption(row, 1);
1159   }
1160}
1161
1162void GuiGameListMenuCtrl::changeOption(S32 delta)
1163{
1164   if (getSelected() != NO_ROW)
1165   {
1166      Row* row = (Row*)mRows[getSelected()];
1167      changeOption(row, delta);
1168   }
1169}
1170
1171void GuiGameListMenuCtrl::changeOption(Row* row, S32 delta)
1172{
1173   S32 optionCount = row->mOptions.size();
1174
1175   S32 newSelection = row->mSelectedOption + delta;
1176   if (optionCount == 0)
1177   {
1178      newSelection = NO_OPTION;
1179   }
1180   else if (!row->mWrapOptions)
1181   {
1182      newSelection = mClamp(newSelection, 0, optionCount - 1);
1183   }
1184   else if (newSelection < 0)
1185   {
1186      newSelection = optionCount - 1;
1187   }
1188   else if (newSelection >= optionCount)
1189   {
1190      newSelection = 0;
1191   }
1192   row->mSelectedOption = newSelection;
1193
1194   if (row->mMode == GuiGameListMenuCtrl::Row::Slider)
1195   {
1196      row->mValue += row->mStepSize * delta;
1197
1198      row->mValue = mRound(row->mValue / row->mStepSize) * row->mStepSize;
1199
1200      if (row->mValue < row->mRange.x)
1201         row->mValue = row->mRange.x;
1202      if (row->mValue > row->mRange.y)
1203         row->mValue = row->mRange.y;
1204   }
1205
1206   static StringTableEntry LEFT = StringTable->insert("LEFT", true);
1207   static StringTableEntry RIGHT = StringTable->insert("RIGHT", true);
1208
1209   if (row->mScriptCallback != NULL && (row->mSelectedOption != NO_OPTION && row->mMode != GuiGameListMenuCtrl::Row::Slider))
1210   {
1211      setThisControl();
1212      StringTableEntry direction = NULL;
1213      if (delta < 0)
1214      {
1215         direction = LEFT;
1216      }
1217      else if (delta > 0)
1218      {
1219         direction = RIGHT;
1220      }
1221      if ((direction != NULL) && (Con::isFunction(row->mScriptCallback)))
1222      {
1223         Con::executef(row->mScriptCallback, direction);
1224      }
1225   }
1226}
1227IMPLEMENT_CONOBJECT(GuiGameListMenuCtrl);
1228
1229void GuiGameListMenuCtrl::clickSlider(Row* row, S32 xPos)
1230{
1231   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
1232   if (!profile->hasArrows())
1233   {
1234      return;
1235   }
1236
1237   F32 xScale = (float)getWidth() / profile->getRowWidth();
1238
1239   S32 bitmapArrowWidth = mProfile->getBitmapArrayRect(Profile::TEX_FIRST_ARROW).extent.x;
1240
1241   S32 leftArrowX1 = profile->mColumnSplit * xScale;
1242   S32 leftArrowX2 = leftArrowX1 + bitmapArrowWidth;
1243
1244   S32 rightArrowX2 = (profile->mHitAreaLowerRight.x - profile->mRightPad) * xScale;
1245   S32 rightArrowX1 = rightArrowX2 - bitmapArrowWidth;
1246
1247   if ((leftArrowX1 <= xPos) && (xPos <= leftArrowX2))
1248   {
1249      row->mValue -= row->mStepSize;
1250
1251      row->mValue = mRound(row->mValue / row->mStepSize) * row->mStepSize;
1252
1253      if (row->mValue < row->mRange.x)
1254         row->mValue = row->mRange.x;
1255
1256   }
1257   else if ((rightArrowX1 <= xPos) && (xPos <= rightArrowX2))
1258   {
1259      //F32 snap = row->mValue % row->mStepSize;
1260      //row->mValue.y -= snap;
1261
1262      row->mValue += row->mStepSize;
1263
1264      row->mValue = mRound(row->mValue / row->mStepSize) * row->mStepSize;
1265
1266      if (row->mValue > row->mRange.y)
1267         row->mValue = row->mRange.y;
1268   }
1269   else
1270   {
1271      //see if we clicked on the sliderbar itself
1272      S32 barStart = leftArrowX2;
1273      S32 barEnd = rightArrowX1;
1274
1275      if (xPos >= barStart && xPos <= barEnd)
1276      {
1277         //find the position
1278         F32 newValue = (((xPos - barStart) * (row->mRange.y - row->mRange.x)) / (barEnd - barStart)) + row->mRange.x;
1279
1280         newValue = mRound(newValue / row->mStepSize) * row->mStepSize;
1281
1282         row->mValue = newValue;
1283      }
1284   }
1285}
1286
1287void GuiGameListMenuCtrl::clickKeybind(Row* row, S32 xPos)
1288{
1289   GuiGameListMenuProfile* profile = (GuiGameListMenuProfile*)mProfile;
1290   F32 xScale = (float)getWidth() / profile->getRowWidth();
1291   S32 columnSplit = profile->mColumnSplit * xScale;
1292
1293   S32 rowHeight = profile->getRowHeight();
1294
1295   S32 optionWidth = xScale - columnSplit;
1296
1297   GFXDrawUtil* drawer = GFX->getDrawUtil();
1298   //drawer->drawBitmap(row->mBitmap, )
1299
1300   Point2I button;
1301   button.x = columnSplit + (columnSplit / 2)/* + (optionWidth / 2)*/;
1302   button.y = rowHeight / 4;
1303
1304   Point2I buttonSize;
1305   buttonSize.x = rowHeight / 2;
1306   buttonSize.y = rowHeight / 2;
1307
1308   GFXTextureObject* texture = row->mBitmapTex;
1309   RectI rect(button, buttonSize);
1310
1311   if (rect.pointInRect(Point2I(xPos, rowHeight / 2)))
1312   {
1313      if (row->mScriptCallback != StringTable->EmptyString())
1314      {
1315         S32 rowId = getSelected();
1316         Con::executef(row->mScriptCallback, rowId);
1317      }
1318   }
1319}
1320
1321F32 GuiGameListMenuCtrl::getValue(S32 rowIndex)
1322{
1323   if (!isValidRowIndex(rowIndex))
1324   {
1325      return 0;
1326   }
1327
1328   Row* row = (Row*)mRows[rowIndex];
1329
1330   return row->mValue;
1331}
1332
1333void GuiGameListMenuCtrl::setValue(S32 rowIndex, F32 value)
1334{
1335   if (!isValidRowIndex(rowIndex))
1336   {
1337      return;
1338   }
1339
1340   Row* row = (Row*)mRows[rowIndex];
1341
1342   row->mValue = value;
1343}
1344
1345const char* GuiGameListMenuCtrl::getTooltip(S32 rowIndex)
1346{
1347   if (!isValidRowIndex(rowIndex))
1348   {
1349      return "";
1350   }
1351
1352   Row* row = (Row*)mRows[rowIndex];
1353
1354   return row->mTooltip;
1355}
1356
1357ConsoleDocClass( GuiGameListMenuCtrl,
1358   "@brief A base class for cross platform menu controls that are gamepad friendly.\n\n"
1359
1360   "This class is used to build row-based menu GUIs that can be easily navigated "
1361   "using the keyboard, mouse or gamepad. The desired row can be selected using "
1362   "the mouse, or by navigating using the Up and Down buttons.\n\n"
1363
1364   "@tsexample\n\n"
1365   "new GuiGameListMenuCtrl()\n"
1366   "{\n"
1367   "   debugRender = \"0\";\n"
1368   "   callbackOnA = \"applyOptions();\";\n"
1369   "   callbackOnB = \"Canvas.setContent(MainMenuGui);\";\n"
1370   "   callbackOnX = \"\";\n"
1371   "   callbackOnY = \"revertOptions();\";\n"
1372   "   //Properties not specific to this control have been omitted from this example.\n"
1373   "};\n"
1374   "@endtsexample\n\n"
1375
1376   "@see GuiGameListMenuProfile\n\n"
1377
1378   "@ingroup GuiGame"
1379);
1380
1381IMPLEMENT_CALLBACK( GuiGameListMenuCtrl, onChange, void, (), (),
1382   "Called when the selected row changes." );
1383
1384IMPLEMENT_CALLBACK(GuiGameListMenuCtrl, onInputEvent, void, (const char* device, const char* action, bool state),
1385   (device, action, state),
1386   "@brief Callback that occurs when an input is triggered on this control\n\n"
1387   "@param device The device type triggering the input, such as keyboard, mouse, etc\n"
1388   "@param action The actual event occuring, such as a key or button\n"
1389   "@param state True if the action is being pressed, false if it is being release\n\n");
1390
1391IMPLEMENT_CALLBACK(GuiGameListMenuCtrl, onAxisEvent, void, (const char* device, const char* action, F32 axisValue),
1392   (device, action, axisValue),
1393   "@brief Callback that occurs when an axis event is triggered on this control\n\n"
1394   "@param device The device type triggering the input, such as mouse, joystick, gamepad, etc\n"
1395   "@param action The ActionMap code for the axis\n"
1396   "@param axisValue The current value of the axis\n\n");
1397
1398void GuiGameListMenuCtrl::initPersistFields()
1399{
1400   addField("debugRender", TypeBool, Offset(mDebugRender, GuiGameListMenuCtrl),
1401      "Enable debug rendering" );
1402
1403   addField("callbackOnA", TypeString, Offset(mCallbackOnA, GuiGameListMenuCtrl),
1404      "Script callback when the 'A' button is pressed. 'A' inputs are Keyboard: A, Return, Space; Gamepad: A, Start" );
1405
1406   addField("callbackOnB", TypeString, Offset(mCallbackOnB, GuiGameListMenuCtrl),
1407      "Script callback when the 'B' button is pressed. 'B' inputs are Keyboard: B, Esc, Backspace, Delete; Gamepad: B, Back" );
1408
1409   addField("callbackOnX", TypeString, Offset(mCallbackOnX, GuiGameListMenuCtrl),
1410      "Script callback when the 'X' button is pressed. 'X' inputs are Keyboard: X; Gamepad: X" );
1411
1412   addField("callbackOnY", TypeString, Offset(mCallbackOnY, GuiGameListMenuCtrl),
1413      "Script callback when the 'Y' button is pressed. 'Y' inputs are Keyboard: Y; Gamepad: Y" );
1414
1415   addField("callbackOnInputs", TypeBool, Offset(mCallbackOnInputs, GuiGameListMenuCtrl),
1416      "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.");
1417
1418   addField("consumeKeyInputEvents", TypeBool, Offset(mConsumeKeyInputEvents, GuiGameListMenuCtrl),
1419      "When callbackOnInputs is active, this indicates if the input event should be consumed, or allowed 'through' to let other things respond to the event as well.");
1420   
1421
1422   Parent::initPersistFields();
1423}
1424
1425DefineEngineMethod( GuiGameListMenuCtrl, addRow, void,
1426   ( const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, int mode ),
1427   ( -1, 0, true, true, 0 ),
1428   "Add a row to the list control.\n\n"
1429   "@param label The text to display on the row as a label.\n"
1430   "@param callback Name of a script function to use as a callback when this row is activated.\n"
1431   "@param icon [optional] Index of the icon to use as a marker.\n"
1432   "@param yPad [optional] An extra amount of height padding before the row. Does nothing on the first row.\n"
1433   "@param useHighlightIcon [optional] Does this row use the highlight icon?.\n"
1434   "@param enabled [optional] If this row is initially enabled.\n"
1435   "@param mode [optional] What option mode the row is in. 0 = Default, 1 = OptionList, 2 == Keybind")
1436{
1437   object->addRow( label, callback, icon, yPad, useHighlightIcon, enabled, mode);
1438}
1439
1440DefineEngineMethod( GuiGameListMenuCtrl, isRowEnabled, bool, ( S32 row ),,
1441   "Determines if the specified row is enabled or disabled.\n\n"
1442   "@param row The row to set the enabled status of.\n"
1443   "@return True if the specified row is enabled. False if the row is not enabled or the given index was not valid." )
1444{
1445   return object->isRowEnabled( row );
1446}
1447
1448DefineEngineMethod( GuiGameListMenuCtrl, setRowEnabled, void, ( S32 row, bool enabled ),,
1449   "Sets a row's enabled status according to the given parameters.\n\n"
1450   "@param row The index to check for validity.\n"
1451   "@param enabled Indicate true to enable the row or false to disable it." )
1452{
1453   object->setRowEnabled( row, enabled );
1454}
1455
1456DefineEngineMethod( GuiGameListMenuCtrl, activateRow, void, (),,
1457   "Activates the current row. The script callback of  the current row will be called (if it has one)." )
1458{
1459   object->activateRow();
1460}
1461
1462DefineEngineMethod( GuiGameListMenuCtrl, getRowCount, S32, (),,
1463   "Gets the number of rows on the control.\n\n"
1464   "@return (int) The number of rows on the control." )
1465{
1466   return object->getRowCount();
1467}
1468
1469DefineEngineMethod( GuiGameListMenuCtrl, getRowLabel, const char *, ( S32 row ),,
1470   "Gets the label displayed on the specified row.\n\n"
1471   "@param row Index of the row to get the label of.\n"
1472   "@return The label for the row." )
1473{
1474   return object->getRowLabel( row );
1475}
1476
1477DefineEngineMethod( GuiGameListMenuCtrl, setRowLabel, void, ( S32 row, const char* label ),,
1478   "Sets the label on the given row.\n\n"
1479   "@param row Index of the row to set the label on.\n"
1480   "@param label Text to set as the label of the row.\n" )
1481{
1482   object->setRowLabel( row, label );
1483}
1484
1485DefineEngineMethod( GuiGameListMenuCtrl, setSelected, void, ( S32 row ),,
1486   "Sets the selected row. Only rows that are enabled can be selected.\n\n"
1487   "@param row Index of the row to set as selected." )
1488{
1489   object->setSelected( row );
1490}
1491
1492DefineEngineMethod( GuiGameListMenuCtrl, getSelectedRow, S32, (),,
1493   "Gets the index of the currently selected row.\n\n"
1494   "@return Index of the selected row." )
1495{
1496   return object->getSelected();
1497}
1498
1499DefineEngineMethod(GuiGameListMenuCtrl, clearRows, void, (), ,
1500   "Gets the index of the currently selected row.\n\n"
1501   "@return Index of the selected row.")
1502{
1503   return object->clearRows();
1504}
1505
1506DefineEngineMethod(GuiGameListMenuCtrl, refresh, void, (), ,
1507   "Gets the index of the currently selected row.\n\n"
1508   "@return Index of the selected row.")
1509{
1510   return object->refresh();
1511}
1512
1513DefineEngineMethod(GuiGameListMenuCtrl, addOptionRow, void,
1514   (const char* label, const char* options, bool wrapOptions, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip, const char* defaultValue),
1515   (-1, 0, true, "", ""),
1516   "Add a row to the list control.\n\n"
1517   "@param label The text to display on the row as a label.\n"
1518   "@param options A tab separated list of options.\n"
1519   "@param wrapOptions Specify true to allow options to wrap at each end or false to prevent wrapping.\n"
1520   "@param callback Name of a script function to use as a callback when this row is activated.\n"
1521   "@param icon [optional] Index of the icon to use as a marker.\n"
1522   "@param yPad [optional] An extra amount of height padding before the row. Does nothing on the first row.\n"
1523   "@param enabled [optional] If this row is initially enabled.")
1524{
1525   object->addRow(label, options, wrapOptions, callback, icon, yPad, enabled, tooltip, defaultValue);
1526}
1527
1528DefineEngineMethod(GuiGameListMenuCtrl, addSliderRow, void,
1529(const char* label, F32 defaultValue, F32 increment, Point2F range, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip),
1530(-1, 0, true, ""),
1531"Add a row to the list control.\n\n"
1532"@param label The text to display on the row as a label.\n"
1533"@param options A tab separated list of options.\n"
1534"@param wrapOptions Specify true to allow options to wrap at each end or false to prevent wrapping.\n"
1535"@param callback Name of a script function to use as a callback when this row is activated.\n"
1536"@param icon [optional] Index of the icon to use as a marker.\n"
1537"@param yPad [optional] An extra amount of height padding before the row. Does nothing on the first row.\n"
1538"@param enabled [optional] If this row is initially enabled.")
1539{
1540   object->addRow(label, defaultValue, increment, range, callback, icon, yPad, enabled, tooltip);
1541}
1542
1543DefineEngineMethod(GuiGameListMenuCtrl, addKeybindRow, void,
1544(const char* label, const char* bitmapName, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip),
1545(-1, 0, true, ""),
1546"Add a row to the list control.\n\n"
1547"@param label The text to display on the row as a label.\n"
1548"@param options A tab separated list of options.\n"
1549"@param wrapOptions Specify true to allow options to wrap at each end or false to prevent wrapping.\n"
1550"@param callback Name of a script function to use as a callback when this row is activated.\n"
1551"@param icon [optional] Index of the icon to use as a marker.\n"
1552"@param yPad [optional] An extra amount of height padding before the row. Does nothing on the first row.\n"
1553"@param enabled [optional] If this row is initially enabled.")
1554{
1555   object->addRow(label, bitmapName, callback, icon, yPad, enabled, tooltip);
1556}
1557
1558DefineEngineMethod(GuiGameListMenuCtrl, removeRow, void, (S32 row),,
1559   "Removes the row at the provided index")
1560{
1561   object->removeRow(row);
1562}
1563
1564DefineEngineMethod(GuiGameListMenuCtrl, getCurrentOption, const char*, (S32 row), ,
1565   "Gets the text for the currently selected option of the given row.\n\n"
1566   "@param row Index of the row to get the option from.\n"
1567   "@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.")
1568{
1569   return object->getCurrentOption(row);
1570}
1571
1572DefineEngineMethod(GuiGameListMenuCtrl, selectOption, bool, (S32 row, const char* option), ,
1573   "Set the row's current option to the one specified\n\n"
1574   "@param row Index of the row to set an option on.\n"
1575   "@param option The option to be made active.\n"
1576   "@return True if the row contained the option and was set, false otherwise.")
1577{
1578   return object->selectOption(row, option);
1579}
1580
1581DefineEngineMethod(GuiGameListMenuCtrl, setOptions, void, (S32 row, const char* optionsList), ,
1582   "Sets the list of options on the given row.\n\n"
1583   "@param row Index of the row to set options on."
1584   "@param optionsList A tab separated list of options for the control.")
1585{
1586   object->setOptions(row, optionsList);
1587}
1588
1589DefineEngineMethod(GuiGameListMenuCtrl, getValue, F32, (S32 row), ,
1590   "Sets the list of options on the given row.\n\n"
1591   "@param row Index of the row to set options on."
1592   "@param optionsList A tab separated list of options for the control.")
1593{
1594   return object->getValue(row);
1595}
1596
1597DefineEngineMethod(GuiGameListMenuCtrl, setValue, void, (S32 row, F32 value), ,
1598   "Sets the list of options on the given row.\n\n"
1599   "@param row Index of the row to set options on."
1600   "@param optionsList A tab separated list of options for the control.")
1601{
1602   object->setValue(row, value);
1603}
1604
1605DefineEngineMethod(GuiGameListMenuCtrl, getTooltip, const char*, (S32 row), ,
1606   "Sets the list of options on the given row.\n\n"
1607   "@param row Index of the row to set options on."
1608   "@param optionsList A tab separated list of options for the control.")
1609{
1610   return object->getTooltip(row);
1611}
1612
1613//-----------------------------------------------------------------------------
1614// GuiGameListMenuProfile
1615//-----------------------------------------------------------------------------
1616
1617GuiGameListMenuProfile::GuiGameListMenuProfile()
1618   : mHitAreaUpperLeft(0, 0),
1619   mHitAreaLowerRight(0, 0),
1620   mIconOffset(0, 0),
1621   mRowSize(0, 0),
1622   mRowScale(1.0f, 1.0f),
1623   mColumnSplit(0),
1624   mRightPad(0)
1625{
1626}
1627
1628bool GuiGameListMenuProfile::onAdd()
1629{
1630   if (! Parent::onAdd())
1631   {
1632      return false;
1633   }
1634
1635   // We can't call enforceConstraints() here because incRefCount initializes
1636   // some of the things to enforce. Do a basic sanity check here instead.
1637   
1638   if( !mBitmapName || !dStrlen(mBitmapName) )
1639   {
1640      Con::errorf( "GuiGameListMenuProfile: %s can't be created without a bitmap. Please add a 'Bitmap' property to the object definition.", getName() );
1641      return false;
1642   }
1643   
1644   if( mRowSize.x < 0 )
1645   {
1646      Con::errorf( "GuiGameListMenuProfile: %s can't have a negative row width. Please change the row width to be non-negative.", getName() );
1647      return false;
1648   }
1649   
1650   if( mRowSize.y < 0 )
1651   {
1652      Con::errorf( "GuiGameListMenuProfile: %s can't have a negative row height. Please change the row height to be non-negative.", getName() );
1653      return false;
1654   }
1655
1656   return true;
1657}
1658
1659void GuiGameListMenuProfile::enforceConstraints()
1660{
1661   if( getBitmapArrayRect(0).extent.isZero() )
1662      Con::errorf( "GuiGameListMenuCtrl: %s can't be created without a bitmap. Please add a bitmap to the profile's definition.", getName() );
1663
1664   if( mRowSize.x < 0 )
1665      Con::errorf( "GuiGameListMenuProfile: %s can't have a negative row width. Please change the row width to be non-negative.", getName() );
1666   mRowSize.x = getMax(mRowSize.x, 0);
1667
1668   if( mRowSize.y < 0 )
1669      Con::errorf( "GuiGameListMenuProfile: %s can't have a negative row height. Please change the row height to be non-negative.", getName() );
1670   mRowSize.y = getMax(mRowSize.y, 0);
1671
1672   Point2I rowTexExtent = getBitmapArrayRect(TEX_NORMAL).extent;
1673   mRowScale.x = (float) getRowWidth() / rowTexExtent.x;
1674   mRowScale.y = (float) getRowHeight() / rowTexExtent.y;
1675
1676   if (mHitAreaUpperLeft.x > mColumnSplit || mColumnSplit > mHitAreaLowerRight.x)
1677      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].",
1678         getName(), mColumnSplit, mHitAreaUpperLeft.x, mHitAreaLowerRight.x);
1679
1680   mColumnSplit = mClamp(mColumnSplit, mHitAreaUpperLeft.x, mHitAreaLowerRight.x);
1681}
1682
1683Point2I GuiGameListMenuProfile::getIconExtent()
1684{
1685   Point2I iconExtent = getBitmapArrayRect(TEX_FIRST_ICON).extent;
1686
1687   // scale both by y to keep the aspect ratio
1688   iconExtent.x *= mRowScale.y;
1689   iconExtent.y *= mRowScale.y;
1690
1691   return iconExtent;
1692}
1693
1694Point2I GuiGameListMenuProfile::getArrowExtent()
1695{
1696   Point2I arrowExtent = getBitmapArrayRect(TEX_FIRST_ARROW).extent;
1697
1698   // scale both by y to keep the aspect ratio
1699   arrowExtent.x *= mRowScale.y;
1700   arrowExtent.y *= mRowScale.y;
1701
1702   return arrowExtent;
1703}
1704
1705Point2I GuiGameListMenuProfile::getHitAreaExtent()
1706{
1707   if (mHitAreaLowerRight == mHitAreaUpperLeft)
1708   {
1709      return mRowSize;
1710   }
1711   else
1712   {
1713      return mHitAreaLowerRight - mHitAreaUpperLeft;
1714   }
1715}
1716
1717//-----------------------------------------------------------------------------
1718// Console stuff (GuiGameListMenuProfile)
1719//-----------------------------------------------------------------------------
1720
1721IMPLEMENT_CONOBJECT(GuiGameListMenuProfile);
1722
1723ConsoleDocClass( GuiGameListMenuProfile,
1724   "@brief A GuiControlProfile with additional fields specific to GuiGameListMenuCtrl.\n\n"
1725
1726   "@tsexample\n"
1727   "new GuiGameListMenuProfile()\n"
1728   "{\n"
1729   "   hitAreaUpperLeft = \"10 2\";\n"
1730   "   hitAreaLowerRight = \"190 18\";\n"
1731   "   iconOffset = \"10 2\";\n"
1732   "   rowSize = \"200 20\";\n"
1733   "   columnSplit = \"100\";\n"
1734   "   rightPad = \"4\";\n"
1735   "   //Properties not specific to this control have been omitted from this example.\n"
1736   "};\n"
1737   "@endtsexample\n\n"
1738
1739   "@ingroup GuiGame"
1740);
1741
1742void GuiGameListMenuProfile::initPersistFields()
1743{
1744   addField( "hitAreaUpperLeft", TypePoint2I, Offset(mHitAreaUpperLeft, GuiGameListMenuProfile),
1745      "Position of the upper left corner of the row hit area (relative to row's top left corner)" );
1746
1747   addField( "hitAreaLowerRight", TypePoint2I, Offset(mHitAreaLowerRight, GuiGameListMenuProfile),
1748      "Position of the lower right corner of the row hit area (relative to row's top left corner)" );
1749
1750   addField( "iconOffset", TypePoint2I, Offset(mIconOffset, GuiGameListMenuProfile),
1751      "Offset from the row's top left corner at which to render the row icon" );
1752
1753   addField( "rowSize", TypePoint2I, Offset(mRowSize, GuiGameListMenuProfile),
1754      "The base size (\"width height\") of a row" );
1755
1756   addField("columnSplit", TypeS32, Offset(mColumnSplit, GuiGameListMenuProfile),
1757      "Padding between the leftmost edge of the control, and the row's left arrow.");
1758
1759   addField("rightPad", TypeS32, Offset(mRightPad, GuiGameListMenuProfile),
1760      "Padding between the rightmost edge of the control and the row's right arrow.");
1761
1762   Parent::initPersistFields();
1763
1764   removeField("tab");
1765   removeField("mouseOverSelected");
1766
1767   removeField("modal");
1768   removeField("opaque");
1769   removeField("border");
1770   removeField("borderThickness");
1771   removeField("borderColor");
1772   removeField("borderColorHL");
1773   removeField("borderColorNA");
1774
1775   removeField("bevelColorHL");
1776   removeField("bevelColorLL");
1777
1778   removeField("fontColorLink");
1779   removeField("fontColorLinkHL");
1780
1781   removeField("justify");
1782   removeField("returnTab");
1783   removeField("numbersOnly");
1784   removeField("cursorColor");
1785
1786   removeField("profileForChildren");
1787}
1788