diff --git a/core/input/input.cpp b/core/input/input.cpp index 4d32ddf8d7ba..8ae3bf588470 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -149,6 +149,9 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("start_joy_vibration", "device", "weak_magnitude", "strong_magnitude", "duration"), &Input::start_joy_vibration, DEFVAL(0)); ClassDB::bind_method(D_METHOD("stop_joy_vibration", "device"), &Input::stop_joy_vibration); ClassDB::bind_method(D_METHOD("vibrate_handheld", "duration_ms", "amplitude"), &Input::vibrate_handheld, DEFVAL(500), DEFVAL(-1.0)); + ClassDB::bind_method(D_METHOD("start_joy_triggers_vibration", "device", "left_intensity", "right_intensity", "duration"), &Input::start_joy_triggers_vibration); + ClassDB::bind_method(D_METHOD("stop_joy_triggers_vibration", "device"), &Input::stop_joy_triggers_vibration); + ClassDB::bind_method(D_METHOD("has_joy_triggers_vibration", "device"), &Input::has_joy_triggers_vibration); ClassDB::bind_method(D_METHOD("get_gravity"), &Input::get_gravity); ClassDB::bind_method(D_METHOD("get_accelerometer"), &Input::get_accelerometer); ClassDB::bind_method(D_METHOD("get_magnetometer"), &Input::get_magnetometer); @@ -1246,6 +1249,35 @@ void Input::stop_joy_vibration(int p_device) { joy_vibration[p_device] = vibration; } +bool Input::has_joy_triggers_vibration(int p_device) const { + _THREAD_SAFE_METHOD_ + const Joypad *joypad = joy_names.getptr(p_device); + return joypad != nullptr && joypad->has_triggers_vibration; +} + +void Input::start_joy_triggers_vibration(int p_device, float p_left_intensity, float p_right_intensity, float p_duration) { + _THREAD_SAFE_METHOD_ + if (p_left_intensity < 0 || p_left_intensity > 1 || p_right_intensity < 0 || p_right_intensity > 1 || p_duration < 0) { + return; + } + + Joypad *joypad = joy_names.getptr(p_device); + if (!joypad || joypad->features == nullptr) { + return; + } + + joypad->features->start_joy_triggers_vibration(p_left_intensity, p_right_intensity, p_duration); +} + +void Input::stop_joy_triggers_vibration(int p_device) { + _THREAD_SAFE_METHOD_ + Joypad *joypad = joy_names.getptr(p_device); + if (!joypad || joypad->features == nullptr) { + return; + } + joypad->features->start_joy_triggers_vibration(0.0f, 0.0f, 0.0f); +} + void Input::vibrate_handheld(int p_duration_ms, float p_amplitude) { OS::get_singleton()->vibrate_handheld(p_duration_ms, p_amplitude); } @@ -1751,6 +1783,9 @@ void Input::_update_joypad_features(int p_device) { } motion.last_timestamp = OS::get_singleton()->get_ticks_msec(); } + if (joypad->features->has_joy_triggers_vibration()) { + joypad->has_triggers_vibration = true; + } } Input::JoyEvent Input::_get_mapped_button_event(const JoyDeviceMapping &mapping, JoyButton p_button) { diff --git a/core/input/input.h b/core/input/input.h index 41bea926ad6a..2b71ac08fb6e 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -96,6 +96,9 @@ class Input : public Object { virtual bool has_joy_motion_sensors() const { return false; } virtual void set_joy_motion_sensors_enabled(bool p_enable) {} + + virtual bool has_joy_triggers_vibration() const { return false; } + virtual void start_joy_triggers_vibration(float p_left_intensity, float p_right_intensity, float p_duration) {} }; static constexpr int32_t JOYPADS_MAX = 16; @@ -212,6 +215,7 @@ class Input : public Object { int hat_current = 0; Dictionary info; bool has_light = false; + bool has_triggers_vibration = false; Input::JoypadFeatures *features = nullptr; }; @@ -417,6 +421,10 @@ class Input : public Object { void stop_joy_vibration(int p_device); void vibrate_handheld(int p_duration_ms = 500, float p_amplitude = -1.0); + bool has_joy_triggers_vibration(int p_device) const; + void start_joy_triggers_vibration(int p_device, float p_left_intensity, float p_right_intensity, float p_duration); + void stop_joy_triggers_vibration(int p_device); + void set_mouse_position(const Point2 &p_posf); void action_press(const StringName &p_action, float p_strength = 1.f); diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 6cd6d22eaa5b..ddd6d2d8cea0 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -285,6 +285,15 @@ [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + + + + Returns [code]true[/code] if the joypad has triggers vibration (trigger rumble). + [b]Note:[/b] This feature is only supported on Xbox One controllers. + [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + @@ -657,6 +666,21 @@ [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + + + + + + + Starts triggers vibration (trigger rumble) on the specified joypad, if available. Not to be confused with DualSense's adaptive triggers. + [param left_intensity] should be in the range from [code]0.0[/code] to [code]1.0[/code] (inclusive). + [param right_intensity] should be in the range from [code]0.0[/code] to [code]1.0[/code] (inclusive). + [param duration] should not be negative (a duration of [code]0.0[/code] will try to play the vibration indefinitely). + [b]Note:[/b] This feature is only supported on Xbox One controllers. + [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + @@ -678,6 +702,15 @@ [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + + + + Stops triggers vibration (trigger rumble) on the specified joypad, if available. See also [method start_joy_triggers_vibration]. Not to be confused with DualSense's adaptive triggers. + [b]Note:[/b] This feature is only supported on Xbox One controllers. + [b]Note:[/b] This feature is only supported on Windows, Linux, and macOS. + + diff --git a/drivers/sdl/joypad_sdl.cpp b/drivers/sdl/joypad_sdl.cpp index 4ecc5db2c98a..ef1de313b0ab 100644 --- a/drivers/sdl/joypad_sdl.cpp +++ b/drivers/sdl/joypad_sdl.cpp @@ -333,6 +333,14 @@ void JoypadSDL::Joypad::set_joy_motion_sensors_enabled(bool p_enable) { SDL_SetGamepadSensorEnabled(gamepad, SDL_SENSOR_GYRO, p_enable); } +bool JoypadSDL::Joypad::has_joy_triggers_vibration() const { + return SDL_GetGamepadTypeForID(sdl_instance_idx) == SDL_GAMEPAD_TYPE_XBOXONE; +} + +void JoypadSDL::Joypad::start_joy_triggers_vibration(float p_left_intensity, float p_right_intensity, float p_duration) { + SDL_RumbleJoystickTriggers(get_sdl_joystick(), p_left_intensity * 0xFFFF, p_right_intensity * 0xFFFF, p_duration * 1000); +} + SDL_Joystick *JoypadSDL::Joypad::get_sdl_joystick() const { return SDL_GetJoystickFromID(sdl_instance_idx); } diff --git a/drivers/sdl/joypad_sdl.h b/drivers/sdl/joypad_sdl.h index 0b16900e8956..f875384a2122 100644 --- a/drivers/sdl/joypad_sdl.h +++ b/drivers/sdl/joypad_sdl.h @@ -62,6 +62,9 @@ class JoypadSDL { virtual bool has_joy_motion_sensors() const override; virtual void set_joy_motion_sensors_enabled(bool p_enable) override; + virtual bool has_joy_triggers_vibration() const override; + virtual void start_joy_triggers_vibration(float p_left_intensity, float p_right_intensity, float p_duration) override; + SDL_Joystick *get_sdl_joystick() const; SDL_Gamepad *get_sdl_gamepad() const; };