//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #ifndef _GuiGameListOptionsCtrl_H_ #define _GuiGameListOptionsCtrl_H_ #include "gui/controls/guiGameListMenuCtrl.h" /// \class GuiGameListOptionsCtrl /// A control for showing pages of options that are gamepad friendly. class GuiGameListOptionsCtrl : public GuiGameListMenuCtrl { typedef GuiGameListMenuCtrl Parent; protected: /// \struct Row /// An extension to the parent's row, adding the ability to keep a collection /// of options and track status related to them. struct Row : public Parent::Row { Vector mOptions; ///< Collection of options available to display S32 mSelectedOption; ///< Index into mOptions pointing at the selected option bool mWrapOptions; ///< Determines if options should "wrap around" at the ends enum Mode { Default = 0, OptionsList, Keybind }; Mode mMode; Row() : mSelectedOption(0), mWrapOptions(false), mMode(Mode::Default) { VECTOR_SET_ASSOCIATION( mOptions ); } }; public: /// Gets the text for the currently selected option of the given row. /// /// \param rowIndex Index of the row to get the option from. /// \return A string representing the text currently displayed as the selected /// option on the given row. If there is no such displayed text then the empty /// string is returned. StringTableEntry getCurrentOption(S32 rowIndex) const; /// Attempts to set the given row to the specified selected option. The option /// will only be set if the option exists in the control. /// /// \param rowIndex Index of the row to set an option on. /// \param option The option to be made active. /// \return True if the row contained the option and was set, false otherwise. bool selectOption(S32 rowIndex, StringTableEntry option); /// Sets the list of options on the given row. /// /// \param rowIndex Index of the row to set options on. /// \param optionsList A tab separated list of options for the control. void setOptions(S32 rowIndex, const char * optionsList); /// Adds a row to the control. /// /// \param label The text to display on the row as a label. /// \param optionsList A tab separated list of options for the control. /// \param wrapOptions Specify true to allow options to wrap at the ends or /// false to prevent wrapping. /// \param callback [optional] Name of a script function to use as a callback /// when this row is activated. Default NULL means no callback. /// \param icon [optional] Index of the icon to use as a marker. Default -1 /// means no icon will be shown on this row. /// \param yPad [optional] An extra amount of height padding before the row. /// \param enabled [optional] If this row is initially enabled. Default true. void addRow(const char* label, const char* optionsList, bool wrapOptions, const char* callback, S32 icon = -1, S32 yPad = 0, bool enabled = true); void onRender(Point2I offset, const RectI &updateRect); /// Callback when the mouse button is released. /// /// \param event A reference to the event that triggered the callback. void onMouseUp(const GuiEvent &event); /// Callback when a key is pressed. /// /// \param event The event that triggered this callback. bool onKeyDown(const GuiEvent &event); /// Callback when a key is repeating. /// /// \param event The event that triggered this callback. bool onKeyRepeat(const GuiEvent &event){ return onKeyDown(event); } /// Callback when the gamepad axis is activated. /// /// \param event A reference to the event that triggered the callback. virtual bool onGamepadAxisLeft(const GuiEvent &event); /// Callback when the gamepad axis is activated. /// /// \param event A reference to the event that triggered the callback. virtual bool onGamepadAxisRight(const GuiEvent &event); virtual void clearRows(); GuiGameListOptionsCtrl(); ~GuiGameListOptionsCtrl(); DECLARE_CONOBJECT(GuiGameListOptionsCtrl); DECLARE_DESCRIPTION( "A control for showing pages of options that are gamepad friendly." ); virtual bool onAdd(); /// Initializes fields accessible through the console. static void initPersistFields(); static const S32 NO_OPTION = -1; ///< Indicates there is no option protected: /// Checks to make sure our control has a profile of the correct type. /// /// \return True if the profile is of type GuiGameListOptionsProfile or false /// if the profile is of any other type. bool hasValidProfile() const; /// Enforces the validity of the fields on this control and its profile (if the /// profile is valid, see: hasValidProfile). void enforceConstraints(); /// Adds lines around the column divisions to the feedback already provided /// in the Parent. void onDebugRender(Point2I offset); private: /// Performs a click on the current option row. The x position is used to /// determine if the left or right arrow were clicked. If one was clicked, the /// option will be changed. If neither was clicked, the option is unaffected. /// This method should only be called when there is an actively selected row. /// /// \param row The row to perform the click on. /// \param xPos The x position of the the click, relative to the control. void clickOption(Row * row, S32 xPos); /// Changes the option on the currently selected row. If there is no row /// selected, this method does nothing. /// /// \param delta The amount to change the option selection by. Typically this /// will be 1 or -1. void changeOption(S32 delta); /// Changes the option on the given row. /// /// \param row The row to change the option on. /// \param delta The amount to change the option selection by. Typically this /// will be 1 or -1. void changeOption(Row * row, S32 delta); }; /// \class GuiGameListOptionsProfile /// A gui profile with additional fields specific to GuiGameListOptionsCtrl. class GuiGameListOptionsProfile : public GuiGameListMenuProfile { typedef GuiGameListMenuProfile Parent; public: /// Enforces range constraints on all required fields. void enforceConstraints(); GuiGameListOptionsProfile(); S32 mColumnSplit; ///< Absolute position of the split between columns S32 mRightPad; ///< Extra padding between the right arrow and the hit area DECLARE_CONOBJECT(GuiGameListOptionsProfile); /// Initializes fields accessible through the console. static void initPersistFields(); }; #endif