diff --git a/CMakeLists.txt b/CMakeLists.txt index a00879fe..64c70e68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -139,7 +139,7 @@ option(ENABLE_CUBEB "Enabled cubeb backend" ON) option(ENABLE_WXWIDGETS "Build with wxWidgets UI (Currently required)" ON) find_package(Threads REQUIRED) -find_package(SDL2 REQUIRED) +find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3) find_package(CURL REQUIRED) find_package(pugixml REQUIRED) find_package(RapidJSON REQUIRED) @@ -202,7 +202,6 @@ if (ENABLE_DISCORD_RPC) endif() if (ENABLE_HIDAPI) - find_package(hidapi REQUIRED) set(SUPPORTS_WIIMOTE ON) add_compile_definitions(HAS_HIDAPI) endif () diff --git a/dependencies/vcpkg b/dependencies/vcpkg index af752f21..c3867e71 160000 --- a/dependencies/vcpkg +++ b/dependencies/vcpkg @@ -1 +1 @@ -Subproject commit af752f21c9d79ba3df9cb0250ce2233933f58486 +Subproject commit c3867e714dd3a51c272826eea77267876517ed99 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index e73d5f1f..813aec95 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -166,7 +166,7 @@ target_link_libraries(CemuBin PRIVATE CemuGui CemuInput CemuUtil - SDL2::SDL2 + SDL3::SDL3 ) if(UNIX AND NOT APPLE) diff --git a/src/gui/wxgui/CMakeLists.txt b/src/gui/wxgui/CMakeLists.txt index 12fc62d9..73e4f61a 100644 --- a/src/gui/wxgui/CMakeLists.txt +++ b/src/gui/wxgui/CMakeLists.txt @@ -145,7 +145,7 @@ target_link_libraries(CemuWxGui PRIVATE libzip::zip ZArchive::zarchive CemuComponents - SDL2::SDL2 + SDL3::SDL3 pugixml::pugixml CemuCafe PUBLIC diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index d24a5ca0..48c7d713 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -94,10 +94,6 @@ target_link_libraries(CemuInput PRIVATE CemuGui ) -if (ENABLE_HIDAPI) - target_link_libraries(CemuInput PRIVATE hidapi::hidapi) -endif() - if (ENABLE_BLUEZ) target_link_libraries(CemuInput PRIVATE bluez::bluez) endif () diff --git a/src/input/ControllerFactory.cpp b/src/input/ControllerFactory.cpp index 70a85a2d..f4f0eeab 100644 --- a/src/input/ControllerFactory.cpp +++ b/src/input/ControllerFactory.cpp @@ -68,7 +68,7 @@ ControllerPtr ControllerFactory::CreateController(InputAPI::Type api, std::strin throw std::invalid_argument(fmt::format("invalid sdl uuid format: {}", uuid)); const auto guid_index = ConvertString(uuid.substr(0, index)); - const auto guid = SDL_JoystickGetGUIDFromString(std::string{uuid.substr(index + 1)}.c_str()); + const auto guid = SDL_StringToGUID(std::string{uuid.substr(index + 1)}.c_str()); if (display_name.empty()) return std::make_shared(guid, guid_index); diff --git a/src/input/api/SDL/SDLController.cpp b/src/input/api/SDL/SDLController.cpp index 57971ecc..2e700196 100644 --- a/src/input/api/SDL/SDLController.cpp +++ b/src/input/api/SDL/SDLController.cpp @@ -2,27 +2,30 @@ #include "input/api/SDL/SDLControllerProvider.h" -SDLController::SDLController(const SDL_JoystickGUID& guid, size_t guid_index) +SDLController::SDLController(const SDL_GUID& guid, size_t guid_index) : base_type(fmt::format("{}_", guid_index), fmt::format("Controller {}", guid_index + 1)), m_guid_index(guid_index), m_guid(guid) { char tmp[64]; - SDL_JoystickGetGUIDString(m_guid, tmp, std::size(tmp)); + SDL_GUIDToString(m_guid, tmp, std::size(tmp)); m_uuid += tmp; } -SDLController::SDLController(const SDL_JoystickGUID& guid, size_t guid_index, std::string_view display_name) +SDLController::SDLController(const SDL_GUID& guid, size_t guid_index, std::string_view display_name) : base_type(fmt::format("{}_", guid_index), display_name), m_guid_index(guid_index), m_guid(guid) { char tmp[64]; - SDL_JoystickGetGUIDString(m_guid, tmp, std::size(tmp)); + SDL_GUIDToString(m_guid, tmp, std::size(tmp)); m_uuid += tmp; } SDLController::~SDLController() { if (m_controller) - SDL_GameControllerClose(m_controller); + { + SDL_CloseGamepad(m_controller); + m_controller = nullptr; + } } bool SDLController::is_connected() @@ -33,8 +36,9 @@ bool SDLController::is_connected() return false; } - if (!SDL_GameControllerGetAttached(m_controller)) + if (!SDL_GamepadConnected(m_controller)) { + SDL_CloseGamepad(m_controller); m_controller = nullptr; return false; } @@ -54,63 +58,83 @@ bool SDLController::connect() const auto index = m_provider->get_index(m_guid_index, m_guid); std::scoped_lock lock(m_controller_mutex); - m_diid = SDL_JoystickGetDeviceInstanceID(index); - if (m_diid == -1) - return false; - m_controller = SDL_GameControllerOpen(index); + int gamepad_count = 0; + + SDL_JoystickID *gamepad_ids = SDL_GetGamepads(&gamepad_count); + + if (!gamepad_ids) + { + return false; + } + + m_diid = gamepad_ids[index]; + SDL_free(gamepad_ids); + + m_controller = SDL_OpenGamepad(m_diid); + if (!m_controller) + { return false; + } - if (const char* name = SDL_GameControllerName(m_controller)) + if (const char* name = SDL_GetGamepadName(m_controller)) + { m_display_name = name; - - for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) - { - m_buttons[i] = SDL_GameControllerHasButton(m_controller, (SDL_GameControllerButton)i); } - for (int i = 0; i < SDL_CONTROLLER_AXIS_MAX; ++i) + for (size_t i = 0; i < SDL_GAMEPAD_BUTTON_COUNT; ++i) { - m_axis[i] = SDL_GameControllerHasAxis(m_controller, (SDL_GameControllerAxis)i); + m_buttons[i] = SDL_GamepadHasButton(m_controller, (SDL_GamepadButton)i); } - if (SDL_GameControllerHasSensor(m_controller, SDL_SENSOR_ACCEL)) + for (size_t i = 0; i < SDL_GAMEPAD_AXIS_COUNT; ++i) { - m_has_accel = true; - SDL_GameControllerSetSensorEnabled(m_controller, SDL_SENSOR_ACCEL, SDL_TRUE); + m_axis[i] = SDL_GamepadHasAxis(m_controller, (SDL_GamepadAxis)i); } - if (SDL_GameControllerHasSensor(m_controller, SDL_SENSOR_GYRO)) + if (SDL_GamepadHasSensor(m_controller, SDL_SENSOR_ACCEL)) { - m_has_gyro = true; - SDL_GameControllerSetSensorEnabled(m_controller, SDL_SENSOR_GYRO, SDL_TRUE); + m_has_accel = SDL_SetGamepadSensorEnabled(m_controller, SDL_SENSOR_ACCEL, true); } - m_has_rumble = SDL_GameControllerRumble(m_controller, 0, 0, 0) == 0; + if (SDL_GamepadHasSensor(m_controller, SDL_SENSOR_GYRO)) + { + m_has_gyro = SDL_SetGamepadSensorEnabled(m_controller, SDL_SENSOR_GYRO, true); + } + + m_has_rumble = SDL_RumbleGamepad(m_controller, 0, 0, 0); + return true; } void SDLController::start_rumble() { std::scoped_lock lock(m_controller_mutex); + if (is_connected() && !m_has_rumble) + { return; + } if (m_settings.rumble <= 0) + { return; + } - SDL_GameControllerRumble(m_controller, (Uint16)(m_settings.rumble * 0xFFFF), (Uint16)(m_settings.rumble * 0xFFFF), - 5 * 1000); + SDL_RumbleGamepad(m_controller, (Uint16)(m_settings.rumble * 0xFFFF), (Uint16)(m_settings.rumble * 0xFFFF), 5 * 1000); } void SDLController::stop_rumble() { std::scoped_lock lock(m_controller_mutex); - if (is_connected() && !m_has_rumble) - return; - SDL_GameControllerRumble(m_controller, 0, 0, 0); + if (is_connected() && !m_has_rumble) + { + return; + } + + SDL_RumbleGamepad(m_controller, 0, 0, 0); } MotionSample SDLController::get_motion_sample() @@ -125,8 +149,10 @@ MotionSample SDLController::get_motion_sample() std::string SDLController::get_button_name(uint64 button) const { - if (const char* name = SDL_GameControllerGetStringForButton((SDL_GameControllerButton)button)) + if (const char* name = SDL_GetGamepadStringForButton((SDL_GamepadButton)button)) + { return name; + } return base_type::get_button_name(button); } @@ -136,32 +162,49 @@ ControllerState SDLController::raw_state() ControllerState result{}; std::scoped_lock lock(m_controller_mutex); - if (!is_connected()) - return result; - for (int i = 0; i < SDL_CONTROLLER_BUTTON_MAX; ++i) + if (!is_connected()) { - if (m_buttons[i] && SDL_GameControllerGetButton(m_controller, (SDL_GameControllerButton)i)) - result.buttons.SetButtonState(i, true); + return result; } - if (m_axis[SDL_CONTROLLER_AXIS_LEFTX]) - result.axis.x = (float)SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_LEFTX) / 32767.0f; + for (size_t i = 0; i < SDL_GAMEPAD_BUTTON_COUNT; ++i) + { + if (m_buttons[i] && SDL_GetGamepadButton(m_controller, (SDL_GamepadButton)i)) + { + result.buttons.SetButtonState(i, true); + } + } - if (m_axis[SDL_CONTROLLER_AXIS_LEFTY]) - result.axis.y = (float)SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_LEFTY) / 32767.0f; + if (m_axis[SDL_GAMEPAD_AXIS_LEFTX]) + { + result.axis.x = (float)SDL_GetGamepadAxis(m_controller, SDL_GAMEPAD_AXIS_LEFTX) / 32767.0f; + } - if (m_axis[SDL_CONTROLLER_AXIS_RIGHTX]) - result.rotation.x = (float)SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_RIGHTX) / 32767.0f; + if (m_axis[SDL_GAMEPAD_AXIS_LEFTY]) + { + result.axis.y = (float)SDL_GetGamepadAxis(m_controller, SDL_GAMEPAD_AXIS_LEFTY) / 32767.0f; + } - if (m_axis[SDL_CONTROLLER_AXIS_RIGHTY]) - result.rotation.y = (float)SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_RIGHTY) / 32767.0f; + if (m_axis[SDL_GAMEPAD_AXIS_RIGHTX]) + { + result.rotation.x = (float)SDL_GetGamepadAxis(m_controller, SDL_GAMEPAD_AXIS_RIGHTX) / 32767.0f; + } - if (m_axis[SDL_CONTROLLER_AXIS_TRIGGERLEFT]) - result.trigger.x = (float)SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_TRIGGERLEFT) / 32767.0f; + if (m_axis[SDL_GAMEPAD_AXIS_RIGHTY]) + { + result.rotation.y = (float)SDL_GetGamepadAxis(m_controller, SDL_GAMEPAD_AXIS_RIGHTY) / 32767.0f; + } - if (m_axis[SDL_CONTROLLER_AXIS_TRIGGERRIGHT]) - result.trigger.y = (float)SDL_GameControllerGetAxis(m_controller, SDL_CONTROLLER_AXIS_TRIGGERRIGHT) / 32767.0f; + if (m_axis[SDL_GAMEPAD_AXIS_LEFT_TRIGGER]) + { + result.trigger.x = (float)SDL_GetGamepadAxis(m_controller, SDL_GAMEPAD_AXIS_LEFT_TRIGGER) / 32767.0f; + } + + if (m_axis[SDL_GAMEPAD_AXIS_RIGHT_TRIGGER]) + { + result.trigger.y = (float)SDL_GetGamepadAxis(m_controller, SDL_GAMEPAD_AXIS_RIGHT_TRIGGER) / 32767.0f; + } return result; } diff --git a/src/input/api/SDL/SDLController.h b/src/input/api/SDL/SDLController.h index 0a0aa183..1a4dd8dc 100644 --- a/src/input/api/SDL/SDLController.h +++ b/src/input/api/SDL/SDLController.h @@ -3,13 +3,13 @@ #include "input/api/Controller.h" #include "input/api/SDL/SDLControllerProvider.h" -#include +#include class SDLController : public Controller { public: - SDLController(const SDL_JoystickGUID& guid, size_t guid_index); - SDLController(const SDL_JoystickGUID& guid, size_t guid_index, std::string_view display_name); + SDLController(const SDL_GUID& guid, size_t guid_index); + SDLController(const SDL_GUID& guid, size_t guid_index, std::string_view display_name); ~SDLController() override; @@ -32,29 +32,29 @@ public: MotionSample get_motion_sample() override; std::string get_button_name(uint64 button) const override; - const SDL_JoystickGUID& get_guid() const { return m_guid; } + const SDL_GUID& get_guid() const { return m_guid; } - constexpr static SDL_JoystickGUID kLeftJoyCon{ 0x03, 0x00, 0x00, 0x00, 0x7e, 0x05, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00,0x68 ,0x00 }; - constexpr static SDL_JoystickGUID kRightJoyCon{ 0x03, 0x00, 0x00, 0x00, 0x7e, 0x05, 0x00, 0x00, 0x07, 0x20, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00 }; - constexpr static SDL_JoystickGUID kSwitchProController{ 0x03, 0x00, 0x00, 0x00, 0x7e, 0x05, 0x00, 0x00, 0x09, 0x20, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00 }; + constexpr static SDL_GUID kLeftJoyCon{ 0x03, 0x00, 0x00, 0x00, 0x7e, 0x05, 0x00, 0x00, 0x06, 0x20, 0x00, 0x00, 0x00, 0x00,0x68 ,0x00 }; + constexpr static SDL_GUID kRightJoyCon{ 0x03, 0x00, 0x00, 0x00, 0x7e, 0x05, 0x00, 0x00, 0x07, 0x20, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00 }; + constexpr static SDL_GUID kSwitchProController{ 0x03, 0x00, 0x00, 0x00, 0x7e, 0x05, 0x00, 0x00, 0x09, 0x20, 0x00, 0x00, 0x00, 0x00, 0x68, 0x00 }; protected: ControllerState raw_state() override; private: - inline static SDL_JoystickGUID kEmptyGUID{}; + inline static SDL_GUID kEmptyGUID{}; size_t m_guid_index; - SDL_JoystickGUID m_guid; + SDL_GUID m_guid; std::recursive_mutex m_controller_mutex; - SDL_GameController* m_controller = nullptr; + SDL_Gamepad* m_controller = nullptr; SDL_JoystickID m_diid = -1; bool m_has_gyro = false; bool m_has_accel = false; bool m_has_rumble = false; - std::array m_buttons{}; - std::array m_axis{}; + std::array m_buttons{}; + std::array m_axis{}; }; diff --git a/src/input/api/SDL/SDLControllerProvider.cpp b/src/input/api/SDL/SDLControllerProvider.cpp index 9b21b306..ea88fab7 100644 --- a/src/input/api/SDL/SDLControllerProvider.cpp +++ b/src/input/api/SDL/SDLControllerProvider.cpp @@ -3,12 +3,12 @@ #include "input/api/SDL/SDLController.h" #include "util/helpers/TempState.h" -#include +#include #include struct SDL_JoystickGUIDHash { - std::size_t operator()(const SDL_JoystickGUID& guid) const + std::size_t operator()(const SDL_GUID& guid) const { return boost::hash_value(guid.data); } @@ -17,28 +17,31 @@ struct SDL_JoystickGUIDHash SDLControllerProvider::SDLControllerProvider() { SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_ENHANCED_REPORTS, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5, "1"); - - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, "1"); - SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH, "1"); + SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_SWITCH2, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STADIA, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_STEAM, "1"); SDL_SetHint(SDL_HINT_JOYSTICK_HIDAPI_LUNA, "1"); - if (SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC | SDL_INIT_EVENTS) < 0) + if (!SDL_Init(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC)) + { throw std::runtime_error(fmt::format("couldn't initialize SDL: {}", SDL_GetError())); - + } - if (SDL_GameControllerEventState(SDL_ENABLE) < 0) { + SDL_SetGamepadEventsEnabled(true); + if (!SDL_GamepadEventsEnabled()) + { cemuLog_log(LogType::Force, "Couldn't enable SDL gamecontroller event polling: {}", SDL_GetError()); } + m_motion_states.reserve(8); + m_running = true; m_thread = std::thread(&SDLControllerProvider::event_thread, this); } @@ -50,76 +53,91 @@ SDLControllerProvider::~SDLControllerProvider() m_running = false; // wake the thread with a quit event if it's currently waiting for events SDL_Event evt; - evt.type = SDL_QUIT; + evt.type = SDL_EVENT_QUIT; SDL_PushEvent(&evt); // wait until thread exited m_thread.join(); } - SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC | SDL_INIT_EVENTS); + SDL_QuitSubSystem(SDL_INIT_GAMEPAD | SDL_INIT_HAPTIC); } std::vector> SDLControllerProvider::get_controllers() { std::vector> result; - std::unordered_map guid_counter; + std::unordered_map guid_counter; TempState lock(SDL_LockJoysticks, SDL_UnlockJoysticks); - for (int i = 0; i < SDL_NumJoysticks(); ++i) + + int gamepad_count = 0; + + SDL_JoystickID *gamepad_ids = SDL_GetGamepads(&gamepad_count); + + if (gamepad_ids) { - if (SDL_JoystickGetDeviceType(i) == SDL_JOYSTICK_TYPE_GAMECONTROLLER) + for (size_t i = 0; i < gamepad_count; ++i) { - const auto guid = SDL_JoystickGetDeviceGUID(i); + const auto guid = SDL_GetGamepadGUIDForID(gamepad_ids[i]); const auto it = guid_counter.try_emplace(guid, 0); - if (auto* controller = SDL_GameControllerOpen(i)) + if (const char* name = SDL_GetGamepadNameForID(gamepad_ids[i])) { - const char* name = SDL_GameControllerName(controller); - result.emplace_back(std::make_shared(guid, it.first->second, name)); - SDL_GameControllerClose(controller); } else + { result.emplace_back(std::make_shared(guid, it.first->second)); + } ++it.first->second; } + + SDL_free(gamepad_ids); } return result; } -int SDLControllerProvider::get_index(size_t guid_index, const SDL_JoystickGUID& guid) const +int SDLControllerProvider::get_index(size_t guid_index, const SDL_GUID& guid) const { size_t index = 0; + int gamepad_count = 0; TempState lock(SDL_LockJoysticks, SDL_UnlockJoysticks); - for (int i = 0; i < SDL_NumJoysticks(); ++i) + + SDL_JoystickID *gamepad_ids = SDL_GetGamepads(&gamepad_count); + + if (gamepad_ids) { - if (SDL_JoystickGetDeviceType(i) == SDL_JOYSTICK_TYPE_GAMECONTROLLER) + for (size_t i = 0; i < gamepad_count; ++i) { - if(guid == SDL_JoystickGetDeviceGUID(i)) + if (guid == SDL_GetGamepadGUIDForID(gamepad_ids[i])) { if (index == guid_index) { + SDL_free(gamepad_ids); return i; } ++index; } - } + + SDL_free(gamepad_ids); } return -1; } -MotionSample SDLControllerProvider::motion_sample(int diid) +MotionSample SDLControllerProvider::motion_sample(SDL_JoystickID diid) { - std::scoped_lock lock(m_motion_data_mtx[diid]); - return m_motion_data[diid]; + std::shared_lock lock(m_mutex); + + auto it = m_motion_states.find(diid); + + return (it != m_motion_states.end()) ? it->second.data : MotionSample{}; } void SDLControllerProvider::event_thread() @@ -132,110 +150,126 @@ void SDLControllerProvider::event_thread() switch (event.type) { - case SDL_QUIT: + case SDL_EVENT_QUIT: + { m_running = false; return; - - case SDL_CONTROLLERAXISMOTION: /**< Game controller axis motion */ + } + + case SDL_EVENT_GAMEPAD_AXIS_MOTION: /**< Game controller axis motion */ { break; } - case SDL_CONTROLLERBUTTONDOWN: /**< Game controller button pressed */ + case SDL_EVENT_GAMEPAD_BUTTON_DOWN: /**< Game controller button pressed */ { break; } - case SDL_CONTROLLERBUTTONUP: /**< Game controller button released */ + case SDL_EVENT_GAMEPAD_BUTTON_UP: /**< Game controller button released */ { break; } - case SDL_CONTROLLERDEVICEADDED: /**< A new Game controller has been inserted into the system */ + case SDL_EVENT_GAMEPAD_ADDED: /**< A new Game controller has been inserted into the system */ { InputManager::instance().on_device_changed(); break; } - case SDL_CONTROLLERDEVICEREMOVED: /**< An opened Game controller has been removed */ + case SDL_EVENT_GAMEPAD_REMOVED: /**< An opened Game controller has been removed */ { InputManager::instance().on_device_changed(); + m_motion_states.erase(event.gdevice.which); break; } - case SDL_CONTROLLERDEVICEREMAPPED: /**< The controller mapping was updated */ + case SDL_EVENT_GAMEPAD_REMAPPED: /**< The controller mapping was updated */ { break; } - case SDL_CONTROLLERTOUCHPADDOWN: /**< Game controller touchpad was touched */ + case SDL_EVENT_GAMEPAD_TOUCHPAD_DOWN: /**< Game controller touchpad was touched */ { break; } - case SDL_CONTROLLERTOUCHPADMOTION: /**< Game controller touchpad finger was moved */ + case SDL_EVENT_GAMEPAD_TOUCHPAD_MOTION: /**< Game controller touchpad finger was moved */ { break; } - case SDL_CONTROLLERTOUCHPADUP: /**< Game controller touchpad finger was lifted */ + case SDL_EVENT_GAMEPAD_TOUCHPAD_UP: /**< Game controller touchpad finger was lifted */ { break; } - case SDL_CONTROLLERSENSORUPDATE: /**< Game controller sensor was updated */ + case SDL_EVENT_GAMEPAD_SENSOR_UPDATE: /**< Game controller sensor was updated */ { - const auto index = event.csensor.which; - const auto ts = event.csensor.timestamp; - auto& motionTracking = m_motion_tracking[index]; + SDL_JoystickID id = event.gsensor.which; + uint64_t ts = event.gsensor.timestamp; - if (event.csensor.sensor == SDL_SENSOR_ACCEL) + std::scoped_lock lock(m_mutex); + + auto& state = m_motion_states[id]; + auto& tracking = state.tracking; + + if (event.gsensor.sensor == SDL_SENSOR_ACCEL) { - const auto dif = ts - motionTracking.lastTimestampAccel; + const auto dif = ts - tracking.lastTimestampAccel; if (dif <= 0) - break; - - if (dif >= 10000) { - motionTracking.hasAcc = false; - motionTracking.hasGyro = false; - motionTracking.lastTimestampAccel = ts; break; } - motionTracking.lastTimestampAccel = ts; - motionTracking.acc[0] = -event.csensor.data[0] / 9.81f; - motionTracking.acc[1] = -event.csensor.data[1] / 9.81f; - motionTracking.acc[2] = -event.csensor.data[2] / 9.81f; - motionTracking.hasAcc = true; - } - if (event.csensor.sensor == SDL_SENSOR_GYRO) - { - const auto dif = ts - motionTracking.lastTimestampGyro; - if (dif <= 0) - break; - - if (dif >= 10000) + if (dif >= 10000000000) { - motionTracking.hasAcc = false; - motionTracking.hasGyro = false; - motionTracking.lastTimestampGyro = ts; + tracking.hasAcc = false; + tracking.hasGyro = false; + tracking.lastTimestampAccel = ts; break; } - motionTracking.lastTimestampGyro = ts; - motionTracking.gyro[0] = event.csensor.data[0]; - motionTracking.gyro[1] = -event.csensor.data[1]; - motionTracking.gyro[2] = -event.csensor.data[2]; - motionTracking.hasGyro = true; + + tracking.lastTimestampAccel = ts; + tracking.acc[0] = -event.gsensor.data[0] / 9.81f; + tracking.acc[1] = -event.gsensor.data[1] / 9.81f; + tracking.acc[2] = -event.gsensor.data[2] / 9.81f; + tracking.hasAcc = true; } - if (motionTracking.hasAcc && motionTracking.hasGyro) + if (event.gsensor.sensor == SDL_SENSOR_GYRO) { - auto ts = std::max(motionTracking.lastTimestampGyro, motionTracking.lastTimestampAccel); - if (ts > motionTracking.lastTimestampIntegrate) + const auto dif = ts - tracking.lastTimestampGyro; + if (dif <= 0) { - const auto tsDif = ts - motionTracking.lastTimestampIntegrate; - motionTracking.lastTimestampIntegrate = ts; - float tsDifD = (float)tsDif / 1000.0f; + break; + } + + if (dif >= 10000000000) + { + tracking.hasAcc = false; + tracking.hasGyro = false; + tracking.lastTimestampGyro = ts; + break; + } + + tracking.lastTimestampGyro = ts; + tracking.gyro[0] = event.gsensor.data[0]; + tracking.gyro[1] = -event.gsensor.data[1]; + tracking.gyro[2] = -event.gsensor.data[2]; + tracking.hasGyro = true; + } + if (tracking.hasAcc && tracking.hasGyro) + { + auto ts = std::max(tracking.lastTimestampGyro, tracking.lastTimestampAccel); + + if (ts > tracking.lastTimestampIntegrate) + { + const auto tsDif = ts - tracking.lastTimestampIntegrate; + tracking.lastTimestampIntegrate = ts; + float tsDifD = (float)tsDif / 1000000000.0f; + if (tsDifD >= 1.0f) + { tsDifD = 1.0f; - m_motion_handler[index].processMotionSample(tsDifD, motionTracking.gyro.x, motionTracking.gyro.y, motionTracking.gyro.z, motionTracking.acc.x, -motionTracking.acc.y, -motionTracking.acc.z); + } - std::scoped_lock lock(m_motion_data_mtx[index]); - m_motion_data[index] = m_motion_handler[index].getMotionSample(); + state.handler.processMotionSample(tsDifD, tracking.gyro.x, tracking.gyro.y, tracking.gyro.z, tracking.acc.x, -tracking.acc.y, -tracking.acc.z); + state.data = state.handler.getMotionSample(); } - motionTracking.hasAcc = false; - motionTracking.hasGyro = false; + + tracking.hasAcc = false; + tracking.hasGyro = false; } break; } diff --git a/src/input/api/SDL/SDLControllerProvider.h b/src/input/api/SDL/SDLControllerProvider.h index b736ba75..4763885e 100644 --- a/src/input/api/SDL/SDLControllerProvider.h +++ b/src/input/api/SDL/SDLControllerProvider.h @@ -1,5 +1,5 @@ #pragma once -#include +#include #include "input/motion/MotionHandler.h" #include "input/api/ControllerProvider.h" @@ -7,9 +7,9 @@ #define HAS_SDL 1 #endif -static bool operator==(const SDL_JoystickGUID& g1, const SDL_JoystickGUID& g2) +static bool operator==(const SDL_GUID& g1, const SDL_GUID& g2) { - return memcmp(&g1, &g2, sizeof(SDL_JoystickGUID)) == 0; + return memcmp(&g1, &g2, sizeof(SDL_GUID)) == 0; } class SDLControllerProvider : public ControllerProviderBase @@ -24,20 +24,17 @@ public: std::vector> get_controllers() override; - int get_index(size_t guid_index, const SDL_JoystickGUID& guid) const; + int get_index(size_t guid_index, const SDL_GUID& guid) const; - MotionSample motion_sample(int diid); + MotionSample motion_sample(SDL_JoystickID diid); private: void event_thread(); std::atomic_bool m_running = false; std::thread m_thread; - - std::array m_motion_handler{}; - std::array m_motion_data{}; - std::array m_motion_data_mtx{}; - + mutable std::shared_mutex m_mutex; + struct MotionInfoTracking { uint64 lastTimestampGyro{}; @@ -49,6 +46,14 @@ private: glm::vec3 acc{}; }; - std::array m_motion_tracking{}; + struct MotionState + { + WiiUMotionHandler handler; + MotionSample data; + MotionInfoTracking tracking; + MotionState() = default; + }; + + std::unordered_map m_motion_states{}; }; diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp index 5780909f..02e12cee 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.cpp @@ -7,18 +7,18 @@ static constexpr uint16 WIIMOTE_MP_PRODUCT_ID = 0x0330; static constexpr uint16 WIIMOTE_MAX_INPUT_REPORT_LENGTH = 22; static constexpr auto PRO_CONTROLLER_NAME = L"Nintendo RVL-CNT-01-UC"; -HidapiWiimote::HidapiWiimote(hid_device* dev, std::string_view path) +HidapiWiimote::HidapiWiimote(SDL_hid_device* dev, std::string_view path) : m_handle(dev), m_path(path) { } bool HidapiWiimote::write_data(const std::vector &data) { - return hid_write(m_handle, data.data(), data.size()) >= 0; + return SDL_hid_write(m_handle, data.data(), data.size()) >= 0; } std::optional> HidapiWiimote::read_data() { std::array read_data{}; - const auto result = hid_read(m_handle, read_data.data(), WIIMOTE_MAX_INPUT_REPORT_LENGTH); + const auto result = SDL_hid_read(m_handle, read_data.data(), WIIMOTE_MAX_INPUT_REPORT_LENGTH); if (result < 0) return {}; return {{read_data.cbegin(), read_data.cbegin() + result}}; @@ -26,24 +26,24 @@ std::optional> HidapiWiimote::read_data() { std::vector HidapiWiimote::get_devices() { std::vector wiimote_devices; - hid_init(); - const auto device_enumeration = hid_enumerate(WIIMOTE_VENDOR_ID, 0x0); + SDL_hid_init(); + const auto device_enumeration = SDL_hid_enumerate(WIIMOTE_VENDOR_ID, 0x0); for (auto it = device_enumeration; it != nullptr; it = it->next){ if (it->product_id != WIIMOTE_PRODUCT_ID && it->product_id != WIIMOTE_MP_PRODUCT_ID) continue; if (std::wcscmp(it->product_string, PRO_CONTROLLER_NAME) == 0) continue; - auto dev = hid_open_path(it->path); + auto dev = SDL_hid_open_path(it->path); if (!dev){ - cemuLog_logDebug(LogType::Force, "Unable to open Wiimote device at {}: {}", it->path, boost::nowide::narrow(hid_error(nullptr))); + cemuLog_logDebug(LogType::Force, "Unable to open Wiimote device at {}: {}", it->path, SDL_GetError()); } else { - hid_set_nonblocking(dev, true); + SDL_hid_set_nonblocking(dev, true); wiimote_devices.push_back(std::make_shared(dev, it->path)); } } - hid_free_enumeration(device_enumeration); + SDL_hid_free_enumeration(device_enumeration); return wiimote_devices; } @@ -55,5 +55,5 @@ bool HidapiWiimote::operator==(const WiimoteDevice& rhs) const { } HidapiWiimote::~HidapiWiimote() { - hid_close(m_handle); + SDL_hid_close(m_handle); } diff --git a/src/input/api/Wiimote/hidapi/HidapiWiimote.h b/src/input/api/Wiimote/hidapi/HidapiWiimote.h index 952a36f0..ffb83541 100644 --- a/src/input/api/Wiimote/hidapi/HidapiWiimote.h +++ b/src/input/api/Wiimote/hidapi/HidapiWiimote.h @@ -1,11 +1,11 @@ #pragma once #include -#include +#include class HidapiWiimote : public WiimoteDevice { public: - HidapiWiimote(hid_device* dev, std::string_view path); + HidapiWiimote(SDL_hid_device* dev, std::string_view path); ~HidapiWiimote() override; bool write_data(const std::vector &data) override; @@ -15,7 +15,7 @@ public: static std::vector get_devices(); private: - hid_device* m_handle; + SDL_hid_device* m_handle; const std::string m_path; }; diff --git a/src/main.cpp b/src/main.cpp index df2b57fb..88faece3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,8 @@ #endif #define SDL_MAIN_HANDLED -#include +#include +#include #if BOOST_OS_LINUX #define _putenv(__s) putenv((char*)(__s)) diff --git a/src/util/ScreenSaver/ScreenSaver.h b/src/util/ScreenSaver/ScreenSaver.h index 45291122..49625978 100644 --- a/src/util/ScreenSaver/ScreenSaver.h +++ b/src/util/ScreenSaver/ScreenSaver.h @@ -1,5 +1,5 @@ #include "Cemu/Logging/CemuLogging.h" -#include +#include class ScreenSaver { @@ -23,7 +23,7 @@ public: if (inhibit) { SDL_DisableScreenSaver(); - if (SDL_IsScreenSaverEnabled() == SDL_TRUE) + if (SDL_ScreenSaverEnabled()) { cemuLog_log(LogType::Force, "Could not verify if screen saver was disabled (`SDL_IsScreenSaverEnabled()` returned SDL_TRUE)"); } @@ -31,7 +31,7 @@ public: else { SDL_EnableScreenSaver(); - if (SDL_IsScreenSaverEnabled() == SDL_FALSE) + if (!SDL_ScreenSaverEnabled()) { cemuLog_log(LogType::Force, "Could not verify if screen saver was re-enabled (`SDL_IsScreenSaverEnabled()` returned SDL_FALSE)"); } diff --git a/vcpkg.json b/vcpkg.json index 634b7e5a..576c7b27 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -11,7 +11,10 @@ "default-features": false }, "rapidjson", - "sdl2", + { + "name": "sdl3", + "default-features": false + }, "boost-tokenizer", "boost-container", "boost-program-options", @@ -29,7 +32,6 @@ "name": "fmt", "version>=": "12.1.0" }, - "hidapi", "libpng", "glm", { @@ -37,7 +39,13 @@ "default-features": false }, "zstd", - "wxwidgets", + { + "name": "wxwidgets", + "default-features": false, + "features": [ + "debug-support" + ] + }, "openssl", { "name": "curl", @@ -67,8 +75,8 @@ "version": "15.1.0" }, { - "name": "sdl2", - "version": "2.32.10" + "name": "sdl3", + "version": "3.4.2" }, { "name": "wxwidgets",