@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