81 lines
2.5 KiB
GDScript
81 lines
2.5 KiB
GDScript
@tool
|
|
extends MeshInstance3D
|
|
class_name GridHighlightController
|
|
|
|
@export var grid_manager_path: NodePath
|
|
@export var camera_path: NodePath
|
|
|
|
var _grid_manager: GridPlaneManager = null
|
|
var _camera: Camera3D = null
|
|
var _hovered_cell: Vector2i = Vector2i(-1, -1)
|
|
|
|
func _ready() -> void:
|
|
set_process(true)
|
|
_resolve_references()
|
|
_refresh_mesh()
|
|
if _grid_manager:
|
|
_grid_manager.grid_layout_changed.connect(_on_grid_layout_changed)
|
|
|
|
func _on_grid_layout_changed(_cells: Dictionary) -> void:
|
|
_refresh_mesh()
|
|
_hovered_cell = Vector2i(-1, -1)
|
|
visible = false
|
|
|
|
func _process(_delta: float) -> void:
|
|
if Engine.is_editor_hint():
|
|
return
|
|
if not _grid_manager or not _camera:
|
|
return
|
|
var viewport: Viewport = get_viewport()
|
|
if viewport == null:
|
|
return
|
|
var mouse_position: Vector2 = viewport.get_mouse_position()
|
|
_update_hovered_cell(mouse_position)
|
|
|
|
func _resolve_references() -> void:
|
|
if grid_manager_path != NodePath():
|
|
_grid_manager = get_node_or_null(grid_manager_path) as GridPlaneManager
|
|
else:
|
|
_grid_manager = get_parent() as GridPlaneManager
|
|
if camera_path != NodePath():
|
|
_camera = get_node_or_null(camera_path) as Camera3D
|
|
|
|
func _refresh_mesh() -> void:
|
|
if not _grid_manager:
|
|
return
|
|
mesh = _grid_manager.make_highlight_mesh()
|
|
visible = false
|
|
|
|
func _update_hovered_cell(mouse_position: Vector2) -> void:
|
|
var ray_origin: Vector3 = _camera.project_ray_origin(mouse_position)
|
|
var ray_direction: Vector3 = _camera.project_ray_normal(mouse_position)
|
|
var plane_normal: Vector3 = _grid_manager.global_transform.basis.y.normalized()
|
|
var plane_point: Vector3 = _grid_manager.global_transform.origin
|
|
var denominator: float = plane_normal.dot(ray_direction)
|
|
if abs(denominator) < 0.0001:
|
|
_set_hover_visible(false)
|
|
return
|
|
var t: float = plane_normal.dot(plane_point - ray_origin) / denominator
|
|
if t <= 0.0:
|
|
_set_hover_visible(false)
|
|
return
|
|
var world_point: Vector3 = ray_origin + ray_direction * t
|
|
var cell_index: Vector2i = _grid_manager.world_to_cell(world_point, false)
|
|
if cell_index.x < 0 or cell_index.y < 0 or not _grid_manager.has_cell(cell_index):
|
|
_set_hover_visible(false)
|
|
return
|
|
if cell_index == _hovered_cell:
|
|
return
|
|
_hovered_cell = cell_index
|
|
var local_center: Vector3 = _grid_manager.cell_to_world(cell_index)
|
|
var target_position: Vector3 = _grid_manager.to_global(local_center)
|
|
global_position = target_position + plane_normal * 0.02
|
|
_set_hover_visible(true)
|
|
|
|
func _set_hover_visible(state: bool) -> void:
|
|
if not state:
|
|
visible = false
|
|
_hovered_cell = Vector2i(-1, -1)
|
|
else:
|
|
visible = true
|