From eb6da5aacbf24ce36945f359991d4e83a668624a Mon Sep 17 00:00:00 2001
From: Ryan Reed <git@ryanreed.net>
Date: Mon, 24 Mar 2025 20:15:42 -0400
Subject: [PATCH 1/4] Adding day/night cycle with gradient and curve resources

---
 resources/world/moon_color_gradient.tres      |  5 ++
 resources/world/moon_intensity_curve.tres     |  5 ++
 .../world/sky_horizon_color_gradient.tres     |  5 ++
 resources/world/sky_top_color_gradient.tres   |  5 ++
 resources/world/sun_color_gradient.tres       |  5 ++
 resources/world/sun_intensity_curve.tres      |  5 ++
 scenes/world/day_night_cycle_component.gd     | 50 +++++++++++++++++++
 scenes/world/day_night_cycle_component.gd.uid |  1 +
 scenes/world/day_night_cycle_component.tscn   | 45 +++++++++++++++++
 scenes/world/world.tscn                       | 23 ++-------
 10 files changed, 129 insertions(+), 20 deletions(-)
 create mode 100644 resources/world/moon_color_gradient.tres
 create mode 100644 resources/world/moon_intensity_curve.tres
 create mode 100644 resources/world/sky_horizon_color_gradient.tres
 create mode 100644 resources/world/sky_top_color_gradient.tres
 create mode 100644 resources/world/sun_color_gradient.tres
 create mode 100644 resources/world/sun_intensity_curve.tres
 create mode 100644 scenes/world/day_night_cycle_component.gd
 create mode 100644 scenes/world/day_night_cycle_component.gd.uid
 create mode 100644 scenes/world/day_night_cycle_component.tscn

