mirror of
https://github.com/libsdl-org/SDL.git
synced 2026-05-21 04:53:03 +08:00
Add trigger rumble support to Emscripten joysticks
This PR adds trigger rumble support to the Emscripten joystick backend.
This commit is contained in:
@@ -448,7 +448,6 @@ static SDL_JoystickID EMSCRIPTEN_JoystickGetDeviceInstanceID(int device_index)
|
|||||||
static bool EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
static bool EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
||||||
{
|
{
|
||||||
SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
|
SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
|
||||||
bool rumble_available = false;
|
|
||||||
|
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return SDL_SetError("No such device");
|
return SDL_SetError("No such device");
|
||||||
@@ -466,22 +465,24 @@ static bool EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
|
|||||||
joystick->nbuttons = item->nbuttons;
|
joystick->nbuttons = item->nbuttons;
|
||||||
joystick->naxes = item->naxes;
|
joystick->naxes = item->naxes;
|
||||||
|
|
||||||
rumble_available = MAIN_THREAD_EM_ASM_INT({
|
item->rumble_available = MAIN_THREAD_EM_ASM_INT({
|
||||||
let gamepads = navigator['getGamepads']();
|
let gamepad = navigator['getGamepads']()[$0];
|
||||||
if (!gamepads) {
|
return gamepad && gamepad['vibrationActuator'] && gamepad['vibrationActuator']['effects']['includes']('dual-rumble');
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
let gamepad = gamepads[$0];
|
|
||||||
if (!gamepad || !gamepad['vibrationActuator']) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}, item->index);
|
}, item->index);
|
||||||
|
|
||||||
if (rumble_available) {
|
if (item->rumble_available) {
|
||||||
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true);
|
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
item->trigger_rumble_available = MAIN_THREAD_EM_ASM_INT({
|
||||||
|
let gamepad = navigator['getGamepads']()[$0];
|
||||||
|
return gamepad && gamepad['vibrationActuator'] && gamepad['vibrationActuator']['effects']['includes']('trigger-rumble');
|
||||||
|
}, item->index);
|
||||||
|
|
||||||
|
if (item->trigger_rumble_available) {
|
||||||
|
SDL_SetBooleanProperty(SDL_GetJoystickProperties(joystick), SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE_BOOLEAN, true);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,36 +583,49 @@ static SDL_GUID EMSCRIPTEN_JoystickGetDeviceGUID(int device_index)
|
|||||||
return JoystickByDeviceIndex(device_index)->guid;
|
return JoystickByDeviceIndex(device_index)->guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool EMSCRIPTEN_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
static bool Emscripten_UpdateRumble(SDL_joylist_item *item)
|
||||||
{
|
{
|
||||||
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
|
|
||||||
|
|
||||||
// clang-format off
|
|
||||||
bool result = MAIN_THREAD_EM_ASM_INT({
|
bool result = MAIN_THREAD_EM_ASM_INT({
|
||||||
let gamepads = navigator['getGamepads']();
|
let gamepad = navigator['getGamepads']()[$0];
|
||||||
if (!gamepads) {
|
if (!gamepad) {
|
||||||
return 0;
|
return false;
|
||||||
}
|
}
|
||||||
let gamepad = gamepads[$0];
|
// We check if rumble is available in EMSCRIPTEN_JoystickRumble() and EMSCRIPTEN_JoystickRumbleTriggers().
|
||||||
if (!gamepad || !gamepad['vibrationActuator']) {
|
// From my testing using "dual-rumble" here covers both main rumble and trigger rumble.
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
gamepad['vibrationActuator']['playEffect']('dual-rumble', {
|
gamepad['vibrationActuator']['playEffect']('dual-rumble', {
|
||||||
'startDelay': 0,
|
'startDelay': 0,
|
||||||
'duration': 3000,
|
'duration': 3000,
|
||||||
'weakMagnitude': $2 / 0xFFFF,
|
'weakMagnitude': $1 / 0xFFFF,
|
||||||
'strongMagnitude': $1 / 0xFFFF,
|
'strongMagnitude': $2 / 0xFFFF,
|
||||||
|
'leftTrigger': $3 / 0xFFFF,
|
||||||
|
'rightTrigger': $4 / 0xFFFF,
|
||||||
});
|
});
|
||||||
return 1;
|
|
||||||
}, item->index, low_frequency_rumble, high_frequency_rumble);
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}, item->index, item->weak_magnitude_rumble, item->strong_magnitude_rumble, item->left_trigger_rumble, item->right_trigger_rumble);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool EMSCRIPTEN_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble)
|
||||||
|
{
|
||||||
|
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
|
||||||
|
if (!item || !item->rumble_available) {
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
item->strong_magnitude_rumble = low_frequency_rumble;
|
||||||
|
item->weak_magnitude_rumble = high_frequency_rumble;
|
||||||
|
return Emscripten_UpdateRumble(item);
|
||||||
|
}
|
||||||
|
|
||||||
static bool EMSCRIPTEN_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
static bool EMSCRIPTEN_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble)
|
||||||
{
|
{
|
||||||
return SDL_Unsupported();
|
SDL_joylist_item *item = (SDL_joylist_item *)joystick->hwdata;
|
||||||
|
if (!item || !item->trigger_rumble_available) {
|
||||||
|
return SDL_Unsupported();
|
||||||
|
}
|
||||||
|
item->left_trigger_rumble = left_rumble;
|
||||||
|
item->right_trigger_rumble = right_rumble;
|
||||||
|
return Emscripten_UpdateRumble(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool EMSCRIPTEN_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
static bool EMSCRIPTEN_JoystickGetGamepadMapping(int device_index, SDL_GamepadMapping *out)
|
||||||
|
|||||||
@@ -46,6 +46,12 @@ typedef struct SDL_joylist_item
|
|||||||
double analogButton[64];
|
double analogButton[64];
|
||||||
EM_BOOL digitalButton[64];
|
EM_BOOL digitalButton[64];
|
||||||
Uint8 hat; // there is (currently) only ever one of these, faked from the d-pad buttons.
|
Uint8 hat; // there is (currently) only ever one of these, faked from the d-pad buttons.
|
||||||
|
bool rumble_available;
|
||||||
|
bool trigger_rumble_available;
|
||||||
|
Uint16 weak_magnitude_rumble;
|
||||||
|
Uint16 strong_magnitude_rumble;
|
||||||
|
Uint16 left_trigger_rumble;
|
||||||
|
Uint16 right_trigger_rumble;
|
||||||
|
|
||||||
struct SDL_joylist_item *next;
|
struct SDL_joylist_item *next;
|
||||||
} SDL_joylist_item;
|
} SDL_joylist_item;
|
||||||
|
|||||||
Reference in New Issue
Block a user