1 /////////////////////////////////////////////////////////////////////////////// 2 // Copyright (C) 2004-2010 by The Allacrost Project 3 // All Rights Reserved 4 // 5 // This code is licensed under the GNU GPL version 2. It is free software 6 // and you may modify it and/or redistribute it under the terms of this license. 7 // See http://www.gnu.org/copyleft/gpl.html for details. 8 /////////////////////////////////////////////////////////////////////////////// 9 10 /** **************************************************************************** 11 *** \file gui.h 12 *** \author Raj Sharma, roos@allacrost.org 13 *** \brief Header file for GUI code 14 *** 15 *** This code implements the base structures of the video engine's GUI system. 16 *** ***************************************************************************/ 17 18 #ifndef __GUI_HEADER__ 19 #define __GUI_HEADER__ 20 21 #include "defs.h" 22 #include "utils.h" 23 24 #include "screen_rect.h" 25 #include "image.h" 26 #include "text.h" 27 28 namespace hoa_gui { 29 30 //! \brief The singleton pointer for the GUI manager 31 extern GUISystem* GUIManager; 32 33 namespace private_gui { 34 35 //! \brief 50% alpha colors used for debug drawing of GUI element outlines 36 //@{ 37 const hoa_video::Color alpha_black(0.0f, 0.0f, 0.0f, 0.5f); 38 const hoa_video::Color alpha_white(1.0f, 1.0f, 1.0f, 0.5f); 39 //@} 40 41 //! \brief Constants used as indeces to access the GUISystem#_scroll_arrows vector 42 //@{ 43 const uint32 SCROLL_UP = 0; 44 const uint32 SCROLL_DOWN = 1; 45 const uint32 SCROLL_LEFT = 2; 46 const uint32 SCROLL_RIGHT = 3; 47 const uint32 SCROLL_UP_GREY = 4; 48 const uint32 SCROLL_DOWN_GREY = 5; 49 const uint32 SCROLL_LEFT_GREY = 6; 50 const uint32 SCROLL_RIGHT_GREY = 7; 51 //@} 52 53 54 /** **************************************************************************** 55 *** \brief An abstract base class for all GUI elements (windows + controls). 56 *** This class contains basic functions such as Draw(), Update(), etc. 57 *** ***************************************************************************/ 58 class GUIElement { 59 public: 60 GUIElement(); 61 62 //! \note The destructor must be re-implemented in all children of this class. ~GUIElement()63 virtual ~GUIElement() 64 {} 65 66 //! \brief Draws the GUI element to the screen. 67 virtual void Draw() = 0; 68 69 /** \brief Updates the state of the element. 70 *** \param frame_time The time that has elapsed since the last frame was drawn, in milliseconds 71 **/ 72 virtual void Update(uint32 frame_time) = 0; 73 74 /** \brief Does a self-check on all its members to see if all its members have been set to valid values. 75 *** \param errors - A reference to a string to be filled with error messages if any errors are found. 76 *** \return True if everything is initialized correctly, false otherwise. 77 *** This is used internally to make sure we have a valid object before doing any complicated operations. 78 *** If it detects any problems, it generates a list of errors and returns it by reference so they can be displayed. 79 **/ 80 virtual bool IsInitialized(std::string &errors) = 0; 81 82 /** \brief Sets the width and height of the element 83 *** \param w The width to set for the element 84 *** \param h The height to set for the element 85 *** If either the width or height arguments are negative (or zero) no change will take place. This method only sets the 86 *** _width and _height members. Deriving classes may need to override this function to take into consideration 87 *** changes that must take place when the element is re-sized. 88 **/ 89 virtual void SetDimensions(float w, float h); 90 91 /** \brief Sets the position of the object. 92 *** \param x A reference to store the x coordinate of the object. 93 *** \param y A reference to store the y coordinate of the object. 94 *** \note X and y are in terms of a 1024x768 coordinate system 95 **/ SetPosition(float x,float y)96 void SetPosition(float x, float y) 97 { _x_position = x; _y_position = y; } 98 99 /** \brief Sets the alignment of the element. 100 *** \param xalign Valid values include VIDEO_X_LEFT, VIDEO_X_CENTER, or VIDEO_X_RIGHT. 101 *** \param yalign Valid values include VIDEO_Y_TOP, VIDEO_Y_CENTER, or VIDEO_Y_BOTTOM. 102 **/ 103 void SetAlignment(int32 xalign, int32 yalign); 104 105 /** \brief Returns the width and height of the GUI element 106 *** \param w Reference to a variable to hold the width 107 *** \param h Reference to a variable to hold the height 108 **/ GetDimensions(float & w,float & h)109 void GetDimensions(float& w, float& h) const 110 { w = _width; h = _height; } 111 112 /** \brief Gets the position of the object. 113 *** \param x A reference to store the x coordinate of the object. 114 *** \param y A reference to store the y coordinate of the object. 115 *** \note X and y are in terms of a 1024x768 coordinate system 116 **/ GetPosition(float & x,float & y)117 void GetPosition(float &x, float &y) const 118 { x = _x_position; y = _y_position; } 119 120 /** \brief Gets the x and y alignment of the element. 121 *** \param xalign - x alignment of the object 122 *** \param yalign - y alignment of the object 123 **/ GetAlignment(int32 & xalign,int32 & yalign)124 void GetAlignment(int32 &xalign, int32 &yalign) const 125 { xalign = _xalign; yalign = _yalign; } 126 127 /** \brief Calculates and returns the four edges for an aligned rectangle 128 *** \param left A reference where to store the coordinates of the rectangle's left edge. 129 *** \param right A reference where to store the coordinates of the rectangle's right edge. 130 *** \param bottom A reference where to store the coordinates of the rectangle's bttom edge. 131 *** \param top A reference where to store the coordinates of the rectangle's top edge. 132 *** 133 *** Given a rectangle specified in VIDEO_X_LEFT and VIDEO_Y_BOTTOM orientation, this function 134 *** transforms the rectangle based on the video engine's alignment flags. 135 *** \todo I think this function needs to be renamed. It seems to only be used to compute the 136 *** four edges of the GUI element. It should be called "CalculateEdges" or somthing more 137 *** specific if it is only used in this manner. 138 **/ 139 virtual void CalculateAlignedRect(float &left, float &right, float &bottom, float &top); 140 141 protected: 142 //! \brief Members for determining the element's draw alignment. 143 int32 _xalign, _yalign; 144 145 //! \brief The x and y position of the gui element. 146 float _x_position, _y_position; 147 148 //! \brief The dimensions of the GUI element in pixels. 149 float _width, _height; 150 151 //! \brief Used to determine if the object is in a valid state. 152 //! \note This member is set after every change to any of the object's settings. 153 bool _initialized; 154 155 //! \brief Contains the errors that need to be resolved if the object is in an invalid state (not ready for rendering). 156 std::string _initialization_errors; 157 158 //! \brief Draws an outline of the element boundaries 159 virtual void _DEBUG_DrawOutline(); 160 }; // class GUIElement 161 162 163 /** **************************************************************************** 164 *** \brief GUIControl is a type of GUI element, specifically for controls. 165 *** This is for functions that controls have, but menu windows don't have, such 166 *** as the SetOwner() function. 167 *** ***************************************************************************/ 168 class GUIControl : public GUIElement { 169 public: GUIControl()170 GUIControl() 171 { _owner = NULL; } 172 ~GUIControl()173 virtual ~GUIControl() 174 {} 175 176 /** \brief Calculates and returns the four edges for an aligned rectangle 177 *** \param left A reference where to store the coordinates of the rectangle's left edge. 178 *** \param right A reference where to store the coordinates of the rectangle's right edge. 179 *** \param bottom A reference where to store the coordinates of the rectangle's bttom edge. 180 *** \param top A reference where to store the coordinates of the rectangle's top edge. 181 *** \note The difference between this function and the one for GUI elements is that 182 *** controls must take their owner window into account. 183 **/ 184 virtual void CalculateAlignedRect(float &left, float &right, float &bottom, float &top); 185 186 /** \brief Sets the menu window which "owns" this control. 187 *** \param owner_window A pointer to the menu that owns the control. 188 *** \note If the control is not owned by any menu window, then set the owner to NULL. 189 *** When a control is owned by a menu, it means that it obeys the menu's scissoring 190 *** rectangle so that the control won't be drawn outside of the bounds of the menu. 191 *** It also means that the position of the control is relative to the position of the 192 *** window. (i.e. control.position += menu.position). 193 **/ SetOwner(MenuWindow * owner_window)194 virtual void SetOwner(MenuWindow *owner_window) 195 { _owner = owner_window; } 196 197 protected: 198 /** \brief A pointer to the menu which owns this control. 199 *** When the owner is set to NULL, the control can draw to any part of the screen 200 *** (so scissoring is ignored) and drawing coordinates are not modified. 201 **/ 202 MenuWindow *_owner; 203 204 /** \brief Draws an outline of the control boundaries 205 *** \note This implementation uses the 206 *** 207 **/ 208 virtual void _DEBUG_DrawOutline(); 209 }; // class GUIControl : public GUIElement 210 211 } // namespace private_gui 212 213 214 /** **************************************************************************** 215 *** \brief A helper class to the video engine to manage all of the GUI functionality. 216 *** 217 *** There is exactly one instance of this class, which is both created and destroyed 218 *** by the VideoEngine class. This class is essentially an extension of the GameVideo 219 *** class which manages the GUI system. It also handles the drawing of the 220 *** average frames per second (FPS) on the screen. 221 *** ***************************************************************************/ 222 class GUISystem : public hoa_utils::Singleton<GUISystem> { 223 friend class hoa_utils::Singleton<GUISystem>; 224 friend class hoa_video::VideoEngine; 225 friend class MenuWindow; 226 friend class TextBox; 227 friend class OptionBox; 228 public: 229 GUISystem(); 230 231 ~GUISystem(); 232 233 bool SingletonInitialize(); 234 235 /** \name Methods for loading of menu skins 236 *** 237 *** These methods all attempt to load a menu skin. The differences between these implementations are 238 *** whether the skin includes a background image, single background color, multiple background colors, 239 *** or some combination thereof. Only the skin_name and border_image arguments are mandatory for all 240 *** versions of this function to have 241 *** 242 *** \param skin_name The name that will be used to refer to the skin after it is successfully loaded 243 *** \param border_image The filename for the multi-image that contains the menu's border images 244 *** \param background_image The filename for the skin's background image (optional) 245 *** \param top_left Sets the background color for the top left portion of the skin 246 *** \param top_right Sets the background color for the top right portion of the skin 247 *** \param bottom_left Sets the background color for the bottom left portion of the skin 248 *** \param bottom_right Sets the background color for the bottom right portion of the skin 249 *** \param make_default If this skin should be the default menu skin to be used, set this argument to true 250 *** \return True if the skin was loaded successfully, or false in case of an error 251 *** 252 *** A few notes about this function: 253 *** - If you set a background image, any background colors will not be visible unless the background image has some transparency 254 *** - If no other menu skins are loaded when this function is called, the default skin will automatically be set to this skin, 255 *** regardless of the value of the make_default parameter. 256 **/ 257 //@{ 258 //! \brief Loads a background image with no background colors 259 bool LoadMenuSkin(std::string skin_name, std::string border_image, std::string background_image, bool make_default = false); 260 261 //! \brief Loads a single background color with no background image 262 bool LoadMenuSkin(std::string skin_name, std::string border_image, hoa_video::Color background_color, bool make_default = false); 263 264 //! \brief Loads multiple multiple background colors with no background image 265 bool LoadMenuSkin(std::string skin_name, std::string border_image, hoa_video::Color top_left, hoa_video::Color top_right, 266 hoa_video::Color bottom_left, hoa_video::Color bottom_right, bool make_default = false); 267 268 //! \brief Loads a background image with a single background color 269 bool LoadMenuSkin(std::string skin_name, std::string border_image, std::string background_image, 270 hoa_video::Color background_color, bool make_default = false); 271 272 //! \brief Loads a background image with multiple background colors 273 bool LoadMenuSkin(std::string skin_name, std::string border_image, std::string background_image, 274 hoa_video::Color top_left, hoa_video::Color top_right, hoa_video::Color bottom_left, hoa_video::Color bottom_right, bool make_default = false); 275 //@} 276 277 /** \brief Deletes a menu skin that has been loaded 278 *** \param skin_name The name of the loaded menu skin that should be removed 279 *** 280 *** This function could fail on one of two circumstances. First, if there is no MenuSkin loaded for 281 *** the key skin_name, the function will do nothing. Second, if any MenuWindow objects are still 282 *** referencing the skin that is trying to be deleted, the function will print a warning message 283 *** and not delete the skin. Therefore, <b>before you call this function, you must delete any and all 284 *** MenuWindow objects which make use of this skin, or change the skin used by those objects</b>. 285 **/ 286 void DeleteMenuSkin(std::string& skin_name); 287 288 //! \brief Returns true if there is a menu skin avialable corresponding to the argument name 289 bool IsMenuSkinAvailable(std::string& skin_name) const; 290 291 /** \brief Sets the default menu skin to use from the set of pre-loaded skins 292 *** \param skin_name The name of the already loaded menu skin that should be made the default skin 293 *** 294 *** If the skin_name does not refer to a valid skin, a warning message will be printed and no change 295 *** will occur. 296 *** \note This method will <b>not</b> change the skins of any active menu windows. 297 **/ 298 void SetDefaultMenuSkin(std::string& skin_name); 299 300 //! \brief Returns true if GUI elements should have outlines drawn over their boundaries DEBUG_DrawOutlines()301 bool DEBUG_DrawOutlines() const 302 { return _DEBUG_draw_outlines; } 303 304 // Don't commit this. GetScrollArrows()305 std::vector<hoa_video::StillImage>* GetScrollArrows() 306 { return &_scroll_arrows; } 307 308 /** \brief Debug functioning for enabling/disabling the drawing of GUI element boundaries 309 *** \param enable Set to true to enable outlines, false to disable 310 **/ DEBUG_EnableGUIOutlines(bool enable)311 void DEBUG_EnableGUIOutlines(bool enable) 312 { _DEBUG_draw_outlines = enable; } 313 314 private: 315 /** \brief Stores the arrow icons used for scrolling through various GUI controls 316 *** The size of this vector is eight. The first four images are the standard arrows and the last 317 *** four are greyed out arrows (used to indicate the end of scrolling). The first four arrow 318 *** images represent up, down, left, right in that order, and the last four arrows follow this 319 *** format as well. 320 **/ 321 std::vector<hoa_video::StillImage> _scroll_arrows; 322 323 /** \brief A map containing all of the menu skins which have been loaded 324 *** The string argument is the reference name of the menu, which is defined 325 *** by the user when they load a new skin. 326 *** 327 **/ 328 std::map<std::string, private_gui::MenuSkin> _menu_skins; 329 330 /** \brief A map containing all of the actively created MenuWindow objects 331 *** The integer key is the MenuWindow's ID number. This primary purpose of this map is to coordinate menu windows 332 *** with menu skins. A menu skin can not be deleted when a menu window is still using that skin, and menu windows 333 *** must be re-drawn when the properties of a menu skin that it uses changes. 334 **/ 335 std::map<uint32, MenuWindow*> _menu_windows; 336 337 /** \brief A pointer to the default menu skin that GUI objects will use if a skin is not explicitly declared 338 *** If no menu skins exist, this member will be NULL. It will never be NULL as long as one menu skin is loaded. 339 *** If the default menu skin is deleted by the user, an alternative default skin will automatically be set. 340 **/ 341 hoa_gui::private_gui::MenuSkin* _default_skin; 342 343 //! \brief The next ID to assign to a MenuWindow when one is created 344 uint32 _next_window_id; 345 346 /** \brief Draws an outline of the boundary for all GUI elements drawn to the screen when true 347 *** The VideoEngine class contains the method that modifies this variable. 348 **/ 349 bool _DEBUG_draw_outlines; 350 351 // ---------- Private methods 352 353 /** \brief Returns a pointer to the MenuSkin of a corresponding skin name 354 *** \param skin_name The name of the menu skin to grab 355 *** \return A pointer to the MenuSkin, or NULL if the skin name was not found 356 **/ 357 private_gui::MenuSkin* _GetMenuSkin(std::string& skin_name); 358 359 //! \brief Returns a pointer to the default menu skin _GetDefaultMenuSkin()360 private_gui::MenuSkin* _GetDefaultMenuSkin() const 361 { return _default_skin; } 362 363 /** \brief Returns the next available MenuWindow ID for a MenuWindow to use 364 *** \return The ID number for the MenuWindow to use 365 *** This method should only need to be called from the MenuWindow constructor. 366 **/ _GetNextMenuWindowID()367 uint32 _GetNextMenuWindowID() 368 { _next_window_id++; return (_next_window_id - 1); } 369 370 /** \brief Adds a newly created MenuWindow into the map of existing windows 371 *** \param new_window A pointer to the newly created MenuWindow 372 *** Don't call this method anywhere else but from MenuWindow::Create(), or you may cause problems. 373 **/ 374 void _AddMenuWindow(MenuWindow* new_window); 375 376 /** \brief Removes an existing MenuWindow from the map of existing windows 377 *** \param old_window A pointer to the MenuWindow to be removed 378 *** Don't call this method anywhere else but from MenuWindow::Destroy(), or you may cause problems. 379 **/ 380 void _RemoveMenuWindow(MenuWindow* old_window); 381 }; // class GUISystem : public hoa_utils::Singleton<GUISystem> 382 383 } // namespace hoa_gui 384 385 #include "menu_window.h" 386 #include "option.h" 387 #include "textbox.h" 388 389 #endif // __GUI_HEADER__ 390