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 menu_window.h 12 *** \author Raj Sharma, roos@allacrost.org 13 *** \brief Header file for menu window class 14 *** ***************************************************************************/ 15 16 #ifndef __MENU_WINDOW_HEADER__ 17 #define __MENU_WINDOW_HEADER__ 18 19 #include "defs.h" 20 #include "utils.h" 21 22 #include "gui.h" 23 #include "screen_rect.h" 24 #include "image.h" 25 26 namespace hoa_gui { 27 28 //! \brief How many milliseconds it takes for a window to scroll in or out of view. 29 const int32 VIDEO_MENU_SCROLL_TIME = 200; 30 31 32 /** \name Menu Edge Bitflags 33 *** \brief These flags control the presence/absence of each edge of the menu window. 34 *** For example, if you want to show a menu with its left edge hidden, then you would pass in all 35 *** the flags except VIDEO_MENU_EDGE_LEFT to the MenuWindow#Create() function, or alternatively 36 *** you could pass the complement of that bit flag (~VIDEO_MENU_EDGE_LEFT). 37 **/ 38 //@{ 39 const int32 VIDEO_MENU_EDGE_LEFT = 0x1; 40 const int32 VIDEO_MENU_EDGE_RIGHT = 0x2; 41 const int32 VIDEO_MENU_EDGE_TOP = 0x4; 42 const int32 VIDEO_MENU_EDGE_BOTTOM = 0x8; 43 const int32 VIDEO_MENU_EDGE_ALL = 0xF; 44 //@} 45 46 47 /** \brief Menu display modes control how the menu window appears or disappears. 48 *** The specific display modes include: 49 *** - VIDEO_MENU_INSTANT: appears/disappears instantly 50 *** - VIDEO_MENU_EXPAND_FROM_CENTER: starts as a thin horizontal line at center and expands out 51 **/ 52 enum VIDEO_MENU_DISPLAY_MODE { 53 VIDEO_MENU_INVALID = -1, 54 VIDEO_MENU_INSTANT = 0, 55 VIDEO_MENU_EXPAND_FROM_CENTER = 1, 56 VIDEO_MENU_TOTAL = 2 57 }; 58 59 60 /** \brief These enums are used to tell the visiblity state of a menu window. 61 *** The possible states and their meaning include: 62 *** - VIDEO_MENU_STATE_SHOWN: the menu is fully shown 63 *** - VIDEO_MENU_STATE_SHOWING: the menu is still in the process of scrolling on to the screen 64 *** - VIDEO_MENU_STATE_HIDING: the menu is scrolling out of view, but is not completely hidden yet 65 *** - VIDEO_MENU_STATE_HIDDEN: the menu is fully hidden 66 **/ 67 enum VIDEO_MENU_STATE { 68 VIDEO_MENU_STATE_INVALID = -1, 69 VIDEO_MENU_STATE_SHOWN = 0, 70 VIDEO_MENU_STATE_SHOWING = 1, 71 VIDEO_MENU_STATE_HIDING = 2, 72 VIDEO_MENU_STATE_HIDDEN = 3, 73 VIDEO_MENU_STATE_TOTAL = 4 74 }; 75 76 77 namespace private_gui { 78 79 /** **************************************************************************** 80 *** \brief A container class for a menu skin, consisting of border images and an interior 81 *** 82 *** The GUISystem class manages all MenuSkins which have been loaded by the user. 83 *** Multiple menu skins may co-exist at one time and be drawn to the screen. The MenuWindow 84 *** class makes extensive use of MenuSkins. 85 *** 86 *** \note The contructor and destructor of this class do nothing. The creation and destruction 87 *** of the images contained by this class is done from the GUI class. 88 *** 89 *** \todo Add support for menu skin backgrounds to be tiled images versus 90 *** stretched images. 91 *** 92 *** \todo Add support to allow menu skin backgrounds to be colors instead of 93 *** images. 94 *** ***************************************************************************/ 95 class MenuSkin { 96 public: MenuSkin()97 MenuSkin() 98 {} 99 ~MenuSkin()100 ~MenuSkin() 101 {} 102 103 /** \brief A 2d array that holds the border images for the menu skin 104 *** The entries in this array represent the following parts: 105 *** - borders[0][0]: upper left corner 106 *** - borders[0][1]: top side 107 *** - borders[0][2]: upper right corner 108 *** - borders[1][0]: left side 109 *** - borders[1][1]: center (this is not an actual image, but rather contains the background colors for the four corners) 110 *** - borders[1][2]: right side 111 *** - borders[2][0]: bottom left corner 112 *** - borders[2][1]: bottom side 113 *** - borders[2][2]: bottom right corner 114 **/ 115 hoa_video::StillImage borders[3][3]; 116 117 /** \brief Border-connecting images, used when two or more MenuWindows are side by side. 118 *** There are four tri-connectors and one quad-connector. tri_t would be an image for 119 *** a 3-way connector on the top of a MenuWindow. 120 *** - connectors[0]: top tri-connector 121 *** - connectors[1]: bottom tri-connector 122 *** - connectors[2]: left tri-connector 123 *** - connectors[3]: right tri-connector 124 *** - connectors[4]: quad connector 125 **/ 126 hoa_video::StillImage connectors[5]; 127 128 //! \brief The (optional) background image of the menu skin that fills the inside of the MenuWindow 129 hoa_video::StillImage background; 130 }; // class MenuSkin 131 132 } // namespace private_gui 133 134 135 /** **************************************************************************** 136 *** \brief Represents GUI menu windows and handles their operation 137 *** 138 *** A menu window is simply a rectangle drawn on the screen that has a border 139 *** image and a background. Menu windows exist to provide a base upon which to 140 *** draw text and images that are not a part of the regular game environment. 141 *** 142 *** \note It is common practice to derive specific windows from this class for 143 *** the display of dialogue text, inventory lists, etc. This class is designed 144 *** with that practice in mind. 145 *** 146 *** \todo Allow the user to specify an arbitrary amount of time for showing/ 147 *** hiding the menu window. 148 *** 149 *** \todo Determine function/behavior of copy constructor and copy assignment 150 *** operator. Should these be set to private, or implemented? How should the 151 *** texture be copied if it is implemented? 152 *** 153 *** \todo Why doesn't the class destructor do what the Destroy function implements? 154 *** It would be much safer for the destructor to auto-destroy anything, or at the 155 *** very least it could print a warning if the class destructor is called when 156 *** destroy has not yet been invoked. If this is changed, remember to update 157 *** the documentation on the wiki for this as well. 158 *** ***************************************************************************/ 159 class MenuWindow : public private_gui::GUIElement { 160 friend class GUISystem; 161 public: 162 MenuWindow(); 163 ~MenuWindow()164 ~MenuWindow() 165 {} 166 167 /** \brief Sets the width and height of the menu. 168 *** \param skin_name The name of the menu skin with which to construct this menu window. 169 *** \param w The window width in pixels, which must be within the range of [0.0f, 1024.f]. 170 *** \param h The window height in pixels, which must be within the range of [0.0f, 768.f]. 171 *** \param visible_flags A combination of bit flags, VIDEO_MENU_EDGE_LEFT, etc. that indicate 172 *** which edges are visible. A non-visible edge means that the border image gets stripped off. 173 *** \param shared_flags A combination of bitflags, VIDEO_MENU_EDGE_LEFT, etc. that tell which 174 *** edges are shared with other menus so they can use the appropriate connector images. 175 *** \return False and print an error message on failure. Otherwise return true upon success. 176 *** \note This function <b>must</b> be called before you attempt to draw the window. 177 **/ 178 bool Create(std::string skin_name, float w, float h, int32 visible_flags = VIDEO_MENU_EDGE_ALL, int32 shared_flags = 0); 179 180 //! \note This version of the create function does not take a skin_name argument. It uses the default menu skin. 181 bool Create(float w, float h, int32 visible_flags = VIDEO_MENU_EDGE_ALL, int32 shared_flags = 0); 182 183 /** \brief You <b>must</b> call this method when you are finished using a menu. 184 *** Failure to neglect this call may result in problems like texture memory not being freed. 185 **/ 186 void Destroy(); 187 188 /** \brief Updates the menu window, used for gradual show/hide effects. 189 *** \param frame_time The time that has elapsed since the previous frame, in milliseconds. 190 **/ 191 void Update(uint32 frame_time); 192 193 /** \brief This version is for the subclasses of menu window (allows us to use a single MenuWindow variable 194 *** to track the active window. 195 **/ Update()196 virtual void Update() 197 {} 198 199 //! \brief Draws the menu window to the screen. 200 void Draw(); 201 202 /** \brief Causes the menu to begin making itself visible. 203 *** Depending on the display mode, the menu might show instantly or gradually. 204 *** You can check for when the menu is fully shown by checking if GetState() 205 *** returns VIDEO_MENU_STATE_SHOWN (until then, it is VIDEO_MENU_STATE_SHOWING). 206 *** \note The time it takes for the menu to show is VIDEO_MENU_SCROLL_TIME. 207 **/ 208 void Show(); 209 210 /** \brief Causes the menu to begin making itself not visible. 211 *** Depending on the display mode, the menu might hide instantly or gradually. 212 *** If it's gradual, you should still continue calling Draw() even after you call 213 *** Hide() until it's fully hidden. You can check if it's fully hidden by checking 214 *** if GetState() returns VIDEO_MENU_STATE_HIDDEN (until then, it will be 215 *** VIDEO_MENU_STATE_HIDING). 216 *** \note The time it takes for the menu to show is VIDEO_MENU_SCROLL_TIME 217 **/ 218 void Hide(); 219 220 /** \brief Does a self-check on all its members to see if all its members have been set to valid values. 221 *** \param &errors A reference to a string to be filled if any errors are found. 222 *** \return True if menu window is properly initialized, false if it is not. 223 *** 224 *** This is used internally to make sure we have a valid object before doing any complicated operations. 225 *** If it detects any problems, it generates a list of errors and returns it by reference so they can be 226 *** displayed 227 **/ 228 bool IsInitialized(std::string &errors); 229 230 /** \brief Indicates whether the window is in the active context 231 *** \return True always here, subclasses can override to change the behaviour 232 **/ IsActive()233 virtual bool IsActive() 234 { return true; } 235 236 //! \name Class Member Access Functions 237 //@{ GetDisplayMode()238 VIDEO_MENU_DISPLAY_MODE GetDisplayMode() const 239 { return _display_mode; } 240 GetState()241 VIDEO_MENU_STATE GetState() const 242 { return _window_state; } 243 244 /** \note When the window is in the process of showing or hiding, subsequent calls to this function 245 *** (in between calls to Update()) will yield different results as the active dimensions of the window 246 *** are changing. When the window is fully shown or fully hidden, this function will always return the 247 *** same scissor rectangle that is reflective of the window's full size. 248 *** 249 **/ GetScissorRect()250 hoa_video::ScreenRect GetScissorRect() const 251 { return _scissor_rect; } 252 253 //! \note This call is somewhat expensive since it has to recreate the menu window image. 254 void SetDimensions(float w, float h); 255 256 //! \note This call is somewhat expensive since it has to recreate the menu window image. SetEdgeVisibleFlags(int32 flags)257 void SetEdgeVisibleFlags(int32 flags) 258 { _edge_visible_flags = flags; _RecreateImage(); } 259 260 //! \note This call is somewhat expensive since it has to recreate the menu window image. SetEdgeSharedFlags(int32 flags)261 void SetEdgeSharedFlags(int32 flags) 262 { _edge_shared_flags = flags; _RecreateImage(); } 263 264 //! \note This call is somewhat expensive since it has to recreate the menu window image. 265 void SetMenuSkin(std::string& skin_name); 266 267 void SetDisplayMode(VIDEO_MENU_DISPLAY_MODE mode); 268 //@} 269 270 private: 271 //! \brief The current id of this object. 272 int32 _id; 273 274 //! \brief The dimensions of the space inside the window borders. 275 float _inner_width, _inner_height; 276 277 //! \brief Flags used to tell which edges of the menu window are visible. 278 int32 _edge_visible_flags; 279 280 //! \brief Flags used to tell which edges are shared with other windows. 281 int32 _edge_shared_flags; 282 283 //! \brief A pointer to the menu skin that the menu window currently uses 284 private_gui::MenuSkin* _skin; 285 286 //! \brief The state of the menu window (hidden, shown, hiding, showing). 287 VIDEO_MENU_STATE _window_state; 288 289 //! \brief The number of milliseconds that have passed since the menu was shown. 290 int32 _display_timer; 291 292 //! \brief The image that creates the window 293 hoa_video::CompositeImage _menu_image; 294 295 //! \brief The window's display mode (instant, expand from center, etc). 296 VIDEO_MENU_DISPLAY_MODE _display_mode; 297 298 //! \brief Set to true if scissoring needs to be used on the window. 299 bool _is_scissored; 300 301 //! \brief The rectangle used for scissoring, set during each call to Update(). 302 hoa_video::ScreenRect _scissor_rect; 303 304 /** \brief Used to create the menu window's image when the visible properties of the window change. 305 *** \return True if the menu image was successfully created, false otherwise. 306 *** 307 *** \note This function may not create a window that is exactly the width and height requested. 308 *** It will automatically adjust the dimneions to minimalize warping. So for example, if the 309 *** border artwork is all 8x8 pixel images and you try to create a menu that is 117x69, it will get 310 *** rounded up to 120x72. 311 **/ 312 bool _RecreateImage(); 313 }; // class MenuWindow : public GUIElement 314 315 } // namespace hoa_gui 316 317 #endif // __MENU_WINDOW_HEADER__ 318