57 lines
1.6 KiB
GDScript
57 lines
1.6 KiB
GDScript
extends Camera3D
|
|
|
|
## Owns dart input. The camera does the raycast because the raycast IS a
|
|
## camera operation — projecting a screen point into the world.
|
|
##
|
|
## The dart exposes begin_drag / update_drag / release_drag and never looks
|
|
## for the camera itself. This script decides who to call them on.
|
|
|
|
const RAY_LENGTH := 1000.0
|
|
|
|
var _held_dart: Dart = null
|
|
|
|
|
|
func _unhandled_input(event: InputEvent) -> void:
|
|
if event is InputEventMouseButton:
|
|
var mb := event as InputEventMouseButton
|
|
if mb.button_index != MOUSE_BUTTON_LEFT:
|
|
return
|
|
if mb.pressed:
|
|
_try_grab(mb.position)
|
|
else:
|
|
_release()
|
|
|
|
elif event is InputEventMouseMotion and _held_dart != null:
|
|
_held_dart.update_drag(self, (event as InputEventMouseMotion).position)
|
|
|
|
|
|
func _try_grab(screen_pos: Vector2) -> void:
|
|
var hit := _raycast(screen_pos)
|
|
if hit.is_empty():
|
|
return
|
|
|
|
var body = hit.get("collider")
|
|
if body is Dart:
|
|
_held_dart = body as Dart
|
|
# NOTE: two args, not three. The old start_drag(camera, mouse_pos, point)
|
|
# passed mouse_pos but never used it — begin_drag only needs the hit point.
|
|
_held_dart.begin_drag(self, hit["position"])
|
|
|
|
|
|
func _release() -> void:
|
|
if _held_dart == null:
|
|
return
|
|
_held_dart.release_drag()
|
|
_held_dart = null
|
|
|
|
|
|
func _raycast(screen_pos: Vector2) -> Dictionary:
|
|
var params := PhysicsRayQueryParameters3D.create(
|
|
project_ray_origin(screen_pos),
|
|
project_ray_origin(screen_pos) + project_ray_normal(screen_pos) * RAY_LENGTH
|
|
)
|
|
if _held_dart != null:
|
|
params.exclude = [_held_dart.get_rid()]
|
|
|
|
return get_world_3d().direct_space_state.intersect_ray(params)
|