Not sure why these files werent comitted
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
@tool
|
||||||
|
extends DirectionalLight3D
|
||||||
|
class_name DayNightController
|
||||||
|
|
||||||
|
@export var grid_manager_path: NodePath
|
||||||
|
@export_range(1.0, 48.0, 0.5) var day_length_hours: float = 12.0
|
||||||
|
@export_range(1.0, 600.0, 1.0) var real_seconds_per_game_hour: float = 60.0
|
||||||
|
@export_range(0.0, 48.0, 0.25) var start_time_of_day_hours: float = 6.0
|
||||||
|
@export var orbit_axis: Vector3 = Vector3(1.0, 0.0, -1.0)
|
||||||
|
@export_range(0.0, 90.0, 0.5) var inclination_degrees: float = 35.0
|
||||||
|
|
||||||
|
var _grid_manager: Node3D = null
|
||||||
|
var _time_of_day_hours: float = 0.0
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
set_process(true)
|
||||||
|
_resolve_references()
|
||||||
|
_time_of_day_hours = clamp(start_time_of_day_hours, 0.0, day_length_hours)
|
||||||
|
_apply_sun_lighting()
|
||||||
|
|
||||||
|
func _process(delta: float) -> void:
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
return
|
||||||
|
if day_length_hours <= 0.0 or real_seconds_per_game_hour <= 0.0:
|
||||||
|
return
|
||||||
|
_time_of_day_hours = fposmod(_time_of_day_hours + delta / real_seconds_per_game_hour, day_length_hours)
|
||||||
|
_apply_sun_lighting()
|
||||||
|
|
||||||
|
func _resolve_references() -> void:
|
||||||
|
if grid_manager_path != NodePath():
|
||||||
|
_grid_manager = get_node_or_null(grid_manager_path)
|
||||||
|
else:
|
||||||
|
_grid_manager = get_parent() as Node3D
|
||||||
|
|
||||||
|
func _apply_sun_lighting() -> void:
|
||||||
|
if day_length_hours <= 0.0:
|
||||||
|
return
|
||||||
|
var cycle: float = 0.0
|
||||||
|
if day_length_hours > 0.0:
|
||||||
|
cycle = fposmod(_time_of_day_hours / day_length_hours, 1.0)
|
||||||
|
var sun_angle: float = cycle * TAU
|
||||||
|
var axis: Vector3 = orbit_axis.normalized()
|
||||||
|
if axis.length() == 0.0:
|
||||||
|
axis = Vector3.RIGHT
|
||||||
|
var direction: Vector3 = Vector3.UP.rotated(axis, sun_angle)
|
||||||
|
direction = direction.rotated(Vector3.UP, deg_to_rad(inclination_degrees)).normalized()
|
||||||
|
var target: Vector3 = _grid_manager.global_transform.origin if _grid_manager else global_transform.origin
|
||||||
|
var sun_distance: float = 60.0
|
||||||
|
var sun_position: Vector3 = target - direction * sun_distance
|
||||||
|
var up_vector: Vector3 = Vector3.UP
|
||||||
|
if direction.is_equal_approx(up_vector) or direction.is_equal_approx(-up_vector):
|
||||||
|
up_vector = Vector3.FORWARD
|
||||||
|
look_at_from_position(sun_position, target, up_vector)
|
||||||
|
var daylight: float = clamp(direction.y * 0.5 + 0.5, 0.0, 1.0)
|
||||||
|
var dawn_color: Color = Color(0.95, 0.58, 0.32)
|
||||||
|
var night_color: Color = Color(0.12, 0.18, 0.35)
|
||||||
|
var day_color: Color = Color(1.0, 0.96, 0.88)
|
||||||
|
var warm_mix: Color = dawn_color.lerp(day_color, clamp((daylight - 0.25) / 0.5, 0.0, 1.0))
|
||||||
|
light_color = night_color.lerp(warm_mix, daylight)
|
||||||
|
light_energy = lerp(0.05, 1.25, daylight)
|
||||||
|
shadow_enabled = daylight > 0.1
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://oy8cl8dscrh2
|
||||||
@@ -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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://5p4mcxw7wann
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
@tool
|
||||||
|
extends Node3D
|
||||||
|
class_name GridCharacterController
|
||||||
|
|
||||||
|
@export var grid_manager_path: NodePath
|
||||||
|
@export var camera_path: NodePath
|
||||||
|
@export var start_cell: Vector2i = Vector2i.ZERO
|
||||||
|
@export_range(0.1, 20.0, 0.1) var move_speed: float = 4.0
|
||||||
|
@export_range(0.0, 2.0, 0.01) var height_offset: float = 0.3
|
||||||
|
|
||||||
|
var _grid_manager: GridPlaneManager = null
|
||||||
|
var _camera: Camera3D = null
|
||||||
|
var _current_cell: Vector2i = Vector2i(-1, -1)
|
||||||
|
var _target_position: Vector3
|
||||||
|
var _is_moving: bool = false
|
||||||
|
|
||||||
|
func _ready() -> void:
|
||||||
|
set_physics_process(true)
|
||||||
|
set_process_unhandled_input(true)
|
||||||
|
_resolve_references()
|
||||||
|
if _grid_manager:
|
||||||
|
_grid_manager.grid_layout_changed.connect(_on_grid_layout_changed)
|
||||||
|
_move_to_cell(start_cell, true)
|
||||||
|
|
||||||
|
func _physics_process(delta: float) -> void:
|
||||||
|
if not _is_moving:
|
||||||
|
return
|
||||||
|
var direction: Vector3 = _target_position - global_transform.origin
|
||||||
|
var distance: float = direction.length()
|
||||||
|
if distance <= 0.01:
|
||||||
|
global_position = _target_position
|
||||||
|
_is_moving = false
|
||||||
|
return
|
||||||
|
var step: float = move_speed * delta
|
||||||
|
var move_vector: Vector3 = direction.normalized() * min(step, distance)
|
||||||
|
global_position += move_vector
|
||||||
|
|
||||||
|
func _unhandled_input(event: InputEvent) -> void:
|
||||||
|
if Engine.is_editor_hint():
|
||||||
|
return
|
||||||
|
if event is InputEventMouseButton and event.pressed and event.button_index == MOUSE_BUTTON_LEFT:
|
||||||
|
_move_to_mouse_click()
|
||||||
|
|
||||||
|
func _move_to_mouse_click() -> void:
|
||||||
|
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()
|
||||||
|
var target_cell: Vector2i = _pick_cell(mouse_position)
|
||||||
|
if target_cell.x < 0 or target_cell.y < 0:
|
||||||
|
return
|
||||||
|
_move_to_cell(target_cell)
|
||||||
|
|
||||||
|
func _move_to_cell(cell: Vector2i, instant: bool = false) -> void:
|
||||||
|
if not _grid_manager or not _grid_manager.has_cell(cell):
|
||||||
|
return
|
||||||
|
_current_cell = cell
|
||||||
|
var local_center: Vector3 = _grid_manager.cell_to_world(cell)
|
||||||
|
var world_center: Vector3 = _grid_manager.to_global(local_center)
|
||||||
|
_target_position = world_center + Vector3.UP * height_offset
|
||||||
|
if instant:
|
||||||
|
global_position = _target_position
|
||||||
|
_is_moving = false
|
||||||
|
else:
|
||||||
|
_is_moving = true
|
||||||
|
|
||||||
|
func _pick_cell(mouse_position: Vector2) -> Vector2i:
|
||||||
|
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:
|
||||||
|
return Vector2i(-1, -1)
|
||||||
|
var t: float = plane_normal.dot(plane_point - ray_origin) / denominator
|
||||||
|
if t <= 0.0:
|
||||||
|
return Vector2i(-1, -1)
|
||||||
|
var world_point: Vector3 = ray_origin + ray_direction * t
|
||||||
|
return _grid_manager.world_to_cell(world_point, true)
|
||||||
|
|
||||||
|
func _on_grid_layout_changed(_cells: Dictionary) -> void:
|
||||||
|
if not _grid_manager:
|
||||||
|
return
|
||||||
|
if not _grid_manager.has_cell(_current_cell):
|
||||||
|
_current_cell = Vector2i(
|
||||||
|
clamp(_current_cell.x, 0, _grid_manager.columns - 1),
|
||||||
|
clamp(_current_cell.y, 0, _grid_manager.rows - 1)
|
||||||
|
)
|
||||||
|
_move_to_cell(_current_cell, true)
|
||||||
|
|
||||||
|
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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://6asq70b60kif
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
@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
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
uid://ehef5rrel4d6
|
||||||
Reference in New Issue
Block a user