extends Control @export var day_night_cycle: Node const SIZE_DIAL := 60.0 const RING_RADIUS := 24.0 const RING_THICKNESS := 4.0 const GLOW_RADIUS := 2.5 const COLOR_NIGHT := Color(0.12, 0.16, 0.42, 1) const COLOR_DAWN := Color(0.95, 0.5, 0.2, 1) const COLOR_DAY := Color(1, 0.84, 0.38, 1) const COLOR_DUSK := Color(0.9, 0.35, 0.2, 1) const COLOR_BG := Color(0.06, 0.06, 0.08, 0.65) var _last_fraction := -1.0 var _last_color := Color.TRANSPARENT func _process(_delta: float) -> void: var fraction := _cycle_fraction() if not is_equal_approx(fraction, _last_fraction): _last_fraction = fraction queue_redraw() func _draw() -> void: var center := Vector2(SIZE_DIAL / 2.0, SIZE_DIAL / 2.0) var fraction := _last_fraction if fraction < 0.0: fraction = _cycle_fraction() _last_fraction = fraction var time_color := _time_color(fraction) draw_circle(center, RING_RADIUS + 1.0, COLOR_BG) var start_angle := -PI / 2.0 var end_angle := start_angle + fraction * TAU draw_arc(center, RING_RADIUS, start_angle, end_angle, 48, time_color, RING_THICKNESS, true) if fraction > 0.0: var tip_dir := Vector2.from_angle(end_angle) var tip_pos := center + tip_dir * RING_RADIUS draw_circle(tip_pos, GLOW_RADIUS, time_color.lightened(0.3)) var label := _phase_label(fraction) var font := ThemeDB.fallback_font if font == null: return var font_size := 11 var text_size := font.get_string_size(label, HORIZONTAL_ALIGNMENT_CENTER, -1, font_size) var text_x := (SIZE_DIAL - text_size.x) / 2.0 var text_y := SIZE_DIAL - text_size.y + 4.0 draw_string(font, Vector2(text_x, text_y), label, HORIZONTAL_ALIGNMENT_LEFT, -1, font_size, Color.WHITE) func _cycle_fraction() -> float: if day_night_cycle == null: return 0.0 var elapsed: float = day_night_cycle.get("elapsed") if "elapsed" in day_night_cycle else 0.0 var duration: float = ( day_night_cycle.get("cycle_duration_seconds") if "cycle_duration_seconds" in day_night_cycle else 240.0 ) if duration <= 0.0: return 0.0 return fmod(elapsed / duration, 1.0) func _time_color(fraction: float) -> Color: if fraction < 0.15: return COLOR_NIGHT if fraction < 0.3: return COLOR_NIGHT.lerp(COLOR_DAWN, smoothstep(0.15, 0.3, fraction)) if fraction < 0.7: return COLOR_DAY if fraction < 0.85: return COLOR_DAY.lerp(COLOR_DUSK, smoothstep(0.7, 0.85, fraction)) return COLOR_DUSK.lerp(COLOR_NIGHT, smoothstep(0.85, 1.0, fraction)) func _phase_label(fraction: float) -> String: if fraction < 0.1: return "Night" if fraction < 0.2: return "Dawn" if fraction < 0.65: return "Day" if fraction < 0.8: return "Dusk" return "Night"