diff --git a/resources/world/moon_color_gradient.tres b/resources/world/moon_color_gradient.tres
new file mode 100644
index 0000000..240d51a
--- /dev/null
+++ b/resources/world/moon_color_gradient.tres
@@ -0,0 +1,5 @@
+[gd_resource type="Gradient" format=3 uid="uid://bgsedjexjylfr"]
+
+[resource]
+offsets = PackedFloat32Array(0)
+colors = PackedColorArray(0.301961, 0.266667, 0.823529, 1)
diff --git a/resources/world/moon_intensity_curve.tres b/resources/world/moon_intensity_curve.tres
new file mode 100644
index 0000000..96ca9a0
--- /dev/null
+++ b/resources/world/moon_intensity_curve.tres
@@ -0,0 +1,5 @@
+[gd_resource type="Curve" format=3 uid="uid://cmmbliff4tja2"]
+
+[resource]
+_data = [Vector2(0, 1), 0.0, 0.0, 0, 0, Vector2(0.25, 0), 0.0, 0.0, 0, 0, Vector2(0.75, 0), 0.0, 0.0, 0, 0, Vector2(1, 1), 0.0, 0.0, 0, 0]
+point_count = 4
diff --git a/resources/world/sky_horizon_color_gradient.tres b/resources/world/sky_horizon_color_gradient.tres
new file mode 100644
index 0000000..45349ac
--- /dev/null
+++ b/resources/world/sky_horizon_color_gradient.tres
@@ -0,0 +1,5 @@
+[gd_resource type="Gradient" format=3 uid="uid://dvpnjt66dtk46"]
+
+[resource]
+offsets = PackedFloat32Array(0.1, 0.25, 0.401515, 0.6, 0.75, 0.9)
+colors = PackedColorArray(0.317647, 0.333333, 0.65098, 1, 0.87451, 0.521569, 0.407843, 1, 0.584314, 0.980392, 0.980392, 1, 0.584314, 0.980392, 0.980392, 1, 0.87451, 0.521569, 0.407843, 1, 0.317647, 0.333333, 0.65098, 1)
diff --git a/resources/world/sky_top_color_gradient.tres b/resources/world/sky_top_color_gradient.tres
new file mode 100644
index 0000000..34d9e28
--- /dev/null
+++ b/resources/world/sky_top_color_gradient.tres
@@ -0,0 +1,5 @@
+[gd_resource type="Gradient" format=3 uid="uid://d0cpq2rok3jsi"]
+
+[resource]
+offsets = PackedFloat32Array(0.1, 0.4, 0.6, 0.9)
+colors = PackedColorArray(0.317647, 0.333333, 0.65098, 1, 0.583728, 0.979416, 0.978736, 1, 0.584314, 0.980392, 0.980392, 1, 0.317647, 0.333333, 0.65098, 1)
diff --git a/resources/world/sun_color_gradient.tres b/resources/world/sun_color_gradient.tres
new file mode 100644
index 0000000..3162e3f
--- /dev/null
+++ b/resources/world/sun_color_gradient.tres
@@ -0,0 +1,5 @@
+[gd_resource type="Gradient" format=3 uid="uid://chetnl1mrww83"]
+
+[resource]
+offsets = PackedFloat32Array(0, 0.3, 0.7, 1)
+colors = PackedColorArray(1, 0.584314, 0.262745, 1, 0.968627, 0.921569, 0.858824, 1, 0.968627, 0.921569, 0.858824, 1, 1, 0.584314, 0.262745, 1)
diff --git a/resources/world/sun_intensity_curve.tres b/resources/world/sun_intensity_curve.tres
new file mode 100644
index 0000000..2e8688c
--- /dev/null
+++ b/resources/world/sun_intensity_curve.tres
@@ -0,0 +1,5 @@
+[gd_resource type="Curve" format=3 uid="uid://ds0dqy41plskw"]
+
+[resource]
+_data = [Vector2(0.2, 0), 0.0, 0.0, 0, 0, Vector2(0.3, 1), 0.0, 0.0, 0, 0, Vector2(0.7, 1), 0.0, 0.0, 0, 0, Vector2(0.8, 0), 0.0, 0.0, 0, 0]
+point_count = 4
diff --git a/scenes/world/day_night_cycle_component.gd b/scenes/world/day_night_cycle_component.gd
new file mode 100644
index 0000000..4defd21
--- /dev/null
+++ b/scenes/world/day_night_cycle_component.gd
@@ -0,0 +1,50 @@
+extends Node3D
+
+
+@export var day_length: float = 10.0 ## Day length in seconds
+@export var start_time: float = 0.3 ## Between 0-1 (0.3 is morning, 0.5 noon)
+
+@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:
+	time += tick_rate * delta
+
+	if time >= 1.0:
+		time = 0.0
+
+	# 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))
diff --git a/scenes/world/day_night_cycle_component.gd.uid b/scenes/world/day_night_cycle_component.gd.uid
new file mode 100644
index 0000000..e4ac955
--- /dev/null
+++ b/scenes/world/day_night_cycle_component.gd.uid
@@ -0,0 +1 @@
+uid://odh7sbmaku32
diff --git a/scenes/world/day_night_cycle_component.tscn b/scenes/world/day_night_cycle_component.tscn
new file mode 100644
index 0000000..a20f1df
--- /dev/null
+++ b/scenes/world/day_night_cycle_component.tscn
@@ -0,0 +1,45 @@
+[gd_scene load_steps=11 format=3 uid="uid://58cvwtpnkq8r"]
+
+[ext_resource type="Script" uid="uid://odh7sbmaku32" path="res://scenes/world/day_night_cycle_component.gd" id="1_xc0aj"]
+[ext_resource type="Gradient" uid="uid://bgsedjexjylfr" path="res://resources/world/moon_color_gradient.tres" id="2_65gyo"]
+[ext_resource type="Curve" uid="uid://cmmbliff4tja2" path="res://resources/world/moon_intensity_curve.tres" id="3_bdvt6"]
+[ext_resource type="Gradient" uid="uid://chetnl1mrww83" path="res://resources/world/sun_color_gradient.tres" id="4_yeijk"]
+[ext_resource type="Curve" uid="uid://ds0dqy41plskw" path="res://resources/world/sun_intensity_curve.tres" id="5_wylv2"]
+[ext_resource type="Gradient" uid="uid://d0cpq2rok3jsi" path="res://resources/world/sky_top_color_gradient.tres" id="6_ckt1h"]
+[ext_resource type="Gradient" uid="uid://dvpnjt66dtk46" path="res://resources/world/sky_horizon_color_gradient.tres" id="7_03v7x"]
+
+[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_4rhad"]
+
+[sub_resource type="Sky" id="Sky_dphjl"]
+sky_material = SubResource("ProceduralSkyMaterial_4rhad")
+
+[sub_resource type="Environment" id="Environment_sl2e5"]
+background_mode = 2
+sky = SubResource("Sky_dphjl")
+tonemap_mode = 2
+glow_enabled = true
+
+[node name="DayNightCycleComponent" type="Node3D" node_paths=PackedStringArray("environment", "sun", "moon")]
+script = ExtResource("1_xc0aj")
+day_length = 60.0
+moon_color = ExtResource("2_65gyo")
+moon_intensity = ExtResource("3_bdvt6")
+sun_color = ExtResource("4_yeijk")
+sun_intensity = ExtResource("5_wylv2")
+sky_top_color = ExtResource("6_ckt1h")
+sky_horizon_color = ExtResource("7_03v7x")
+ground_bottom_color = ExtResource("6_ckt1h")
+ground_horizon_color = ExtResource("7_03v7x")
+environment = NodePath("WorldEnvironment")
+sun = NodePath("Sun")
+moon = NodePath("Moon")
+
+[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
+environment = SubResource("Environment_sl2e5")
+
+[node name="Sun" type="DirectionalLight3D" parent="."]
+shadow_enabled = true
+
+[node name="Moon" type="DirectionalLight3D" parent="."]
+shadow_enabled = true
+sky_mode = 1
diff --git a/scenes/world/world.tscn b/scenes/world/world.tscn
index aa2b175..839ede4 100644
--- a/scenes/world/world.tscn
+++ b/scenes/world/world.tscn
@@ -1,21 +1,9 @@
-[gd_scene load_steps=7 format=3 uid="uid://mkfitwqnerku"]
+[gd_scene load_steps=5 format=3 uid="uid://mkfitwqnerku"]
 
 [ext_resource type="Script" uid="uid://c0jbvki2cylct" path="res://scenes/world/world.gd" id="1_6m72w"]
 [ext_resource type="PackedScene" uid="uid://beu1b4leqwgh3" path="res://scenes/player/player.tscn" id="2_sl2e5"]
 [ext_resource type="PackedScene" uid="uid://c3pqilb6yh5kc" path="res://save_load/components/save_level_data_component.tscn" id="3_1fp7r"]
-
-[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_4rhad"]
-sky_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
-ground_horizon_color = Color(0.662243, 0.671743, 0.686743, 1)
-
-[sub_resource type="Sky" id="Sky_dphjl"]
-sky_material = SubResource("ProceduralSkyMaterial_4rhad")
-
-[sub_resource type="Environment" id="Environment_sl2e5"]
-background_mode = 2
-sky = SubResource("Sky_dphjl")
-tonemap_mode = 2
-glow_enabled = true
+[ext_resource type="PackedScene" uid="uid://58cvwtpnkq8r" path="res://scenes/world/day_night_cycle_component.tscn" id="3_6m72w"]
 
 [node name="World" type="Node3D" node_paths=PackedStringArray("blocks_container", "dropped_items_container", "spawn_position")]
 script = ExtResource("1_6m72w")
@@ -24,12 +12,7 @@ dropped_items_container = NodePath("DroppedItemsContainer")
 player_scene = ExtResource("2_sl2e5")
 spawn_position = NodePath("SpawnPosition")
 
-[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
-environment = SubResource("Environment_sl2e5")
-
-[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
-transform = Transform3D(-0.866025, -0.433013, 0.25, 0, 0.5, 0.866025, -0.5, 0.75, -0.433013, 0, 0, 0)
-shadow_enabled = true
+[node name="DayNightCycleComponent" parent="." instance=ExtResource("3_6m72w")]
 
 [node name="BlocksContainer" type="Node3D" parent="."]
 

From 7856b02ae6bba115ccda0b27448be6ce091f63e5 Mon Sep 17 00:00:00 2001
From: Ryan Reed <git@ryanreed.net>
Date: Mon, 24 Mar 2025 20:32:13 -0400
Subject: [PATCH 2/4] Adding signals for controlling time

---
 scenes/world/day_night_cycle_component.gd | 30 +++++++++++++++++++++++
 1 file changed, 30 insertions(+)

diff --git a/scenes/world/day_night_cycle_component.gd b/scenes/world/day_night_cycle_component.gd
index 4defd21..3003ba0 100644
--- a/scenes/world/day_night_cycle_component.gd
+++ b/scenes/world/day_night_cycle_component.gd
@@ -1,8 +1,16 @@
 extends Node3D
 
 
+signal change_day_length(length_in_seconds: float)
+signal end_of_day
+signal pause_time
+signal resume_time
+signal set_time(time: float) ## Time should be between 0 and 1
+
+
 @export var day_length: float = 10.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
@@ -24,10 +32,13 @@ extends Node3D
 
 
 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
@@ -48,3 +59,22 @@ func _process(delta: float) -> void:
 	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:
+	change_day_length.connect(_on_change_day_length)
+	pause_time.connect(_on_pause_time)
+	resume_time.connect(_on_resume_time)
+
+
+func _on_change_day_length(seconds: float) -> void:
+	day_length = seconds
+	tick_rate = 1.0 / day_length
+
+func _on_pause_time() -> void:
+	time_paused = true
+
+func _on_resume_time() -> void:
+	time_paused = true
+
+func _on_set_time(new_time: float) -> void:
+	time = new_time

From b21e2f94f287819275e938bdddfb603746754202 Mon Sep 17 00:00:00 2001
From: Ryan Reed <git@ryanreed.net>
Date: Mon, 24 Mar 2025 20:40:16 -0400
Subject: [PATCH 3/4] Updating signals

---
 scenes/world/day_night_cycle_component.gd | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/scenes/world/day_night_cycle_component.gd b/scenes/world/day_night_cycle_component.gd
index 3003ba0..b7f6b99 100644
--- a/scenes/world/day_night_cycle_component.gd
+++ b/scenes/world/day_night_cycle_component.gd
@@ -1,10 +1,11 @@
 extends Node3D
 
 
-signal change_day_length(length_in_seconds: float)
 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
 
 
@@ -61,14 +62,15 @@ func _process(delta: float) -> void:
 	environment.environment.sky.sky_material.set("ground_horizon_color", ground_horizon_color.sample(time))
 
 func _ready() -> void:
-	change_day_length.connect(_on_change_day_length)
 	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)
 
 
-func _on_change_day_length(seconds: float) -> void:
-	day_length = seconds
-	tick_rate = 1.0 / day_length
+func update_tick_rate(new_rate: float = 1.0) -> void:
+	tick_rate = new_rate / day_length
+
 
 func _on_pause_time() -> void:
 	time_paused = true
@@ -76,5 +78,12 @@ func _on_pause_time() -> void:
 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

From 52603b13f1336bca9965118524db00154f9237aa Mon Sep 17 00:00:00 2001
From: Ryan Reed <git@ryanreed.net>
Date: Mon, 24 Mar 2025 20:40:57 -0400
Subject: [PATCH 4/4] Setting default day length to 60 seconds

---
 scenes/world/day_night_cycle_component.gd   | 2 +-
 scenes/world/day_night_cycle_component.tscn | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/scenes/world/day_night_cycle_component.gd b/scenes/world/day_night_cycle_component.gd
index b7f6b99..c4c66a1 100644
--- a/scenes/world/day_night_cycle_component.gd
+++ b/scenes/world/day_night_cycle_component.gd
@@ -9,7 +9,7 @@ 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 = 10.0 ## Day length in seconds
+@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
 
diff --git a/scenes/world/day_night_cycle_component.tscn b/scenes/world/day_night_cycle_component.tscn
index a20f1df..aa047b4 100644
--- a/scenes/world/day_night_cycle_component.tscn
+++ b/scenes/world/day_night_cycle_component.tscn
@@ -21,7 +21,6 @@ glow_enabled = true
 
 [node name="DayNightCycleComponent" type="Node3D" node_paths=PackedStringArray("environment", "sun", "moon")]
 script = ExtResource("1_xc0aj")
-day_length = 60.0
 moon_color = ExtResource("2_65gyo")
 moon_intensity = ExtResource("3_bdvt6")
 sun_color = ExtResource("4_yeijk")