Not sure why these files werent comitted
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
@tool
|
||||
extends Camera3D
|
||||
class_name GridCameraController
|
||||
|
||||
@export var grid_manager_path: NodePath
|
||||
@export var ground_mesh_path: NodePath
|
||||
@export var ground_collision_path: NodePath
|
||||
@export_range(0.1, 10.0, 0.1) var zoom_min: float = 0.5
|
||||
@export_range(0.1, 10.0, 0.1) var zoom_max: float = 3.0
|
||||
@export_range(0.01, 1.0, 0.01) var zoom_step: float = 0.1
|
||||
|
||||
var _grid_manager: GridPlaneManager = null
|
||||
var _ground_mesh: MeshInstance3D = null
|
||||
var _ground_collision: CollisionShape3D = null
|
||||
var _zoom_factor: float = 1.0
|
||||
|
||||
func _ready() -> void:
|
||||
_resolve_references()
|
||||
if _grid_manager:
|
||||
_grid_manager.grid_layout_changed.connect(_on_grid_layout_changed)
|
||||
_update_camera_view()
|
||||
_update_ground_assets()
|
||||
|
||||
func _on_grid_layout_changed(_cells: Dictionary) -> void:
|
||||
_update_camera_view()
|
||||
_update_ground_assets()
|
||||
|
||||
func _unhandled_input(event: InputEvent) -> void:
|
||||
if Engine.is_editor_hint():
|
||||
return
|
||||
if event is InputEventMouseButton and event.pressed:
|
||||
var button_event := event as InputEventMouseButton
|
||||
if button_event.button_index == MOUSE_BUTTON_WHEEL_UP:
|
||||
_adjust_zoom(-zoom_step)
|
||||
elif button_event.button_index == MOUSE_BUTTON_WHEEL_DOWN:
|
||||
_adjust_zoom(zoom_step)
|
||||
|
||||
func _adjust_zoom(delta: float) -> void:
|
||||
var new_zoom: float = clamp(_zoom_factor + delta, zoom_min, zoom_max)
|
||||
if is_equal_approx(new_zoom, _zoom_factor):
|
||||
return
|
||||
_zoom_factor = new_zoom
|
||||
_update_camera_view()
|
||||
_update_ground_assets()
|
||||
|
||||
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 ground_mesh_path != NodePath():
|
||||
_ground_mesh = get_node_or_null(ground_mesh_path) as MeshInstance3D
|
||||
if ground_collision_path != NodePath():
|
||||
_ground_collision = get_node_or_null(ground_collision_path) as CollisionShape3D
|
||||
|
||||
func _update_camera_view() -> void:
|
||||
if not is_inside_tree():
|
||||
return
|
||||
var grid_size: Vector2 = Vector2(20, 20)
|
||||
var target: Vector3 = global_transform.origin
|
||||
if _grid_manager:
|
||||
grid_size = _grid_manager.get_grid_size()
|
||||
target = _grid_manager.global_transform.origin
|
||||
var extent: float = max(grid_size.x, grid_size.y)
|
||||
var half_extent: float = max(extent * 0.5, 1.0)
|
||||
var distance: float = max(half_extent * 1.1, 6.0) * _zoom_factor
|
||||
var height: float = max(half_extent * 0.8, 6.0) * _zoom_factor
|
||||
var offset: Vector3 = Vector3(distance, height, distance)
|
||||
var desired_position: Vector3 = target + offset
|
||||
look_at_from_position(desired_position, target, Vector3.UP)
|
||||
|
||||
func _update_ground_assets() -> void:
|
||||
if not is_inside_tree():
|
||||
return
|
||||
var required_size: Vector2 = _compute_required_ground_size()
|
||||
if _ground_mesh and _ground_mesh.mesh is PlaneMesh:
|
||||
var plane_mesh: PlaneMesh = _ground_mesh.mesh as PlaneMesh
|
||||
plane_mesh.size = required_size
|
||||
if _ground_collision and _ground_collision.shape is BoxShape3D:
|
||||
var box: BoxShape3D = _ground_collision.shape as BoxShape3D
|
||||
var thickness: float = _grid_manager.get_ground_thickness() if _grid_manager else 0.4
|
||||
box.size = Vector3(required_size.x, thickness, required_size.y)
|
||||
|
||||
func _compute_required_ground_size() -> Vector2:
|
||||
var grid_size: Vector2 = Vector2(20, 20)
|
||||
var padding: float = 20.0
|
||||
if _grid_manager:
|
||||
grid_size = _grid_manager.get_grid_size()
|
||||
padding = _grid_manager.get_ground_padding()
|
||||
var base_half: Vector2 = Vector2(max(grid_size.x * 0.5, 1.0), max(grid_size.y * 0.5, 1.0))
|
||||
var half_extents: Vector2 = base_half
|
||||
var viewport: Viewport = get_viewport()
|
||||
if viewport:
|
||||
var view_size: Vector2 = viewport.get_visible_rect().size
|
||||
var corners: Array = [
|
||||
Vector2.ZERO,
|
||||
Vector2(view_size.x, 0),
|
||||
Vector2(0, view_size.y),
|
||||
view_size
|
||||
]
|
||||
var plane_normal: Vector3 = (_grid_manager.global_transform.basis.y if _grid_manager else global_transform.basis.y).normalized()
|
||||
var plane_point: Vector3 = (_grid_manager.global_transform.origin if _grid_manager else global_transform.origin)
|
||||
for corner in corners:
|
||||
var origin: Vector3 = project_ray_origin(corner)
|
||||
var direction: Vector3 = project_ray_normal(corner)
|
||||
var denominator: float = plane_normal.dot(direction)
|
||||
if abs(denominator) < 0.0001:
|
||||
continue
|
||||
var t: float = plane_normal.dot(plane_point - origin) / denominator
|
||||
if t <= 0.0:
|
||||
continue
|
||||
var world_point: Vector3 = origin + direction * t
|
||||
var local_point: Vector3 = _grid_manager.to_local(world_point) if _grid_manager else 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 = Vector2.ONE * padding
|
||||
return (half_extents + padding_vec) * 2.0
|
||||
Reference in New Issue
Block a user