mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-04-11 02:41:32 -06:00
Merge 602726b1dd into b3e310220e
This commit is contained in:
commit
3ea56457fa
@ -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 ()
|
||||
|
||||
2
dependencies/vcpkg
vendored
2
dependencies/vcpkg
vendored
@ -1 +1 @@
|
||||
Subproject commit af752f21c9d79ba3df9cb0250ce2233933f58486
|
||||
Subproject commit c3867e714dd3a51c272826eea77267876517ed99
|
||||
@ -166,7 +166,7 @@ target_link_libraries(CemuBin PRIVATE
|
||||
CemuGui
|
||||
CemuInput
|
||||
CemuUtil
|
||||
SDL2::SDL2
|
||||
SDL3::SDL3
|
||||
)
|
||||
|
||||
if(UNIX AND NOT APPLE)
|
||||
|
||||
@ -145,7 +145,7 @@ target_link_libraries(CemuWxGui PRIVATE
|
||||
libzip::zip
|
||||
ZArchive::zarchive
|
||||
CemuComponents
|
||||
SDL2::SDL2
|
||||
SDL3::SDL3
|
||||
pugixml::pugixml
|
||||
CemuCafe
|
||||
PUBLIC
|
||||
|
||||
@ -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 ()
|
||||
|
||||
@ -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<size_t>(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<SDLController>(guid, guid_index);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -3,13 +3,13 @@
|
||||
#include "input/api/Controller.h"
|
||||
#include "input/api/SDL/SDLControllerProvider.h"
|
||||
|
||||
#include <SDL2/SDL_gamecontroller.h>
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
|
||||
class SDLController : public Controller<SDLControllerProvider>
|
||||
{
|
||||
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<bool, SDL_CONTROLLER_BUTTON_MAX> m_buttons{};
|
||||
std::array<bool, SDL_CONTROLLER_AXIS_MAX> m_axis{};
|
||||
std::array<bool, SDL_GAMEPAD_BUTTON_COUNT> m_buttons{};
|
||||
std::array<bool, SDL_GAMEPAD_AXIS_COUNT> m_axis{};
|
||||
};
|
||||
|
||||
|
||||
@ -3,12 +3,12 @@
|
||||
#include "input/api/SDL/SDLController.h"
|
||||
#include "util/helpers/TempState.h"
|
||||
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
||||
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<std::shared_ptr<ControllerBase>> SDLControllerProvider::get_controllers()
|
||||
{
|
||||
std::vector<std::shared_ptr<ControllerBase>> result;
|
||||
|
||||
std::unordered_map<SDL_JoystickGUID, size_t, SDL_JoystickGUIDHash> guid_counter;
|
||||
std::unordered_map<SDL_GUID, size_t, SDL_JoystickGUIDHash> 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<SDLController>(guid, it.first->second, name));
|
||||
SDL_GameControllerClose(controller);
|
||||
}
|
||||
else
|
||||
{
|
||||
result.emplace_back(std::make_shared<SDLController>(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;
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include <SDL2/SDL_joystick.h>
|
||||
#include <SDL3/SDL_joystick.h>
|
||||
#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<std::shared_ptr<ControllerBase>> 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<WiiUMotionHandler, 8> m_motion_handler{};
|
||||
std::array<MotionSample, 8> m_motion_data{};
|
||||
std::array<std::mutex, 8> m_motion_data_mtx{};
|
||||
|
||||
mutable std::shared_mutex m_mutex;
|
||||
|
||||
struct MotionInfoTracking
|
||||
{
|
||||
uint64 lastTimestampGyro{};
|
||||
@ -49,6 +46,14 @@ private:
|
||||
glm::vec3 acc{};
|
||||
};
|
||||
|
||||
std::array<MotionInfoTracking, 8> m_motion_tracking{};
|
||||
struct MotionState
|
||||
{
|
||||
WiiUMotionHandler handler;
|
||||
MotionSample data;
|
||||
MotionInfoTracking tracking;
|
||||
|
||||
MotionState() = default;
|
||||
};
|
||||
|
||||
std::unordered_map<SDL_JoystickID, MotionState> m_motion_states{};
|
||||
};
|
||||
|
||||
@ -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<uint8> &data) {
|
||||
return hid_write(m_handle, data.data(), data.size()) >= 0;
|
||||
return SDL_hid_write(m_handle, data.data(), data.size()) >= 0;
|
||||
}
|
||||
|
||||
std::optional<std::vector<uint8>> HidapiWiimote::read_data() {
|
||||
std::array<uint8, WIIMOTE_MAX_INPUT_REPORT_LENGTH> 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<std::vector<uint8>> HidapiWiimote::read_data() {
|
||||
|
||||
std::vector<WiimoteDevicePtr> HidapiWiimote::get_devices() {
|
||||
std::vector<WiimoteDevicePtr> 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<HidapiWiimote>(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);
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <api/Wiimote/WiimoteDevice.h>
|
||||
#include <hidapi.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
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<uint8> &data) override;
|
||||
@ -15,7 +15,7 @@ public:
|
||||
static std::vector<WiimoteDevicePtr> get_devices();
|
||||
|
||||
private:
|
||||
hid_device* m_handle;
|
||||
SDL_hid_device* m_handle;
|
||||
const std::string m_path;
|
||||
|
||||
};
|
||||
|
||||
@ -31,7 +31,8 @@
|
||||
#endif
|
||||
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include <SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_main.h>
|
||||
|
||||
#if BOOST_OS_LINUX
|
||||
#define _putenv(__s) putenv((char*)(__s))
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#include "Cemu/Logging/CemuLogging.h"
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL3/SDL.h>
|
||||
|
||||
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)");
|
||||
}
|
||||
|
||||
18
vcpkg.json
18
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",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user