Add support for joypad motion sensors

This commit is contained in:
Nintorch 2025-12-05 17:47:31 +05:00
parent 481f36ed20
commit a3eb202b25
10 changed files with 1940 additions and 0 deletions

View file

@ -169,6 +169,7 @@ void JoypadSDL::process_events() {
joypads[joy_id].sdl_instance_idx = sdl_event.jdevice.which;
joypads[joy_id].supports_force_feedback = SDL_GetBooleanProperty(propertiesID, SDL_PROP_JOYSTICK_CAP_RUMBLE_BOOLEAN, false);
joypads[joy_id].guid = StringName(String(guid));
joypads[joy_id].supports_motion_sensors = SDL_GamepadHasSensor(gamepad, SDL_SENSOR_ACCEL) && SDL_GamepadHasSensor(gamepad, SDL_SENSOR_GYRO);
sdl_instance_id_to_joypad_id.insert(sdl_event.jdevice.which, joy_id);
@ -198,6 +199,11 @@ void JoypadSDL::process_events() {
joypad_info);
Input::get_singleton()->set_joy_features(joy_id, &joypads[joy_id]);
if (joypads[joy_id].supports_motion_sensors) {
// Data rate for all sensors should be the same.
Input::get_singleton()->set_joy_motion_sensors_rate(joy_id, SDL_GetGamepadSensorDataRate(gamepad, SDL_SENSOR_ACCEL));
}
}
// An event for an attached joypad
} else if (sdl_event.type >= SDL_EVENT_JOYSTICK_AXIS_MOTION && sdl_event.type < SDL_EVENT_FINGER_DOWN && sdl_instance_id_to_joypad_id.has(sdl_event.jdevice.which)) {
@ -272,6 +278,25 @@ void JoypadSDL::process_events() {
}
}
}
for (int i = 0; i < Input::JOYPADS_MAX; i++) {
Joypad &joy = joypads[i];
if (!joy.attached || !joy.supports_motion_sensors) {
continue;
}
SDL_Gamepad *gamepad = SDL_GetGamepadFromID(joy.sdl_instance_idx);
// gamepad should not be NULL since joy.supports_motion_sensors is true here.
float accel_data[3];
float gyro_data[3];
SDL_GetGamepadSensorData(gamepad, SDL_SENSOR_ACCEL, accel_data, 3);
SDL_GetGamepadSensorData(gamepad, SDL_SENSOR_GYRO, gyro_data, 3);
Input::get_singleton()->joy_motion_sensors(
i,
Vector3(-accel_data[0], -accel_data[1], -accel_data[2]),
Vector3(gyro_data[0], gyro_data[1], gyro_data[2]));
}
}
void JoypadSDL::close_joypad(int p_pad_idx) {
@ -301,6 +326,16 @@ void JoypadSDL::Joypad::set_joy_light(const Color &p_color) {
SDL_SetJoystickLED(get_sdl_joystick(), p_color.get_r8(), p_color.get_g8(), p_color.get_b8());
}
bool JoypadSDL::Joypad::has_joy_motion_sensors() const {
return supports_motion_sensors;
}
void JoypadSDL::Joypad::set_joy_motion_sensors_enabled(bool p_enable) {
SDL_Gamepad *gamepad = get_sdl_gamepad();
SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_ACCEL, p_enable);
SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_GYRO, p_enable);
}
SDL_Joystick *JoypadSDL::Joypad::get_sdl_joystick() const {
return SDL_GetJoystickFromID(sdl_instance_idx);
}

View file

@ -56,11 +56,15 @@ private:
SDL_JoystickID sdl_instance_idx;
bool supports_force_feedback = false;
bool supports_motion_sensors = false;
uint64_t ff_effect_timestamp = 0;
virtual bool has_joy_light() const override;
virtual void set_joy_light(const Color &p_color) override;
virtual bool has_joy_motion_sensors() const override;
virtual void set_joy_motion_sensors_enabled(bool p_enable) override;
SDL_Joystick *get_sdl_joystick() const;
SDL_Gamepad *get_sdl_gamepad() const;
};