Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions core/input/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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) {
Expand Down
8 changes: 8 additions & 0 deletions core/input/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
};

Expand Down Expand Up @@ -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);
Expand Down
33 changes: 33 additions & 0 deletions doc/classes/Input.xml
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,15 @@
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
</description>
</method>
<method name="has_joy_triggers_vibration" qualifiers="const" experimental="">
<return type="bool" />
<param index="0" name="device" type="int" />
<description>
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.
</description>
</method>
<method name="is_action_just_pressed" qualifiers="const">
<return type="bool" />
<param index="0" name="action" type="StringName" />
Expand Down Expand Up @@ -657,6 +666,21 @@
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
</description>
</method>
<method name="start_joy_triggers_vibration" experimental="">
<return type="void" />
<param index="0" name="device" type="int" />
<param index="1" name="left_intensity" type="float" />
<param index="2" name="right_intensity" type="float" />
<param index="3" name="duration" type="float" />
<description>
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.
</description>
</method>
<method name="start_joy_vibration">
<return type="void" />
<param index="0" name="device" type="int" />
Expand All @@ -678,6 +702,15 @@
[b]Note:[/b] This feature is only supported on Windows, Linux, and macOS.
</description>
</method>
<method name="stop_joy_triggers_vibration" experimental="">
<return type="void" />
<param index="0" name="device" type="int" />
<description>
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.
</description>
</method>
<method name="stop_joy_vibration">
<return type="void" />
<param index="0" name="device" type="int" />
Expand Down
8 changes: 8 additions & 0 deletions drivers/sdl/joypad_sdl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Copy Markdown
Member Author

@Nintorch Nintorch Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should probably check here if SDL_RumbleJoystickTriggers doesn't return an error, and if it does, trigger vibration is not supported.

EDIT: Just remembered there should be a joystick property for that similarly to how we check for LED support.

}

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);
}
Expand Down
3 changes: 3 additions & 0 deletions drivers/sdl/joypad_sdl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down