98 lines
2.3 KiB
GDScript
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)
|