From b677255a1be27d3f361463542ff0f5bb12a7e7c3 Mon Sep 17 00:00:00 2001 From: rainmakerv3 <30595646+rainmakerv3@users.noreply.github.com> Date: Sat, 28 Jun 2025 17:36:55 +0800 Subject: [PATCH 1/6] initial commit - not cleanup yet, not usable with imGUI --- src/common/config.cpp | 11 + src/common/config.h | 2 + src/imgui/renderer/imgui_impl_sdl3.cpp | 4 +- src/qt_gui/control_settings.cpp | 171 +++++++-- src/qt_gui/control_settings.h | 11 +- src/qt_gui/control_settings.ui | 478 ++++++++++++++----------- src/sdl_window.cpp | 54 ++- src/sdl_window.h | 1 + 8 files changed, 487 insertions(+), 245 deletions(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index 9c316949a..dd4f72221 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -73,6 +73,7 @@ static bool compatibilityData = false; static bool checkCompatibilityOnStartup = false; static std::string trophyKey; static bool isPSNSignedIn = false; +static std::string defaultControllerID = ""; // Gui static bool load_game_size = true; @@ -528,6 +529,14 @@ void setPSNSignedIn(bool sign) { isPSNSignedIn = sign; } +std::string getDefaultControllerID() { + return defaultControllerID; +} + +void setDefaultControllerID(std::string id) { + defaultControllerID = id; +} + void load(const std::filesystem::path& path) { // If the configuration file does not exist, create it and return std::error_code error; @@ -566,6 +575,7 @@ void load(const std::filesystem::path& path) { checkCompatibilityOnStartup = toml::find_or(general, "checkCompatibilityOnStartup", false); chooseHomeTab = toml::find_or(general, "chooseHomeTab", "Release"); + defaultControllerID = toml::find_or(general, "defaultControllerID", ""); } if (data.contains("Input")) { @@ -725,6 +735,7 @@ void save(const std::filesystem::path& path) { data["General"]["sideTrophy"] = isSideTrophy; data["General"]["compatibilityEnabled"] = compatibilityData; data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup; + data["General"]["defaultControllerID"] = defaultControllerID; data["Input"]["cursorState"] = cursorState; data["Input"]["cursorHideTimeout"] = cursorHideTimeout; data["Input"]["useSpecialPad"] = useSpecialPad; diff --git a/src/common/config.h b/src/common/config.h index 38114983f..624a3a51f 100644 --- a/src/common/config.h +++ b/src/common/config.h @@ -93,6 +93,8 @@ bool isDevKitConsole(); // no set bool vkValidationGpuEnabled(); // no set bool getIsMotionControlsEnabled(); void setIsMotionControlsEnabled(bool use); +std::string getDefaultControllerID(); +void setDefaultControllerID(std::string id); // TODO bool GetLoadGameSizeEnabled(); diff --git a/src/imgui/renderer/imgui_impl_sdl3.cpp b/src/imgui/renderer/imgui_impl_sdl3.cpp index ccd31d03a..bd0c1a5db 100644 --- a/src/imgui/renderer/imgui_impl_sdl3.cpp +++ b/src/imgui/renderer/imgui_impl_sdl3.cpp @@ -730,6 +730,7 @@ static void UpdateGamepads() { ImGuiIO& io = ImGui::GetIO(); SdlData* bd = GetBackendData(); + /* // Update list of gamepads to use if (bd->want_update_gamepads_list && bd->gamepad_mode != ImGui_ImplSDL3_GamepadMode_Manual) { CloseGamepads(); @@ -741,8 +742,9 @@ static void UpdateGamepads() { if (bd->gamepad_mode == ImGui_ImplSDL3_GamepadMode_AutoFirst) break; } - bd->want_update_gamepads_list = false; + bd->want_update_gamepads_list = false; } + */ // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) diff --git a/src/qt_gui/control_settings.cpp b/src/qt_gui/control_settings.cpp index 319daecdd..15f4d4b95 100644 --- a/src/qt_gui/control_settings.cpp +++ b/src/qt_gui/control_settings.cpp @@ -9,8 +9,12 @@ #include "common/path_util.h" #include "control_settings.h" #include "input/input_handler.h" +#include "sdl_window.h" #include "ui_control_settings.h" +std::string ControllerSelect::ActiveGamepad = ""; +std::string ControllerSelect::DefaultGamepad = ""; + ControlSettings::ControlSettings(std::shared_ptr game_info_get, bool isGameRunning, std::string GameRunningSerial, QWidget* parent) : QDialog(parent), m_game_info(game_info_get), GameRunning(isGameRunning), @@ -21,7 +25,6 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b if (!GameRunning) { SDL_InitSubSystem(SDL_INIT_GAMEPAD); SDL_InitSubSystem(SDL_INIT_EVENTS); - CheckGamePad(); } else { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); } @@ -29,6 +32,8 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b AddBoxItems(); SetUIValuestoMappings(); UpdateLightbarColor(); + CheckGamePad(); + ResetActiveControllerBox(); installEventFilter(this); ButtonsList = {ui->CrossButton, @@ -119,6 +124,18 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b connect(this, &ControlSettings::AxisChanged, this, [this]() { ConnectAxisInputs(MappingButton); }); + connect(ui->ActiveGamepadBox, &QComboBox::currentIndexChanged, this, + &ControlSettings::ActiveControllerChanged); + connect(ui->DefaultGamepadButton, &QPushButton::clicked, this, [this]() { + char pszGUID[33]; + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[ui->ActiveGamepadBox->currentIndex()]), + pszGUID, 33); + Config::setDefaultControllerID(std::string(pszGUID)); + Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); + QMessageBox::information(this, tr("Default Controller Selected"), + tr("Active controller set as default")); + }); + RemapWrapper = SdlEventWrapper::Wrapper::GetInstance(); SdlEventWrapper::Wrapper::wrapperActive = true; QObject::connect(RemapWrapper, &SdlEventWrapper::Wrapper::SDLEvent, this, @@ -129,6 +146,99 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b } } +void ControlSettings::ActiveControllerChanged(int value) { + char pszGUID[33]; + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[value]), pszGUID, 33); + QString GUID = QString::fromStdString(std::string(pszGUID)).right(16); + ui->ActiveGamepadLabel->setText("ID: " + GUID); + ControllerSelect::ActiveGamepad = std::string(pszGUID); + + if (!GameRunning) { + if (gamepad) { + SDL_CloseGamepad(gamepad); + gamepad = nullptr; + } + + gamepads = SDL_GetGamepads(&gamepad_count); + if (!gamepads) { + LOG_ERROR(Input, "Cannot get gamepad list: {}", SDL_GetError()); + return; + } + + for (int i = 0; i < gamepad_count; i++) { + char pszGUID[33]; + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + std::string currentGUID = std::string(pszGUID); + if (currentGUID == ControllerSelect::ActiveGamepad) { + gamepad = SDL_OpenGamepad(gamepads[i]); + LOG_WARNING(Input, "Opened gamepad: {}", i); + if (!gamepad) { + LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError()); + } + break; + } + } + + if (!gamepad) { + LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError()); + return; + } + } +} + +void ControlSettings::ResetActiveControllerBox() { + SDL_free(gamepads); + gamepads = SDL_GetGamepads(&gamepad_count); + if (!gamepads) { + LOG_ERROR(Input, "Cannot get gamepad list: {}", SDL_GetError()); + return; + } + + if (gamepad_count == 0) { + ui->ActiveGamepadBox->addItem("No gamepads detected"); + ui->ActiveGamepadBox->setCurrentIndex(0); + LOG_INFO(Input, "No gamepad found!"); + return; + } else { + for (int i = 0; i < gamepad_count; i++) { + QString name = SDL_GetGamepadNameForID(gamepads[i]); + ui->ActiveGamepadBox->addItem(QString("%1: %2").arg(QString::number(i + 1), name)); + } + } + + char pszGUID[33]; + if (ControllerSelect::ActiveGamepad != "") { + for (int i = 0; i < gamepad_count; i++) { + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + std::string currentGUID = std::string(pszGUID); + if (currentGUID == ControllerSelect::ActiveGamepad) { + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + QString GUID = QString::fromStdString(std::string(pszGUID)).right(16); + ui->ActiveGamepadLabel->setText("ID: " + GUID); + ui->ActiveGamepadBox->setCurrentIndex(i); + break; + } + } + } else if (Config::getDefaultControllerID() != "") { + for (int i = 0; i < gamepad_count; i++) { + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + std::string currentGUID = std::string(pszGUID); + if (currentGUID == Config::getDefaultControllerID()) { + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + QString GUID = QString::fromStdString(std::string(pszGUID)).right(16); + ui->ActiveGamepadLabel->setText("ID: " + GUID); + ui->ActiveGamepadBox->setCurrentIndex(i); + break; + } + } + } else { + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[0]), pszGUID, 33); + QString GUID = QString::fromStdString(std::string(pszGUID)).right(16); + ui->ActiveGamepadLabel->setText("ID: " + GUID); + ui->ActiveGamepadBox->setCurrentIndex(0); + } +} + void ControlSettings::SaveControllerConfig(bool CloseOnSave) { QList list; list << ui->RStickUpButton << ui->RStickRightButton << ui->LStickUpButton @@ -640,38 +750,42 @@ void ControlSettings::UpdateLightbarColor() { } void ControlSettings::CheckGamePad() { - if (GameRunning) - return; - - if (gamepad) { + if ((gamepad)) { SDL_CloseGamepad(gamepad); gamepad = nullptr; } - int gamepad_count; - SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count); - + gamepads = SDL_GetGamepads(&gamepad_count); if (!gamepads) { LOG_ERROR(Input, "Cannot get gamepad list: {}", SDL_GetError()); return; } - if (gamepad_count == 0) { - LOG_INFO(Input, "No gamepad found!"); - SDL_free(gamepads); - return; + if (!GameRunning) { + if (ControllerSelect::ActiveGamepad != "") { + for (int i = 0; i < gamepad_count; i++) { + char pszGUID[33]; + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + std::string currentGUID = std::string(pszGUID); + if (currentGUID == ControllerSelect::ActiveGamepad) { + gamepad = SDL_OpenGamepad(gamepads[i]); + LOG_WARNING(Input, "Opened gamepad: {}", i); + if (!gamepad) { + LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError()); + } + break; + } + } + } else { + LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count); + gamepad = SDL_OpenGamepad(gamepads[0]); + } + + if (!gamepad) { + LOG_ERROR(Input, "Failed to open gamepad 0: {}", SDL_GetError()); + return; + } } - - LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count); - gamepad = SDL_OpenGamepad(gamepads[0]); - - if (!gamepad) { - LOG_ERROR(Input, "Failed to open gamepad 0: {}", SDL_GetError()); - SDL_free(gamepads); - return; - } - - SDL_free(gamepads); } void ControlSettings::DisableMappingButtons() { @@ -914,6 +1028,8 @@ void ControlSettings::pollSDLEvents() { } if (event.type == SDL_EVENT_GAMEPAD_ADDED) { + ui->ActiveGamepadBox->clear(); + ResetActiveControllerBox(); CheckGamePad(); } @@ -923,8 +1039,12 @@ void ControlSettings::pollSDLEvents() { void ControlSettings::Cleanup() { SdlEventWrapper::Wrapper::wrapperActive = false; - if (gamepad) + if (gamepad) { SDL_CloseGamepad(gamepad); + gamepad = nullptr; + } + + SDL_free(gamepads); if (!GameRunning) { SDL_Event quitLoop{}; @@ -937,6 +1057,9 @@ void ControlSettings::Cleanup() { SDL_Quit(); } else { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "0"); + SDL_Event checkGamepad{}; + checkGamepad.type = SDL_EVENT_CHANGE_CONTROLLER; + SDL_PushEvent(&checkGamepad); } } diff --git a/src/qt_gui/control_settings.h b/src/qt_gui/control_settings.h index 76d16b84e..91c5442f0 100644 --- a/src/qt_gui/control_settings.h +++ b/src/qt_gui/control_settings.h @@ -1,6 +1,6 @@ // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later - +#pragma once #include #include #include @@ -29,6 +29,7 @@ private Q_SLOTS: void CheckMapping(QPushButton*& button); void StartTimer(QPushButton*& button, bool isButton); void ConnectAxisInputs(QPushButton*& button); + void ActiveControllerChanged(int value); private: std::unique_ptr ui; @@ -45,6 +46,7 @@ private: void DisableMappingButtons(); void EnableMappingButtons(); void Cleanup(); + void ResetActiveControllerBox(); QList ButtonsList; QList AxisList; @@ -59,9 +61,11 @@ private: bool MappingCompleted = false; QString mapping; int MappingTimer; + int gamepad_count; QTimer* timer; QPushButton* MappingButton; SDL_Gamepad* gamepad = nullptr; + SDL_JoystickID* gamepads; SdlEventWrapper::Wrapper* RemapWrapper; QFuture Polling; @@ -81,3 +85,8 @@ protected: Cleanup(); } }; + +namespace ControllerSelect { +extern std::string ActiveGamepad; +extern std::string DefaultGamepad; +} // namespace ControllerSelect diff --git a/src/qt_gui/control_settings.ui b/src/qt_gui/control_settings.ui index 2eb4c754c..c8cdc655c 100644 --- a/src/qt_gui/control_settings.ui +++ b/src/qt_gui/control_settings.ui @@ -1,6 +1,4 @@ - ControlSettings @@ -11,8 +9,8 @@ 0 0 - 1114 - 794 + 1124 + 847 @@ -33,8 +31,8 @@ 0 0 - 1094 - 744 + 1104 + 797 @@ -42,8 +40,8 @@ 0 0 - 1091 - 741 + 1101 + 791 @@ -246,14 +244,82 @@ + + + + L1 and L2 + + + + + + L2 + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + unmapped + + + + + + + + + + + 0 + 0 + + + + L1 + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + unmapped + + + + + + + + + Qt::Orientation::Vertical - - QSizePolicy::Policy::Maximum - 20 @@ -512,7 +578,7 @@ - + 0 @@ -598,199 +664,100 @@ - - - - - - - 0 - - - - - + + + + + 9 + true + + + + Active Gamepad + + - - - - - - 0 - 0 - - - - L1 - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - unmapped - - - - - - - - - - Qt::Orientation::Horizontal - - - QSizePolicy::Policy::Fixed - - - - 133 - 20 - - - - - - - - - 0 - 0 - - - - R1 - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - unmapped - - - - - - - + + + + 9 + false + + + - - - - - L2 - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - unmapped - - - - - - - - - - Options - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - unmapped - - - - - - - - - - R2 - - - - 5 - - - 5 - - - 5 - - - 5 - - - - - unmapped - - - - - - - + + + + 9 + false + + + + Gamepad ID + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + - - - - + + + + + + + 9 + true + + + + Default Gamepad + + + + + + No default selected + + + + + + + + 9 + false + + + + Gamepad ID + + + Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter + + + + + + + + + + + 9 + true + + + + Set Active Gamepad as Default + + + + + @@ -880,20 +847,32 @@ - - - Qt::Orientation::Horizontal + + + Options - - QSizePolicy::Policy::Fixed - - - - 133 - 20 - - - + + + 5 + + + 5 + + + 5 + + + 5 + + + + + unmapped + + + + + @@ -1338,13 +1317,84 @@ + + + + R1 and R2 + + + + + + R2 + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + unmapped + + + + + + + + + + + 0 + 0 + + + + R1 + + + + 5 + + + 5 + + + 5 + + + 5 + + + + + unmapped + + + + + + + + + Qt::Orientation::Vertical - QSizePolicy::Policy::Maximum + QSizePolicy::Policy::Expanding diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index 69819a00f..4d0715060 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -21,6 +21,7 @@ #include "video_core/renderdoc.h" #ifdef ENABLE_QT_GUI +#include "qt_gui/control_settings.h" #include "qt_gui/sdl_event_wrapper.h" #endif @@ -100,6 +101,7 @@ void SDLInputEngine::Init() { if (m_gamepad) { SDL_CloseGamepad(m_gamepad); m_gamepad = nullptr; + LOG_WARNING(Input, "closed gamepad"); } int gamepad_count; @@ -114,12 +116,51 @@ void SDLInputEngine::Init() { return; } - LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count); - m_gamepad = SDL_OpenGamepad(gamepads[0]); + std::string activeGamepad = ""; + std::string defaultGamepad = Config::getDefaultControllerID(); +#ifdef ENABLE_QT_GUI + activeGamepad = ControllerSelect::ActiveGamepad; +#endif + + // If user selects an active gamepad, use that, otherwise, try the default if (!m_gamepad) { - LOG_ERROR(Input, "Failed to open gamepad 0: {}", SDL_GetError()); - SDL_free(gamepads); - return; + if (activeGamepad != "") { + for (int i = 0; i < gamepad_count; i++) { + char pszGUID[33]; + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + std::string currentGUID = std::string(pszGUID); + if (currentGUID == activeGamepad) { + m_gamepad = SDL_OpenGamepad(gamepads[i]); + if (!m_gamepad) { + LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError()); + } + break; + } + } + } else if (Config::getDefaultControllerID() != "") { + for (int i = 0; i < gamepad_count; i++) { + char pszGUID[33]; + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + std::string currentGUID = std::string(pszGUID); + if (currentGUID == Config::getDefaultControllerID()) { + m_gamepad = SDL_OpenGamepad(gamepads[i]); + if (!m_gamepad) { + LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError()); + } + break; + } + } + } + } + + if (!m_gamepad) { + LOG_INFO(Input, "Got {} gamepads. Opening the first one.", gamepad_count); + m_gamepad = SDL_OpenGamepad(gamepads[0]); + if (!m_gamepad) { + LOG_ERROR(Input, "Failed to open gamepad: {}", SDL_GetError()); + SDL_free(gamepads); + return; + } } SDL_Joystick* joystick = SDL_GetGamepadJoystick(m_gamepad); @@ -426,6 +467,9 @@ void WindowSDL::WaitEvent() { DebugState.PauseGuestThreads(); } break; + case SDL_EVENT_CHANGE_CONTROLLER: + controller->GetEngine()->Init(); + break; default: break; } diff --git a/src/sdl_window.h b/src/sdl_window.h index 48a9be58c..ce79eedd0 100644 --- a/src/sdl_window.h +++ b/src/sdl_window.h @@ -9,6 +9,7 @@ #include "string" #define SDL_EVENT_TOGGLE_FULLSCREEN (SDL_EVENT_USER + 1) #define SDL_EVENT_TOGGLE_PAUSE (SDL_EVENT_USER + 2) +#define SDL_EVENT_CHANGE_CONTROLLER (SDL_EVENT_USER + 3) struct SDL_Window; struct SDL_Gamepad; From 336e8a7563ec849b1d36d4b30cbf6ca0dbb6efa5 Mon Sep 17 00:00:00 2001 From: rainmakerv3 <30595646+rainmakerv3@users.noreply.github.com> Date: Sun, 29 Jun 2025 06:01:03 +0800 Subject: [PATCH 2/6] Ugly solution to working with ImGUI --- src/imgui/renderer/imgui_impl_sdl3.cpp | 31 +++++++++++++++----------- src/qt_gui/control_settings.ui | 2 ++ src/sdl_window.cpp | 2 ++ src/sdl_window.h | 4 ++-- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/imgui/renderer/imgui_impl_sdl3.cpp b/src/imgui/renderer/imgui_impl_sdl3.cpp index bd0c1a5db..fd703ee19 100644 --- a/src/imgui/renderer/imgui_impl_sdl3.cpp +++ b/src/imgui/renderer/imgui_impl_sdl3.cpp @@ -7,6 +7,7 @@ #include "common/config.h" #include "core/debug_state.h" #include "imgui_impl_sdl3.h" +#include "sdl_window.h" // SDL #include @@ -730,21 +731,25 @@ static void UpdateGamepads() { ImGuiIO& io = ImGui::GetIO(); SdlData* bd = GetBackendData(); - /* - // Update list of gamepads to use - if (bd->want_update_gamepads_list && bd->gamepad_mode != ImGui_ImplSDL3_GamepadMode_Manual) { - CloseGamepads(); - int sdl_gamepads_count = 0; - const SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); - for (int n = 0; n < sdl_gamepads_count; n++) - if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) { - bd->gamepads.push_back(gamepad); - if (bd->gamepad_mode == ImGui_ImplSDL3_GamepadMode_AutoFirst) - break; - } + SDL_Gamepad* SDLGamepad = Input::m_gamepad; + if (SDLGamepad) { + bd->gamepads.push_back(SDLGamepad); + } else { + // Update list of gamepads to use + if (bd->want_update_gamepads_list && + bd->gamepad_mode != ImGui_ImplSDL3_GamepadMode_Manual) { + CloseGamepads(); + int sdl_gamepads_count = 0; + const SDL_JoystickID* sdl_gamepads = SDL_GetGamepads(&sdl_gamepads_count); + for (int n = 0; n < sdl_gamepads_count; n++) + if (SDL_Gamepad* gamepad = SDL_OpenGamepad(sdl_gamepads[n])) { + bd->gamepads.push_back(gamepad); + if (bd->gamepad_mode == ImGui_ImplSDL3_GamepadMode_AutoFirst) + break; + } bd->want_update_gamepads_list = false; + } } - */ // FIXME: Technically feeding gamepad shouldn't depend on this now that they are regular inputs. if ((io.ConfigFlags & ImGuiConfigFlags_NavEnableGamepad) == 0) diff --git a/src/qt_gui/control_settings.ui b/src/qt_gui/control_settings.ui index c8cdc655c..d620490ee 100644 --- a/src/qt_gui/control_settings.ui +++ b/src/qt_gui/control_settings.ui @@ -1,4 +1,6 @@ + ControlSettings diff --git a/src/sdl_window.cpp b/src/sdl_window.cpp index 4d0715060..34f570626 100644 --- a/src/sdl_window.cpp +++ b/src/sdl_window.cpp @@ -31,6 +31,8 @@ namespace Input { +SDL_Gamepad* m_gamepad = nullptr; + using Libraries::Pad::OrbisPadButtonDataOffset; static OrbisPadButtonDataOffset SDLGamepadToOrbisButton(u8 button) { diff --git a/src/sdl_window.h b/src/sdl_window.h index ce79eedd0..3ea96c734 100644 --- a/src/sdl_window.h +++ b/src/sdl_window.h @@ -17,6 +17,8 @@ union SDL_Event; namespace Input { +extern SDL_Gamepad* m_gamepad; + class SDLInputEngine : public Engine { public: ~SDLInputEngine() override; @@ -28,8 +30,6 @@ public: State ReadState() override; private: - SDL_Gamepad* m_gamepad = nullptr; - float m_gyro_poll_rate = 0.0f; float m_accel_poll_rate = 0.0f; }; From f4c096ea4e34b0feee122120f18f75641522345f Mon Sep 17 00:00:00 2001 From: rainmakerv3 <30595646+rainmakerv3@users.noreply.github.com> Date: Sun, 29 Jun 2025 06:47:35 +0800 Subject: [PATCH 3/6] Populate the default controller labels --- src/qt_gui/control_settings.cpp | 37 ++++++++++++++++++++++----------- src/qt_gui/control_settings.h | 1 - src/qt_gui/control_settings.ui | 2 +- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/src/qt_gui/control_settings.cpp b/src/qt_gui/control_settings.cpp index 15f4d4b95..4960d9524 100644 --- a/src/qt_gui/control_settings.cpp +++ b/src/qt_gui/control_settings.cpp @@ -13,7 +13,6 @@ #include "ui_control_settings.h" std::string ControllerSelect::ActiveGamepad = ""; -std::string ControllerSelect::DefaultGamepad = ""; ControlSettings::ControlSettings(std::shared_ptr game_info_get, bool isGameRunning, std::string GameRunningSerial, QWidget* parent) @@ -130,6 +129,9 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b char pszGUID[33]; SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[ui->ActiveGamepadBox->currentIndex()]), pszGUID, 33); + ui->DefaultGamepadName->setText(ui->ActiveGamepadBox->currentText()); + ui->DefaultGamepadLabel->setText("ID: " + + QString::fromStdString(std::string(pszGUID)).right(16)); Config::setDefaultControllerID(std::string(pszGUID)); Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); QMessageBox::information(this, tr("Default Controller Selected"), @@ -207,6 +209,26 @@ void ControlSettings::ResetActiveControllerBox() { } char pszGUID[33]; + int defaultIndex; + QString defaultID = ""; + + if (Config::getDefaultControllerID() != "") { + for (int i = 0; i < gamepad_count; i++) { + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); + std::string currentGUID = std::string(pszGUID); + if (currentGUID == Config::getDefaultControllerID()) { + defaultIndex = i; + defaultID = QString::fromStdString(std::string(pszGUID)).right(16); + ui->DefaultGamepadName->setText(SDL_GetGamepadNameForID(gamepads[i])); + ui->DefaultGamepadLabel->setText("ID: " + defaultID); + break; + } + } + + if (defaultID == "") + ui->DefaultGamepadName->setText("Default controller not connected"); + } + if (ControllerSelect::ActiveGamepad != "") { for (int i = 0; i < gamepad_count; i++) { SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); @@ -220,17 +242,8 @@ void ControlSettings::ResetActiveControllerBox() { } } } else if (Config::getDefaultControllerID() != "") { - for (int i = 0; i < gamepad_count; i++) { - SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); - std::string currentGUID = std::string(pszGUID); - if (currentGUID == Config::getDefaultControllerID()) { - SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); - QString GUID = QString::fromStdString(std::string(pszGUID)).right(16); - ui->ActiveGamepadLabel->setText("ID: " + GUID); - ui->ActiveGamepadBox->setCurrentIndex(i); - break; - } - } + ui->ActiveGamepadLabel->setText(defaultID); + ui->ActiveGamepadBox->setCurrentIndex(defaultIndex); } else { SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[0]), pszGUID, 33); QString GUID = QString::fromStdString(std::string(pszGUID)).right(16); diff --git a/src/qt_gui/control_settings.h b/src/qt_gui/control_settings.h index 91c5442f0..235485ed5 100644 --- a/src/qt_gui/control_settings.h +++ b/src/qt_gui/control_settings.h @@ -88,5 +88,4 @@ protected: namespace ControllerSelect { extern std::string ActiveGamepad; -extern std::string DefaultGamepad; } // namespace ControllerSelect diff --git a/src/qt_gui/control_settings.ui b/src/qt_gui/control_settings.ui index d620490ee..d7860b28a 100644 --- a/src/qt_gui/control_settings.ui +++ b/src/qt_gui/control_settings.ui @@ -735,7 +735,7 @@ - Gamepad ID + n/a Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter From 22b9d04fb52722ce8d268cc3caaa6f93dfcd68a9 Mon Sep 17 00:00:00 2001 From: rainmakerv3 <30595646+rainmakerv3@users.noreply.github.com> Date: Sun, 29 Jun 2025 08:43:00 +0800 Subject: [PATCH 4/6] Add remove default button --- src/qt_gui/control_settings.cpp | 14 +++++++++++- src/qt_gui/control_settings.ui | 39 +++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/qt_gui/control_settings.cpp b/src/qt_gui/control_settings.cpp index 4960d9524..bc9e6ed4f 100644 --- a/src/qt_gui/control_settings.cpp +++ b/src/qt_gui/control_settings.cpp @@ -122,9 +122,9 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b [this]() { CheckMapping(MappingButton); }); connect(this, &ControlSettings::AxisChanged, this, [this]() { ConnectAxisInputs(MappingButton); }); - connect(ui->ActiveGamepadBox, &QComboBox::currentIndexChanged, this, &ControlSettings::ActiveControllerChanged); + connect(ui->DefaultGamepadButton, &QPushButton::clicked, this, [this]() { char pszGUID[33]; SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[ui->ActiveGamepadBox->currentIndex()]), @@ -138,6 +138,18 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b tr("Active controller set as default")); }); + connect(ui->RemoveDefaultGamepadButton, &QPushButton::clicked, this, [this]() { + char pszGUID[33]; + SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[ui->ActiveGamepadBox->currentIndex()]), + pszGUID, 33); + ui->DefaultGamepadName->setText("No default selected"); + ui->DefaultGamepadLabel->setText("n/a"); + Config::setDefaultControllerID(""); + Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); + QMessageBox::information(this, tr("Default Controller Removed"), + tr("No default controller currently selected")); + }); + RemapWrapper = SdlEventWrapper::Wrapper::GetInstance(); SdlEventWrapper::Wrapper::wrapperActive = true; QObject::connect(RemapWrapper, &SdlEventWrapper::Wrapper::SDLEvent, this, diff --git a/src/qt_gui/control_settings.ui b/src/qt_gui/control_settings.ui index d7860b28a..efab94e2c 100644 --- a/src/qt_gui/control_settings.ui +++ b/src/qt_gui/control_settings.ui @@ -746,17 +746,34 @@ - - - - 9 - true - - - - Set Active Gamepad as Default - - + + + + + + 9 + true + + + + Set Active Gamepad as Default + + + + + + + + 9 + true + + + + Remove Default Gamepad + + + + From 2e36ddb5596c151df5f29318e54f3cefe7af32d4 Mon Sep 17 00:00:00 2001 From: rainmakerv3 <30595646+rainmakerv3@users.noreply.github.com> Date: Sun, 29 Jun 2025 08:46:37 +0800 Subject: [PATCH 5/6] missing tr calls --- src/qt_gui/control_settings.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/qt_gui/control_settings.cpp b/src/qt_gui/control_settings.cpp index bc9e6ed4f..44c3d2e3d 100644 --- a/src/qt_gui/control_settings.cpp +++ b/src/qt_gui/control_settings.cpp @@ -130,7 +130,7 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[ui->ActiveGamepadBox->currentIndex()]), pszGUID, 33); ui->DefaultGamepadName->setText(ui->ActiveGamepadBox->currentText()); - ui->DefaultGamepadLabel->setText("ID: " + + ui->DefaultGamepadLabel->setText(tr("ID: ") + QString::fromStdString(std::string(pszGUID)).right(16)); Config::setDefaultControllerID(std::string(pszGUID)); Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); @@ -142,8 +142,8 @@ ControlSettings::ControlSettings(std::shared_ptr game_info_get, b char pszGUID[33]; SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[ui->ActiveGamepadBox->currentIndex()]), pszGUID, 33); - ui->DefaultGamepadName->setText("No default selected"); - ui->DefaultGamepadLabel->setText("n/a"); + ui->DefaultGamepadName->setText(tr("No default selected")); + ui->DefaultGamepadLabel->setText(tr("n/a")); Config::setDefaultControllerID(""); Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml"); QMessageBox::information(this, tr("Default Controller Removed"), @@ -232,7 +232,7 @@ void ControlSettings::ResetActiveControllerBox() { defaultIndex = i; defaultID = QString::fromStdString(std::string(pszGUID)).right(16); ui->DefaultGamepadName->setText(SDL_GetGamepadNameForID(gamepads[i])); - ui->DefaultGamepadLabel->setText("ID: " + defaultID); + ui->DefaultGamepadLabel->setText(tr("ID: ") + defaultID); break; } } @@ -248,7 +248,7 @@ void ControlSettings::ResetActiveControllerBox() { if (currentGUID == ControllerSelect::ActiveGamepad) { SDL_GUIDToString(SDL_GetGamepadGUIDForID(gamepads[i]), pszGUID, 33); QString GUID = QString::fromStdString(std::string(pszGUID)).right(16); - ui->ActiveGamepadLabel->setText("ID: " + GUID); + ui->ActiveGamepadLabel->setText(tr("ID: ") + GUID); ui->ActiveGamepadBox->setCurrentIndex(i); break; } From 50067ffadf5f54323848d7411121ad355d0f7678 Mon Sep 17 00:00:00 2001 From: rainmakerv3 <30595646+rainmakerv3@users.noreply.github.com> Date: Sun, 29 Jun 2025 17:33:19 +0800 Subject: [PATCH 6/6] edit imgui flag after updating --- src/imgui/renderer/imgui_impl_sdl3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/imgui/renderer/imgui_impl_sdl3.cpp b/src/imgui/renderer/imgui_impl_sdl3.cpp index fd703ee19..99f3b662e 100644 --- a/src/imgui/renderer/imgui_impl_sdl3.cpp +++ b/src/imgui/renderer/imgui_impl_sdl3.cpp @@ -734,6 +734,7 @@ static void UpdateGamepads() { SDL_Gamepad* SDLGamepad = Input::m_gamepad; if (SDLGamepad) { bd->gamepads.push_back(SDLGamepad); + bd->want_update_gamepads_list = false; } else { // Update list of gamepads to use if (bd->want_update_gamepads_list &&