Make gamepad vibration work on web export
Input.start_joy_vibration() is a documented engine no-op on Godot's HTML5 export (never wired to the browser side). Controls.vibrate() wraps it: native platforms go straight through as before, web drives the browser's Gamepad Haptic Actuator API directly via JavaScriptBridge. Gamepad movement/ability input already worked on desktop browsers via the standard Web Gamepad API, so only vibration needed a fix. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MXBNaEBmrYDSMcv4NgUWtV
This commit is contained in:
@@ -835,9 +835,8 @@ func take_sword_hit(cause: String = "", hit_pos: Vector3 = Vector3.ZERO) -> void
|
||||
health_changed.emit(_hp, _max_hp)
|
||||
hit_taken.emit(cause)
|
||||
camera_pivot.call(&"trigger_hit", 0.7)
|
||||
# Vibrate controller 0 with half weak strength, full strong strength, for 0.5 seconds
|
||||
if DP.b("gamepad_vibration"):
|
||||
Input.start_joy_vibration(0, 0.5, 1, 0.2)
|
||||
# Vibrate controller 0 with half weak strength, full strong strength, for 0.2 seconds
|
||||
Controls.vibrate(0, 0.5, 1, 0.2)
|
||||
|
||||
# A spear gores a spot — blood spurts from the entry wound (where it struck the
|
||||
# bull). Melee gores pass no position and skip the spurt; gore can be turned off.
|
||||
|
||||
@@ -11,5 +11,4 @@ func _process(_delta: float) -> void:
|
||||
if Run.bear_gate_open() or DP.b("gate_unlocked_bear"):
|
||||
bear_gate_open = true
|
||||
$AnimationPlayer.play("Gate_opening")
|
||||
if DP.b("gamepad_vibration"):
|
||||
Input.start_joy_vibration(0, 0.5, .5, 7)
|
||||
Controls.vibrate(0, 0.5, .5, 7)
|
||||
|
||||
@@ -222,6 +222,35 @@ func rigid_skin_enabled() -> bool:
|
||||
return DP.b("use_rigid_skin")
|
||||
|
||||
|
||||
## Rumble a connected gamepad, gated on the DP "gamepad_vibration" flag. Off web this is a thin
|
||||
## wrapper over Input.start_joy_vibration(); on web that call is a documented engine no-op
|
||||
## (godotengine/godot#96985 — never wired to the browser side), so there we drive the Gamepad
|
||||
## Haptic Actuator API ourselves. Safe no-op wherever it's unsupported (Safari, most Firefox
|
||||
## versions, or a controller with no rumble motors) — desktop Chromium/Edge is the target.
|
||||
func vibrate(device: int, weak_magnitude: float, strong_magnitude: float, duration: float) -> void:
|
||||
if not DP.b("gamepad_vibration"):
|
||||
return
|
||||
if not OS.has_feature("web"):
|
||||
Input.start_joy_vibration(device, weak_magnitude, strong_magnitude, duration)
|
||||
return
|
||||
JavaScriptBridge.eval("""
|
||||
(function(){
|
||||
try {
|
||||
var pads = navigator.getGamepads ? navigator.getGamepads() : [];
|
||||
var pad = pads[%d];
|
||||
var act = pad && pad.vibrationActuator;
|
||||
if (act && act.playEffect) {
|
||||
act.playEffect('dual-rumble', {
|
||||
duration: %d,
|
||||
weakMagnitude: %f,
|
||||
strongMagnitude: %f
|
||||
});
|
||||
}
|
||||
} catch (e) {}
|
||||
})();
|
||||
""" % [device, int(duration * 1000.0), weak_magnitude, strong_magnitude], true)
|
||||
|
||||
|
||||
## Returns the first keyboard event bound to an action, or null.
|
||||
func get_key_event(action: StringName) -> InputEventKey:
|
||||
for event: InputEvent in InputMap.action_get_events(action):
|
||||
|
||||
Reference in New Issue
Block a user