1 //  SuperTuxKart - a fun racing game with go-kart
2 //  Copyright (C) 2009-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 STATE_MANAGER_HPP
20 #define STATE_MANAGER_HPP
21 
22 /**
23   * \defgroup states_screens
24   * Contains the various screens and dialogs of the STK user interface,
25   * using the facilities of the guiengine module.
26   */
27 
28 #include <string>
29 
30 #include "config/player_profile.hpp"
31 #include "guiengine/abstract_state_manager.hpp"
32 #include "utils/ptr_vector.hpp"
33 
34 class AbstractKart;
35 class InputDevice;
36 struct Input;
37 namespace Online
38 {
39     class OnlineProfile;
40 }
41 
42 namespace GUIEngine
43 {
44     class Widget;
45 }
46 
47 /**
48   * \brief the player ID of the "game master" player
49   * the game master is the player that can perform the game setup
50   * \ingroup states_screens
51   */
52 const static int PLAYER_ID_GAME_MASTER = 0;
53 
54 /**
55   * \brief A concrete scene manager, derived from GUIEngine's
56   * AbastractSceneManager
57   * \ingroup states_screens
58   */
59 class StateManager : public GUIEngine::AbstractStateManager
60 {
61 
62     void updateActivePlayerIDs();
63 
64 
65 public:
66 
67     /**
68       * Represents a player that is currently playing.
69       * Ties together :
70       *   - a player's identity (and thus his/her highscores)
71       *   - which input device is used by which player
72       *  (we're very flexible on this; ActivePlayer #1
73       *   can choose to e.g. use profile #5 and device #2)
74       */
75     class ActivePlayer
76     {
77         friend class StateManager;
78 
79         PlayerProfile *m_player;
80         InputDevice   *m_device;
81 
82         /** Pointer to the kart of this player, only valid during the game. */
83         AbstractKart  *m_kart;
84 
85         /** ID of this player within the list of active players */
86         int m_id;
87 
88         ActivePlayer(PlayerProfile* player, InputDevice* device);
89 
90 #ifdef DEBUG
91         unsigned int m_magic_number;
92 #endif
93 
94     public:
95 
96         ~ActivePlayer();
97 
98 #ifdef DEBUG
ok()99         bool ok()
100         {
101             return (m_magic_number == 0xAC1EF1AE);
102         }   // ok
103 #endif
104         // --------------------------------------------------------------------
105         /** \return the identity of this active player */
getProfile()106         PlayerProfile* getProfile()
107         {
108 #ifdef DEBUG
109             assert(m_magic_number == 0xAC1EF1AE);
110 #endif
111             return m_player;
112         }   // getProfile
113 
114         // --------------------------------------------------------------------
115         /** \return the identity of this active player */
getConstProfile() const116         const PlayerProfile* getConstProfile() const
117         {
118 #ifdef DEBUG
119             assert(m_magic_number == 0xAC1EF1AE);
120 #endif
121             return m_player;
122         }   // getConstProfile
123 
124         // --------------------------------------------------------------------
125         /** Call to change the identity of this player (useful when player is
126          *  selecting his identity) */
127         void setPlayerProfile(PlayerProfile* player);
128 
129         // --------------------------------------------------------------------
130         /** ID of this player within the list of active players */
getID() const131         int getID() const
132         {
133 #ifdef DEBUG
134             assert(m_magic_number == 0xAC1EF1AE);
135 #endif
136             return m_id;
137         }   // getID
138         // --------------------------------------------------------------------
139 
140         /** \return Which input device this player is using, or NULL if none
141          *  is set yet */
getDevice() const142         InputDevice* getDevice() const
143         {
144 #ifdef DEBUG
145             assert(m_magic_number == 0xAC1EF1AE);
146 #endif
147             return m_device;
148         }   // getDevice
149 
150         // --------------------------------------------------------------------
151         void setDevice(InputDevice* device);
152 
153         // --------------------------------------------------------------------
154         /** Sets the kart for this player. */
setKart(AbstractKart * kart)155         void setKart(AbstractKart *kart)
156         {
157 #ifdef DEBUG
158             assert(m_magic_number == 0xAC1EF1AE);
159 #endif
160             m_kart = kart;
161         }   // setKart
162 
163         // --------------------------------------------------------------------
164         /** \return the kart of this player. Only valid while world exists. */
getKart()165         AbstractKart* getKart()
166         {
167 #ifdef DEBUG
168             assert(m_magic_number == 0xAC1EF1AE);
169 #endif
170             return m_kart;
171         }   // getKart
172 
173     };   // ActivePlayer
174 
175     // ========================================================================
getActivePlayers()176     const PtrVector<ActivePlayer, HOLD>& getActivePlayers()
177                                  { return m_active_players; }
178     ActivePlayer* getActivePlayer(const int id);
179 
180     /** \return    the PlayerProfile of a given ActivePlayer.
181       * \param id  the ID of the active player for whichyou want the profile
182       */
183     const PlayerProfile* getActivePlayerProfile(const int id);
184 
185     int createActivePlayer(PlayerProfile *profile, InputDevice *device);
186     void removeActivePlayer(int id);
187 
188     unsigned int activePlayerCount();
189     void resetActivePlayers();
190 
191     /** \return whether to reduce FPS at the moment
192       * \note   this can be useful to avoid being too CPU/GPU intensive in
193       *         parts of the game that don't require high framerates, like
194       *         menus
195       */
196     bool throttleFPS();
197 
198     /** \brief implementing callback from base class AbstractStateManager */
199     void escapePressed();
200 
201     /** \brief implementing callback from base class AbstractStateManager */
202     virtual void onGameStateChange(GUIEngine::GameState new_state);
203 
204     /** \brief implementing callback from base class AbstractStateManager */
205     virtual void onStackEmptied();
206 
207     /** \brief implementing callback from base class AbstractStateManager */
208     virtual void onTopMostScreenChanged();
209 
210     // singleton
211     static StateManager* get();
212     static void deallocate();
213     static void clear();
clearMenuStack()214     void clearMenuStack() { m_menu_stack.clear(); }
215 private:
216     /**
217      * A list of all currently playing players.
218      */
219     PtrVector<ActivePlayer, HOLD> m_active_players;
220 };
221 
222 #endif
223