Files
godot-apointa/scripts/click_manager.gd
2026-05-16 11:51:19 +02:00

98 lines
2.3 KiB
GDScript

extends Node
signal camera_move_requested(destination: Transform3D)
signal back_requested
var _hovered: Clickable = null
func get_camera() -> Camera3D:
return get_viewport().get_camera_3d()
func _ready() -> void:
back_requested.connect(_on_back_requested)
func _process(_delta: float) -> void:
_update_hover(get_viewport().get_mouse_position())
func _unhandled_input(event: InputEvent) -> void:
if event is InputEventMouseButton:
if event.button_index == MOUSE_BUTTON_LEFT and event.pressed:
_raycast_click(get_viewport().get_mouse_position())
if event is InputEventKey and event.pressed and not event.echo:
if event.keycode == KEY_ESCAPE or event.keycode == KEY_BACKSPACE:
request_back()
func _on_back_requested() -> void:
var cam = get_camera()
if cam and cam.has_method("go_back"):
cam.go_back()
func request_back() -> void:
back_requested.emit()
func _update_hover(screen_pos: Vector2) -> void:
var clickable = _raycast_find_clickable(screen_pos)
if clickable != _hovered:
_hovered = clickable
if _hovered:
CursorManager.set_cursor(_hovered.cursor_hint)
else:
CursorManager.reset()
func _raycast_click(screen_pos: Vector2) -> void:
var clickable = _raycast_find_clickable(screen_pos)
if clickable:
clickable.on_clicked(_raycast_position(screen_pos))
func _raycast_find_clickable(screen_pos: Vector2) -> Clickable:
var result = _raycast(screen_pos)
if result.is_empty():
return null
return _find_clickable_in(result.collider)
func _raycast_position(screen_pos: Vector2) -> Vector3:
var result = _raycast(screen_pos)
return result.get("position", Vector3.ZERO)
func _raycast(screen_pos: Vector2) -> Dictionary:
var camera = get_camera()
if not camera:
return {}
var space = camera.get_world_3d().direct_space_state
var origin = camera.project_ray_origin(screen_pos)
var end = origin + camera.project_ray_normal(screen_pos) * 100.0
var query = PhysicsRayQueryParameters3D.create(origin, end)
return space.intersect_ray(query)
func _find_clickable_in(node: Node) -> Clickable:
while node:
var c = node.find_child("Clickable", false, false)
if c:
return c as Clickable
node = node.get_parent()
return null
func request_camera_move(destination: Transform3D) -> void:
camera_move_requested.emit(destination)