1 //  SuperTuxKart - a fun racing game with go-kart
2 //  Copyright (C) 2010-2015 Marianne Gagnon
3 //
4 //  This program is free software; you can redistribute it and/or
5 //  modify it under the terms of the GNU General Public License
6 //  as published by the Free Software Foundation; either version 3
7 //  of the License, or (at your option) any later version.
8 //
9 //  This program is distributed in the hope that it will be useful,
10 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
11 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 //  GNU General Public License for more details.
13 //
14 //  You should have received a copy of the GNU General Public License
15 //  along with this program; if not, write to the Free Software
16 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
17 
18 
19 #ifndef HEADER_ENGINE_HPP
20 #define HEADER_ENGINE_HPP
21 
22 /**
23  * \defgroup guiengine
24  * Contains the generic GUI engine (contains the widgets and the backing logic
25  * for event handling, the skin, screens and dialogs). See module @ref states_screens
26  * for the actual STK GUI screens. Note that all input comes through this module
27  * too.
28  */
29 
30 namespace irr
31 {
32     class IrrlichtDevice;
33     namespace gui   { class IGUIEnvironment; class ScalableFont; }
34     namespace video { class IVideoDriver; class ITexture;        }
35 }
36 
37 #include <functional>
38 #include <string>
39 
40 #include "utils/constants.hpp"
41 #include "utils/ptr_vector.hpp"
42 
43 #include "irrString.h"
44 
45 /**
46  * \ingroup guiengine
47  * \brief Contains all GUI engine related classes and functions
48  *
49  * See \ref gui_overview for more information.
50  */
51 namespace GUIEngine
52 {
53     class Screen;
54     class Widget;
55     class Skin;
56     class AbstractStateManager;
57 
58     /** \brief Returns the widget currently focused by given player, or NULL if none.
59       * \note Do NOT use irrLicht's GUI focus facilities; it's too limited for our
60       *       needs, so we use ours. (i.e. always call these functions, never those
61       *       in IGUIEnvironment)
62       */
63     Widget* getFocusForPlayer(const unsigned int playerID);
64 
65     /** \brief Focuses nothing for given player (removes any selection for this player).
66       * \note Do NOT use irrLicht's GUI focus facilities; it's too limited for our
67       *       needs, so we use ours. (i.e. always call these functions, never those
68       *       in IGUIEnvironment)
69       */
70     void focusNothingForPlayer(const unsigned int playerID);
71 
72     /** \brief Returns whether given the widget is currently focused by given player.
73       * \note  Do NOT use irrLicht's GUI focus facilities; it's too limited for our
74       *        needs, so we use ours. (i.e. always call these functions, never those
75       *        in IGUIEnvironment)
76       */
77     bool isFocusedForPlayer(const Widget*w, const unsigned int playerID);
78 
79     /**
80       * In an attempt to make getters as fast as possible, by possibly still allowing inlining
81       * These fields should never be accessed outside of the GUI engine.
82       */
83     namespace Private
84     {
85         extern irr::gui::IGUIEnvironment* g_env;
86         extern Skin* g_skin;
87         extern irr::gui::ScalableFont* g_small_font;
88         extern irr::gui::ScalableFont* g_font;
89         extern irr::gui::ScalableFont* g_outline_font;
90         extern irr::gui::ScalableFont* g_large_font;
91         extern irr::gui::ScalableFont* g_title_font;
92         extern irr::gui::ScalableFont* g_small_title_font;
93         extern irr::gui::ScalableFont* g_tiny_title_font;
94         extern irr::gui::ScalableFont* g_digit_font;
95 
96         extern irr::IrrlichtDevice* g_device;
97         extern irr::video::IVideoDriver* g_driver;
98         extern Screen* g_current_screen;
99         extern AbstractStateManager* g_state_manager;
100         extern Widget* g_focus_for_player[MAX_PLAYER_COUNT];
101     }
102 
103     /** Widgets that need to be notified at every frame can add themselves there (FIXME: unclean) */
104     extern PtrVector<Widget, REF> needsUpdate;
105 
106     /**
107       * \brief               Call this method to init the GUI engine.
108       * \pre        A irrlicht device and its corresponding video drivers must have been created
109       * \param device        An initialized irrlicht device object
110       * \param driver        An initialized irrlicht driver object
111       * \param state_manager An instance of a class derived from abstract base AbstractStateManager
112       * \param loading if it's (re-)loading the GUIEngine
113       */
114     void init(irr::IrrlichtDevice* device, irr::video::IVideoDriver* driver,
115               AbstractStateManager* state_manager, bool loading = true);
116 
117     void cleanUp();
118 
119     void deallocate();
120 
121     void resetGlobalVariables();
122 
123     /**
124       * \return the irrlicht device object
125       */
getDevice()126     inline irr::IrrlichtDevice*       getDevice()        { return Private::g_device;         }
127 
128     /**
129       * \return the irrlicht GUI environment object
130       */
getGUIEnv()131     inline irr::gui::IGUIEnvironment* getGUIEnv()        { return Private::g_env;            }
132 
133     /**
134       * \return the irrlicht video driver object
135      */
getDriver()136     inline irr::video::IVideoDriver*  getDriver()        { return Private::g_driver;         }
137 
138     /**
139       * \return the smaller font (useful for less important messages)
140       */
getSmallFont()141     inline irr::gui::ScalableFont*    getSmallFont()     { return Private::g_small_font;     }
142 
143     /**
144       * \return the "normal" font (useful for text)
145       */
getFont()146     inline irr::gui::ScalableFont*    getFont()          { return Private::g_font;           }
147 
getOutlineFont()148     inline irr::gui::ScalableFont*    getOutlineFont()   { return Private::g_outline_font;   }
149 
150     /**
151       * \return the "large" font (useful for text)
152       */
getLargeFont()153     inline irr::gui::ScalableFont*    getLargeFont()     { return Private::g_large_font;     }
154 
155     /**
156      * \return the "high-res digits" font (useful for big numbers)
157      */
getHighresDigitFont()158     inline irr::gui::ScalableFont*    getHighresDigitFont() { return Private::g_digit_font;  }
159 
160     /**
161       * \return the "title" font (it's bigger and orange, useful for headers/captions)
162       */
getTitleFont()163     inline irr::gui::ScalableFont*    getTitleFont()     { return Private::g_title_font;     }
164 
165     /**
166       * \return the "small title" font (it's bigger and orange, useful for sub headers/captions)
167       */
getSmallTitleFont()168     inline irr::gui::ScalableFont*    getSmallTitleFont() { return Private::g_small_title_font; }
169 
170     /**
171       * \return the "tiny title" font (it's bigger and orange, useful for sub headers/captions)
172       */
getTinyTitleFont()173     inline irr::gui::ScalableFont*    getTinyTitleFont() { return Private::g_tiny_title_font; }
174 
175     /**
176       * \return the currently shown screen, or NULL if none
177       */
getCurrentScreen()178     inline Screen*                    getCurrentScreen() { return Private::g_current_screen; }
179 
180     /**
181       * \return the state manager being used, as passed to GUIEngine::init
182       */
getStateManager()183     inline AbstractStateManager*      getStateManager()  { return Private::g_state_manager;  }
184 
185     void clearScreenCache();
186 
187     /**
188       * \pre GUIEngine::init must have been called first
189       * \return       the skin object used to render widgets
190       */
getSkin()191     inline Skin*                      getSkin()          { return Private::g_skin;           }
192 
setSkin(Skin * skin)193     inline void                       setSkin(Skin* skin) { Private::g_skin = skin;          }
194     Screen*                           getScreenNamed(const char* name);
195 
196     /** \return the height of the title font in pixels */
197     int   getTitleFontHeight();
198 
199     /** \return the height of the font in pixels */
200     int   getFontHeight();
201 
202     /** \return the height of the small font in pixels */
203     int   getSmallFontHeight();
204 
205     /**
206       * \pre the value returned by this function is only valid when invoked from GUIEngine::render
207       * \return the time delta between the last two frames
208       */
209     float getLatestDt();
210 
211     /**
212       * \brief shows a message at the bottom of the screen for a while
213       * \param message  the message to display
214       * \param time     the time to display the message, in seconds
215       */
216     void showMessage(const irr::core::stringw& message, const float time=5.0f);
217 
218     /** \brief Add a screen to the list of screens known by the gui engine */
219     void  addScreenToList(Screen* screen);
220     /** \brief Remove a screen from the list of screens known by the gui engine */
221     void  removeScreen(Screen* screen);
222 
223     /** \brief Low-level mean to change current screen.
224       * \note Do not use directly. Use a state manager instead to get higher-level functionnality.
225       */
226     void switchToScreen(Screen* screen);
227 
228     /** \brief erases the currently displayed screen, removing all added irrLicht widgets
229       * \note Do not use directly. Use a state manager instead to get higher-level functionnality.
230       */
231     void clear();
232 
233     void update(float dt);
234 
235     /** \brief like GUIEngine::clear, but to be called before going into game */
236     void cleanForGame();
237 
238     /** \brief to be called after e.g. a resolution switch */
239     void reshowCurrentScreen();
240 
241     /**
242       * \brief called on every frame to trigger the rendering of the GUI
243       */
244     void render(float dt, bool is_loading = false);
245 
246     void clearLoadingTips();
247 
248     /** \brief renders a "loading" screen */
249     void renderLoading(bool clearIcons = true, bool launching = false, bool update_tips = true);
250 
251     /** \brief to spice up a bit the loading icon : add icons to the loading screen */
252     void addLoadingIcon(irr::video::ITexture* icon);
253 
254     /** \brief      Finds a widget from its name (PROP_ID) in the current screen/dialog
255       * \param name the name (PROP_ID) of the widget to search for
256       * \return     the widget that bears that name, or NULL if it was not found
257       */
258     Widget* getWidget(const char* name);
259 
260     /** \brief      Finds a widget from its irrlicht widget ID in the current screen/dialog
261       * \param name the irrlicht widget ID (not to be confused with PROP_ID, which is a string)
262       *             of the widget to search for
263       * \return     the widget that bears that irrlicht ID, or NULL if it was not found
264       */
265     Widget* getWidget(const int id);
266 
267     /**
268       * \brief call when skin in user config was updated
269       */
270     void reloadSkin();
271 
272     /**
273       * \brief call when screen size changed
274       */
275     void reloadForNewSize();
276 
277     /**
278       * \brief Add gui-related function before rendering GUI (from other thread)
279       */
280     void addGUIFunctionBeforeRendering(std::function<void()> func);
281 
282 #ifdef SERVER_ONLY
disableGraphics()283     inline void disableGraphics() {}
isNoGraphics()284     constexpr bool isNoGraphics() { return true; }
285 #else
286     void disableGraphics();
287     bool isNoGraphics();
288 #endif
289 }
290 
291 #endif
292