Files
godot-playground/scenes/Grid/day_night_controller.gd
T

62 lines
2.4 KiB
GDScript

@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