Start dynamic sky
This commit is contained in:
313
dynamic-sky/scripts/day_night_controller.gd
Normal file
313
dynamic-sky/scripts/day_night_controller.gd
Normal file
@@ -0,0 +1,313 @@
|
||||
@tool
|
||||
class_name DayNightController
|
||||
extends Node
|
||||
|
||||
signal time_changed(time_of_day: float)
|
||||
signal hour_changed(hour: int)
|
||||
signal day_changed(day: int)
|
||||
signal sunrise_started()
|
||||
signal sunset_started()
|
||||
signal night_started()
|
||||
signal noon_reached()
|
||||
|
||||
const HOURS_PER_DAY := 24.0
|
||||
const SUNRISE_START := 0.2 # ~5 AM
|
||||
const SUNRISE_END := 0.3 # ~7 AM
|
||||
const SUNSET_START := 0.75 # ~6 PM
|
||||
const SUNSET_END := 0.85 # ~8 PM
|
||||
const NOON := 0.5
|
||||
|
||||
@export_group("Time Settings")
|
||||
@export var time_of_day: float = 0.25:
|
||||
set(value):
|
||||
var old_hour := get_current_hour()
|
||||
time_of_day = wrapf(value, 0.0, 1.0)
|
||||
var new_hour := get_current_hour()
|
||||
if old_hour != new_hour:
|
||||
hour_changed.emit(new_hour)
|
||||
time_changed.emit(time_of_day)
|
||||
_check_time_events(old_hour, new_hour)
|
||||
|
||||
@export var day_length_minutes: float = 30.0:
|
||||
set(value):
|
||||
day_length_minutes = clampf(value, 1.0, 1440.0)
|
||||
|
||||
@export var paused: bool = false
|
||||
@export var time_scale: float = 1.0
|
||||
@export var current_day: int = 1
|
||||
|
||||
@export_group("Sun Arc")
|
||||
@export var sun_arc_tilt: float = 23.5
|
||||
@export var sun_arc_offset: float = 0.0
|
||||
|
||||
@export_group("Moon Arc")
|
||||
@export var moon_arc_tilt: float = 15.0
|
||||
@export var moon_arc_offset: float = 180.0
|
||||
@export var moon_phase: float = 0.0
|
||||
|
||||
@export_group("Sun Curves")
|
||||
@export var sun_color_curve: Gradient
|
||||
@export var sun_intensity_curve: Curve
|
||||
|
||||
@export_group("Moon Curves")
|
||||
@export var moon_color_curve: Gradient
|
||||
@export var moon_intensity_curve: Curve
|
||||
|
||||
@export_group("Ambient Curves")
|
||||
@export var ambient_color_curve: Gradient
|
||||
@export var ambient_intensity_curve: Curve
|
||||
|
||||
@export_group("Fog Curves")
|
||||
@export var fog_color_curve: Gradient
|
||||
@export var fog_density_curve: Curve
|
||||
|
||||
@export_group("Stars")
|
||||
@export var stars_visibility_curve: Curve
|
||||
|
||||
var _last_hour: int = -1
|
||||
var _sunrise_emitted := false
|
||||
var _sunset_emitted := false
|
||||
var _night_emitted := false
|
||||
var _noon_emitted := false
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
_initialize_default_curves()
|
||||
_last_hour = get_current_hour()
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
if paused:
|
||||
return
|
||||
|
||||
var time_increment := delta / (day_length_minutes * 60.0) * time_scale
|
||||
var old_time := time_of_day
|
||||
time_of_day += time_increment
|
||||
|
||||
if time_of_day < old_time:
|
||||
current_day += 1
|
||||
day_changed.emit(current_day)
|
||||
_reset_time_events()
|
||||
|
||||
|
||||
func _initialize_default_curves() -> void:
|
||||
if sun_color_curve == null:
|
||||
sun_color_curve = Gradient.new()
|
||||
sun_color_curve.set_color(0, Color(1.0, 0.6, 0.4)) # Dawn
|
||||
sun_color_curve.add_point(0.25, Color(1.0, 0.95, 0.85)) # Morning
|
||||
sun_color_curve.add_point(0.5, Color(1.0, 1.0, 0.95)) # Noon
|
||||
sun_color_curve.add_point(0.75, Color(1.0, 0.7, 0.4)) # Sunset
|
||||
sun_color_curve.set_color(1, Color(1.0, 0.5, 0.3)) # Dusk
|
||||
|
||||
if sun_intensity_curve == null:
|
||||
sun_intensity_curve = Curve.new()
|
||||
sun_intensity_curve.add_point(Vector2(0.0, 0.0))
|
||||
sun_intensity_curve.add_point(Vector2(0.2, 0.0))
|
||||
sun_intensity_curve.add_point(Vector2(0.3, 0.8))
|
||||
sun_intensity_curve.add_point(Vector2(0.5, 1.0))
|
||||
sun_intensity_curve.add_point(Vector2(0.7, 0.8))
|
||||
sun_intensity_curve.add_point(Vector2(0.85, 0.0))
|
||||
sun_intensity_curve.add_point(Vector2(1.0, 0.0))
|
||||
|
||||
if moon_color_curve == null:
|
||||
moon_color_curve = Gradient.new()
|
||||
moon_color_curve.set_color(0, Color(0.7, 0.8, 1.0))
|
||||
moon_color_curve.set_color(1, Color(0.7, 0.8, 1.0))
|
||||
|
||||
if moon_intensity_curve == null:
|
||||
moon_intensity_curve = Curve.new()
|
||||
moon_intensity_curve.add_point(Vector2(0.0, 0.4))
|
||||
moon_intensity_curve.add_point(Vector2(0.2, 0.3))
|
||||
moon_intensity_curve.add_point(Vector2(0.25, 0.0))
|
||||
moon_intensity_curve.add_point(Vector2(0.75, 0.0))
|
||||
moon_intensity_curve.add_point(Vector2(0.85, 0.3))
|
||||
moon_intensity_curve.add_point(Vector2(1.0, 0.4))
|
||||
|
||||
if ambient_color_curve == null:
|
||||
ambient_color_curve = Gradient.new()
|
||||
ambient_color_curve.set_color(0, Color(0.15, 0.18, 0.3)) # Night
|
||||
ambient_color_curve.add_point(0.25, Color(0.5, 0.55, 0.65)) # Morning
|
||||
ambient_color_curve.add_point(0.5, Color(0.6, 0.65, 0.75)) # Noon
|
||||
ambient_color_curve.add_point(0.75, Color(0.55, 0.5, 0.55)) # Evening
|
||||
ambient_color_curve.set_color(1, Color(0.15, 0.18, 0.3)) # Night
|
||||
|
||||
if ambient_intensity_curve == null:
|
||||
ambient_intensity_curve = Curve.new()
|
||||
ambient_intensity_curve.add_point(Vector2(0.0, 0.2))
|
||||
ambient_intensity_curve.add_point(Vector2(0.25, 0.5))
|
||||
ambient_intensity_curve.add_point(Vector2(0.5, 0.7))
|
||||
ambient_intensity_curve.add_point(Vector2(0.75, 0.5))
|
||||
ambient_intensity_curve.add_point(Vector2(1.0, 0.2))
|
||||
|
||||
if fog_color_curve == null:
|
||||
fog_color_curve = Gradient.new()
|
||||
fog_color_curve.set_color(0, Color(0.1, 0.12, 0.2))
|
||||
fog_color_curve.add_point(0.25, Color(0.6, 0.65, 0.75))
|
||||
fog_color_curve.add_point(0.5, Color(0.7, 0.75, 0.85))
|
||||
fog_color_curve.add_point(0.75, Color(0.7, 0.55, 0.5))
|
||||
fog_color_curve.set_color(1, Color(0.1, 0.12, 0.2))
|
||||
|
||||
if fog_density_curve == null:
|
||||
fog_density_curve = Curve.new()
|
||||
fog_density_curve.add_point(Vector2(0.0, 0.02))
|
||||
fog_density_curve.add_point(Vector2(0.25, 0.015))
|
||||
fog_density_curve.add_point(Vector2(0.5, 0.01))
|
||||
fog_density_curve.add_point(Vector2(0.75, 0.015))
|
||||
fog_density_curve.add_point(Vector2(1.0, 0.02))
|
||||
|
||||
if stars_visibility_curve == null:
|
||||
stars_visibility_curve = Curve.new()
|
||||
stars_visibility_curve.add_point(Vector2(0.0, 1.0))
|
||||
stars_visibility_curve.add_point(Vector2(0.2, 0.8))
|
||||
stars_visibility_curve.add_point(Vector2(0.3, 0.0))
|
||||
stars_visibility_curve.add_point(Vector2(0.7, 0.0))
|
||||
stars_visibility_curve.add_point(Vector2(0.85, 0.8))
|
||||
stars_visibility_curve.add_point(Vector2(1.0, 1.0))
|
||||
|
||||
|
||||
func _check_time_events(old_hour: int, new_hour: int) -> void:
|
||||
if time_of_day >= SUNRISE_START and time_of_day < SUNRISE_END and not _sunrise_emitted:
|
||||
_sunrise_emitted = true
|
||||
sunrise_started.emit()
|
||||
|
||||
if time_of_day >= SUNSET_START and time_of_day < SUNSET_END and not _sunset_emitted:
|
||||
_sunset_emitted = true
|
||||
sunset_started.emit()
|
||||
|
||||
if time_of_day >= SUNSET_END and not _night_emitted:
|
||||
_night_emitted = true
|
||||
night_started.emit()
|
||||
|
||||
if time_of_day >= NOON - 0.01 and time_of_day < NOON + 0.01 and not _noon_emitted:
|
||||
_noon_emitted = true
|
||||
noon_reached.emit()
|
||||
|
||||
|
||||
func _reset_time_events() -> void:
|
||||
_sunrise_emitted = false
|
||||
_sunset_emitted = false
|
||||
_night_emitted = false
|
||||
_noon_emitted = false
|
||||
|
||||
|
||||
func get_current_hour() -> int:
|
||||
return int(time_of_day * HOURS_PER_DAY)
|
||||
|
||||
|
||||
func get_current_hour_float() -> float:
|
||||
return time_of_day * HOURS_PER_DAY
|
||||
|
||||
|
||||
func set_time_from_hours(hours: float) -> void:
|
||||
time_of_day = fmod(hours, HOURS_PER_DAY) / HOURS_PER_DAY
|
||||
|
||||
|
||||
func get_sun_direction() -> Vector3:
|
||||
var angle := (time_of_day - 0.25) * TAU
|
||||
var tilt_rad := deg_to_rad(sun_arc_tilt)
|
||||
var offset_rad := deg_to_rad(sun_arc_offset)
|
||||
|
||||
var direction := Vector3(
|
||||
cos(angle + offset_rad),
|
||||
sin(angle),
|
||||
sin(angle) * sin(tilt_rad)
|
||||
).normalized()
|
||||
|
||||
return direction
|
||||
|
||||
|
||||
func get_moon_direction() -> Vector3:
|
||||
var angle := (time_of_day + 0.25) * TAU
|
||||
var tilt_rad := deg_to_rad(moon_arc_tilt)
|
||||
var offset_rad := deg_to_rad(moon_arc_offset)
|
||||
|
||||
var direction := Vector3(
|
||||
cos(angle + offset_rad),
|
||||
sin(angle),
|
||||
sin(angle) * sin(tilt_rad)
|
||||
).normalized()
|
||||
|
||||
return direction
|
||||
|
||||
|
||||
func get_sun_color() -> Color:
|
||||
if sun_color_curve:
|
||||
return sun_color_curve.sample(time_of_day)
|
||||
return Color.WHITE
|
||||
|
||||
|
||||
func get_sun_intensity() -> float:
|
||||
if sun_intensity_curve:
|
||||
return sun_intensity_curve.sample(time_of_day)
|
||||
return 1.0
|
||||
|
||||
|
||||
func get_moon_color() -> Color:
|
||||
if moon_color_curve:
|
||||
return moon_color_curve.sample(time_of_day)
|
||||
return Color(0.7, 0.8, 1.0)
|
||||
|
||||
|
||||
func get_moon_intensity() -> float:
|
||||
var base_intensity := 1.0
|
||||
if moon_intensity_curve:
|
||||
base_intensity = moon_intensity_curve.sample(time_of_day)
|
||||
var phase_factor := 0.5 + 0.5 * cos(moon_phase * TAU)
|
||||
return base_intensity * phase_factor
|
||||
|
||||
|
||||
func get_ambient_color() -> Color:
|
||||
if ambient_color_curve:
|
||||
return ambient_color_curve.sample(time_of_day)
|
||||
return Color(0.5, 0.55, 0.65)
|
||||
|
||||
|
||||
func get_ambient_intensity() -> float:
|
||||
if ambient_intensity_curve:
|
||||
return ambient_intensity_curve.sample(time_of_day)
|
||||
return 0.5
|
||||
|
||||
|
||||
func get_fog_color() -> Color:
|
||||
if fog_color_curve:
|
||||
return fog_color_curve.sample(time_of_day)
|
||||
return Color(0.7, 0.75, 0.85)
|
||||
|
||||
|
||||
func get_fog_density() -> float:
|
||||
if fog_density_curve:
|
||||
return fog_density_curve.sample(time_of_day)
|
||||
return 0.01
|
||||
|
||||
|
||||
func get_stars_visibility() -> float:
|
||||
if stars_visibility_curve:
|
||||
return stars_visibility_curve.sample(time_of_day)
|
||||
return 0.0
|
||||
|
||||
|
||||
func is_daytime() -> bool:
|
||||
return time_of_day >= SUNRISE_END and time_of_day < SUNSET_START
|
||||
|
||||
|
||||
func is_nighttime() -> bool:
|
||||
return time_of_day < SUNRISE_START or time_of_day >= SUNSET_END
|
||||
|
||||
|
||||
func is_dawn() -> bool:
|
||||
return time_of_day >= SUNRISE_START and time_of_day < SUNRISE_END
|
||||
|
||||
|
||||
func is_dusk() -> bool:
|
||||
return time_of_day >= SUNSET_START and time_of_day < SUNSET_END
|
||||
|
||||
|
||||
func get_time_period() -> String:
|
||||
if is_dawn():
|
||||
return "dawn"
|
||||
elif is_dusk():
|
||||
return "dusk"
|
||||
elif is_daytime():
|
||||
return "day"
|
||||
else:
|
||||
return "night"
|
||||
Reference in New Issue
Block a user