19
19
#include < algorithm>
20
20
21
21
#include " control/input_manager.hpp"
22
+ #include " object/player.hpp"
23
+ #include " supertux/gameconfig.hpp"
24
+ #include " supertux/globals.hpp"
25
+ #include " supertux/game_session.hpp"
26
+ #include " supertux/savegame.hpp"
27
+ #include " supertux/sector.hpp"
22
28
#include " util/log.hpp"
23
29
24
30
GameControllerManager::GameControllerManager (InputManager* parent) :
@@ -34,15 +40,26 @@ GameControllerManager::~GameControllerManager()
34
40
{
35
41
for (const auto & con : m_game_controllers)
36
42
{
37
- SDL_GameControllerClose (con);
43
+ SDL_GameControllerClose (con. first );
38
44
}
39
45
}
40
46
41
47
void
42
48
GameControllerManager::process_button_event (const SDL_ControllerButtonEvent& ev)
43
49
{
50
+ int player_id;
51
+
52
+ {
53
+ auto it = m_game_controllers.find (SDL_GameControllerFromInstanceID (ev.which ));
54
+
55
+ if (it == m_game_controllers.end () || it->second < 0 )
56
+ return ;
57
+
58
+ player_id = it->second ;
59
+ }
60
+
44
61
// log_info << "button event: " << static_cast<int>(ev.button) << " " << static_cast<int>(ev.state) << std::endl;
45
- Controller& controller = m_parent->get_controller ();
62
+ Controller& controller = m_parent->get_controller (player_id );
46
63
auto set_control = [this , &controller](Control control, Uint8 value)
47
64
{
48
65
m_button_state[static_cast <int >(control)] = (value != 0 );
@@ -116,11 +133,22 @@ GameControllerManager::process_button_event(const SDL_ControllerButtonEvent& ev)
116
133
void
117
134
GameControllerManager::process_axis_event (const SDL_ControllerAxisEvent& ev)
118
135
{
136
+ int player_id;
137
+
138
+ {
139
+ auto it = m_game_controllers.find (SDL_GameControllerFromInstanceID (ev.which ));
140
+
141
+ if (it == m_game_controllers.end () || it->second < 0 )
142
+ return ;
143
+
144
+ player_id = it->second ;
145
+ }
146
+
119
147
// FIXME: buttons and axis are fighting for control ownership, need
120
148
// to OR the values together
121
149
122
150
// log_info << "axis event: " << static_cast<int>(ev.axis) << " " << ev.value << std::endl;
123
- Controller& controller = m_parent->get_controller ();
151
+ Controller& controller = m_parent->get_controller (player_id );
124
152
auto set_control = [this , &controller](Control control, bool value)
125
153
{
126
154
m_stick_state[static_cast <int >(control)] = value;
@@ -192,27 +220,146 @@ GameControllerManager::on_controller_added(int joystick_index)
192
220
}
193
221
else
194
222
{
195
- m_game_controllers.push_back (game_controller);
223
+ m_game_controllers[game_controller] = -1 ;
224
+
225
+ if (m_parent->m_use_game_controller && g_config->multiplayer_auto_manage_players )
226
+ {
227
+ int id = m_parent->get_num_users ();
228
+ for (int i = 0 ; i < m_parent->get_num_users (); i++)
229
+ {
230
+ if (!m_parent->has_corresponsing_controller (i) && !m_parent->m_uses_keyboard [i])
231
+ {
232
+ id = i;
233
+ break ;
234
+ }
235
+ }
236
+
237
+ if (id == m_parent->get_num_users ())
238
+ m_parent->push_user ();
239
+
240
+ m_game_controllers[game_controller] = id;
241
+
242
+ if (GameSession::current () && !GameSession::current ()->get_savegame ().is_title_screen () && id != 0 )
243
+ {
244
+ auto & sector = GameSession::current ()->get_current_sector ();
245
+ auto & player_status = GameSession::current ()->get_savegame ().get_player_status ();
246
+
247
+ if (player_status.m_num_players <= id)
248
+ player_status.add_player ();
249
+
250
+ // ID = 0 is impossible, so no need to write `(id == 0) ? "" : ...`
251
+ auto & player = sector.add <Player>(player_status, " Tux" + std::to_string (id + 1 ), id);
252
+
253
+ player.multiplayer_prepare_spawn ();
254
+ }
255
+ }
196
256
}
197
257
}
198
258
}
199
259
200
260
void
201
261
GameControllerManager::on_controller_removed (int instance_id)
202
262
{
203
- for (auto & controller : m_game_controllers)
263
+ std::vector<SDL_GameController*> erase_us;
264
+
265
+ auto it = std::find_if (m_game_controllers.begin (), m_game_controllers.end (), [instance_id] (decltype (m_game_controllers)::const_reference pair) {
266
+ return SDL_JoystickInstanceID (SDL_GameControllerGetJoystick (pair.first )) == instance_id;
267
+ });
268
+
269
+ if (it != m_game_controllers.end ())
204
270
{
205
- auto joy = SDL_GameControllerGetJoystick (controller);
206
- SDL_JoystickID id = SDL_JoystickInstanceID (joy);
207
- if (id == instance_id)
271
+ SDL_GameControllerClose (it->first );
272
+
273
+ auto deleted_player_id = it->second ;
274
+
275
+ m_game_controllers.erase (it);
276
+
277
+ if (m_parent->m_use_game_controller && g_config->multiplayer_auto_manage_players
278
+ && deleted_player_id != 0 && !m_parent->m_uses_keyboard [deleted_player_id])
208
279
{
209
- SDL_GameControllerClose (controller);
210
- controller = nullptr ;
280
+ // Sectors in worldmaps have no Player's of that class
281
+ if (Sector::current () && Sector::current ()->get_object_count <Player>() > 0 )
282
+ {
283
+ auto players = Sector::current ()->get_objects_by_type <Player>();
284
+ auto it_players = players.begin ();
285
+
286
+ while (it_players != players.end ())
287
+ {
288
+ if (it_players->get_id () == deleted_player_id)
289
+ it_players->remove_me ();
290
+
291
+ it_players++;
292
+ }
293
+ }
211
294
}
212
295
}
296
+ else
297
+ {
298
+ log_debug << " Controller was unplugged but was not initially detected: "
299
+ << SDL_JoystickName (SDL_JoystickFromInstanceID (instance_id))
300
+ << std::endl;
301
+ }
302
+ }
303
+
304
+ void
305
+ GameControllerManager::on_player_removed (int player_id)
306
+ {
307
+ auto it2 = std::find_if (m_game_controllers.begin (), m_game_controllers.end (), [player_id](decltype (m_game_controllers)::const_reference pair) {
308
+ return pair.second == player_id;
309
+ });
310
+ if (it2 != m_game_controllers.end ())
311
+ {
312
+ it2->second = -1 ;
313
+ // Try again, in case multiple controllers were bount to a player
314
+ // Recursive call shouldn't go too deep except in hardcore scenarios
315
+ on_player_removed (player_id);
316
+ }
317
+ }
318
+
319
+ bool
320
+ GameControllerManager::has_corresponding_game_controller (int player_id) const
321
+ {
322
+ return std::find_if (m_game_controllers.begin (), m_game_controllers.end (), [player_id](decltype (m_game_controllers)::const_reference pair) {
323
+ return pair.second == player_id;
324
+ }) != m_game_controllers.end ();
325
+ }
326
+
327
+ int
328
+ GameControllerManager::rumble (SDL_GameController* controller) const
329
+ {
330
+ #if SDL_VERSION_ATLEAST(2, 0, 9)
331
+ if (g_config->multiplayer_buzz_controllers )
332
+ {
333
+ #if SDL_VERSION_ATLEAST(2, 0, 18)
334
+ if (SDL_GameControllerHasRumble (controller))
335
+ {
336
+ #endif
337
+ // TODO: Rumble intensity setting (like volume)
338
+ SDL_GameControllerRumble (controller, 0xFFFF , 0xFFFF , 300 );
339
+ #if SDL_VERSION_ATLEAST(2, 0, 18)
340
+ }
341
+ else
342
+ {
343
+ return 1 ;
344
+ }
345
+ #endif
346
+ }
347
+
348
+ return 0 ;
349
+ #else
350
+ return 2 ;
351
+ #endif
352
+ }
353
+
354
+ void
355
+ GameControllerManager::bind_controller (SDL_GameController* controller, int player_id)
356
+ {
357
+ m_game_controllers[controller] = player_id;
213
358
214
- m_game_controllers.erase (std::remove (m_game_controllers.begin (), m_game_controllers.end (), nullptr ),
215
- m_game_controllers.end ());
359
+ if (!g_config->multiplayer_multibind )
360
+ for (auto & pair2 : m_game_controllers)
361
+ if (pair2.second == player_id && pair2.first != controller)
362
+ pair2.second = -1 ;
216
363
}
217
364
218
365
/* EOF */
0 commit comments