Skip to content
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

Multiple gamepad support #6559

Closed
wn2000 opened this issue Jun 30, 2023 · 4 comments
Closed

Multiple gamepad support #6559

wn2000 opened this issue Jun 30, 2023 · 4 comments

Comments

@wn2000
Copy link

wn2000 commented Jun 30, 2023

Version/Branch of Dear ImGui:

Version: 1.89.6
Branch: master

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_sdl2.cpp
Operating System: Linux

My Issue/Question:

ImGui currently only opens the first game controller, and it opens the controller in each frame without closing it:

SDL_GameController* game_controller = SDL_GameControllerOpen(0);

Although by examining SDL2's code, repeatedly opening a game controller does not cause anything bad except incrementing the ref count on the controller handle each time, this still feels awkward.
On the other hand, adding a Close call at the end of the function is not appropriate either, as that'll cause a joystick initialization and deinitialization each frame.

The bigger issues to the end user are:

  • It only responds to the first controller.

  • If the first controller gets disconnected, the underlying joystick device is still open, so the 2nd controller does not automatically become the first controller and the UI would lose response to game controllers.

I created a patch here to address this issue:
wn2000@bc19596

The reason I did not create a PR is that my solution assumes SDL event is enabled for the controller, which the application can choose not to enable.
So I'm creating this issue for further consideration.

@ocornut
Copy link
Owner

ocornut commented Jun 30, 2023

Hello,

Thanks for the suggestion.

  • I agree that the repeated calls to SDL_GameControllerOpen() seems to be an issue.
  • I am favorable with trying to handle when a gamepad is removed and another added.
  • I am not sure about handling multiple controllers simultaneously (see below).

my solution assumes SDL event is enabled for the controller, which the application can choose not to enable.

Can you clarify this?
I couldn't see a way to enable/disable those events?

adding a Close call at the end of the function is not appropriate either, as that'll cause a joystick initialization and deinitialization each frame.

Couldn't our handler for SDL_CONTROLLERDEVICEADDED/SDL_CONTROLLERDEVICEREMOVED maintain the device to use and we keep only one open, and then poll in ImGui_ImplSDL2_UpdateGamepads() ?

Also note #3884, which suggested to allow multiple controllers to work simultaneously.
They modified MAP_BUTTON() to accumulate into io.NavInputs[] (io.NavInputs[NAV_NO] += VALUE) which I am not entirely sure was without edge-cases/issues. However, this definitively doesn't map well into 1.87+ API of calling AddKeyAnalogEvent(). Hypothetical support for multiple simultaneous gamepads (which I am not yet sure about) should probably use maximum absolute values for each button/axis and then submit to AddKeyAnalogEvent() once.

Similarly, in your situation if multiple gamepads are connected simultaneously I presume they would all keep submitting data for each analog axis, and submitting interleaved data all the time (e.g. gamepad 0 L2 = 10000, gamepad 1 L2 = 0, etc.) would be incorrect and breaks controls.

Assuming the events are always available (but you implied they aren't?) I would be more in favor of using them to maintain the gamepad id to use, ensure only one is open (with logic in ImGui_ImplSDL2_UpdateGamepads() to close/reopen + a final close on Shutdown).

(Once this works well we can apply the same changes to experimental SDL3 backend as well)

@wn2000
Copy link
Author

wn2000 commented Jul 4, 2023

Sorry missed your comment.

my solution assumes SDL event is enabled for the controller, which the application can choose not to enable.

Can you clarify this?
I couldn't see a way to enable/disable those events?

An application can call SDL_GameControllerEventState(SDL_IGNORE) to disable controller events (similarly SDL_JoystickEventState(SDL_IGNORE) disables joystick events).

I agree that processing analog events from multiple controllers needs careful consideration, probably needs a global map to understand the overall scenario and decide what to do.

Couldn't our handler for SDL_CONTROLLERDEVICEADDED/SDL_CONTROLLERDEVICEREMOVED maintain the device to use and we keep only one open, and then poll in ImGui_ImplSDL2_UpdateGamepads() ?

I think the motivation of this issue and also #3884 is that we could grab any connected controller to control the UI, and not having to figure out which one is active.

@ocornut
Copy link
Owner

ocornut commented Feb 13, 2024

Added support for disconnecton/reconnection + support for multiple controllers: bf1c96d + f966da1 + final api 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);

Thanks for the help!

@ocornut ocornut closed this as completed Feb 13, 2024
ocornut added a commit that referenced this issue Feb 14, 2024
ocornut added a commit that referenced this issue Feb 14, 2024
… support for multiple gamepads. Added ImGui_ImplSDL3_SetGamepadMode(). (#7180, #3884, #6559, #6890)
@ocornut
Copy link
Owner

ocornut commented Feb 14, 2024

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 backend has same API too.
Used "Gamepad" in function names to match SDL3 code and make things easier to diff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants