guiGameListMenuCtrl.h
Engine/source/gui/controls/guiGameListMenuCtrl.h
Classes:
class
A base class for cross platform menu controls that are gamepad friendly.
class
Internal data representation of a single row in the control.
class
A gui profile with additional fields specific to GuiGameListMenuCtrl.
Detailed Description
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#ifndef _GuiGameListMenuCtrl_H_ 25#define _GuiGameListMenuCtrl_H_ 26 27#include "gui/core/guiControl.h" 28#include "gui/controls/guiBitmapCtrl.h" 29 30class GuiGameListMenuProfile; 31 32/// \class GuiGameListMenuCtrl 33/// A base class for cross platform menu controls that are gamepad friendly. 34class GuiGameListMenuCtrl : public GuiControl 35{ 36public: 37 typedef GuiControl Parent; 38 typedef GuiGameListMenuProfile Profile; 39 40protected: 41 /// \struct Row 42 /// Internal data representation of a single row in the control. 43 struct Row 44 { 45 StringTableEntry mLabel; ///< Text to display in the row as a label 46 StringTableEntry mScriptCallback; ///< Script callback when row is activated 47 StringTableEntry mTooltip; ///< A descriptive tooltip message for what the row is 48 S32 mIconIndex; ///< Index of the icon to display on the row (-1 = no icon) 49 S32 mHeightPad; ///< Extra amount to pad above this row 50 bool mUseHighlightIcon; ///< Toggle the use of the highlight icon 51 bool mEnabled; ///< If this row is enabled or not (grayed out) 52 53 enum Mode 54 { 55 Default = 0, 56 OptionList, 57 Slider, 58 Keybind 59 }; 60 61 Mode mMode; 62 63 //List options 64 Vector<StringTableEntry> mOptions; ///< Collection of options available to display 65 S32 mSelectedOption; ///< Index into mOptions pointing at the selected option 66 bool mWrapOptions; ///< Determines if options should "wrap around" at the ends 67 68 //Slider option 69 F32 mValue; ///< When working as a slider, this contains the value 70 F32 mStepSize; ///< When working as a slider, this is the increment levels in the range 71 Point2F mRange; ///< When working as a slider, this sets our min/max range 72 73 //Keybind option 74 StringTableEntry mBitmap; 75 GFXTexHandle mBitmapTex; 76 77 Row() : mLabel(StringTable->EmptyString()), mScriptCallback(StringTable->EmptyString()), mTooltip(StringTable->EmptyString()), mIconIndex(-1), mHeightPad(0), mUseHighlightIcon(false), mEnabled(true), 78 mSelectedOption(0), mWrapOptions(false), mMode(Mode::Default), mValue(0), mStepSize(1), mRange(Point2F(0, 1)), mBitmap(StringTable->EmptyString()), mBitmapTex(nullptr) 79 { 80 VECTOR_SET_ASSOCIATION(mOptions); 81 } 82 83 virtual ~Row() {} 84 }; 85 86public: 87 /// \return The index of the highlighted row or NO_ROW if none of the rows 88 /// are currently highlighted. 89 virtual S32 getHighlighted() const { return mHighlighted; } 90 91 /// \return The index of the selected row or NO_ROW if none of the rows are 92 /// currently selected. 93 virtual S32 getSelected() const { return mSelected; } 94 95 /// Sets the selected row. Only rows that are enabled can be selected. Input is 96 /// clamped to [0, mRows.size()) 97 /// 98 /// \param index The index to set as selected. 99 virtual void setSelected(S32 index); 100 101 /// Determines if the specified row is enabled or disabled. 102 /// 103 /// \param index Index of the row to check. 104 /// \return True if the specified row is enabled. False if the row is not 105 /// enabled or the given index was not valid. 106 virtual bool isRowEnabled(S32 index) const; 107 108 /// Sets a row's enabled status according to the given parameters. 109 /// 110 /// \param index The row to set the enabled status of. 111 /// \param enabled Indicate true to enable the row or false to disable it. 112 virtual void setRowEnabled(S32 index, bool enabled); 113 114 /// Gets the label displayed on the specified row. 115 /// 116 /// \param rowIndex Index of the row to get the label of. 117 /// \return The label for the row. 118 virtual StringTableEntry getRowLabel(S32 rowIndex) const; 119 120 /// Sets the label on the given row. 121 /// 122 /// \param rowIndex Index of the row to set the label on. 123 /// \param label Text to set as the label of the row. 124 virtual void setRowLabel(S32 rowIndex, const char * label); 125 126 /// Adds a row to the control. 127 /// 128 /// \param label The text to display on the row as a label. 129 /// \param callback Name of a script function to use as a callback when this 130 /// row is activated. 131 /// \param icon [optional] Index of the icon to use as a marker. Default -1 132 /// means no icon will be shown on this row. 133 /// \param yPad [optional] An extra amount of height padding before the row. 134 /// \param enabled [optional] If this row is initially enabled. Default true. 135 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 = ""); 136 137 /// Adds a row to the control. 138 /// 139 /// \param label The text to display on the row as a label. 140 /// \param optionsList A tab separated list of options for the control. 141 /// \param wrapOptions Specify true to allow options to wrap at the ends or 142 /// false to prevent wrapping. 143 /// \param callback [optional] Name of a script function to use as a callback 144 /// when this row is activated. Default NULL means no callback. 145 /// \param icon [optional] Index of the icon to use as a marker. Default -1 146 /// means no icon will be shown on this row. 147 /// \param yPad [optional] An extra amount of height padding before the row. 148 /// \param enabled [optional] If this row is initially enabled. Default true. 149 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 = ""); 150 151 /// Adds a row to the control. 152 /// 153 /// \param label The text to display on the row as a label. 154 /// \param defaultValue A float indicating the slider's default value 155 /// \param increments A float indicating the incremental values the slider snaps along between it's range 156 /// \param range A Point2F that indicates the minimum and maximum value range 157 /// \param callback [optional] Name of a script function to use as a callback 158 /// when this row is activated. Default NULL means no callback. 159 /// \param icon [optional] Index of the icon to use as a marker. Default -1 160 /// means no icon will be shown on this row. 161 /// \param yPad [optional] An extra amount of height padding before the row. 162 /// \param enabled [optional] If this row is initially enabled. Default true. 163 void addRow(const char* label, F32 defaultValue, F32 increments, Point2F range, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip = ""); 164 165 void addRow(const char* label, const char* bitmapName, const char* callback, S32 icon, S32 yPad, bool enabled, const char* tooltip); 166 167 //Removes row at the provided index 168 void removeRow(const S32& row); 169 170 /// Gets the text for the currently selected option of the given row. 171 /// 172 /// \param rowIndex Index of the row to get the option from. 173 /// \return A string representing the text currently displayed as the selected 174 /// option on the given row. If there is no such displayed text then the empty 175 /// string is returned. 176 StringTableEntry getCurrentOption(S32 rowIndex) const; 177 178 /// Attempts to set the given row to the specified selected option. The option 179 /// will only be set if the option exists in the control. 180 /// 181 /// \param rowIndex Index of the row to set an option on. 182 /// \param option The option to be made active. 183 /// \return True if the row contained the option and was set, false otherwise. 184 bool selectOption(S32 rowIndex, StringTableEntry option); 185 186 /// Sets the list of options on the given row. 187 /// 188 /// \param rowIndex Index of the row to set options on. 189 /// \param optionsList A tab separated list of options for the control. 190 void setOptions(S32 rowIndex, const char* optionsList); 191 192 /// Activates the current row. The script callback of the current row will 193 /// be called (if it has one). 194 virtual void activateRow(); 195 196 /// Gets the number of rows in the control. 197 /// 198 /// \return The number of rows in this control. 199 virtual S32 getRowCount() const { return mRows.size(); } 200 201 /// Gets the value of a row 202 /// 203 /// \param rowIndex Index of the row to get the value of. 204 F32 getValue(S32 rowIndex); 205 206 /// Sets the value of a row 207 /// 208 /// \param rowIndex Index of the row to set the value of. 209 /// \param value The new value to be set. 210 void setValue(S32 rowIndex, F32 value); 211 212 /// Gets the tooltip of a row 213 /// 214 /// \param rowIndex Index of the row to get the tooltip of. 215 const char* getTooltip(S32 rowIndex); 216 217 GuiGameListMenuCtrl(); 218 ~GuiGameListMenuCtrl(); 219 220 void onRender(Point2I offset, const RectI &updateRect); 221 222 void onRenderListOption(Row* row, Point2I currentOffset); 223 void onRenderSliderOption(Row* row, Point2I currentOffset); 224 225 void onRenderKeybindOption(Row* row, Point2I currentOffset); 226 227 /// Callback when the object is registered with the sim. 228 /// 229 /// \return True if the profile was successfully added, false otherwise. 230 bool onAdd(); 231 232 /// Callback when the control wakes up. 233 bool onWake(); 234 235 /// Callback when a key is pressed. 236 /// 237 /// \param event The event that triggered this callback. 238 bool onKeyDown(const GuiEvent &event); 239 240 /// Callback when a key is repeating. 241 /// 242 /// \param event The event that triggered this callback. 243 bool onKeyRepeat(const GuiEvent &event){ return onKeyDown(event); } 244 245 /// Callback when the mouse button is clicked on the control. 246 /// 247 /// \param event A reference to the event that triggered the callback. 248 void onMouseDown(const GuiEvent &event); 249 250 /// Callback when the mouse is dragged on the control. 251 /// 252 /// \param event A reference to the event that triggered the callback. 253 void onMouseDragged(const GuiEvent &event){ onMouseDown(event); } 254 255 /// Callback when the mouse leaves the control. 256 /// 257 /// \param event A reference to the event that triggered the callback. 258 void onMouseLeave(const GuiEvent &event); 259 260 /// Callback when the mouse is moving over this control 261 /// 262 /// \param event A reference to the event that triggered the callback. 263 void onMouseMove(const GuiEvent &event); 264 265 /// Callback when the mouse button is released. 266 /// 267 /// \param event A reference to the event that triggered the callback. 268 void onMouseUp(const GuiEvent &event); 269 270 virtual bool onInputEvent(const InputEventInfo& event); 271 272 /// Callback when the gamepad axis is activated. 273 /// 274 /// \param event A reference to the event that triggered the callback. 275 virtual bool onGamepadAxisUp(const GuiEvent & event); 276 277 /// Callback when the gamepad axis is activated. 278 /// 279 /// \param event A reference to the event that triggered the callback. 280 virtual bool onGamepadAxisDown(const GuiEvent & event); 281 282 /// Callback when the gamepad axis is activated. 283 /// 284 /// \param event A reference to the event that triggered the callback. 285 virtual bool onGamepadAxisLeft(const GuiEvent& event); 286 287 /// Callback when the gamepad axis is activated. 288 /// 289 /// \param event A reference to the event that triggered the callback. 290 virtual bool onGamepadAxisRight(const GuiEvent& event); 291 292 void clearRows(); 293 294 void refresh(); 295 296 RectI getRowBounds(S32 rowIndex); 297 298 DECLARE_CONOBJECT(GuiGameListMenuCtrl); 299 DECLARE_CATEGORY( "Gui Game" ); 300 DECLARE_DESCRIPTION( "Base class for cross platform menu controls that are gamepad friendly." ); 301 302 /// Initializes fields accessible through the console. 303 static void initPersistFields(); 304 305 static const S32 NO_ROW = -1; ///< Indicates a query result of no row found. 306 static const S32 NO_ICON = -1; ///< Indicates a row has no extra icon available 307 static const S32 NO_OPTION = -1; ///< Indicates there is no option 308 309protected: 310 /// Adds a row to the control. 311 /// 312 /// \param row A reference to the row object to fill. 313 /// \param label The text to display on the row as a label. 314 /// \param callback Name of a script function to use as a callback when this 315 /// row is activated. 316 /// \param icon [optional] Index of the icon to use as a marker. Default -1 317 /// means no icon will be shown on this row. 318 /// \param yPad [optional] An extra amount of height padding before the row. 319 /// \param enabled [optional] If this row is initially enabled. Default true. 320 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 = ""); 321 322 /// Determines if the given index is a valid row index. Any index pointing at 323 /// an existing row is valid. 324 /// 325 /// \param index The index to check for validity. 326 /// \return True if the index points at a valid row, false otherwise. 327 virtual bool isValidRowIndex(S32 index) const; 328 329 /// Sets the script variable $ThisControl to reflect this control. 330 virtual void setThisControl(); 331 332 /// Called to implement debug rendering which displays colored lines to 333 /// provide visual feedback on extents and hit zones. 334 virtual void onDebugRender(Point2I offset); 335 336 /// Looks up the row having a hit area at the given global point. 337 /// 338 /// \param globalPoint The point we want to check for hitting a row. 339 /// \return The index of the hit row or NO_ROW if no row was hit. 340 virtual S32 getRow(Point2I globalPoint); 341 342 /// Checks to make sure our control has a profile of the correct type. 343 /// 344 /// \return True if the profile is of type GuiGameListMenuProfile or false if 345 /// the profile is of any other type. 346 virtual bool hasValidProfile() const; 347 348 /// Enforces the validity of the fields on this control and its profile (if 349 /// the profile is valid, see: hasValidProfile). 350 virtual void enforceConstraints(); 351 352 /// @name Callbacks 353 /// @{ 354 DECLARE_CALLBACK( void, onChange, () ); 355 356 DECLARE_CALLBACK(void, onInputEvent, (const char* device, const char* action, bool state)); 357 358 DECLARE_CALLBACK(void, onAxisEvent, (const char* device, const char* action, F32 axisValue)); 359 /// @} 360 361 /// Evaluates some script. If the command is empty then nothing is evaluated. 362 /// 363 /// \param command The script to evaluate. 364 void doScriptCommand(StringTableEntry command); 365 366 StringTableEntry mCallbackOnA; ///< Script callback when the 'A' button is pressed 367 StringTableEntry mCallbackOnB; ///< Script callback when the 'B' button is pressed 368 StringTableEntry mCallbackOnX; ///< Script callback when the 'X' button is pressed 369 StringTableEntry mCallbackOnY; ///< Script callback when the 'Y' button is pressed 370 371 bool mDebugRender; ///< Determines when to show debug render lines 372 Vector<Row*> mRows; ///< Holds data wrappers on all the rows we have 373 374private: 375 /// Performs a click on the current option row. The x position is used to 376 /// determine if the left or right arrow were clicked. If one was clicked, the 377 /// option will be changed. If neither was clicked, the option is unaffected. 378 /// This method should only be called when there is an actively selected row. 379 /// 380 /// \param row The row to perform the click on. 381 /// \param xPos The x position of the the click, relative to the control. 382 void clickOption(Row* row, S32 xPos); 383 384 /// Changes the option on the currently selected row. If there is no row 385 /// selected, this method does nothing. 386 /// 387 /// \param delta The amount to change the option selection by. Typically this 388 /// will be 1 or -1. 389 void changeOption(S32 delta); 390 391 /// Changes the option on the given row. 392 /// 393 /// \param row The row to change the option on. 394 /// \param delta The amount to change the option selection by. Typically this 395 /// will be 1 or -1. 396 void changeOption(Row* row, S32 delta); 397 398 /// Performs a click on the current slider row. The x position is used to 399 /// determine if the left or right arrow were clicked, or if it landed somewhere on the sliderbar. 400 /// If one was clicked, the option will be changed. If neither was clicked, the option is unaffected. 401 /// This method should only be called when there is an actively selected row. 402 /// 403 /// \param row The row to perform the click on. 404 /// \param xPos The x position of the the click, relative to the control. 405 void clickSlider(Row* row, S32 xPos); 406 407 void clickKeybind(Row* row, S32 xPos); 408 409private: 410 /// Recalculates the height of this control based on the stored row height and 411 /// and padding on the rows. 412 virtual Point2I getMinExtent() const; 413 414 /// Makes sure the height will allow all rows to be displayed without being 415 /// truncated. 416 void updateHeight(); 417 418 /// Sets the first enabled row as selected. If there are no enabled rows then 419 /// selected will be set to NO_ROW. 420 void selectFirstEnabledRow(); 421 422 /// Changes the currently selected row. 423 /// 424 /// \param delta The amount to change the row selection by. Typically this will 425 /// be 1 or -1. 426 void changeRow(S32 delta); 427 428 S32 mSelected; ///< index of the currently selected row 429 S32 mHighlighted; ///< index of the currently highlighted row 430 431 bool mCallbackOnInputs; 432 bool mConsumeKeyInputEvents; 433}; 434 435/// \class GuiGameListMenuProfile 436/// A gui profile with additional fields specific to GuiGameListMenuCtrl. 437class GuiGameListMenuProfile : public GuiControlProfile 438{ 439 typedef GuiControlProfile Parent; 440 441public: 442 /// Enforces range constraints on all required fields. 443 virtual void enforceConstraints(); 444 445 /// Get the height of rows in this profile. All rows are considered to be the 446 /// same base height. Rows can have an extra amount of y padding defined when 447 /// they are added to the control. 448 /// 449 /// \return The height of rows in this profile. 450 S32 getRowHeight() { return (mRowSize.y) ? mRowSize.y : getBitmapArrayRect(TEX_NORMAL).extent.y; } 451 452 /// Get the width of rows in this profile. All rows are considered to be the 453 /// same width. 454 /// 455 /// \return The width of rows in this profile. 456 S32 getRowWidth() { return (mRowSize.x) ? mRowSize.x : getBitmapArrayRect(TEX_NORMAL).extent.x; } 457 458 /// Row scale is the ratio between the defined row size and the raw size of 459 /// the bitmap. 460 /// 461 /// \return The row scale. 462 const Point2F & getRowScale() const { return mRowScale; } 463 464 /// Gets the extent of icons for this profile. If there are no icons you will 465 /// get a point of (0, 0); 466 /// 467 /// \return The extent of icons or (0, 0) if there aren't any. 468 Point2I getIconExtent(); 469 470 /// Gets the extent of arrows for this profile. If there are no arrows you 471 /// will get a point of (0, 0). 472 /// 473 /// \return The extent of icons or (0, 0) if there aren't any. 474 Point2I getArrowExtent(); 475 476 /// Gets the extent of the defined hit area for this profile. If the hit area 477 /// is not defined then it defaults to the full size of a row. 478 /// 479 /// \return The extents of the defined hit area or the full size of the row. 480 Point2I getHitAreaExtent(); 481 482 /// Determines if this profile has textures for the left and right arrows. 483 /// 484 /// \return True if the profile's bitmap has textures for the arrows, false 485 /// otherwise. 486 bool hasArrows(){ return (! getBitmapArrayRect(TEX_FIRST_ARROW).extent.isZero()); } 487 488 /// Callback when the object is registered with the sim. 489 /// 490 /// \return True if the profile was successfully added, false otherwise. 491 bool onAdd(); 492 493 Point2I mHitAreaUpperLeft; ///< Offset for the upper left corner of the hit area 494 Point2I mHitAreaLowerRight; ///< Offset for the lower right corner of the hit area 495 Point2I mIconOffset; ///< Offset for a row's extra icon 496 Point2I mRowSize; ///< The base size of a row 497 498 S32 mColumnSplit; ///< Absolute position of the split between columns 499 S32 mRightPad; ///< Extra padding between the right arrow and the hit area 500 501 GuiGameListMenuProfile(); 502 503 DECLARE_CONOBJECT(GuiGameListMenuProfile); 504 505 /// Initializes fields accessible through the console. 506 static void initPersistFields(); 507 508 enum 509 { 510 TEX_NORMAL = 0, ///< texture index for a normal, unselected row 511 TEX_SELECTED = 1, ///< texture index for a selected row 512 TEX_HIGHLIGHT = 2, ///< texture index for a highlighted row (moused over, not selected) 513 TEX_DISABLED = 3, ///< texture index for a disabled row 514 TEX_L_ARROW_OFF = 4, ///< texture index for the left arrow of an unselected row 515 TEX_L_ARROW_ON = 5, ///< texture index for the left arrow of a selected row 516 TEX_R_ARROW_OFF = 6, ///< texture index for the right arrow of an unselected row 517 TEX_R_ARROW_ON = 7, ///< texture index for the right arrow of a selected row 518 519 TEX_FIRST_ARROW = 4, ///< texture index for the first arrow 520 TEX_FIRST_ICON = 8, ///< texture index for the first row marker icon 521 }; 522 523private: 524 Point2F mRowScale; ///< Ratio of row size to actual bitmap size 525}; 526 527#endif 528