1 //  SuperTuxKart - a fun racing game with go-kart
2 //
3 //  Copyright (C) 2006-2015 SuperTuxKart-Team
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License
7 //  as published by the Free Software Foundation; either version 3
8 //  of the License, or (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18 
19 #ifndef KART_SELECTION_INCLUDED
20 #define KART_SELECTION_INCLUDED
21 
22 #include "guiengine/screen.hpp"
23 #include "guiengine/widgets/dynamic_ribbon_widget.hpp"
24 #include "guiengine/widgets/player_kart_widget.hpp"
25 #include "states_screens/state_manager.hpp"
26 
27 namespace GUIEngine
28 {
29     class Widget;
30     class BubbleWidget;
31     enum EventPropagation;
32 }
33 namespace Online
34 {
35     class User;
36     class OnlineProfile;
37 }
38 
39 class FocusDispatcher;
40 class InputDevice;
41 class PlayerProfile;
42 class KartHoverListener;
43 
44 extern int g_root_id;
45 
46 /**
47   * \brief screen where players can choose their kart
48   * \ingroup states_screens
49   */
50 class KartSelectionScreen : public GUIEngine::Screen
51 {
52     friend class KartHoverListener;
53     friend class PlayerNameSpinner;
54     friend class FocusDispatcher;
55 protected:
56     /** Contains the custom widget shown for every player. (ref only since
57      *  we're adding them to a Screen, and the Screen will take ownership
58      *  of these widgets)
59      */
60     PtrVector<GUIEngine::PlayerKartWidget, REF> m_kart_widgets;
61 
62     friend class GUIEngine::ScreenSingleton<KartSelectionScreen>;
63     friend class GUIEngine::PlayerKartWidget;
64 
65     bool m_multiplayer;
66 
67     /** Whether this screen is being visited from overworld or not */
68     bool m_from_overworld;
69 
70     bool m_go_to_overworld_next;
71 
72     bool m_must_delete_on_back; //!< To delete the screen if back is pressed
73 
74     /** Stores whether any player confirmed their choice; then, some things
75       * are "frozen", for instance the selected kart group tab
76       */
77     bool m_game_master_confirmed;
78 
79     GUIEngine::PlayerKartWidget* m_removed_widget;
80 
81     /** Message shown in multiplayer mode */
82     GUIEngine::BubbleWidget* m_multiplayer_message;
83 
84     FocusDispatcher  *m_dispatcher;
85 
86     KartSelectionScreen(const char* filename);
87 
88     /** Called when all players selected their kart */
89     virtual void allPlayersDone();
90 
91     /** Called when number/order of karts changed, so that all will keep
92      *  an up-to-date ID */
93     void renumberKarts();
94 
95     /** Checks identities chosen by players, making sure no duplicates are
96       * used.
97       * \return Whether all choices are ok
98       */
99     bool validateIdentChoices();
100 
101     /** Checks karts chosen by players, making sure no duplicates are used.
102       * \return Whether all choices are ok
103       */
104     bool validateKartChoices();
105 
106     /** Fill the ribbon with the karts from the currently selected group */
107     void setKartsFromCurrentGroup();
108 
109     void playerConfirm(const int playerID);
110 
111     void updateKartStats(uint8_t widget_id,
112                          const std::string& selection);
113 
114     /** updates model of a kart widget, to have the good selection when the
115      *  user validates */
116     void updateKartWidgetModel(int widget_id,
117                 const std::string& selection,
118                 const irr::core::stringw& selectionText,
119                 float kart_color);
120 
121     /** Adds a message to the screen which indicates that players must press fire to join. */
122     void addMultiplayerMessage();
123 
124     /** Remove the multiplayer message. */
125     void removeMultiplayerMessage();
126 
isIgnored(const std::string & ident) const127     virtual bool isIgnored(const std::string& ident) const { return false; }
128 
129     /** Stores a pointer to the current selection screen */
130     static KartSelectionScreen* m_instance_ptr;
131 private:
132     PtrVector<const KartProperties, REF> getUsableKarts(
133         const std::string& selected_kart_group);
134     bool useContinueButton() const;
135 public:
136     /** Returns the current instance */
137     static KartSelectionScreen* getRunningInstance();
138 
139     /** \brief implement callback from parent class GUIEngine::Screen */
140     virtual void loadedFromFile() OVERRIDE;
141 
142     void setMultiplayer(bool multiplayer);
143 
144     /** \brief Set whether this screen is being visited from overworld or not */
setFromOverworld(bool from_overworld)145     void setFromOverworld(bool from_overworld) { m_from_overworld = from_overworld; }
146 
setGoToOverworldNext()147     void setGoToOverworldNext() { m_go_to_overworld_next = true; }
148 
149     /** \brief Called when a player hits 'fire'/'select' on his device to
150      *  join the game */
151     bool joinPlayer(InputDevice* device, PlayerProfile* p);
152 
153     /**
154       * \brief Called when a player hits 'rescue'/'cancel' on his device
155       *  to leave the game
156       * \return true if event was handled succesfully
157       */
158     virtual bool playerQuit(StateManager::ActivePlayer* player);
159 
160      /** \brief implement callback from parent class GUIEngine::Screen */
161     virtual void init() OVERRIDE;
162 
163     virtual void beforeAddingWidget() OVERRIDE;
164 
165      /** \brief implement callback from parent class GUIEngine::Screen */
166     virtual void tearDown() OVERRIDE;
167 
168     /** \brief implement callback from parent class GUIEngine::Screen */
169     virtual void eventCallback(GUIEngine::Widget* widget, const std::string& name,
170                                const int playerID) OVERRIDE;
171 
172     /** \brief implement callback from parent class GUIEngine::Screen */
173     virtual void onUpdate(float dt) OVERRIDE;
174 
175     /** \brief implement optional callback from parent
176      *  class GUIEngine::Screen */
177     virtual void unloaded() OVERRIDE;
178 
179     /** \brief implement optional callback from parent
180      *  class GUIEngine::Screen */
181     virtual bool onEscapePressed() OVERRIDE;
182 
183 };   // KartSelectionScreen
184 
185 //!----------------------------------------------------------------------------
186 //! FocusDispatcher :
187 /** Currently, navigation for multiple players at the same time is implemented
188     in a somewhat clunky way. An invisible "dispatcher" widget is added above
189     kart icons. When a player moves up, he focuses the dispatcher, which in
190     turn moves the selection to the appropriate spinner. "tabbing roots" are
191     used to make navigation back down possible. (FIXME: maybe find a cleaner
192     way?) */
193 class FocusDispatcher : public GUIEngine::Widget
194 {
195 protected:
196     KartSelectionScreen* m_parent;
197     int m_reserved_id;
198 
199     bool m_is_initialised;
200 
201 public:
202 
203     LEAK_CHECK()
204 
205     // ------------------------------------------------------------------------
206     FocusDispatcher(KartSelectionScreen* parent);
207     // ------------------------------------------------------------------------
208     void setRootID(const int reservedID);
209 
210     // ------------------------------------------------------------------------
211     virtual void add();
212 
213     // ------------------------------------------------------------------------
214 
215     virtual GUIEngine::EventPropagation focused(const int playerID);
216 };   // FocusDispatcher
217 
218 //!----------------------------------------------------------------------------
219 //! KartHoverListener :
220 class KartHoverListener : public GUIEngine::DynamicRibbonHoverListener
221 {
222     KartSelectionScreen* m_parent;
223 public:
224     unsigned int m_magic_number;
225 
226     KartHoverListener(KartSelectionScreen* parent);
227 
228     // ------------------------------------------------------------------------
229     virtual ~KartHoverListener();
230 
231     // ------------------------------------------------------------------------
232     void onSelectionChanged(GUIEngine::DynamicRibbonWidget* theWidget,
233                             const std::string& selectionID,
234                             const irr::core::stringw& selectionText,
235                             const int playerID);
236 };   // KartHoverListener
237 
238 #endif
239 
240