2023-10-23 02:58:18 +03:00
|
|
|
extends Node3D
|
|
|
|
|
|
|
|
@onready var _controller := XRHelpers.get_xr_controller(self)
|
|
|
|
@export var ray: RayCast3D
|
|
|
|
|
|
|
|
# Called when the node enters the scene tree for the first time.
|
|
|
|
func _ready():
|
2023-11-05 14:59:33 +02:00
|
|
|
_controller.button_pressed.connect(_on_button_pressed)
|
|
|
|
_controller.button_released.connect(_on_button_released)
|
2023-10-23 02:58:18 +03:00
|
|
|
|
2023-11-05 14:59:33 +02:00
|
|
|
var _last_collided: Object = null
|
|
|
|
var _is_pressed := false
|
|
|
|
var _is_grabbed := false
|
|
|
|
var _moved := false
|
|
|
|
var _click_point := Vector3.ZERO
|
|
|
|
|
|
|
|
func _physics_process(delta):
|
|
|
|
_handle_enter_leave()
|
|
|
|
_handle_move()
|
|
|
|
|
|
|
|
func _handle_move():
|
2023-11-05 22:32:50 +02:00
|
|
|
if _is_pressed == false && _is_grabbed == false:
|
|
|
|
return
|
|
|
|
|
2023-11-05 14:59:33 +02:00
|
|
|
var distance = ray.get_collision_point().distance_to(_click_point)
|
|
|
|
|
2023-11-14 00:25:59 +02:00
|
|
|
if _moved || distance > 0.02:
|
2023-11-05 14:59:33 +02:00
|
|
|
if _is_pressed:
|
2023-11-14 00:25:59 +02:00
|
|
|
_call_fn(_last_collided, "_on_press_move")
|
2023-11-05 14:59:33 +02:00
|
|
|
_moved = true
|
|
|
|
if _is_grabbed:
|
2023-11-14 00:25:59 +02:00
|
|
|
_call_fn(_last_collided, "_on_grab_move")
|
2023-11-05 14:59:33 +02:00
|
|
|
_moved = true
|
|
|
|
|
|
|
|
func _handle_enter_leave():
|
|
|
|
var collider = ray.get_collider()
|
|
|
|
|
2023-11-14 00:25:59 +02:00
|
|
|
if collider == _last_collided || _is_grabbed || _is_pressed:
|
2023-11-05 14:59:33 +02:00
|
|
|
return
|
|
|
|
|
2023-11-05 15:09:19 +02:00
|
|
|
_call_fn(collider, "_on_ray_enter")
|
|
|
|
_call_fn(_last_collided, "_on_ray_leave")
|
2023-11-05 14:59:33 +02:00
|
|
|
|
|
|
|
_last_collided = collider
|
2023-10-23 02:58:18 +03:00
|
|
|
|
|
|
|
func _on_button_pressed(button):
|
2023-11-05 14:59:33 +02:00
|
|
|
var collider = ray.get_collider()
|
|
|
|
|
|
|
|
if collider == null:
|
2023-10-23 02:58:18 +03:00
|
|
|
return
|
2023-11-05 14:59:33 +02:00
|
|
|
|
|
|
|
match button:
|
|
|
|
"trigger_click":
|
|
|
|
_is_pressed = true
|
|
|
|
_click_point = ray.get_collision_point()
|
2023-11-05 15:09:19 +02:00
|
|
|
_call_fn(collider, "_on_press_down")
|
2023-11-05 14:59:33 +02:00
|
|
|
"grip_click":
|
|
|
|
_is_grabbed = true
|
|
|
|
_click_point = ray.get_collision_point()
|
2023-11-05 15:09:19 +02:00
|
|
|
_call_fn(collider, "_on_grab_down")
|
2023-11-05 14:59:33 +02:00
|
|
|
|
|
|
|
func _on_button_released(button):
|
2023-11-14 01:51:48 +02:00
|
|
|
if _last_collided == null:
|
2023-10-23 02:58:18 +03:00
|
|
|
return
|
|
|
|
|
2023-11-05 14:59:33 +02:00
|
|
|
match button:
|
|
|
|
"trigger_click":
|
|
|
|
if _is_pressed:
|
|
|
|
if _moved == false:
|
2023-11-14 01:51:48 +02:00
|
|
|
_call_fn(_last_collided, "_on_click")
|
|
|
|
_call_fn(_last_collided, "_on_press_up")
|
2023-11-05 14:59:33 +02:00
|
|
|
_is_pressed = false
|
|
|
|
_moved = false
|
|
|
|
"grip_click":
|
|
|
|
if _is_grabbed:
|
2023-11-14 01:51:48 +02:00
|
|
|
_call_fn(_last_collided, "_on_grab_up")
|
2023-11-05 14:59:33 +02:00
|
|
|
_is_grabbed = false
|
|
|
|
_moved = false
|
2023-10-23 02:58:18 +03:00
|
|
|
|
2023-11-16 20:23:17 +02:00
|
|
|
func _call_fn(collider: Object, fn_name: String, node: Node3D = null, event = null):
|
2023-11-11 19:17:25 +02:00
|
|
|
if collider == null:
|
|
|
|
return
|
|
|
|
|
|
|
|
if node == null:
|
|
|
|
node = collider
|
2023-11-16 20:23:17 +02:00
|
|
|
event = {
|
|
|
|
"controller": _controller,
|
|
|
|
"ray": ray,
|
|
|
|
"target": collider,
|
|
|
|
}
|
|
|
|
|
|
|
|
if node.has_method(fn_name):
|
|
|
|
var result = node.call(fn_name, event)
|
|
|
|
|
|
|
|
if result != null && result is Dictionary:
|
|
|
|
result.merge(event, true)
|
2023-11-18 16:32:37 +02:00
|
|
|
event = result
|
2023-11-16 20:23:17 +02:00
|
|
|
|
|
|
|
if result != null && result is bool && result == false:
|
|
|
|
# Stop the event from bubbling up
|
|
|
|
return
|
2023-11-11 19:17:25 +02:00
|
|
|
|
|
|
|
for child in node.get_children():
|
|
|
|
if child is Function && child.has_method(fn_name):
|
|
|
|
child.call(fn_name, event)
|
2023-11-16 20:23:17 +02:00
|
|
|
|
2023-11-11 19:17:25 +02:00
|
|
|
|
|
|
|
var parent = node.get_parent()
|
2023-11-05 22:32:50 +02:00
|
|
|
|
2023-11-11 19:17:25 +02:00
|
|
|
if parent != null && parent is Node3D:
|
2023-11-16 20:23:17 +02:00
|
|
|
_call_fn(collider, fn_name, parent, event)
|