Ver código fonte

Add trigger rumble support to Emscripten joysticks

This PR adds trigger rumble support to the Emscripten joystick backend.
Nintorch 2 semanas atrás
pai
commit
651136ac7a

+ 43 - 29
src/joystick/emscripten/SDL_sysjoystick.c

@@ -448,7 +448,6 @@ static SDL_JoystickID EMSCRIPTEN_JoystickGetDeviceInstanceID(int device_index)
 static bool EMSCRIPTEN_JoystickOpen(SDL_Joystick *joystick, int device_index)
 {
     SDL_joylist_item *item = JoystickByDeviceIndex(device_index);
-    bool rumble_available = false;
 
     if (!item) {
         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->naxes = item->naxes;
 
-    rumble_available = MAIN_THREAD_EM_ASM_INT({
-        let gamepads = navigator['getGamepads']();
-        if (!gamepads) {
-            return 0;
-        }
-        let gamepad = gamepads[$0];
-        if (!gamepad || !gamepad['vibrationActuator']) {
-            return 0;
-        }
-        return 1;
+    item->rumble_available = MAIN_THREAD_EM_ASM_INT({
+        let gamepad = navigator['getGamepads']()[$0];
+        return gamepad && gamepad['vibrationActuator'] && gamepad['vibrationActuator']['effects']['includes']('dual-rumble');
         }, item->index);
 
-    if (rumble_available) {
+    if (item->rumble_available) {
         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;
 }
 
@@ -582,36 +583,49 @@ static SDL_GUID EMSCRIPTEN_JoystickGetDeviceGUID(int device_index)
     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({
-        let gamepads = navigator['getGamepads']();
-        if (!gamepads) {
-            return 0;
-        }
-        let gamepad = gamepads[$0];
-        if (!gamepad || !gamepad['vibrationActuator']) {
-            return 0;
+        let gamepad = navigator['getGamepads']()[$0];
+        if (!gamepad) {
+            return false;
         }
-
+        // We check if rumble is available in EMSCRIPTEN_JoystickRumble() and EMSCRIPTEN_JoystickRumbleTriggers().
+        // From my testing using "dual-rumble" here covers both main rumble and trigger rumble.
         gamepad['vibrationActuator']['playEffect']('dual-rumble', {
             'startDelay': 0,
             'duration': 3000,
-            'weakMagnitude': $2 / 0xFFFF,
-            'strongMagnitude': $1 / 0xFFFF,
+            'weakMagnitude': $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;
 }
 
+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)
 {
-    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)

+ 6 - 0
src/joystick/emscripten/SDL_sysjoystick_c.h

@@ -46,6 +46,12 @@ typedef struct SDL_joylist_item
     double analogButton[64];
     EM_BOOL digitalButton[64];
     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;
 } SDL_joylist_item;