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