mirror of
https://github.com/TorqueGameEngines/Torque3D.git
synced 2026-01-19 20:24:49 +00:00
Additional changes include disabling certain options when they are not valid(ie, resolution is disabled when in borderless mode)
526 lines
22 KiB
C++
526 lines
22 KiB
C++
//-----------------------------------------------------------------------------
|
|
// 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 _GuiGameListMenuCtrl_H_
|
|
#define _GuiGameListMenuCtrl_H_
|
|
|
|
#include "gui/core/guiControl.h"
|
|
#include "gui/controls/guiBitmapCtrl.h"
|
|
|
|
class GuiGameListMenuProfile;
|
|
|
|
/// \class GuiGameListMenuCtrl
|
|
/// A base class for cross platform menu controls that are gamepad friendly.
|
|
class GuiGameListMenuCtrl : public GuiControl
|
|
{
|
|
public:
|
|
typedef GuiControl Parent;
|
|
typedef GuiGameListMenuProfile Profile;
|
|
|
|
protected:
|
|
/// \struct Row
|
|
/// Internal data representation of a single row in the control.
|
|
struct Row
|
|
{
|
|
StringTableEntry mLabel; ///< Text to display in the row as a label
|
|
StringTableEntry mScriptCallback; ///< Script callback when row is activated
|
|
StringTableEntry mTooltip; ///< A descriptive tooltip message for what the row is
|
|
S32 mIconIndex; ///< Index of the icon to display on the row (-1 = no icon)
|
|
S32 mHeightPad; ///< Extra amount to pad above this row
|
|
bool mUseHighlightIcon; ///< Toggle the use of the highlight icon
|
|
bool mEnabled; ///< If this row is enabled or not (grayed out)
|
|
|
|
enum Mode
|
|
{
|
|
Default = 0,
|
|
OptionList,
|
|
Slider,
|
|
Keybind
|
|
};
|
|
|
|
Mode mMode;
|
|
|
|
//List options
|
|
Vector<StringTableEntry> mOptions; ///< Collection of options available to display
|
|
S32 mSelectedOption; ///< Index into mOptions pointing at the selected option
|
|
bool mWrapOptions; ///< Determines if options should "wrap around" at the ends
|
|
|
|
//Slider option
|
|
F32 mValue; ///< When working as a slider, this contains the value
|
|
F32 mStepSize; ///< When working as a slider, this is the increment levels in the range
|
|
Point2F mRange; ///< When working as a slider, this sets our min/max range
|
|
|
|
//Keybind option
|
|
StringTableEntry mBitmap;
|
|
GFXTexHandle mBitmapTex;
|
|
|
|
Row() : mLabel(StringTable->EmptyString()), mScriptCallback(StringTable->EmptyString()), mTooltip(StringTable->EmptyString()), mIconIndex(-1), mHeightPad(0), mUseHighlightIcon(false), mEnabled(true),
|
|
mSelectedOption(0), mWrapOptions(false), mMode(Mode::Default), mValue(0), mStepSize(1), mRange(Point2F(0, 1)), mBitmap(StringTable->EmptyString()), mBitmapTex(nullptr)
|
|
{
|
|
VECTOR_SET_ASSOCIATION(mOptions);
|
|
}
|
|
|
|
virtual ~Row() {}
|
|
};
|
|
|
|
public:
|
|
/// \return The index of the highlighted row or NO_ROW if none of the rows
|
|
/// are currently highlighted.
|
|
virtual S32 getHighlighted() const { return mHighlighted; }
|
|
|
|
/// \return The index of the selected row or NO_ROW if none of the rows are
|
|
/// currently selected.
|
|
virtual S32 getSelected() const { return mSelected; }
|
|
|
|
/// Sets the selected row. Only rows that are enabled can be selected. Input is
|
|
/// clamped to [0, mRows.size())
|
|
///
|
|
/// \param index The index to set as selected.
|
|
virtual void setSelected(S32 index);
|
|
|
|
/// Determines if the specified row is enabled or disabled.
|
|
///
|
|
/// \param index Index of the row to check.
|
|
/// \return True if the specified row is enabled. False if the row is not
|
|
/// enabled or the given index was not valid.
|
|
virtual bool isRowEnabled(S32 index) const;
|
|
|
|
/// Sets a row's enabled status according to the given parameters.
|
|
///
|
|
/// \param index The row to set the enabled status of.
|
|
/// \param enabled Indicate true to enable the row or false to disable it.
|
|
virtual void setRowEnabled(S32 index, bool enabled);
|
|
|
|
/// Gets the label displayed on the specified row.
|
|
///
|
|
/// \param rowIndex Index of the row to get the label of.
|
|
/// \return The label for the row.
|
|
virtual StringTableEntry getRowLabel(S32 rowIndex) const;
|
|
|
|
/// Sets the label on the given row.
|
|
///
|
|
/// \param rowIndex Index of the row to set the label on.
|
|
/// \param label Text to set as the label of the row.
|
|
virtual void setRowLabel(S32 rowIndex, const char * label);
|
|
|
|
/// Adds a row to the control.
|
|
///
|
|
/// \param label The text to display on the row as a label.
|
|
/// \param callback Name of a script function to use as a callback when this
|
|
/// row is activated.
|
|
/// \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.
|
|
virtual void addRow(const char* label, const char* callback, S32 icon = -1, S32 yPad = 0, bool useHighlightIcon = true, bool enabled = true, S32 mode = 0, const char* tooltip = "");
|
|
|
|
/// Adds a row to the control.
|
|
///
|
|
/// \param label The text to display on the row as a label.
|
|
/// \param optionsList A tab separated list of options for the control.
|
|
/// \param wrapOptions Specify true to allow options to wrap at the ends or
|
|
/// false to prevent wrapping.
|
|
/// \param callback [optional] Name of a script function to use as a callback
|
|
/// when this row is activated. Default NULL means no callback.
|
|
/// \param icon [optional] Index of the icon to use as a marker. Default -1
|
|
/// means no icon will be shown on this row.
|
|
/// \param yPad [optional] An extra amount of height padding before the row.
|
|
/// \param enabled [optional] If this row is initially enabled. Default true.
|
|
void addRow(const char* label, const char* optionsList, bool wrapOptions, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip = "", const char* defaultValue = "");
|
|
|
|
/// Adds a row to the control.
|
|
///
|
|
/// \param label The text to display on the row as a label.
|
|
/// \param defaultValue A float indicating the slider's default value
|
|
/// \param increments A float indicating the incremental values the slider snaps along between it's range
|
|
/// \param range A Point2F that indicates the minimum and maximum value range
|
|
/// \param callback [optional] Name of a script function to use as a callback
|
|
/// when this 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, F32 defaultValue, F32 increments, Point2F range, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip = "");
|
|
|
|
void addRow(const char* label, const char* bitmapName, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip);
|
|
|
|
//Removes row at the provided index
|
|
void GuiGameListMenuCtrl::removeRow(const S32& row);
|
|
|
|
/// Gets the text for the currently selected option of the given row.
|
|
///
|
|
/// \param rowIndex Index of the row to get the option from.
|
|
/// \return A string representing the text currently displayed as the selected
|
|
/// option on the given row. If there is no such displayed text then the empty
|
|
/// string is returned.
|
|
StringTableEntry getCurrentOption(S32 rowIndex) const;
|
|
|
|
/// Attempts to set the given row to the specified selected option. The option
|
|
/// will only be set if the option exists in the control.
|
|
///
|
|
/// \param rowIndex Index of the row to set an option on.
|
|
/// \param option The option to be made active.
|
|
/// \return True if the row contained the option and was set, false otherwise.
|
|
bool selectOption(S32 rowIndex, StringTableEntry option);
|
|
|
|
/// Sets the list of options on the given row.
|
|
///
|
|
/// \param rowIndex Index of the row to set options on.
|
|
/// \param optionsList A tab separated list of options for the control.
|
|
void setOptions(S32 rowIndex, const char* optionsList);
|
|
|
|
/// Activates the current row. The script callback of the current row will
|
|
/// be called (if it has one).
|
|
virtual void activateRow();
|
|
|
|
/// Gets the number of rows in the control.
|
|
///
|
|
/// \return The number of rows in this control.
|
|
virtual S32 getRowCount() const { return mRows.size(); }
|
|
|
|
/// Gets the value of a row
|
|
///
|
|
/// \param rowIndex Index of the row to get the value of.
|
|
F32 getValue(S32 rowIndex);
|
|
|
|
/// Sets the value of a row
|
|
///
|
|
/// \param rowIndex Index of the row to set the value of.
|
|
/// \param value The new value to be set.
|
|
void setValue(S32 rowIndex, F32 value);
|
|
|
|
/// Gets the tooltip of a row
|
|
///
|
|
/// \param rowIndex Index of the row to get the tooltip of.
|
|
const char* getTooltip(S32 rowIndex);
|
|
|
|
GuiGameListMenuCtrl();
|
|
~GuiGameListMenuCtrl();
|
|
|
|
void onRender(Point2I offset, const RectI &updateRect);
|
|
|
|
void onRenderListOption(Row* row, Point2I currentOffset);
|
|
void onRenderSliderOption(Row* row, Point2I currentOffset);
|
|
|
|
void onRenderKeybindOption(Row* row, Point2I currentOffset);
|
|
|
|
/// Callback when the object is registered with the sim.
|
|
///
|
|
/// \return True if the profile was successfully added, false otherwise.
|
|
bool onAdd();
|
|
|
|
/// Callback when the control wakes up.
|
|
bool onWake();
|
|
|
|
/// 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 mouse button is clicked on the control.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
void onMouseDown(const GuiEvent &event);
|
|
|
|
/// Callback when the mouse is dragged on the control.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
void onMouseDragged(const GuiEvent &event){ onMouseDown(event); }
|
|
|
|
/// Callback when the mouse leaves the control.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
void onMouseLeave(const GuiEvent &event);
|
|
|
|
/// Callback when the mouse is moving over this control
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
void onMouseMove(const GuiEvent &event);
|
|
|
|
/// Callback when the mouse button is released.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
void onMouseUp(const GuiEvent &event);
|
|
|
|
virtual bool onInputEvent(const InputEventInfo& event);
|
|
|
|
/// Callback when the gamepad axis is activated.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
virtual bool onGamepadAxisUp(const GuiEvent & event);
|
|
|
|
/// Callback when the gamepad axis is activated.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
virtual bool onGamepadAxisDown(const GuiEvent & event);
|
|
|
|
/// Callback when the gamepad axis is activated.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
virtual bool onGamepadAxisLeft(const GuiEvent& event);
|
|
|
|
/// Callback when the gamepad axis is activated.
|
|
///
|
|
/// \param event A reference to the event that triggered the callback.
|
|
virtual bool onGamepadAxisRight(const GuiEvent& event);
|
|
|
|
void clearRows();
|
|
|
|
void refresh();
|
|
|
|
RectI getRowBounds(S32 rowIndex);
|
|
|
|
DECLARE_CONOBJECT(GuiGameListMenuCtrl);
|
|
DECLARE_CATEGORY( "Gui Game" );
|
|
DECLARE_DESCRIPTION( "Base class for cross platform menu controls that are gamepad friendly." );
|
|
|
|
/// Initializes fields accessible through the console.
|
|
static void initPersistFields();
|
|
|
|
static const S32 NO_ROW = -1; ///< Indicates a query result of no row found.
|
|
static const S32 NO_ICON = -1; ///< Indicates a row has no extra icon available
|
|
static const S32 NO_OPTION = -1; ///< Indicates there is no option
|
|
|
|
protected:
|
|
/// Adds a row to the control.
|
|
///
|
|
/// \param row A reference to the row object to fill.
|
|
/// \param label The text to display on the row as a label.
|
|
/// \param callback Name of a script function to use as a callback when this
|
|
/// row is activated.
|
|
/// \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.
|
|
virtual void addRow(Row * row, const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled, S32 mode = 0, const char* tooltip = "");
|
|
|
|
/// Determines if the given index is a valid row index. Any index pointing at
|
|
/// an existing row is valid.
|
|
///
|
|
/// \param index The index to check for validity.
|
|
/// \return True if the index points at a valid row, false otherwise.
|
|
virtual bool isValidRowIndex(S32 index) const;
|
|
|
|
/// Sets the script variable $ThisControl to reflect this control.
|
|
virtual void setThisControl();
|
|
|
|
/// Called to implement debug rendering which displays colored lines to
|
|
/// provide visual feedback on extents and hit zones.
|
|
virtual void onDebugRender(Point2I offset);
|
|
|
|
/// Looks up the row having a hit area at the given global point.
|
|
///
|
|
/// \param globalPoint The point we want to check for hitting a row.
|
|
/// \return The index of the hit row or NO_ROW if no row was hit.
|
|
virtual S32 getRow(Point2I globalPoint);
|
|
|
|
/// Checks to make sure our control has a profile of the correct type.
|
|
///
|
|
/// \return True if the profile is of type GuiGameListMenuProfile or false if
|
|
/// the profile is of any other type.
|
|
virtual bool hasValidProfile() const;
|
|
|
|
/// Enforces the validity of the fields on this control and its profile (if
|
|
/// the profile is valid, see: hasValidProfile).
|
|
virtual void enforceConstraints();
|
|
|
|
/// @name Callbacks
|
|
/// @{
|
|
DECLARE_CALLBACK( void, onChange, () );
|
|
|
|
DECLARE_CALLBACK(void, onInputEvent, (const char* device, const char* action, bool state));
|
|
|
|
DECLARE_CALLBACK(void, onAxisEvent, (const char* device, const char* action, F32 axisValue));
|
|
/// @}
|
|
|
|
/// Evaluates some script. If the command is empty then nothing is evaluated.
|
|
///
|
|
/// \param command The script to evaluate.
|
|
void doScriptCommand(StringTableEntry command);
|
|
|
|
StringTableEntry mCallbackOnA; ///< Script callback when the 'A' button is pressed
|
|
StringTableEntry mCallbackOnB; ///< Script callback when the 'B' button is pressed
|
|
StringTableEntry mCallbackOnX; ///< Script callback when the 'X' button is pressed
|
|
StringTableEntry mCallbackOnY; ///< Script callback when the 'Y' button is pressed
|
|
|
|
bool mDebugRender; ///< Determines when to show debug render lines
|
|
Vector<Row *> mRows; ///< Holds data wrappers on all the rows we have
|
|
|
|
private:
|
|
/// Performs a click on the current option row. The x position is used to
|
|
/// determine if the left or right arrow were clicked. If one was clicked, the
|
|
/// option will be changed. If neither was clicked, the option is unaffected.
|
|
/// This method should only be called when there is an actively selected row.
|
|
///
|
|
/// \param row The row to perform the click on.
|
|
/// \param xPos The x position of the the click, relative to the control.
|
|
void clickOption(Row* row, S32 xPos);
|
|
|
|
/// Changes the option on the currently selected row. If there is no row
|
|
/// selected, this method does nothing.
|
|
///
|
|
/// \param delta The amount to change the option selection by. Typically this
|
|
/// will be 1 or -1.
|
|
void changeOption(S32 delta);
|
|
|
|
/// Changes the option on the given row.
|
|
///
|
|
/// \param row The row to change the option on.
|
|
/// \param delta The amount to change the option selection by. Typically this
|
|
/// will be 1 or -1.
|
|
void changeOption(Row* row, S32 delta);
|
|
|
|
/// Performs a click on the current slider row. The x position is used to
|
|
/// determine if the left or right arrow were clicked, or if it landed somewhere on the sliderbar.
|
|
/// If one was clicked, the option will be changed. If neither was clicked, the option is unaffected.
|
|
/// This method should only be called when there is an actively selected row.
|
|
///
|
|
/// \param row The row to perform the click on.
|
|
/// \param xPos The x position of the the click, relative to the control.
|
|
void clickSlider(Row* row, S32 xPos);
|
|
|
|
void clickKeybind(Row* row, S32 xPos);
|
|
|
|
private:
|
|
/// Recalculates the height of this control based on the stored row height and
|
|
/// and padding on the rows.
|
|
virtual Point2I getMinExtent() const;
|
|
|
|
/// Makes sure the height will allow all rows to be displayed without being
|
|
/// truncated.
|
|
void updateHeight();
|
|
|
|
/// Sets the first enabled row as selected. If there are no enabled rows then
|
|
/// selected will be set to NO_ROW.
|
|
void selectFirstEnabledRow();
|
|
|
|
/// Changes the currently selected row.
|
|
///
|
|
/// \param delta The amount to change the row selection by. Typically this will
|
|
/// be 1 or -1.
|
|
void changeRow(S32 delta);
|
|
|
|
S32 mSelected; ///< index of the currently selected row
|
|
S32 mHighlighted; ///< index of the currently highlighted row
|
|
|
|
bool mCallbackOnInputs;
|
|
};
|
|
|
|
/// \class GuiGameListMenuProfile
|
|
/// A gui profile with additional fields specific to GuiGameListMenuCtrl.
|
|
class GuiGameListMenuProfile : public GuiControlProfile
|
|
{
|
|
typedef GuiControlProfile Parent;
|
|
|
|
public:
|
|
/// Enforces range constraints on all required fields.
|
|
virtual void enforceConstraints();
|
|
|
|
/// Get the height of rows in this profile. All rows are considered to be the
|
|
/// same base height. Rows can have an extra amount of y padding defined when
|
|
/// they are added to the control.
|
|
///
|
|
/// \return The height of rows in this profile.
|
|
S32 getRowHeight() { return (mRowSize.y) ? mRowSize.y : getBitmapArrayRect(TEX_NORMAL).extent.y; }
|
|
|
|
/// Get the width of rows in this profile. All rows are considered to be the
|
|
/// same width.
|
|
///
|
|
/// \return The width of rows in this profile.
|
|
S32 getRowWidth() { return (mRowSize.x) ? mRowSize.x : getBitmapArrayRect(TEX_NORMAL).extent.x; }
|
|
|
|
/// Row scale is the ratio between the defined row size and the raw size of
|
|
/// the bitmap.
|
|
///
|
|
/// \return The row scale.
|
|
const Point2F & getRowScale() const { return mRowScale; }
|
|
|
|
/// Gets the extent of icons for this profile. If there are no icons you will
|
|
/// get a point of (0, 0);
|
|
///
|
|
/// \return The extent of icons or (0, 0) if there aren't any.
|
|
Point2I getIconExtent();
|
|
|
|
/// Gets the extent of arrows for this profile. If there are no arrows you
|
|
/// will get a point of (0, 0).
|
|
///
|
|
/// \return The extent of icons or (0, 0) if there aren't any.
|
|
Point2I getArrowExtent();
|
|
|
|
/// Gets the extent of the defined hit area for this profile. If the hit area
|
|
/// is not defined then it defaults to the full size of a row.
|
|
///
|
|
/// \return The extents of the defined hit area or the full size of the row.
|
|
Point2I getHitAreaExtent();
|
|
|
|
/// Determines if this profile has textures for the left and right arrows.
|
|
///
|
|
/// \return True if the profile's bitmap has textures for the arrows, false
|
|
/// otherwise.
|
|
bool hasArrows(){ return (! getBitmapArrayRect(TEX_FIRST_ARROW).extent.isZero()); }
|
|
|
|
/// Callback when the object is registered with the sim.
|
|
///
|
|
/// \return True if the profile was successfully added, false otherwise.
|
|
bool onAdd();
|
|
|
|
Point2I mHitAreaUpperLeft; ///< Offset for the upper left corner of the hit area
|
|
Point2I mHitAreaLowerRight; ///< Offset for the lower right corner of the hit area
|
|
Point2I mIconOffset; ///< Offset for a row's extra icon
|
|
Point2I mRowSize; ///< The base size of a row
|
|
|
|
S32 mColumnSplit; ///< Absolute position of the split between columns
|
|
S32 mRightPad; ///< Extra padding between the right arrow and the hit area
|
|
|
|
GuiGameListMenuProfile();
|
|
|
|
DECLARE_CONOBJECT(GuiGameListMenuProfile);
|
|
|
|
/// Initializes fields accessible through the console.
|
|
static void initPersistFields();
|
|
|
|
enum
|
|
{
|
|
TEX_NORMAL = 0, ///< texture index for a normal, unselected row
|
|
TEX_SELECTED = 1, ///< texture index for a selected row
|
|
TEX_HIGHLIGHT = 2, ///< texture index for a highlighted row (moused over, not selected)
|
|
TEX_DISABLED = 3, ///< texture index for a disabled row
|
|
TEX_L_ARROW_OFF = 4, ///< texture index for the left arrow of an unselected row
|
|
TEX_L_ARROW_ON = 5, ///< texture index for the left arrow of a selected row
|
|
TEX_R_ARROW_OFF = 6, ///< texture index for the right arrow of an unselected row
|
|
TEX_R_ARROW_ON = 7, ///< texture index for the right arrow of a selected row
|
|
|
|
TEX_FIRST_ARROW = 4, ///< texture index for the first arrow
|
|
TEX_FIRST_ICON = 8, ///< texture index for the first row marker icon
|
|
};
|
|
|
|
private:
|
|
Point2F mRowScale; ///< Ratio of row size to actual bitmap size
|
|
};
|
|
|
|
#endif
|