diff --git a/doc/classes/Input.xml b/doc/classes/Input.xml index 805576f17014..74e54a89ded8 100644 --- a/doc/classes/Input.xml +++ b/doc/classes/Input.xml @@ -433,7 +433,7 @@ Starts to vibrate the joypad. Joypads usually come with two rumble motors, a strong and a weak one. [param weak_magnitude] is the strength of the weak motor (between 0 and 1) and [param strong_magnitude] is the strength of the strong motor (between 0 and 1). [param duration] is the duration of the effect in seconds (a duration of 0 will try to play the vibration indefinitely). The vibration can be stopped early by calling [method stop_joy_vibration]. [b]Note:[/b] Not every hardware is compatible with long effect durations; it is recommended to restart an effect if it has to be played for more than a few seconds. - [b]Note:[/b] For macOS, vibration is only supported in macOS 11 and later. + [b]Note:[/b] For Android and web browsers running on Android, joypad vibration is not supported due to OS restrictions. For macOS, vibration is only supported in macOS 11 and later. For the web browsers running on macOS, vibration only works in Safari. diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index eda004f908d4..47e299beec61 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -991,6 +991,8 @@ void DisplayServerWeb::process_joypads() { for (int a = 0; a < s_axes_num; a++) { input->joy_axis(idx, (JoyAxis)a, s_axes[a]); } + Vector2 vibration_strength = input->get_joy_vibration_strength(idx); + godot_js_input_gamepad_process_vibration(idx, input->get_joy_vibration_timestamp(idx), vibration_strength.x, vibration_strength.y, input->get_joy_vibration_duration(idx)); } } diff --git a/platform/web/godot_js.h b/platform/web/godot_js.h index 29b291d566a4..8d9ea49b6dc3 100644 --- a/platform/web/godot_js.h +++ b/platform/web/godot_js.h @@ -76,6 +76,7 @@ extern void godot_js_input_gamepad_cb(void (*p_on_change)(int p_index, int p_con extern int godot_js_input_gamepad_sample(); extern int godot_js_input_gamepad_sample_count(); extern int godot_js_input_gamepad_sample_get(int p_idx, float r_btns[16], int32_t *r_btns_num, float r_axes[10], int32_t *r_axes_num, int32_t *r_standard); +extern void godot_js_input_gamepad_process_vibration(int p_index, double p_timestamp, float p_weak_magnitude, float p_strong_magnitude, float p_duration); extern void godot_js_input_paste_cb(void (*p_callback)(const char *p_text)); extern void godot_js_input_drop_files_cb(void (*p_callback)(const char **p_filev, int p_filec)); diff --git a/platform/web/js/libs/library_godot_input.js b/platform/web/js/libs/library_godot_input.js index 576d1a7e2196..d4ab2fb9c0ef 100644 --- a/platform/web/js/libs/library_godot_input.js +++ b/platform/web/js/libs/library_godot_input.js @@ -177,6 +177,7 @@ const GodotInputGamepads = { $GodotInputGamepads__deps: ['$GodotRuntime', '$GodotEventListeners'], $GodotInputGamepads: { samples: [], + vibration_timestamp: [], get_pads: function () { try { @@ -228,6 +229,29 @@ const GodotInputGamepads = { GodotInputGamepads.samples = samples; }, + process_vibration: function (index, timestamp, weak_magnitude, strong_magnitude, duration) { + const pad = GodotInputGamepads.get_pads()[index]; + if (!pad) { + return; + } + const actuator = pad['vibrationActuator']; + if (!actuator) { + return; + } + const prev_timestamp = GodotInputGamepads.vibration_timestamp[index]; + if (prev_timestamp >= timestamp) { + return; + } + GodotInputGamepads.vibration_timestamp[index] = timestamp; + + actuator['playEffect']('dual-rumble', { + 'startDelay': 0, + 'duration': duration * 1000, + 'weakMagnitude': weak_magnitude, + 'strongMagnitude': strong_magnitude, + }); + }, + init: function (onchange) { GodotInputGamepads.samples = []; function add(pad) { @@ -679,6 +703,12 @@ const GodotInput = { return 0; }, + godot_js_input_gamepad_process_vibration__proxy: 'sync', + godot_js_input_gamepad_process_vibration__sig: 'viffff', + godot_js_input_gamepad_process_vibration: function (p_index, p_timestamp, p_weak_magnitude, p_strong_magnitude, p_duration) { + GodotInputGamepads.process_vibration(p_index, p_timestamp, p_weak_magnitude, p_strong_magnitude, p_duration); + }, + /* * Drag/Drop API */