guiGameListMenuCtrl.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #ifndef _GuiGameListMenuCtrl_H_
  23. #define _GuiGameListMenuCtrl_H_
  24. #include "gui/core/guiControl.h"
  25. class GuiGameListMenuProfile;
  26. /// \class GuiGameListMenuCtrl
  27. /// A base class for cross platform menu controls that are gamepad friendly.
  28. class GuiGameListMenuCtrl : public GuiControl
  29. {
  30. public:
  31. typedef GuiControl Parent;
  32. typedef GuiGameListMenuProfile Profile;
  33. protected:
  34. /// \struct Row
  35. /// Internal data representation of a single row in the control.
  36. struct Row
  37. {
  38. StringTableEntry mLabel; ///< Text to display in the row as a label
  39. StringTableEntry mScriptCallback; ///< Script callback when row is activated
  40. S32 mIconIndex; ///< Index of the icon to display on the row (-1 = no icon)
  41. S32 mHeightPad; ///< Extra amount to pad above this row
  42. bool mUseHighlightIcon; ///< Toggle the use of the highlight icon
  43. bool mEnabled; ///< If this row is enabled or not (grayed out)
  44. virtual ~Row() {}
  45. };
  46. public:
  47. /// \return The index of the highlighted row or NO_ROW if none of the rows
  48. /// are currently highlighted.
  49. virtual S32 getHighlighted() const { return mHighlighted; }
  50. /// \return The index of the selected row or NO_ROW if none of the rows are
  51. /// currently selected.
  52. virtual S32 getSelected() const { return mSelected; }
  53. /// Sets the selected row. Only rows that are enabled can be selected. Input is
  54. /// clamped to [0, mRows.size())
  55. ///
  56. /// \param index The index to set as selected.
  57. virtual void setSelected(S32 index);
  58. /// Determines if the specified row is enabled or disabled.
  59. ///
  60. /// \param index Index of the row to check.
  61. /// \return True if the specified row is enabled. False if the row is not
  62. /// enabled or the given index was not valid.
  63. virtual bool isRowEnabled(S32 index) const;
  64. /// Sets a row's enabled status according to the given parameters.
  65. ///
  66. /// \param index The row to set the enabled status of.
  67. /// \param enabled Indicate true to enable the row or false to disable it.
  68. virtual void setRowEnabled(S32 index, bool enabled);
  69. /// Gets the label displayed on the specified row.
  70. ///
  71. /// \param rowIndex Index of the row to get the label of.
  72. /// \return The label for the row.
  73. virtual StringTableEntry getRowLabel(S32 rowIndex) const;
  74. /// Sets the label on the given row.
  75. ///
  76. /// \param rowIndex Index of the row to set the label on.
  77. /// \param label Text to set as the label of the row.
  78. virtual void setRowLabel(S32 rowIndex, const char * label);
  79. /// Adds a row to the control.
  80. ///
  81. /// \param label The text to display on the row as a label.
  82. /// \param callback Name of a script function to use as a callback when this
  83. /// row is activated.
  84. /// \param icon [optional] Index of the icon to use as a marker. Default -1
  85. /// means no icon will be shown on this row.
  86. /// \param yPad [optional] An extra amount of height padding before the row.
  87. /// \param enabled [optional] If this row is initially enabled. Default true.
  88. virtual void addRow(const char* label, const char* callback, S32 icon = -1, S32 yPad = 0, bool useHighlightIcon = true, bool enabled = true);
  89. /// Activates the current row. The script callback of the current row will
  90. /// be called (if it has one).
  91. virtual void activateRow();
  92. /// Gets the number of rows in the control.
  93. ///
  94. /// \return The number of rows in this control.
  95. virtual S32 getRowCount() const { return mRows.size(); }
  96. GuiGameListMenuCtrl();
  97. ~GuiGameListMenuCtrl();
  98. void onRender(Point2I offset, const RectI &updateRect);
  99. /// Callback when the object is registered with the sim.
  100. ///
  101. /// \return True if the profile was successfully added, false otherwise.
  102. bool onAdd();
  103. /// Callback when the control wakes up.
  104. bool onWake();
  105. /// Callback when a key is pressed.
  106. ///
  107. /// \param event The event that triggered this callback.
  108. bool onKeyDown(const GuiEvent &event);
  109. /// Callback when a key is repeating.
  110. ///
  111. /// \param event The event that triggered this callback.
  112. bool onKeyRepeat(const GuiEvent &event){ return onKeyDown(event); }
  113. /// Callback when the mouse button is clicked on the control.
  114. ///
  115. /// \param event A reference to the event that triggered the callback.
  116. void onMouseDown(const GuiEvent &event);
  117. /// Callback when the mouse is dragged on the control.
  118. ///
  119. /// \param event A reference to the event that triggered the callback.
  120. void onMouseDragged(const GuiEvent &event){ onMouseDown(event); }
  121. /// Callback when the mouse leaves the control.
  122. ///
  123. /// \param event A reference to the event that triggered the callback.
  124. void onMouseLeave(const GuiEvent &event);
  125. /// Callback when the mouse is moving over this control
  126. ///
  127. /// \param event A reference to the event that triggered the callback.
  128. void onMouseMove(const GuiEvent &event);
  129. /// Callback when the mouse button is released.
  130. ///
  131. /// \param event A reference to the event that triggered the callback.
  132. void onMouseUp(const GuiEvent &event);
  133. /// Callback when the gamepad axis is activated.
  134. ///
  135. /// \param event A reference to the event that triggered the callback.
  136. virtual bool onGamepadAxisUp(const GuiEvent & event);
  137. /// Callback when the gamepad axis is activated.
  138. ///
  139. /// \param event A reference to the event that triggered the callback.
  140. virtual bool onGamepadAxisDown(const GuiEvent & event);
  141. DECLARE_CONOBJECT(GuiGameListMenuCtrl);
  142. DECLARE_CATEGORY( "Gui Game" );
  143. DECLARE_DESCRIPTION( "Base class for cross platform menu controls that are gamepad friendly." );
  144. /// Initializes fields accessible through the console.
  145. static void initPersistFields();
  146. static const S32 NO_ROW = -1; ///< Indicates a query result of no row found.
  147. static const S32 NO_ICON = -1; ///< Indicates a row has no extra icon available
  148. protected:
  149. /// Adds a row to the control.
  150. ///
  151. /// \param row A reference to the row object to fill.
  152. /// \param label The text to display on the row as a label.
  153. /// \param callback Name of a script function to use as a callback when this
  154. /// row is activated.
  155. /// \param icon [optional] Index of the icon to use as a marker. Default -1
  156. /// means no icon will be shown on this row.
  157. /// \param yPad [optional] An extra amount of height padding before the row.
  158. /// \param enabled [optional] If this row is initially enabled. Default true.
  159. virtual void addRow(Row * row, const char* label, const char* callback, S32 icon, S32 yPad, bool useHighlightIcon, bool enabled);
  160. /// Determines if the given index is a valid row index. Any index pointing at
  161. /// an existing row is valid.
  162. ///
  163. /// \param index The index to check for validity.
  164. /// \return True if the index points at a valid row, false otherwise.
  165. virtual bool isValidRowIndex(S32 index) const;
  166. /// Sets the script variable $ThisControl to reflect this control.
  167. virtual void setThisControl();
  168. /// Called to implement debug rendering which displays colored lines to
  169. /// provide visual feedback on extents and hit zones.
  170. virtual void onDebugRender(Point2I offset);
  171. /// Looks up the row having a hit area at the given global point.
  172. ///
  173. /// \param globalPoint The point we want to check for hitting a row.
  174. /// \return The index of the hit row or NO_ROW if no row was hit.
  175. virtual S32 getRow(Point2I globalPoint);
  176. /// Checks to make sure our control has a profile of the correct type.
  177. ///
  178. /// \return True if the profile is of type GuiGameListMenuProfile or false if
  179. /// the profile is of any other type.
  180. virtual bool hasValidProfile() const;
  181. /// Enforces the validity of the fields on this control and its profile (if
  182. /// the profile is valid, see: hasValidProfile).
  183. virtual void enforceConstraints();
  184. /// @name Callbacks
  185. /// @{
  186. DECLARE_CALLBACK( void, onChange, () );
  187. /// @}
  188. /// Evaluates some script. If the command is empty then nothing is evaluated.
  189. ///
  190. /// \param command The script to evaluate.
  191. void doScriptCommand(StringTableEntry command);
  192. StringTableEntry mCallbackOnA; ///< Script callback when the 'A' button is pressed
  193. StringTableEntry mCallbackOnB; ///< Script callback when the 'B' button is pressed
  194. StringTableEntry mCallbackOnX; ///< Script callback when the 'X' button is pressed
  195. StringTableEntry mCallbackOnY; ///< Script callback when the 'Y' button is pressed
  196. bool mDebugRender; ///< Determines when to show debug render lines
  197. Vector<Row *> mRows; ///< Holds data wrappers on all the rows we have
  198. private:
  199. /// Recalculates the height of this control based on the stored row height and
  200. /// and padding on the rows.
  201. virtual Point2I getMinExtent() const;
  202. /// Makes sure the height will allow all rows to be displayed without being
  203. /// truncated.
  204. void updateHeight();
  205. /// Sets the first enabled row as selected. If there are no enabled rows then
  206. /// selected will be set to NO_ROW.
  207. void selectFirstEnabledRow();
  208. /// Changes the currently selected row.
  209. ///
  210. /// \param delta The amount to change the row selection by. Typically this will
  211. /// be 1 or -1.
  212. void changeRow(S32 delta);
  213. S32 mSelected; ///< index of the currently selected row
  214. S32 mHighlighted; ///< index of the currently highlighted row
  215. };
  216. /// \class GuiGameListMenuProfile
  217. /// A gui profile with additional fields specific to GuiGameListMenuCtrl.
  218. class GuiGameListMenuProfile : public GuiControlProfile
  219. {
  220. typedef GuiControlProfile Parent;
  221. public:
  222. /// Enforces range constraints on all required fields.
  223. virtual void enforceConstraints();
  224. /// Get the height of rows in this profile. All rows are considered to be the
  225. /// same base height. Rows can have an extra amount of y padding defined when
  226. /// they are added to the control.
  227. ///
  228. /// \return The height of rows in this profile.
  229. S32 getRowHeight() { return (mRowSize.y) ? mRowSize.y : getBitmapArrayRect(TEX_NORMAL).extent.y; }
  230. /// Get the width of rows in this profile. All rows are considered to be the
  231. /// same width.
  232. ///
  233. /// \return The width of rows in this profile.
  234. S32 getRowWidth() { return (mRowSize.x) ? mRowSize.x : getBitmapArrayRect(TEX_NORMAL).extent.x; }
  235. /// Row scale is the ratio between the defined row size and the raw size of
  236. /// the bitmap.
  237. ///
  238. /// \return The row scale.
  239. const Point2F & getRowScale() const { return mRowScale; }
  240. /// Gets the extent of icons for this profile. If there are no icons you will
  241. /// get a point of (0, 0);
  242. ///
  243. /// \return The extent of icons or (0, 0) if there aren't any.
  244. Point2I getIconExtent();
  245. /// Gets the extent of arrows for this profile. If there are no arrows you
  246. /// will get a point of (0, 0).
  247. ///
  248. /// \return The extent of icons or (0, 0) if there aren't any.
  249. Point2I getArrowExtent();
  250. /// Gets the extent of the defined hit area for this profile. If the hit area
  251. /// is not defined then it defaults to the full size of a row.
  252. ///
  253. /// \return The extents of the defined hit area or the full size of the row.
  254. Point2I getHitAreaExtent();
  255. /// Determines if this profile has textures for the left and right arrows.
  256. ///
  257. /// \return True if the profile's bitmap has textures for the arrows, false
  258. /// otherwise.
  259. bool hasArrows(){ return (! getBitmapArrayRect(TEX_FIRST_ARROW).extent.isZero()); }
  260. /// Callback when the object is registered with the sim.
  261. ///
  262. /// \return True if the profile was successfully added, false otherwise.
  263. bool onAdd();
  264. Point2I mHitAreaUpperLeft; ///< Offset for the upper left corner of the hit area
  265. Point2I mHitAreaLowerRight; ///< Offset for the lower right corner of the hit area
  266. Point2I mIconOffset; ///< Offset for a row's extra icon
  267. Point2I mRowSize; ///< The base size of a row
  268. GuiGameListMenuProfile();
  269. DECLARE_CONOBJECT(GuiGameListMenuProfile);
  270. /// Initializes fields accessible through the console.
  271. static void initPersistFields();
  272. enum
  273. {
  274. TEX_NORMAL = 0, ///< texture index for a normal, unselected row
  275. TEX_SELECTED = 1, ///< texture index for a selected row
  276. TEX_HIGHLIGHT = 2, ///< texture index for a highlighted row (moused over, not selected)
  277. TEX_DISABLED = 3, ///< texture index for a disabled row
  278. TEX_L_ARROW_OFF = 4, ///< texture index for the left arrow of an unselected row
  279. TEX_L_ARROW_ON = 5, ///< texture index for the left arrow of a selected row
  280. TEX_R_ARROW_OFF = 6, ///< texture index for the right arrow of an unselected row
  281. TEX_R_ARROW_ON = 7, ///< texture index for the right arrow of a selected row
  282. TEX_FIRST_ARROW = 4, ///< texture index for the first arrow
  283. TEX_FIRST_ICON = 8, ///< texture index for the first row marker icon
  284. };
  285. private:
  286. Point2F mRowScale; ///< Ratio of row size to actual bitmap size
  287. };
  288. #endif