-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
SDL2 backend: Implement multiple gamepad support #3884
SDL2 backend: Implement multiple gamepad support #3884
Conversation
2d4995a
to
b8f9dbc
Compare
Thanks for the PR. Some quick feedback:
Thank you I am not sure this change is desirable for all users but I'm open to try. |
b8f9dbc
to
3a75237
Compare
Thanks for the quick feedback! I believe I've addressed most of your comments now.
Done - I still kept the commit adding So what happened was that I wanted to build the SDL2 example in order to preapre this PR - I had only built ImGui as part of my own project's build system before. But I then got a linker error when running
I then consulted MSDN for the referenced function My suspicion is that earlier versions of SDL (I'm using 2.0.14) did not require this lib, so the build worked fine, but some newer version now needs it. But I need to verify that. Let me know if you'd prefer a separate PR for that change, as it is indeed unrelated to the rest of this PR.
Thanks, added!
Whoops, forgot to remove the old one, fixed now. Thanks!
Both done ✔️
I personally find the one-liners harder to read, but your point that this is unlikely to change frequently makes sense. And it also seems better to keep the code local to To explain how I ended up with these functions: When doing these changes in my project originally, I converted the macros to C++ 11 lambdas so that I would have an easier time understanding the code and making the changes (here's how that looks). Once I decided to upstream the changes, I then converted the lambdas to functions to avoid the need for C++ 11. But the aspect of keeping the code local is unfortunately lost that way.
Done, let me know if that looks ok!
Ah yes, good catch, it can indeed return NULL. I've changed the code to only add it to the list if the return value is non-null. Please let me know if doing this type of combined assignment & check in an if-statement is ok, or if you'd prefer to have the assignment as a separate statement. |
dae475e
to
f8a814e
Compare
Yes I would like us to clarify that, I honestly think it would be surprising if SDL suddenly started requiring shell32 especially for such a a simple version it would usually prefer experimenting. The spacing in the first two functions is also odd. We normally have this specced in the |
f8a814e
to
38d600d
Compare
Yup, I just tested with an older version of SDL, and indeed the linker error does not happen with that one. So it seems my suspicion was correct, but I'll try to track down more precisely in which version that changed and why.. In the meantime, I've removed the commit and also fixed the spacing (I'm using Vim 😄) |
Ok, I managed to track it down in the SDL source. The dependency on |
This makes the SDL2 backend work correctly with multiple gamepads. Instead of hard-coding gamepad index 0, we keep a list of all currently available gamepads. When gamepads are added or removed, we update the list accordingly. When processing gamepad input, we then iterate over this list and combine the button and axis state of all gamepads. Note that it's not necessary to enumerate gamepads during initialization of the backend, because SDL automatically sends a `SDL_CONTROLLERDEVICEADDED` event for every gamepad that was already present during initialization of SDL. The main motivation for this change is that I can have multiple gamepads connected to my system and grab any one of them at random, and have ImGui recognize my inputs. Previously, this was not guaranteed, because the gamepad I grabbed might not have index 0. It's also possible now to (for example) use the D-pad on one gamepad and and buttons on another one at the same time, although that seems less useful in practice :) Additionally, we now properly close all previously opened gamepads when shutting down the backend.
38d600d
to
4473548
Compare
0c1e5bd
to
bb6a60b
Compare
8b83e0a
to
d735066
Compare
b3b85d8
to
0755767
Compare
c817acb
to
8d39063
Compare
I have pushed bf1c96d+f966da1 which:
I am not entirely against an API for multiple-gamepad support but I'm not entirely sure this is what you actually truly needed (vs simply better handling or disconnection/reconnection). |
I reopened as I am going to work those API right now. |
Rework API and added support for multiple controllers: d15e410 IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeAutoFirst(); // Use first available gamepad (default)
IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeAutoAll();
IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadModeManual(struct _SDL_GameController** gamepads_array, int gamepads_count); |
@ocornut nice, that new auto-all mode looks exactly like what I need. Thanks! |
Reworked API it is now: enum ImGui_ImplSDL2_GamepadMode
{
ImGui_ImplSDL2_GamepadMode_AutoFirst,
ImGui_ImplSDL2_GamepadMode_AutoAll,
ImGui_ImplSDL2_GamepadMode_Manual
};
IMGUI_IMPL_API void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array = NULL, int manual_gamepads_count = -1); SDL3 has same API. |
This makes the SDL2 backend work correctly with multiple gamepads. Instead of
hard-coding gamepad index 0, we keep a list of all currently available
gamepads. When gamepads are added or removed, we update the list accordingly.
When processing gamepad input, we then iterate over this list and combine the
button and axis state of all gamepads.
Note that it's not necessary to enumerate gamepads during initialization of the backend, because SDL automatically sends a
SDL_CONTROLLERDEVICEADDED
event for every gamepad that was already present during initialization of SDL.The main motivation for this change is that I can have multiple gamepads
connected to my system and grab any one of them at random, and have ImGui
recognize my inputs. Previously, this was not guaranteed, because the gamepad I
grabbed might not have index 0. It's also possible now to (for example) use the
D-pad on one gamepad and buttons on another one at the same time, although
that seems less useful in practice :)
Additionally, we now properly close all previously opened gamepads when
shutting down the backend.