Files
DartGame/game/scenes/camera_3d.gd
T

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)