feat: add circular time-of-day dial to UI
A 60x60 circular dial drawn at the top-center of the screen shows the current position in the day/night cycle. A filled arc sweeps clockwise from the top; the color transitions from dark blue (night) through orange (dawn), gold (day), and pink (dusk). A small glow dot marks the leading tip; a phase label (Night/Dawn/Day/Dusk) sits below. Redraws only when the cycle fraction changes. References DayNightCycle via node_path so it stays in sync with the environment lighting.
This commit is contained in:
@@ -9,6 +9,7 @@
|
|||||||
[ext_resource type="Script" uid="uid://bbwol3mrjgn2x" path="res://world/active_world_adapter.gd" id="9_adapter"]
|
[ext_resource type="Script" uid="uid://bbwol3mrjgn2x" path="res://world/active_world_adapter.gd" id="9_adapter"]
|
||||||
[ext_resource type="Script" path="res://simulation/persistence/SaveSlotController.gd" id="10_save"]
|
[ext_resource type="Script" path="res://simulation/persistence/SaveSlotController.gd" id="10_save"]
|
||||||
[ext_resource type="PackedScene" path="res://world/jajce/JajceWorld.tscn" id="11_jajce"]
|
[ext_resource type="PackedScene" path="res://world/jajce/JajceWorld.tscn" id="11_jajce"]
|
||||||
|
[ext_resource type="Script" path="res://world/ui/time_dial.gd" id="12_timedial"]
|
||||||
|
|
||||||
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_o5qli"]
|
[sub_resource type="CapsuleShape3D" id="CapsuleShape3D_o5qli"]
|
||||||
radius = 0.4
|
radius = 0.4
|
||||||
@@ -124,3 +125,12 @@ layout_mode = 2
|
|||||||
theme_override_colors/font_color = Color(0.96, 0.91, 0.78, 1)
|
theme_override_colors/font_color = Color(0.96, 0.91, 0.78, 1)
|
||||||
theme_override_font_sizes/font_size = 15
|
theme_override_font_sizes/font_size = 15
|
||||||
text = "Villager inspector"
|
text = "Villager inspector"
|
||||||
|
|
||||||
|
[node name="TimeDial" type="Control" parent="UI" node_paths=PackedStringArray("day_night_cycle")]
|
||||||
|
layout_mode = 0
|
||||||
|
offset_left = 880.0
|
||||||
|
offset_top = 6.0
|
||||||
|
offset_right = 940.0
|
||||||
|
offset_bottom = 66.0
|
||||||
|
script = ExtResource("12_timedial")
|
||||||
|
day_night_cycle = NodePath("../JajceWorld/DayNightCycle")
|
||||||
|
|||||||
@@ -0,0 +1,93 @@
|
|||||||
|
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"
|
||||||
Reference in New Issue
Block a user