diff --git a/scenes/Grid/grid_field.tscn b/scenes/Grid/grid_field.tscn index 0ccc0f8..5653df4 100644 --- a/scenes/Grid/grid_field.tscn +++ b/scenes/Grid/grid_field.tscn @@ -43,6 +43,7 @@ columns = 10 rows = 10 cell_size = 1.0 ground_thickness = 0.4 +ground_padding = null show_grid_lines = true grid_line_color = Color(0.2, 0.7, 1, 0.65) diff --git a/scenes/Grid/grid_plane_manager.gd b/scenes/Grid/grid_plane_manager.gd index 6b9ae1f..aa5c409 100644 --- a/scenes/Grid/grid_plane_manager.gd +++ b/scenes/Grid/grid_plane_manager.gd @@ -60,6 +60,17 @@ var _ground_thickness: float = 0.4 get: return _ground_thickness +var _ground_padding: float = 20.0 +@export_range(0.0, 200.0, 1.0) var ground_padding: float: + set(value): + value = max(value, 0.0) + if is_equal_approx(value, _ground_padding): + return + _ground_padding = value + _update_ground_assets() + get: + return _ground_padding + var _show_grid_lines: bool = true @export var show_grid_lines: bool: set(value): @@ -137,19 +148,20 @@ func _rebuild_grid() -> void: _generate_hex_grid() _: _generate_square_grid() - _update_ground_assets() _update_grid_lines() _update_highlight_mesh() _update_camera_view() + _update_ground_assets() emit_signal("grid_layout_changed", _cells) func _update_ground_assets() -> void: + var required_size := _compute_required_ground_size() if _ground_mesh and _ground_mesh.mesh is PlaneMesh: var plane_mesh := _ground_mesh.mesh as PlaneMesh - plane_mesh.size = _grid_size + plane_mesh.size = required_size if _ground_collision and _ground_collision.shape is BoxShape3D: var box := _ground_collision.shape as BoxShape3D - box.size = Vector3(_grid_size.x, _ground_thickness, _grid_size.y) + box.size = Vector3(required_size.x, _ground_thickness, required_size.y) func _generate_square_grid() -> void: _hex_center_offset_local = Vector3.ZERO @@ -354,6 +366,37 @@ func _update_camera_view() -> void: var desired_position: Vector3 = target + offset_global _camera.look_at_from_position(desired_position, target, Vector3.UP) +func _compute_required_ground_size() -> Vector2: + var base_half := Vector2(_grid_size.x * 0.5, _grid_size.y * 0.5) + var half_extents := base_half + if is_instance_valid(_camera) and not Engine.is_editor_hint(): + var viewport := get_viewport() + if viewport: + var view_size: Vector2 = viewport.get_visible_rect().size + var corners := [ + Vector2.ZERO, + Vector2(view_size.x, 0), + Vector2(0, view_size.y), + view_size + ] + var plane_normal: Vector3 = global_transform.basis.y.normalized() + var plane_point: Vector3 = global_transform.origin + for corner in corners: + var origin := _camera.project_ray_origin(corner) + var direction := _camera.project_ray_normal(corner) + var denominator := plane_normal.dot(direction) + if abs(denominator) < 0.0001: + continue + var t := plane_normal.dot(plane_point - origin) / denominator + if t <= 0.0: + continue + var world_point := origin + direction * t + var local_point := to_local(world_point) + half_extents.x = max(half_extents.x, abs(local_point.x)) + half_extents.y = max(half_extents.y, abs(local_point.z)) + var padding_vec := Vector2.ONE * _ground_padding + return (half_extents + padding_vec) * 2.0 + func _process(_delta: float) -> void: if Engine.is_editor_hint(): return