mirror of
https://github.com/RetroDECK/Duckstation.git
synced 2025-01-18 06:25:37 +00:00
SDLControllerInterface: Use SDL_GameControllerRumble where supported
Allows vibration on DualShock 4 without using DS4Windows.
This commit is contained in:
parent
bea6f0beb4
commit
3ffbbe82e8
|
@ -77,7 +77,7 @@ Other features include:
|
||||||
## System Requirements
|
## System Requirements
|
||||||
- A CPU faster than a potato. But it needs to be x86_64, AArch32/armv7, or AArch64/ARMv8, otherwise you won't get a recompiler and it'll be slow.
|
- A CPU faster than a potato. But it needs to be x86_64, AArch32/armv7, or AArch64/ARMv8, otherwise you won't get a recompiler and it'll be slow.
|
||||||
- For the hardware renderers, a GPU capable of OpenGL 3.1/OpenGL ES 3.0/Direct3D 11 Feature Level 10.0 (or Vulkan 1.0) and above. So, basically anything made in the last 10 years or so.
|
- For the hardware renderers, a GPU capable of OpenGL 3.1/OpenGL ES 3.0/Direct3D 11 Feature Level 10.0 (or Vulkan 1.0) and above. So, basically anything made in the last 10 years or so.
|
||||||
- SDL, XInput or DInput compatible game controller (e.g. XB360/XBOne). DualShock 3 users on Windows will need to install the official DualShock 3 drivers included as part of PlayStation Now. DualShock 4 users will need to use a wrapper such as DS4Windows for vibration support.
|
- SDL, XInput or DInput compatible game controller (e.g. XB360/XBOne). DualShock 3 users on Windows will need to install the official DualShock 3 drivers included as part of PlayStation Now.
|
||||||
|
|
||||||
## Downloading and running
|
## Downloading and running
|
||||||
Binaries of DuckStation for Windows x64/ARM64, x86_64 Linux x86_64 (in AppImage format), and Android ARMv8/AArch64 are available via GitHub Releases and are automatically built with every commit/push. Binaries or packages distributed through other sources may be out of date and are not supported by the developer.
|
Binaries of DuckStation for Windows x64/ARM64, x86_64 Linux x86_64 (in AppImage format), and Android ARMv8/AArch64 are available via GitHub Releases and are automatically built with every commit/push. Binaries or packages distributed through other sources may be out of date and are not supported by the developer.
|
||||||
|
|
|
@ -203,8 +203,20 @@ bool SDLControllerInterface::OpenGameController(int index)
|
||||||
cd.player_id = player_id;
|
cd.player_id = player_id;
|
||||||
cd.joystick_id = joystick_id;
|
cd.joystick_id = joystick_id;
|
||||||
cd.haptic_left_right_effect = -1;
|
cd.haptic_left_right_effect = -1;
|
||||||
cd.is_game_controller = true;
|
cd.game_controller = gcontroller;
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 9)
|
||||||
|
cd.use_game_controller_rumble = (SDL_GameControllerRumble(gcontroller, 0, 0, 0) == 0);
|
||||||
|
#else
|
||||||
|
cd.use_game_controller_rumble = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (cd.use_game_controller_rumble)
|
||||||
|
{
|
||||||
|
Log_InfoPrintf("Rumble is supported on '%s' via gamecontroller", SDL_GameControllerName(gcontroller));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
SDL_Haptic* haptic = SDL_HapticOpenFromJoystick(joystick);
|
SDL_Haptic* haptic = SDL_HapticOpenFromJoystick(joystick);
|
||||||
if (haptic)
|
if (haptic)
|
||||||
{
|
{
|
||||||
|
@ -234,8 +246,10 @@ bool SDLControllerInterface::OpenGameController(int index)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cd.haptic)
|
if (cd.haptic)
|
||||||
Log_InfoPrintf("Rumble is supported on '%s'", SDL_GameControllerName(gcontroller));
|
Log_InfoPrintf("Rumble is supported on '%s' via haptic", SDL_GameControllerName(gcontroller));
|
||||||
else
|
}
|
||||||
|
|
||||||
|
if (!cd.haptic && !cd.use_game_controller_rumble)
|
||||||
Log_WarningPrintf("Rumble is not supported on '%s'", SDL_GameControllerName(gcontroller));
|
Log_WarningPrintf("Rumble is not supported on '%s'", SDL_GameControllerName(gcontroller));
|
||||||
|
|
||||||
m_controllers.push_back(std::move(cd));
|
m_controllers.push_back(std::move(cd));
|
||||||
|
@ -254,7 +268,7 @@ bool SDLControllerInterface::CloseGameController(int joystick_index, bool notify
|
||||||
if (it->haptic)
|
if (it->haptic)
|
||||||
SDL_HapticClose(static_cast<SDL_Haptic*>(it->haptic));
|
SDL_HapticClose(static_cast<SDL_Haptic*>(it->haptic));
|
||||||
|
|
||||||
SDL_GameControllerClose(SDL_GameControllerFromInstanceID(joystick_index));
|
SDL_GameControllerClose(static_cast<SDL_GameController*>(it->game_controller));
|
||||||
m_controllers.erase(it);
|
m_controllers.erase(it);
|
||||||
|
|
||||||
if (notify)
|
if (notify)
|
||||||
|
@ -295,7 +309,8 @@ bool SDLControllerInterface::OpenJoystick(int index)
|
||||||
cd.player_id = player_id;
|
cd.player_id = player_id;
|
||||||
cd.joystick_id = joystick_id;
|
cd.joystick_id = joystick_id;
|
||||||
cd.haptic_left_right_effect = -1;
|
cd.haptic_left_right_effect = -1;
|
||||||
cd.is_game_controller = false;
|
cd.game_controller = nullptr;
|
||||||
|
cd.use_game_controller_rumble = false;
|
||||||
|
|
||||||
SDL_Haptic* haptic = SDL_HapticOpenFromJoystick(joystick);
|
SDL_Haptic* haptic = SDL_HapticOpenFromJoystick(joystick);
|
||||||
if (haptic)
|
if (haptic)
|
||||||
|
@ -341,7 +356,7 @@ bool SDLControllerInterface::HandleJoystickAxisEvent(const SDL_JoyAxisEvent* eve
|
||||||
Log_DebugPrintf("controller %d axis %d %d %f", event->which, event->axis, event->value, value);
|
Log_DebugPrintf("controller %d axis %d %d %f", event->which, event->axis, event->value, value);
|
||||||
|
|
||||||
auto it = GetControllerDataForJoystickId(event->which);
|
auto it = GetControllerDataForJoystickId(event->which);
|
||||||
if (it == m_controllers.end() || it->is_game_controller)
|
if (it == m_controllers.end() || it->IsGameController())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (DoEventHook(Hook::Type::Axis, it->player_id, event->axis, value, true))
|
if (DoEventHook(Hook::Type::Axis, it->player_id, event->axis, value, true))
|
||||||
|
@ -409,7 +424,7 @@ bool SDLControllerInterface::HandleJoystickButtonEvent(const SDL_JoyButtonEvent*
|
||||||
event->state == SDL_PRESSED ? "pressed" : "released");
|
event->state == SDL_PRESSED ? "pressed" : "released");
|
||||||
|
|
||||||
auto it = GetControllerDataForJoystickId(event->which);
|
auto it = GetControllerDataForJoystickId(event->which);
|
||||||
if (it == m_controllers.end() || it->is_game_controller)
|
if (it == m_controllers.end() || it->IsGameController())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const bool pressed = (event->state == SDL_PRESSED);
|
const bool pressed = (event->state == SDL_PRESSED);
|
||||||
|
@ -438,7 +453,7 @@ bool SDLControllerInterface::HandleJoystickHatEvent(const SDL_JoyHatEvent* event
|
||||||
Log_DebugPrintf("controller %d hat %d %d", event->which, event->hat, event->value);
|
Log_DebugPrintf("controller %d hat %d %d", event->which, event->hat, event->value);
|
||||||
|
|
||||||
auto it = GetControllerDataForJoystickId(event->which);
|
auto it = GetControllerDataForJoystickId(event->which);
|
||||||
if (it == m_controllers.end() || it->is_game_controller)
|
if (it == m_controllers.end() || it->IsGameController())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto HatEventHook = [hat = event->hat, value = event->value, player_id = it->player_id, this](int hat_position) {
|
auto HatEventHook = [hat = event->hat, value = event->value, player_id = it->player_id, this](int hat_position) {
|
||||||
|
@ -685,7 +700,7 @@ u32 SDLControllerInterface::GetControllerRumbleMotorCount(int controller_index)
|
||||||
if (it == m_controllers.end())
|
if (it == m_controllers.end())
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return (it->haptic_left_right_effect >= 0) ? 2 : (it->haptic ? 1 : 0);
|
return (it->use_game_controller_rumble ? 2 : ((it->haptic_left_right_effect >= 0) ? 2 : (it->haptic ? 1 : 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SDLControllerInterface::SetControllerRumbleStrength(int controller_index, const float* strengths, u32 num_motors)
|
void SDLControllerInterface::SetControllerRumbleStrength(int controller_index, const float* strengths, u32 num_motors)
|
||||||
|
@ -695,7 +710,17 @@ void SDLControllerInterface::SetControllerRumbleStrength(int controller_index, c
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// we'll update before this duration is elapsed
|
// we'll update before this duration is elapsed
|
||||||
static constexpr u32 DURATION = 100000;
|
static constexpr u32 DURATION = 1000;
|
||||||
|
|
||||||
|
#if SDL_VERSION_ATLEAST(2, 0, 9)
|
||||||
|
if (it->use_game_controller_rumble)
|
||||||
|
{
|
||||||
|
const u16 large = static_cast<u16>(strengths[0] * 65535.0f);
|
||||||
|
const u16 small = static_cast<u32>(strengths[1] * 65535.0f);
|
||||||
|
SDL_GameControllerRumble(static_cast<SDL_GameController*>(it->game_controller), large, small, DURATION);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_Haptic* haptic = static_cast<SDL_Haptic*>(it->haptic);
|
SDL_Haptic* haptic = static_cast<SDL_Haptic*>(it->haptic);
|
||||||
if (it->haptic_left_right_effect >= 0 && num_motors > 1)
|
if (it->haptic_left_right_effect >= 0 && num_motors > 1)
|
||||||
|
|
|
@ -46,10 +46,11 @@ private:
|
||||||
struct ControllerData
|
struct ControllerData
|
||||||
{
|
{
|
||||||
void* haptic;
|
void* haptic;
|
||||||
|
void* game_controller;
|
||||||
int haptic_left_right_effect;
|
int haptic_left_right_effect;
|
||||||
int joystick_id;
|
int joystick_id;
|
||||||
int player_id;
|
int player_id;
|
||||||
bool is_game_controller;
|
bool use_game_controller_rumble;
|
||||||
|
|
||||||
float deadzone = 0.25f;
|
float deadzone = 0.25f;
|
||||||
|
|
||||||
|
@ -60,6 +61,8 @@ private:
|
||||||
std::array<std::array<ButtonCallback, 2>, MAX_NUM_AXISES> axis_button_mapping;
|
std::array<std::array<ButtonCallback, 2>, MAX_NUM_AXISES> axis_button_mapping;
|
||||||
std::array<AxisCallback, MAX_NUM_BUTTONS> button_axis_mapping;
|
std::array<AxisCallback, MAX_NUM_BUTTONS> button_axis_mapping;
|
||||||
std::vector<std::array<ButtonCallback, 4>> hat_button_mapping;
|
std::vector<std::array<ButtonCallback, 4>> hat_button_mapping;
|
||||||
|
|
||||||
|
ALWAYS_INLINE bool IsGameController() const { return (game_controller != nullptr); }
|
||||||
};
|
};
|
||||||
|
|
||||||
using ControllerDataVector = std::vector<ControllerData>;
|
using ControllerDataVector = std::vector<ControllerData>;
|
||||||
|
|
Loading…
Reference in a new issue