From 262e30e300197b499a102b450984217fb494fc4f Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 14 Feb 2024 11:30:43 +0100 Subject: [PATCH] Backends: SDL2: rework new API as ImGui_ImplSDL2_SetGamepadMode(). (#3884, #6559, #6890, #7180) Code is simpler this way. --- backends/imgui_impl_sdl2.cpp | 48 ++++++++++++------------------------ backends/imgui_impl_sdl2.h | 7 +++--- docs/CHANGELOG.txt | 2 +- 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index ecd8f9426..7abeb0e89 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -21,7 +21,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) -// 2024-02-13: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadModeAutoFirst(), ImGui_ImplSDL2_SetGamepadModeAutoAll(), ImGui_ImplSDL2_SetGamepadModeManual(). +// 2024-02-14: Inputs: Handle gamepad disconnection. Added ImGui_ImplSDL2_SetGamepadMode(). // 2023-10-05: Inputs: Added support for extra ImGuiKey values: F13 to F24 function keys, app back/forward keys. // 2023-04-06: Inputs: Avoid calling SDL_StartTextInput()/SDL_StopTextInput() as they don't only pertain to IME. It's unclear exactly what their relation is to IME. (#6306) // 2023-04-04: Inputs: Added support for io.AddMouseSourceEvent() to discriminate ImGuiMouseSource_Mouse/ImGuiMouseSource_TouchScreen. (#2702) @@ -102,13 +102,6 @@ #define SDL_HAS_VULKAN SDL_VERSION_ATLEAST(2,0,6) // SDL Data -enum ImGui_ImplSDL2_GamepadMode -{ - ImGui_ImplSDL2_GamepadMode_AutoFirst, // (Default) Use first available gamepad - ImGui_ImplSDL2_GamepadMode_AutoAll, // Use all available gamepad - ImGui_ImplSDL2_GamepadMode_Manual, -}; - struct ImGui_ImplSDL2_Data { SDL_Window* Window; @@ -612,29 +605,22 @@ static void ImGui_ImplSDL2_CloseGamepads() bd->Gamepads.resize(0); } -void ImGui_ImplSDL2_SetGamepadModeAutoFirst() +void ImGui_ImplSDL2_SetGamepadMode(ImGui_ImplSDL2_GamepadMode mode, struct _SDL_GameController** manual_gamepads_array, int manual_gamepads_count) { ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); ImGui_ImplSDL2_CloseGamepads(); - bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoFirst; - bd->WantUpdateGamepadsList = true; -} - -void ImGui_ImplSDL2_SetGamepadModeAutoAll() -{ - ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - ImGui_ImplSDL2_CloseGamepads(); - bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_AutoAll; - bd->WantUpdateGamepadsList = true; -} - -void ImGui_ImplSDL2_SetGamepadModeManual(struct _SDL_GameController** gamepads_array, int gamepads_count) -{ - ImGui_ImplSDL2_Data* bd = ImGui_ImplSDL2_GetBackendData(); - ImGui_ImplSDL2_CloseGamepads(); - for (int n = 0; n < gamepads_count; n++) - bd->Gamepads.push_back(gamepads_array[n]); - bd->GamepadMode = ImGui_ImplSDL2_GamepadMode_Manual; + if (mode == ImGui_ImplSDL2_GamepadMode_Manual) + { + IM_ASSERT(manual_gamepads_array != nullptr && manual_gamepads_count > 0); + for (int n = 0; n < manual_gamepads_count; n++) + bd->Gamepads.push_back(manual_gamepads_array[n]); + } + else + { + IM_ASSERT(manual_gamepads_array == nullptr && manual_gamepads_count <= 0); + bd->WantUpdateGamepadsList = true; + } + bd->GamepadMode = mode; } static void ImGui_ImplSDL2_UpdateGamepadButton(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerButton button_no) @@ -645,13 +631,13 @@ static void ImGui_ImplSDL2_UpdateGamepadButton(ImGui_ImplSDL2_Data* bd, ImGuiIO& io.AddKeyEvent(key, merged_value); } +static inline float Saturate(float v) { return v < 0.0f ? 0.0f : v > 1.0f ? 1.0f : v; } static void ImGui_ImplSDL2_UpdateGamepadAnalog(ImGui_ImplSDL2_Data* bd, ImGuiIO& io, ImGuiKey key, SDL_GameControllerAxis axis_no, float v0, float v1) { float merged_value = 0.0f; for (SDL_GameController* gamepad : bd->Gamepads) { - float vn = (float)(SDL_GameControllerGetAxis(gamepad, axis_no) - v0) / (float)(v1 - v0); - vn = (vn < 0.0f) ? 0.0f : (vn > 1.0f) ? 1.0f : vn; + float vn = Saturate((float)(SDL_GameControllerGetAxis(gamepad, axis_no) - v0) / (float)(v1 - v0)); if (merged_value < vn) merged_value = vn; } @@ -682,8 +668,6 @@ static void ImGui_ImplSDL2_UpdateGamepads() // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) return; - - // Get gamepad io.BackendFlags &= ~ImGuiBackendFlags_HasGamepad; if (bd->Gamepads.Size == 0) return; diff --git a/backends/imgui_impl_sdl2.h b/backends/imgui_impl_sdl2.h index 1d8d6e28c..d330da281 100644 --- a/backends/imgui_impl_sdl2.h +++ b/backends/imgui_impl_sdl2.h @@ -37,11 +37,10 @@ IMGUI_IMPL_API void ImGui_ImplSDL2_Shutdown(); IMGUI_IMPL_API void ImGui_ImplSDL2_NewFrame(); IMGUI_IMPL_API bool ImGui_ImplSDL2_ProcessEvent(const SDL_Event* event); -// Gamepad selection automatically starts in Auto mode, picking first available SDL_GameController. You may override this. +// Gamepad selection automatically starts in AutoFirst mode, picking first available SDL_Gamepad. You may override this. // When using manual mode, caller is responsible for opening/closing gamepad. -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); +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); #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS static inline void ImGui_ImplSDL2_NewFrame(SDL_Window*) { ImGui_ImplSDL2_NewFrame(); } // 1.84: removed unnecessary parameter diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 915d02d08..861ab7b28 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -52,7 +52,7 @@ Other changes: a scrollbar when contents is over parent viewport size. (#7287, #7063) [@ZingBallyhoo] - Backends: SDL2: Handle gamepad disconnection + fixed increasing gamepad reference counter continuously. Added support for multiple simultaneous gamepads. - Added ImGui_ImplSDL2_SetGamepadModeXXX() functions to select whether to automatically pick + Added ImGui_ImplSDL2_SetGamepadMode()) function to select whether to automatically pick first available gamepad, all gamepads, or specific gamepads. (#3884, #6559, #6890) [@ocornut, @lethal-guitar, @wn2000, @bog-dan-ro] - Backends: SDLRenderer3: query newly added SDL_RenderViewportSet() to not restore