From edd98128e7bca6c0e6f1458fbf86146e5e3a9642 Mon Sep 17 00:00:00 2001 From: TheLastRar Date: Sun, 16 Feb 2025 22:14:28 +0000 Subject: [PATCH] SDLInputSource: Use controller information for icons --- pcsx2/ImGui/ImGuiManager.cpp | 2 +- pcsx2/Input/SDLInputSource.cpp | 200 +++++++++++++++++++++++++++++---- pcsx2/Input/SDLInputSource.h | 6 + 3 files changed, 186 insertions(+), 22 deletions(-) diff --git a/pcsx2/ImGui/ImGuiManager.cpp b/pcsx2/ImGui/ImGuiManager.cpp index 975818ae7c..41c3963017 100644 --- a/pcsx2/ImGui/ImGuiManager.cpp +++ b/pcsx2/ImGui/ImGuiManager.cpp @@ -489,7 +489,7 @@ bool ImGuiManager::AddIconFonts(float size) { // clang-format off static constexpr ImWchar range_fa[] = { 0xe06f,0xe06f,0xf002,0xf002,0xf005,0xf005,0xf007,0xf007,0xf00c,0xf00e,0xf011,0xf011,0xf013,0xf013,0xf017,0xf017,0xf019,0xf019,0xf021,0xf023,0xf025,0xf028,0xf02b,0xf02b,0xf02e,0xf02e,0xf030,0xf030,0xf03a,0xf03a,0xf03d,0xf03e,0xf04b,0xf04c,0xf04e,0xf04e,0xf050,0xf050,0xf052,0xf052,0xf05a,0xf05a,0xf05e,0xf05e,0xf063,0xf063,0xf067,0xf067,0xf06a,0xf06a,0xf06e,0xf06e,0xf071,0xf071,0xf077,0xf078,0xf07b,0xf07c,0xf084,0xf084,0xf091,0xf091,0xf0ac,0xf0ad,0xf0b0,0xf0b0,0xf0c5,0xf0c5,0xf0c7,0xf0c8,0xf0cb,0xf0cb,0xf0d0,0xf0d0,0xf0dc,0xf0dc,0xf0e2,0xf0e2,0xf0eb,0xf0eb,0xf0f3,0xf0f3,0xf0fe,0xf0fe,0xf11b,0xf11c,0xf120,0xf121,0xf129,0xf12a,0xf140,0xf140,0xf14a,0xf14a,0xf15b,0xf15b,0xf15d,0xf15d,0xf187,0xf188,0xf191,0xf192,0xf1b3,0xf1b3,0xf1de,0xf1de,0xf1e6,0xf1e6,0xf1ea,0xf1eb,0xf1f8,0xf1f8,0xf1fc,0xf1fc,0xf21e,0xf21e,0xf245,0xf245,0xf26c,0xf26c,0xf279,0xf279,0xf2bd,0xf2bd,0xf2db,0xf2db,0xf2f2,0xf2f2,0xf302,0xf302,0xf3c1,0xf3c1,0xf3fd,0xf3fd,0xf410,0xf410,0xf462,0xf462,0xf466,0xf466,0xf4e2,0xf4e2,0xf51f,0xf51f,0xf545,0xf545,0xf54c,0xf54c,0xf553,0xf553,0xf56d,0xf56d,0xf5a2,0xf5a2,0xf65d,0xf65e,0xf6a9,0xf6a9,0xf70e,0xf70e,0xf756,0xf756,0xf780,0xf780,0xf794,0xf794,0xf815,0xf815,0xf84c,0xf84c,0xf8cc,0xf8cc,0x0,0x0 }; - static constexpr ImWchar range_pf[] = { 0x2198,0x2199,0x219e,0x21a3,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21ce,0x21d0,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21f3,0x21f3,0x21f7,0x21f8,0x21fa,0x21fb,0x221a,0x221a,0x227a,0x227d,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x235e,0x2360,0x2361,0x2364,0x2367,0x237a,0x237b,0x237d,0x237d,0x237f,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x243a,0x243d,0x243d,0x2443,0x2443,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24fd,0x24ff,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0xe001,0xe001,0xff21,0xff3a,0x0,0x0 }; + static constexpr ImWchar range_pf[] = { 0x2198,0x2199,0x219e,0x21a7,0x21b0,0x21b3,0x21ba,0x21c3,0x21ce,0x21ce,0x21d0,0x21d4,0x21dc,0x21dd,0x21e0,0x21e3,0x21e6,0x21e8,0x21f3,0x21f3,0x21f7,0x21f8,0x21fa,0x21fb,0x2206,0x2208,0x221a,0x221a,0x227a,0x227d,0x22bf,0x22c8,0x2349,0x2349,0x235a,0x235e,0x2360,0x2361,0x2364,0x2367,0x237a,0x237b,0x237d,0x237d,0x237f,0x237f,0x23b2,0x23b5,0x23cc,0x23cc,0x23f4,0x23f7,0x2427,0x243a,0x243d,0x243d,0x2443,0x2443,0x2460,0x246b,0x248f,0x248f,0x24f5,0x24fd,0x24ff,0x24ff,0x2605,0x2605,0x2699,0x2699,0x278a,0x278e,0xe000,0xe001,0xff21,0xff3a,0x0,0x0 }; // clang-format on { diff --git a/pcsx2/Input/SDLInputSource.cpp b/pcsx2/Input/SDLInputSource.cpp index d07a88b2e5..afe319c183 100644 --- a/pcsx2/Input/SDLInputSource.cpp +++ b/pcsx2/Input/SDLInputSource.cpp @@ -33,9 +33,28 @@ static constexpr const char* s_sdl_axis_icons[][2] = { {ICON_PF_LEFT_ANALOG_UP, ICON_PF_LEFT_ANALOG_DOWN}, // SDL_GAMEPAD_AXIS_LEFTY {ICON_PF_RIGHT_ANALOG_LEFT, ICON_PF_RIGHT_ANALOG_RIGHT}, // SDL_GAMEPAD_AXIS_RIGHTX {ICON_PF_RIGHT_ANALOG_UP, ICON_PF_RIGHT_ANALOG_DOWN}, // SDL_GAMEPAD_AXIS_RIGHTY - {nullptr, ICON_PF_LEFT_TRIGGER_PULL}, // SDL_GAMEPAD_AXIS_LEFT_TRIGGER - {nullptr, ICON_PF_RIGHT_TRIGGER_PULL}, // SDL_GAMEPAD_AXIS_RIGHT_TRIGGER }; + +static constexpr const char* s_sdl_trigger_icons[] = { + ICON_PF_LEFT_TRIGGER_PULL, // SDL_GAMEPAD_AXIS_LEFT_TRIGGER + ICON_PF_RIGHT_TRIGGER_PULL, // SDL_GAMEPAD_AXIS_RIGHT_TRIGGER +}; +static constexpr const char* s_sdl_trigger_ps_icons[] = { + ICON_PF_LEFT_TRIGGER_L2, // SDL_GAMEPAD_AXIS_LEFT_TRIGGER + ICON_PF_RIGHT_TRIGGER_R2, // SDL_GAMEPAD_AXIS_RIGHT_TRIGGER +}; + +static const char* const* s_sdl_trigger_icons_list[] = { + s_sdl_trigger_icons, // SDL_GAMEPAD_TYPE_UNKNOWN + s_sdl_trigger_icons, // SDL_GAMEPAD_TYPE_STANDARD + s_sdl_trigger_icons, // SDL_GAMEPAD_TYPE_XBOX360 + s_sdl_trigger_icons, // SDL_GAMEPAD_TYPE_XBOXONE + s_sdl_trigger_ps_icons, // SDL_GAMEPAD_TYPE_PS3 + s_sdl_trigger_ps_icons, // SDL_GAMEPAD_TYPE_PS4 + s_sdl_trigger_ps_icons, // SDL_GAMEPAD_TYPE_PS5 + // Switch +}; + static constexpr const GenericInputBinding s_sdl_generic_binding_axis_mapping[][2] = { {GenericInputBinding::LeftStickLeft, GenericInputBinding::LeftStickRight}, // SDL_GAMEPAD_AXIS_LEFTX {GenericInputBinding::LeftStickUp, GenericInputBinding::LeftStickDown}, // SDL_GAMEPAD_AXIS_LEFTY @@ -68,11 +87,23 @@ static constexpr const char* s_sdl_button_names[] = { "Paddle4", // SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 "Touchpad", // SDL_GAMEPAD_BUTTON_TOUCHPAD }; + +static constexpr const char* s_sdl_face_button_icons[] = { + nullptr, // SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN + ICON_PF_BUTTON_A, // SDL_GAMEPAD_BUTTON_LABEL_A + ICON_PF_BUTTON_B, // SDL_GAMEPAD_BUTTON_LABEL_B + ICON_PF_BUTTON_X, // SDL_GAMEPAD_BUTTON_LABEL_X + ICON_PF_BUTTON_Y, // SDL_GAMEPAD_BUTTON_LABEL_Y + ICON_PF_BUTTON_CROSS, // SDL_GAMEPAD_BUTTON_LABEL_CROSS + ICON_PF_BUTTON_CIRCLE, // SDL_GAMEPAD_BUTTON_LABEL_CIRCLE + ICON_PF_BUTTON_SQUARE, // SDL_GAMEPAD_BUTTON_LABEL_SQUARE + ICON_PF_BUTTON_TRIANGLE, // SDL_GAMEPAD_BUTTON_LABEL_TRIANGLE +}; static constexpr const char* s_sdl_button_icons[] = { - ICON_PF_BUTTON_A, // SDL_GAMEPAD_BUTTON_SOUTH - ICON_PF_BUTTON_B, // SDL_GAMEPAD_BUTTON_EAST - ICON_PF_BUTTON_X, // SDL_GAMEPAD_BUTTON_WEST - ICON_PF_BUTTON_Y, // SDL_GAMEPAD_BUTTON_NORTH + ICON_PF_BUTTON_DOWN_A, // SDL_GAMEPAD_BUTTON_SOUTH + ICON_PF_BUTTON_RIGHT_B, // SDL_GAMEPAD_BUTTON_EAST + ICON_PF_BUTTON_LEFT_X, // SDL_GAMEPAD_BUTTON_WEST + ICON_PF_BUTTON_UP_Y, // SDL_GAMEPAD_BUTTON_NORTH ICON_PF_SHARE_CAPTURE, // SDL_GAMEPAD_BUTTON_BACK ICON_PF_XBOX, // SDL_GAMEPAD_BUTTON_GUIDE ICON_PF_BURGER_MENU, // SDL_GAMEPAD_BUTTON_START @@ -85,6 +116,91 @@ static constexpr const char* s_sdl_button_icons[] = { ICON_PF_XBOX_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT ICON_PF_XBOX_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT }; +static constexpr const char* s_sdl_button_ps3_icons[] = { + ICON_PF_BUTTON_CROSS, // SDL_GAMEPAD_BUTTON_SOUTH + ICON_PF_BUTTON_CIRCLE, // SDL_GAMEPAD_BUTTON_EAST + ICON_PF_BUTTON_SQUARE, // SDL_GAMEPAD_BUTTON_WEST + ICON_PF_BUTTON_TRIANGLE, // SDL_GAMEPAD_BUTTON_NORTH + ICON_PF_SELECT_SHARE, // SDL_GAMEPAD_BUTTON_BACK + ICON_PF_XBOX, // SDL_GAMEPAD_BUTTON_GUIDE + ICON_PF_START, // SDL_GAMEPAD_BUTTON_START + ICON_PF_LEFT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_LEFT_STICK + ICON_PF_RIGHT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_RIGHT_STICK + ICON_PF_LEFT_SHOULDER_L1, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER + ICON_PF_RIGHT_SHOULDER_R1, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER + ICON_PF_DPAD_UP, // SDL_GAMEPAD_BUTTON_DPAD_UP + ICON_PF_DPAD_DOWN, // SDL_GAMEPAD_BUTTON_DPAD_DOWN + ICON_PF_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT + ICON_PF_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT +}; +static constexpr const char* s_sdl_button_ps4_icons[] = { + ICON_PF_BUTTON_CROSS, // SDL_GAMEPAD_BUTTON_SOUTH + ICON_PF_BUTTON_CIRCLE, // SDL_GAMEPAD_BUTTON_EAST + ICON_PF_BUTTON_SQUARE, // SDL_GAMEPAD_BUTTON_WEST + ICON_PF_BUTTON_TRIANGLE, // SDL_GAMEPAD_BUTTON_NORTH + ICON_PF_DUALSHOCK_SHARE, // SDL_GAMEPAD_BUTTON_BACK + ICON_PF_PLAYSTATION, // SDL_GAMEPAD_BUTTON_GUIDE + ICON_PF_DUALSHOCK_OPTIONS, // SDL_GAMEPAD_BUTTON_START + ICON_PF_LEFT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_LEFT_STICK + ICON_PF_RIGHT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_RIGHT_STICK + ICON_PF_LEFT_SHOULDER_L1, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER + ICON_PF_RIGHT_SHOULDER_R1, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER + ICON_PF_DPAD_UP, // SDL_GAMEPAD_BUTTON_DPAD_UP + ICON_PF_DPAD_DOWN, // SDL_GAMEPAD_BUTTON_DPAD_DOWN + ICON_PF_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT + ICON_PF_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT + nullptr, // SDL_GAMEPAD_BUTTON_MISC1 + nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 + nullptr, // SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 + nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 + nullptr, // SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 + ICON_PF_DUALSHOCK_TOUCHPAD, // SDL_GAMEPAD_BUTTON_TOUCHPAD +}; +static constexpr const char* s_sdl_button_ps5_icons[] = { + ICON_PF_BUTTON_CROSS, // SDL_GAMEPAD_BUTTON_SOUTH + ICON_PF_BUTTON_CIRCLE, // SDL_GAMEPAD_BUTTON_EAST + ICON_PF_BUTTON_SQUARE, // SDL_GAMEPAD_BUTTON_WEST + ICON_PF_BUTTON_TRIANGLE, // SDL_GAMEPAD_BUTTON_NORTH + ICON_PF_DUALSENSE_SHARE, // SDL_GAMEPAD_BUTTON_BACK + ICON_PF_PLAYSTATION, // SDL_GAMEPAD_BUTTON_GUIDE + ICON_PF_DUALSENSE_OPTIONS, // SDL_GAMEPAD_BUTTON_START + ICON_PF_LEFT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_LEFT_STICK + ICON_PF_RIGHT_ANALOG_CLICK, // SDL_GAMEPAD_BUTTON_RIGHT_STICK + ICON_PF_LEFT_SHOULDER_L1, // SDL_GAMEPAD_BUTTON_LEFT_SHOULDER + ICON_PF_RIGHT_SHOULDER_R1, // SDL_GAMEPAD_BUTTON_RIGHT_SHOULDER + ICON_PF_DPAD_UP, // SDL_GAMEPAD_BUTTON_DPAD_UP + ICON_PF_DPAD_DOWN, // SDL_GAMEPAD_BUTTON_DPAD_DOWN + ICON_PF_DPAD_LEFT, // SDL_GAMEPAD_BUTTON_DPAD_LEFT + ICON_PF_DPAD_RIGHT, // SDL_GAMEPAD_BUTTON_DPAD_RIGHT + nullptr, // SDL_GAMEPAD_BUTTON_MISC1 + nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE1 + nullptr, // SDL_GAMEPAD_BUTTON_LEFT_PADDLE1 + nullptr, // SDL_GAMEPAD_BUTTON_RIGHT_PADDLE2 + nullptr, // SDL_GAMEPAD_BUTTON_LEFT_PADDLE2 + ICON_PF_DUALSENSE_TOUCHPAD, // SDL_GAMEPAD_BUTTON_TOUCHPAD +}; + +static constexpr const char* const* s_sdl_button_icons_list[] = { + s_sdl_button_icons, // SDL_GAMEPAD_TYPE_UNKNOWN + s_sdl_button_icons, // SDL_GAMEPAD_TYPE_STANDARD + s_sdl_button_icons, // SDL_GAMEPAD_TYPE_XBOX360 + s_sdl_button_icons, // SDL_GAMEPAD_TYPE_XBOXONE + s_sdl_button_ps3_icons, // SDL_GAMEPAD_TYPE_PS3 + s_sdl_button_ps4_icons, // SDL_GAMEPAD_TYPE_PS4 + s_sdl_button_ps5_icons, // SDL_GAMEPAD_TYPE_PS5 + // Switch +}; +static constexpr size_t s_sdl_button_iconsize_list[] = { + std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_UNKNOWN + std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_STANDARD + std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_XBOX360 + std::size(s_sdl_button_icons), // SDL_GAMEPAD_TYPE_XBOXONE + std::size(s_sdl_button_ps3_icons), // SDL_GAMEPAD_TYPE_PS3 + std::size(s_sdl_button_ps4_icons), // SDL_GAMEPAD_TYPE_PS4 + std::size(s_sdl_button_ps5_icons), // SDL_GAMEPAD_TYPE_PS5 + // Switch +}; + static constexpr const GenericInputBinding s_sdl_generic_binding_button_mapping[] = { GenericInputBinding::Cross, // SDL_GAMEPAD_BUTTON_SOUTH GenericInputBinding::Circle, // SDL_GAMEPAD_BUTTON_EAST @@ -543,17 +659,52 @@ TinyString SDLInputSource::ConvertKeyToIcon(InputBindingKey key) if (key.source_type == InputSourceType::SDL) { + std::lock_guard lock(m_controllers_key_mutex); + + SDL_GamepadType type = SDL_GAMEPAD_TYPE_UNKNOWN; + auto it = GetControllerDataForPlayerId(key.source_index); + if (it != m_controllers.end()) + type = SDL_GetRealGamepadType(it->gamepad); + if (key.source_subtype == InputSubclass::ControllerAxis) { - if (key.data < std::size(s_sdl_axis_icons) && key.modifier != InputModifier::FullAxis) + if (key.modifier != InputModifier::FullAxis) { - ret.format("SDL-{} {}", static_cast(key.source_index), - s_sdl_axis_icons[key.data][key.modifier == InputModifier::None]); + if (key.data < std::size(s_sdl_axis_icons)) + { + ret.format("SDL-{} {}", static_cast(key.source_index), + s_sdl_axis_icons[key.data][key.modifier == InputModifier::None]); + } + else if (key.data - std::size(s_sdl_axis_icons) < std::size(s_sdl_trigger_icons)) + { + const u32 trigger_index = key.data - std::size(s_sdl_axis_icons); + + if (type < std::size(s_sdl_button_icons_list)) + ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_trigger_icons_list[type][trigger_index]); + else + ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_trigger_icons[trigger_index]); + } } } else if (key.source_subtype == InputSubclass::ControllerButton) { - if (key.data < std::size(s_sdl_button_icons)) + if (type > SDL_GAMEPAD_TYPE_STANDARD && type < std::size(s_sdl_button_icons_list)) + { + if (key.data < s_sdl_button_iconsize_list[type] && s_sdl_button_icons_list[type][key.data] != nullptr) + ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_button_icons_list[type][key.data]); + } + else if (key.data < 4) + { + SDL_GamepadButtonLabel label = SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN; + if (it != m_controllers.end() && it->gamepad) + label = SDL_GetGamepadButtonLabel(it->gamepad, static_cast(key.data)); + + if (label > SDL_GAMEPAD_BUTTON_LABEL_UNKNOWN && label < std::size(s_sdl_face_button_icons)) + ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_face_button_icons[label]); + else + ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_button_icons[key.data]); + } + else if (key.data < std::size(s_sdl_button_icons)) ret.format("SDL-{} {}", static_cast(key.source_index), s_sdl_button_icons[key.data]); } } @@ -822,7 +973,10 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamepad) } } - m_controllers.push_back(std::move(cd)); + { + std::unique_lock lock(m_controllers_key_mutex); + m_controllers.push_back(std::move(cd)); + } InputManager::OnInputDeviceConnected(fmt::format("SDL-{}", player_id), name); return true; @@ -834,19 +988,23 @@ bool SDLInputSource::CloseDevice(int joystick_index) if (it == m_controllers.end()) return false; - InputManager::OnInputDeviceDisconnected( - {InputBindingKey{.source_type = InputSourceType::SDL, .source_index = static_cast(it->player_id)}}, - fmt::format("SDL-{}", it->player_id)); + { + std::lock_guard lock(m_controllers_key_mutex); + InputManager::OnInputDeviceDisconnected( + {InputBindingKey{.source_type = InputSourceType::SDL, .source_index = static_cast(it->player_id)}}, + fmt::format("SDL-{}", it->player_id)); - if (it->haptic) - SDL_CloseHaptic(it->haptic); + if (it->haptic) + SDL_CloseHaptic(it->haptic); - if (it->gamepad) - SDL_CloseGamepad(it->gamepad); - else - SDL_CloseJoystick(it->joystick); + if (it->gamepad) + SDL_CloseGamepad(it->gamepad); + else + SDL_CloseJoystick(it->joystick); + + m_controllers.erase(it); + } - m_controllers.erase(it); return true; } diff --git a/pcsx2/Input/SDLInputSource.h b/pcsx2/Input/SDLInputSource.h index 324a4c2e9f..98cd6cc512 100644 --- a/pcsx2/Input/SDLInputSource.h +++ b/pcsx2/Input/SDLInputSource.h @@ -88,6 +88,12 @@ private: ControllerDataVector m_controllers; + // ConvertKeyToIcon can inspect the currently connected gamepad + // to provide labels matching the connected gamepad + // Those functions can be called on the main thread, while + // gamepad addition/removal is done on the CPU thread + std::mutex m_controllers_key_mutex; + std::array m_led_colors{}; std::vector> m_sdl_hints;