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