Explorar o código

Expose Steam Controller touchpads in Gamepad API (#15378)

Kuratius hai 2 semanas
pai
achega
74a746281f
Modificáronse 1 ficheiros con 65 adicións e 0 borrados
  1. 65 0
      src/joystick/hidapi/SDL_hidapi_steam.c

+ 65 - 0
src/joystick/hidapi/SDL_hidapi_steam.c

@@ -1011,6 +1011,13 @@ typedef struct
     Uint64 sensor_timestamp;
     Uint64 pairing_time;
 
+    bool left_touch_down;
+    float left_touch_x;
+    float left_touch_y;
+    bool right_touch_down;
+    float right_touch_x;
+    float right_touch_y;
+
     SteamControllerPacketAssembler m_assembler;
     SteamControllerStateInternal_t m_state;
     SteamControllerStateInternal_t m_last_state;
@@ -1269,6 +1276,9 @@ static bool HIDAPI_DriverSteam_OpenJoystick(SDL_HIDAPI_Device *device, SDL_Joyst
     SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_GYRO, update_rate_in_hz);
     SDL_PrivateJoystickAddSensor(joystick, SDL_SENSOR_ACCEL, update_rate_in_hz);
 
+    SDL_PrivateJoystickAddTouchpad(joystick, 1);
+    SDL_PrivateJoystickAddTouchpad(joystick, 1);
+
     SDL_AddHintCallback(SDL_HINT_JOYSTICK_HIDAPI_STEAM_HOME_LED,
                         SDL_HomeLEDHintChanged, ctx);
 
@@ -1348,6 +1358,21 @@ static bool ControllerConnected(SDL_HIDAPI_Device *device, SDL_Joystick **joysti
     return true;
 }
 
+static float FilterTouch(float newValue, float oldValue)
+{
+    const float jitter = 256.0f / (1 << 16);
+    if (newValue > (oldValue - jitter * 0.5f) && newValue < (oldValue + jitter * 0.5f)) {
+        return oldValue;
+    }
+    if (newValue > (oldValue - jitter) && newValue < (oldValue + jitter)) {
+        return oldValue * 0.75f + newValue * 0.25f;
+    }
+    if (newValue > (oldValue - jitter * 2.0f) && newValue < (oldValue + jitter * 2.0f)) {
+        return (oldValue + newValue) * 0.5f;
+    }
+    return newValue;
+}
+
 static void ControllerDisconnected(SDL_HIDAPI_Device *device, SDL_Joystick **joystick)
 {
     SDL_DriverSteam_Context *ctx = (SDL_DriverSteam_Context *)device->context;
@@ -1469,6 +1494,46 @@ static bool HIDAPI_DriverSteam_UpdateDevice(SDL_HIDAPI_Device *device)
             SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTX, ctx->m_state.sRightPadX);
             SDL_SendJoystickAxis(timestamp, joystick, SDL_GAMEPAD_AXIS_RIGHTY, ~ctx->m_state.sRightPadY);
 
+            // Note that the left pad is normally mapped to D-Pad, so you should ignore that input if you use the touchpad instead.
+            {
+                const bool down = (ctx->m_state.ulButtons & STEAM_LEFTPAD_FINGERDOWN_MASK) ? true : false;
+                if (down || ctx->left_touch_down) {
+                    const bool clicked = (ctx->m_state.ulButtons & STEAM_BUTTON_LEFTPAD_CLICKED_MASK) ? true : false;
+                    const float leftX = (float)ctx->m_state.sLeftPadX / (1 << 16) + 0.5f;
+                    const float leftY = -(float)ctx->m_state.sLeftPadY / (1 << 16) + 0.5f;
+                    float pressure = down ? 0.5f : 0.0f;
+                    if (clicked) {
+                        pressure += 0.5f;
+                    }
+                    if (down) {
+                        ctx->left_touch_x = FilterTouch(leftX, ctx->left_touch_x);
+                        ctx->left_touch_y = FilterTouch(leftY, ctx->left_touch_y);
+                    }
+                    SDL_SendJoystickTouchpad(timestamp, joystick, 0, 0, down, ctx->left_touch_x, ctx->left_touch_y, pressure);
+                    ctx->left_touch_down = down;
+                }
+            }
+
+            // Note that the right pad is normally mapped to right thumbstick, so you should ignore that input if you use the touchpad instead.
+            {
+                const bool down = (ctx->m_state.ulButtons & STEAM_RIGHTPAD_FINGERDOWN_MASK) ? true : false;
+                if (down || ctx->right_touch_down) {
+                    const bool clicked = (ctx->m_state.ulButtons & STEAM_BUTTON_RIGHTPAD_CLICKED_MASK) ? true : false;
+                    const float rightX = (float)ctx->m_state.sRightPadX / (1 << 16) + 0.5f;
+                    const float rightY = -(float)ctx->m_state.sRightPadY / (1 << 16) + 0.5f;
+                    float pressure = down ? 0.5f : 0.0f;
+                    if (clicked) {
+                        pressure += 0.5f;
+                    }
+                    if (down) {
+                        ctx->right_touch_x = FilterTouch(rightX, ctx->right_touch_x);
+                        ctx->right_touch_y = FilterTouch(rightY, ctx->right_touch_y);
+                    }
+                    SDL_SendJoystickTouchpad(timestamp, joystick, 1, 0, down, ctx->right_touch_x, ctx->right_touch_y, pressure);
+                    ctx->right_touch_down = down;
+                }
+            }
+
             if (ctx->report_sensors) {
                 float values[3];