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;
};