81 lines
3.1 KiB
GDScript
81 lines
3.1 KiB
GDScript
extends Sprite3D
|
|
|
|
const SLIDE_DURATION := 0.25
|
|
const UP_DURATION := 0.1
|
|
const HOLD_DURATION := 0.05
|
|
const DOWN_DURATION := 0.18
|
|
const ENTRY_OFFSET := 0.5
|
|
const ENTRY_DURATION := 0.5
|
|
|
|
var _open_button: Node3D
|
|
var _close_button: Node3D
|
|
var _target_button: Node3D
|
|
var _close_rest_x: float
|
|
var _open_rest_x: float
|
|
var _rest_y: float
|
|
var _slide_tween: Tween
|
|
var _press_tween: Tween
|
|
|
|
func _ready() -> void:
|
|
if not get_parent().is_node_ready():
|
|
await get_parent().ready
|
|
await get_tree().process_frame
|
|
_open_button = get_parent().get_node("DoorOpen")
|
|
_close_button = get_parent().get_node("DoorClose")
|
|
_close_rest_x = _project_to_hand_plane(_close_button)
|
|
_open_rest_x = _project_to_hand_plane(_open_button)
|
|
_rest_y = position.y
|
|
_target_button = _close_button
|
|
position = Vector3(_close_rest_x, _rest_y, position.z)
|
|
visible = false
|
|
print("[VirtuaHand] close_x=", _close_rest_x, " open_x=", _open_rest_x, " hand_pos=", position)
|
|
|
|
EventBus.button_pressed.connect(_animate_press)
|
|
EventBus.active_button_changed.connect(_on_active_button_changed)
|
|
EventBus.intro_finished.connect(_on_intro_finished)
|
|
|
|
func _on_intro_finished() -> void:
|
|
var sprite_height := texture.get_height() * pixel_size * scale.y
|
|
position.y = _rest_y - sprite_height - ENTRY_OFFSET
|
|
visible = true
|
|
var entry_tween := create_tween()
|
|
entry_tween.tween_property(self, "position:y", _rest_y, ENTRY_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
|
|
|
|
func _project_to_hand_plane(button: Node3D) -> float:
|
|
var cam := get_viewport().get_camera_3d()
|
|
if not cam:
|
|
return button.position.x
|
|
var screen_pos := cam.unproject_position(button.global_position)
|
|
var ray_origin := cam.project_ray_origin(screen_pos)
|
|
var ray_dir := cam.project_ray_normal(screen_pos)
|
|
if absf(ray_dir.z) < 0.0001:
|
|
return button.position.x
|
|
var t := (global_position.z - ray_origin.z) / ray_dir.z
|
|
var hit := ray_origin + ray_dir * t
|
|
return get_parent().to_local(hit).x
|
|
|
|
func _on_active_button_changed(target: String) -> void:
|
|
var new_button: Node3D = _open_button if target == "open" else _close_button
|
|
if new_button == _target_button:
|
|
return
|
|
_target_button = new_button
|
|
var target_x: float = _open_rest_x if target == "open" else _close_rest_x
|
|
print("[VirtuaHand] slide target=", target, " target_x=", target_x, " current_pos=", position)
|
|
if _press_tween and _press_tween.is_valid():
|
|
_press_tween.kill()
|
|
if _slide_tween and _slide_tween.is_valid():
|
|
_slide_tween.kill()
|
|
_slide_tween = create_tween()
|
|
_slide_tween.tween_property(self, "position:x", target_x, SLIDE_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN_OUT)
|
|
|
|
func _animate_press() -> void:
|
|
if not is_instance_valid(_target_button):
|
|
return
|
|
if _press_tween and _press_tween.is_valid():
|
|
_press_tween.kill()
|
|
var fingertip_offset := texture.get_height() * 0.5 * pixel_size * scale.y
|
|
var press_y := _target_button.position.y - fingertip_offset
|
|
_press_tween = create_tween()
|
|
_press_tween.tween_property(self, "position:y", press_y, UP_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_OUT)
|
|
_press_tween.tween_interval(HOLD_DURATION)
|
|
_press_tween.tween_property(self, "position:y", _rest_y, DOWN_DURATION).set_trans(Tween.TRANS_SINE).set_ease(Tween.EASE_IN)
|