|
class_name DayNightCycleComponent
|
|
extends Node
|
|
|
|
|
|
signal end_of_day
|
|
signal pause_time
|
|
signal resume_time
|
|
signal set_day_length(length_in_seconds: float)
|
|
signal set_rate_of_time(rate: float) ## 2.0 for 2x
|
|
signal set_time(time: float) ## Time should be between 0 and 1
|
|
|
|
|
|
@export var day_length: float = 60.0 ## Day length in seconds
|
|
@export var start_time: float = 0.3 ## Between 0-1 (0.3 is morning, 0.5 noon)
|
|
@export var time_paused: bool = false
|
|
|
|
@export_group("Colors and Intensity")
|
|
@export var moon_color: Gradient
|
|
@export var moon_intensity: Curve
|
|
@export var sun_color: Gradient
|
|
@export var sun_intensity: Curve
|
|
@export var sky_top_color: Gradient
|
|
@export var sky_horizon_color: Gradient
|
|
@export var ground_bottom_color: Gradient
|
|
@export var ground_horizon_color: Gradient
|
|
|
|
@export_group("Node Exports")
|
|
@export var environment: WorldEnvironment
|
|
@export var sun: DirectionalLight3D
|
|
@export var moon: DirectionalLight3D
|
|
|
|
@onready var tick_rate: float = 1.0 / day_length
|
|
@onready var time: float = start_time ## Between 0-1 (0.5 - noon)
|
|
|
|
|
|
func _process(delta: float) -> void:
|
|
if time_paused: return
|
|
|
|
time += tick_rate * delta
|
|
|
|
if time >= 1.0:
|
|
time = 0.0
|
|
end_of_day.emit()
|
|
|
|
# 90 to fix alignment
|
|
sun.rotation_degrees.x = time * 360 + 90
|
|
sun.light_color = sun_color.sample(time)
|
|
sun.light_energy = sun_intensity.sample(time)
|
|
|
|
# 90 to fix alignment
|
|
moon.rotation_degrees.x = time * 360 + 90 + 180 # 180 for opposite of sun
|
|
moon.light_color = moon_color.sample(time)
|
|
moon.light_energy = moon_intensity.sample(time)
|
|
|
|
# Show / Hide Sun and Moon
|
|
sun.visible = sun.light_energy > 0
|
|
moon.visible = moon.light_energy > 0
|
|
|
|
# Sky and Ground Colors
|
|
environment.environment.sky.sky_material.set("sky_top_color", sky_top_color.sample(time))
|
|
environment.environment.sky.sky_material.set("sky_horizon_color", sky_horizon_color.sample(time))
|
|
environment.environment.sky.sky_material.set("ground_bottom_color", ground_bottom_color.sample(time))
|
|
environment.environment.sky.sky_material.set("ground_horizon_color", ground_horizon_color.sample(time))
|
|
|
|
func _ready() -> void:
|
|
pause_time.connect(_on_pause_time)
|
|
resume_time.connect(_on_resume_time)
|
|
set_day_length.connect(_on_set_day_length)
|
|
set_rate_of_time.connect(_on_set_rate_of_time)
|
|
set_time.connect(_on_set_time)
|
|
|
|
|
|
func update_tick_rate(new_rate: float = 1.0) -> void:
|
|
tick_rate = new_rate / day_length
|
|
|
|
|
|
func _on_pause_time() -> void:
|
|
time_paused = true
|
|
|
|
func _on_resume_time() -> void:
|
|
time_paused = true
|
|
|
|
func _on_set_day_length(seconds: float) -> void:
|
|
day_length = seconds
|
|
update_tick_rate()
|
|
|
|
func _on_set_rate_of_time(new_rate: float) -> void:
|
|
update_tick_rate(new_rate)
|
|
|
|
func _on_set_time(new_time: float) -> void:
|
|
time = new_time
|