From 8b50844a34658faed8dd29988fb7e30d0fc01578 Mon Sep 17 00:00:00 2001 From: mchughalex <25671999+mchughalex@users.noreply.github.com> Date: Tue, 21 Jul 2026 10:10:56 +0100 Subject: [PATCH] ui: controller input backend row in the settings menu --- .../rex/ui/overlay/simple_settings_overlay.h | 1 + src/ui/overlay/simple_settings_overlay.cpp | 45 ++++++++++++++++++- 2 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/rex/ui/overlay/simple_settings_overlay.h b/include/rex/ui/overlay/simple_settings_overlay.h index ccf20e7..e4d1c0c 100644 --- a/include/rex/ui/overlay/simple_settings_overlay.h +++ b/include/rex/ui/overlay/simple_settings_overlay.h @@ -130,6 +130,7 @@ class SimpleSettingsDialog final : public ImGuiDialog { bool rumble_ = true; float mnk_sensitivity_ = 1.0f; int chord_index_ = 0; + int input_backend_index_ = 0; std::string chord_custom_; // Navigation state. diff --git a/src/ui/overlay/simple_settings_overlay.cpp b/src/ui/overlay/simple_settings_overlay.cpp index f2c93b4..2b85be7 100644 --- a/src/ui/overlay/simple_settings_overlay.cpp +++ b/src/ui/overlay/simple_settings_overlay.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -53,7 +54,7 @@ constexpr std::array kCoreSimpleSettingsCvars = { // Optional cvars persisted when the host defines them (HasCvar-gated: app // cvars like the native-renderer knobs don't exist in every embedder, and // backend/platform cvars don't exist in every build). -constexpr std::array kOptionalSimpleSettingsCvars = { +constexpr std::array kOptionalSimpleSettingsCvars = { "skate3_native_render_scene", "skate3_native_render_scene_msaa", "skate3_native_render_scene_shadows", @@ -74,6 +75,7 @@ constexpr std::array kOptionalSimpleSettingsCvars = { "mnk_sensitivity", "hid_rumble_enabled", "menu_chord", + "input_backend", "audio_mute", "audio_device_sample_frames", "user_language"}; @@ -576,6 +578,21 @@ void SetBoolCvar(std::string_view name, bool value) { rex::cvar::SetFlagByName(name, value ? "true" : "false"); } +// The Controller Backend row is Windows-only: every other platform always +// runs the SDL input driver, so there is nothing to choose. +bool HasInputBackendChoice() { +#if REX_PLATFORM_WIN32 + return HasCvar("input_backend"); +#else + return false; +#endif +} + +// 0 = XInput, 1 = SDL. +int InputBackendIndexFromCvar() { + return rex::cvar::Query("input_backend") == "sdl" ? 1 : 0; +} + // The Graphics API row only exists on builds with both backends compiled in; // each backend's UI provider registers its device cvar, so their joint // presence identifies such a build. @@ -1040,6 +1057,7 @@ void SimpleSettingsDialog::LoadSettingsFromCvars() { : 1.0f; chord_custom_.clear(); chord_index_ = HasCvar("menu_chord") ? MenuChordIndexFromCvar(&chord_custom_) : 0; + input_backend_index_ = HasInputBackendChoice() ? InputBackendIndexFromCvar() : 0; } bool SimpleSettingsDialog::HasSettingsChanges() const { @@ -1822,9 +1840,32 @@ void SimpleSettingsDialog::BuildRows(std::vector& rows, int category) { }; rows.push_back(std::move(row)); } - if (HasCvar("hid_rumble_enabled") || HasCvar("menu_chord")) { + if (HasInputBackendChoice() || HasCvar("hid_rumble_enabled") || HasCvar("menu_chord")) { header("Controller"); } + if (HasInputBackendChoice()) { + RowSpec row; + row.kind = RowSpec::kEnum; + row.label = "Controller Backend"; + row.desc = + "Which API reads controllers. XInput supports Xbox controllers; " + "SDL also supports PlayStation, Switch and most generic " + "controllers without extra software. Applies after restarting " + "the game."; + row.value_note = "Restart to apply"; + row.options = {"XInput", "SDL"}; + row.index = &input_backend_index_; + row.on_enum_change = [this](int value) { + rex::cvar::SetFlagByName("input_backend", value == 1 ? "sdl" : "xinput"); + SaveSimpleSettingsConfig(config_path_); + }; + row.reset = [this] { + input_backend_index_ = 0; + rex::cvar::SetFlagByName("input_backend", "xinput"); + SaveSimpleSettingsConfig(config_path_); + }; + rows.push_back(std::move(row)); + } if (HasCvar("hid_rumble_enabled")) { RowSpec row; row.kind = RowSpec::kEnum;