fix stutter
This commit is contained in:
@@ -1,5 +1,9 @@
|
||||
extends Node3D
|
||||
|
||||
const CHUNK_GENERATION_STEPS_PER_FRAME: int = 2
|
||||
const CHUNK_CLEANUP_STEPS_PER_FRAME: int = 4
|
||||
const LAMPPOST_WIRE_STEPS_PER_FRAME: int = 1
|
||||
|
||||
@export_group("Rails")
|
||||
@export var rail_path: Path3D
|
||||
|
||||
@@ -20,6 +24,12 @@ var last_pos_train: Vector2i = Vector2i(999999, 999999)
|
||||
var noise_generator: FastNoiseLite
|
||||
var altitude_generator: FastNoiseLite
|
||||
var wire_connections: Dictionary = {}
|
||||
var chunk_candidate_cache: Dictionary = {}
|
||||
var pending_generation_cells: Array[Vector2i] = []
|
||||
var pending_cleanup_cells: Array[Vector2i] = []
|
||||
var pending_wire_cells: Array[Vector2i] = []
|
||||
var pending_wire_lookup: Dictionary = {}
|
||||
var pending_radar_update: bool = false
|
||||
|
||||
var manual_biome: Biome = null
|
||||
|
||||
@@ -36,6 +46,7 @@ func _ready() -> void:
|
||||
altitude_generator.seed = randi()
|
||||
altitude_generator.frequency = district_scale * 0.5
|
||||
|
||||
_warm_chunk_candidate_cache()
|
||||
_update_set_pieces()
|
||||
|
||||
func _update_set_pieces() -> void:
|
||||
@@ -47,7 +58,7 @@ func _update_set_pieces() -> void:
|
||||
if not "exclusive_biome" in sp or sp.exclusive_biome == "":
|
||||
print("⚠️ Set Piece '", sp.name, "' not have exclusive biome -> always visible.")
|
||||
continue
|
||||
|
||||
|
||||
var local_biome = ""
|
||||
if manual_biome != null:
|
||||
local_biome = manual_biome.nome
|
||||
@@ -55,7 +66,7 @@ func _update_set_pieces() -> void:
|
||||
var grid_x = roundi(sp.global_position.x / chunk_size)
|
||||
var grid_z = roundi(sp.global_position.z / chunk_size)
|
||||
local_biome = _get_procedural_biome_name(noise_generator.get_noise_2d(grid_x, grid_z))
|
||||
|
||||
|
||||
print("Analyze: '", sp.name, "' | Need: [", sp.exclusive_biome, "] | Current biome is: [", local_biome, "]")
|
||||
if local_biome == sp.exclusive_biome:
|
||||
sp.show()
|
||||
@@ -67,15 +78,18 @@ func _update_set_pieces() -> void:
|
||||
print(" ❌ Temple is an invisible ghost.")
|
||||
|
||||
func _destroy_and_regenrate_world() -> void:
|
||||
_warm_chunk_candidate_cache()
|
||||
_clear_pending_world_work()
|
||||
|
||||
#Turn off old temples
|
||||
_update_set_pieces()
|
||||
|
||||
#Destroy all models
|
||||
for pos in board.keys():
|
||||
var cella = board[pos]
|
||||
if cella["tipo"] == "bioma":
|
||||
if cella.has("nodo") and is_instance_valid(cella["nodo"]):
|
||||
cella["nodo"].queue_free()
|
||||
if cella["type"] != "obstacle":
|
||||
if cella.has("node") and is_instance_valid(cella["node"]):
|
||||
cella["node"].queue_free()
|
||||
|
||||
#Clean board and wire connections
|
||||
board.clear()
|
||||
@@ -83,9 +97,20 @@ func _destroy_and_regenrate_world() -> void:
|
||||
|
||||
#Create train
|
||||
last_pos_train = Vector2i(999999, 999999)
|
||||
_train_radar()
|
||||
last_pos_train = Vector2i(999999, 999999)
|
||||
_train_radar()
|
||||
if rail_path != null and rail_path.train_instance != null:
|
||||
var train_pos = rail_path.train_instance.global_position
|
||||
var current_pos = Vector2i(roundi(train_pos.x / chunk_size), roundi(train_pos.z / chunk_size))
|
||||
_refresh_world_work(current_pos)
|
||||
pending_radar_update = true
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
_drain_cleanup_queue()
|
||||
_drain_generation_queue()
|
||||
_drain_wire_queue()
|
||||
|
||||
if pending_radar_update:
|
||||
pending_radar_update = false
|
||||
_train_radar()
|
||||
|
||||
func _physics_process(_delta: float) -> void:
|
||||
if rail_path == null or rail_path.train_instance == null: return
|
||||
@@ -97,9 +122,8 @@ func _physics_process(_delta: float) -> void:
|
||||
|
||||
if current_pos != last_pos_train:
|
||||
last_pos_train = current_pos
|
||||
_generate_pieces_around_train(current_pos)
|
||||
_clean_far_chunks(current_pos)
|
||||
_train_radar()
|
||||
_refresh_world_work(current_pos)
|
||||
pending_radar_update = true
|
||||
|
||||
func collect_all_chunkinfo(root: Node, list: Array[Node]) -> void:
|
||||
if root == null: return
|
||||
@@ -110,11 +134,173 @@ func collect_all_chunkinfo(root: Node, list: Array[Node]) -> void:
|
||||
for child in root.get_children():
|
||||
collect_all_chunkinfo(child, list)
|
||||
|
||||
func _warm_chunk_candidate_cache() -> void:
|
||||
var unique_scenes: Dictionary = {}
|
||||
|
||||
for biome in biome_list:
|
||||
if biome == null:
|
||||
continue
|
||||
for scene in biome.available_chunks:
|
||||
if scene == null:
|
||||
continue
|
||||
unique_scenes[_get_chunk_scene_cache_key(scene)] = scene
|
||||
|
||||
if manual_biome != null:
|
||||
for scene in manual_biome.available_chunks:
|
||||
if scene == null:
|
||||
continue
|
||||
unique_scenes[_get_chunk_scene_cache_key(scene)] = scene
|
||||
|
||||
for scene in unique_scenes.values():
|
||||
_get_chunk_scene_metadata(scene)
|
||||
|
||||
func _get_chunk_scene_cache_key(scene: PackedScene) -> String:
|
||||
if scene == null:
|
||||
return ""
|
||||
if scene.resource_path != "":
|
||||
return scene.resource_path
|
||||
return "scene_%s" % scene.get_instance_id()
|
||||
|
||||
func _get_chunk_scene_metadata(scene: PackedScene) -> Dictionary:
|
||||
if scene == null:
|
||||
return {}
|
||||
|
||||
var key = _get_chunk_scene_cache_key(scene)
|
||||
if chunk_candidate_cache.has(key):
|
||||
return chunk_candidate_cache[key]
|
||||
|
||||
var preview_chunk = scene.instantiate()
|
||||
var info_list: Array[Node] = []
|
||||
collect_all_chunkinfo(preview_chunk, info_list)
|
||||
var info_node = info_list[0] if info_list.size() > 0 else null
|
||||
|
||||
if info_node == null or not info_node.has_method("get_rotated_data"):
|
||||
preview_chunk.queue_free()
|
||||
chunk_candidate_cache[key] = {}
|
||||
return {}
|
||||
|
||||
var info_path: NodePath = NodePath(".")
|
||||
if info_node != preview_chunk:
|
||||
info_path = preview_chunk.get_path_to(info_node)
|
||||
|
||||
var rotations = []
|
||||
for rot in range(4):
|
||||
rotations.append({
|
||||
"rotation": rot,
|
||||
"data": info_node.get_rotated_data(rot)
|
||||
})
|
||||
|
||||
var metadata = {
|
||||
"info_path": info_path,
|
||||
"rotations": rotations,
|
||||
"has_lamppost": "have_lamppost" in info_node and info_node.have_lamppost,
|
||||
}
|
||||
preview_chunk.queue_free()
|
||||
chunk_candidate_cache[key] = metadata
|
||||
return metadata
|
||||
|
||||
func _get_cached_chunk_info(instance: Node, scene: PackedScene) -> Node:
|
||||
var metadata = _get_chunk_scene_metadata(scene)
|
||||
if metadata.is_empty():
|
||||
return null
|
||||
|
||||
var info_path: NodePath = metadata["info_path"]
|
||||
if String(info_path) == ".":
|
||||
return instance
|
||||
return instance.get_node_or_null(info_path)
|
||||
|
||||
func _clear_pending_world_work() -> void:
|
||||
pending_generation_cells.clear()
|
||||
pending_cleanup_cells.clear()
|
||||
pending_wire_cells.clear()
|
||||
pending_wire_lookup.clear()
|
||||
pending_radar_update = false
|
||||
|
||||
func _refresh_world_work(center: Vector2i) -> void:
|
||||
_rebuild_generation_queue(center)
|
||||
_rebuild_cleanup_queue(center)
|
||||
|
||||
func _rebuild_generation_queue(center: Vector2i) -> void:
|
||||
pending_generation_cells.clear()
|
||||
|
||||
for radius in range(eye_line + 1):
|
||||
for x in range(-radius, radius + 1):
|
||||
for z in range(-radius, radius + 1):
|
||||
if maxi(abs(x), abs(z)) != radius:
|
||||
continue
|
||||
|
||||
var grid_pos = center + Vector2i(x, z)
|
||||
if board.has(grid_pos):
|
||||
continue
|
||||
pending_generation_cells.append(grid_pos)
|
||||
|
||||
func _rebuild_cleanup_queue(center: Vector2i) -> void:
|
||||
pending_cleanup_cells.clear()
|
||||
var safe_margin = 2
|
||||
|
||||
for grid_pos in board.keys():
|
||||
var cell = board[grid_pos]
|
||||
if cell["type"] == "obstacle":
|
||||
continue
|
||||
|
||||
var dist_x = abs(grid_pos.x - center.x)
|
||||
var dist_z = abs(grid_pos.y - center.y)
|
||||
if dist_x > eye_line + safe_margin or dist_z > eye_line + safe_margin:
|
||||
pending_cleanup_cells.append(grid_pos)
|
||||
|
||||
func _drain_generation_queue() -> void:
|
||||
var processed = 0
|
||||
while processed < CHUNK_GENERATION_STEPS_PER_FRAME and not pending_generation_cells.is_empty():
|
||||
var grid_pos = pending_generation_cells.pop_front()
|
||||
if board.has(grid_pos):
|
||||
continue
|
||||
|
||||
var is_obstacle = _register_cell_with_ray(grid_pos)
|
||||
if not is_obstacle:
|
||||
_add_compatible_biome(grid_pos)
|
||||
processed += 1
|
||||
|
||||
func _drain_cleanup_queue() -> void:
|
||||
var processed = 0
|
||||
while processed < CHUNK_CLEANUP_STEPS_PER_FRAME and not pending_cleanup_cells.is_empty():
|
||||
var grid_pos = pending_cleanup_cells.pop_front()
|
||||
if not board.has(grid_pos):
|
||||
continue
|
||||
|
||||
var cell = board[grid_pos]
|
||||
if cell["type"] == "obstacle":
|
||||
continue
|
||||
|
||||
if cell.has("node") and is_instance_valid(cell["node"]):
|
||||
cell["node"].queue_free()
|
||||
board.erase(grid_pos)
|
||||
processed += 1
|
||||
|
||||
func _queue_lamppost_wire_connection(grid_pos: Vector2i) -> void:
|
||||
if pending_wire_lookup.has(grid_pos):
|
||||
return
|
||||
pending_wire_lookup[grid_pos] = true
|
||||
pending_wire_cells.append(grid_pos)
|
||||
|
||||
func _drain_wire_queue() -> void:
|
||||
var processed = 0
|
||||
while processed < LAMPPOST_WIRE_STEPS_PER_FRAME and not pending_wire_cells.is_empty():
|
||||
var grid_pos = pending_wire_cells.pop_front()
|
||||
pending_wire_lookup.erase(grid_pos)
|
||||
|
||||
if not board.has(grid_pos):
|
||||
continue
|
||||
if not board[grid_pos].get("have_lamppost", false):
|
||||
continue
|
||||
|
||||
_connect_lamppost_wires(grid_pos)
|
||||
processed += 1
|
||||
|
||||
func _generate_pieces_around_train(center: Vector2i) -> void:
|
||||
for x in range(-eye_line, eye_line + 1):
|
||||
for z in range(-eye_line, eye_line + 1):
|
||||
var grid_pos = center + Vector2i(x, z)
|
||||
|
||||
|
||||
if not board.has(grid_pos):
|
||||
var ce_obstacle = _register_cell_with_ray(grid_pos)
|
||||
if not ce_obstacle:
|
||||
@@ -166,7 +352,7 @@ func _register_cell_with_ray(grid_pos: Vector2i) -> bool:
|
||||
if info_list.size() > 0:
|
||||
var min_distance = 999999.0
|
||||
var center_cell_pos = Vector3(world_pos.x, 0, world_pos.z)
|
||||
|
||||
|
||||
for info in info_list:
|
||||
if info is Node3D:
|
||||
var pos_info = Vector3(info.global_position.x, 0, info.global_position.z)
|
||||
@@ -191,7 +377,7 @@ func _register_cell_with_ray(grid_pos: Vector2i) -> bool:
|
||||
var data = right_info_node.get_rotated_data(rotation_steps)
|
||||
exit_found = data["connections"]
|
||||
height_found = data["heights"]
|
||||
|
||||
|
||||
if "have_lamppost" in right_info_node:
|
||||
have_lamppost = right_info_node.have_lamppost
|
||||
|
||||
@@ -206,7 +392,7 @@ func _register_cell_with_ray(grid_pos: Vector2i) -> bool:
|
||||
}
|
||||
|
||||
if have_lamppost:
|
||||
_connect_lamppost_wires(grid_pos)
|
||||
_queue_lamppost_wire_connection(grid_pos)
|
||||
|
||||
return true
|
||||
return false
|
||||
@@ -229,43 +415,40 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
||||
var valid_candidates = []
|
||||
|
||||
for scene in zone_catalogue:
|
||||
var test_chunk = scene.instantiate()
|
||||
var test_list: Array[Node] = []
|
||||
collect_all_chunkinfo(test_chunk, test_list)
|
||||
var info_test = test_list[0] if test_list.size() > 0 else null
|
||||
var metadata = _get_chunk_scene_metadata(scene)
|
||||
if metadata.is_empty():
|
||||
continue
|
||||
|
||||
if info_test != null and info_test.has_method("get_rotated_data"):
|
||||
for rot in range(4):
|
||||
var data = test_chunk.get_rotated_data(rot)
|
||||
var u_conn = data["connections"]
|
||||
var u_height = data["heights"]
|
||||
for candidate in metadata["rotations"]:
|
||||
var rot = candidate["rotation"]
|
||||
var data = candidate["data"]
|
||||
var u_conn = data["connections"]
|
||||
var u_height = data["heights"]
|
||||
|
||||
var match_conn_n = (req_conn_north == -1) or ((req_conn_north == 1) == u_conn["north"])
|
||||
var match_conn_e = (req_conn_est == -1) or ((req_conn_est == 1) == u_conn["est"])
|
||||
var match_conn_s = (req_conn_south == -1) or ((req_conn_south == 1) == u_conn["south"])
|
||||
var match_conn_o = (req_conn_west == -1) or ((req_conn_west == 1) == u_conn["west"])
|
||||
|
||||
var match_alt_n = (req_height_north == -1) or (req_height_north == u_height["north"])
|
||||
var match_alt_e = (req_height_est == -1) or (req_height_est == u_height["est"])
|
||||
var match_alt_s = (req_height_south == -1) or (req_height_south == u_height["south"])
|
||||
var match_alt_o = (req_height_west == -1) or (req_height_west == u_height["west"])
|
||||
|
||||
var diff_n = abs(u_height["north"] - height_target) if req_height_north == -1 else 0
|
||||
var diff_e = abs(u_height["est"] - height_target) if req_height_est == -1 else 0
|
||||
var diff_s = abs(u_height["south"] - height_target) if req_height_south == -1 else 0
|
||||
var diff_o = abs(u_height["west"] - height_target) if req_height_west == -1 else 0
|
||||
var excessive_jumps = diff_n > 1 or diff_e > 1 or diff_s > 1 or diff_o > 1
|
||||
|
||||
if match_conn_n and match_conn_e and match_conn_s and match_conn_o and match_alt_n and match_alt_e and match_alt_s and match_alt_o and not excessive_jumps:
|
||||
var score = 0
|
||||
if req_height_north == -1 and u_height["north"] == height_target: score += 1
|
||||
if req_height_est == -1 and u_height["est"] == height_target: score += 1
|
||||
if req_height_south == -1 and u_height["south"] == height_target: score += 1
|
||||
if req_height_west == -1 and u_height["west"] == height_target: score += 1
|
||||
|
||||
var match_conn_n = (req_conn_north == -1) or ((req_conn_north == 1) == u_conn["north"])
|
||||
var match_conn_e = (req_conn_est == -1) or ((req_conn_est == 1) == u_conn["est"])
|
||||
var match_conn_s = (req_conn_south == -1) or ((req_conn_south == 1) == u_conn["south"])
|
||||
var match_conn_o = (req_conn_west == -1) or ((req_conn_west == 1) == u_conn["west"])
|
||||
|
||||
var match_alt_n = (req_height_north == -1) or (req_height_north == u_height["north"])
|
||||
var match_alt_e = (req_height_est == -1) or (req_height_est == u_height["est"])
|
||||
var match_alt_s = (req_height_south == -1) or (req_height_south == u_height["south"])
|
||||
var match_alt_o = (req_height_west == -1) or (req_height_west == u_height["west"])
|
||||
|
||||
var diff_n = abs(u_height["north"] - height_target) if req_height_north == -1 else 0
|
||||
var diff_e = abs(u_height["est"] - height_target) if req_height_est == -1 else 0
|
||||
var diff_s = abs(u_height["south"] - height_target) if req_height_south == -1 else 0
|
||||
var diff_o = abs(u_height["west"] - height_target) if req_height_west == -1 else 0
|
||||
var excessive_jumps = diff_n > 1 or diff_e > 1 or diff_s > 1 or diff_o > 1
|
||||
|
||||
if match_conn_n and match_conn_e and match_conn_s and match_conn_o and match_alt_n and match_alt_e and match_alt_s and match_alt_o and not excessive_jumps:
|
||||
var score = 0
|
||||
if req_height_north == -1 and u_height["north"] == height_target: score += 1
|
||||
if req_height_est == -1 and u_height["est"] == height_target: score += 1
|
||||
if req_height_south == -1 and u_height["south"] == height_target: score += 1
|
||||
if req_height_west == -1 and u_height["west"] == height_target: score += 1
|
||||
|
||||
valid_candidates.append({"scene": scene, "rotation": rot, "data": data, "score": score})
|
||||
|
||||
test_chunk.queue_free()
|
||||
valid_candidates.append({"scene": scene, "rotation": rot, "data": data, "score": score})
|
||||
|
||||
if valid_candidates.size() > 0:
|
||||
var max_score = -1
|
||||
@@ -278,16 +461,14 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
||||
|
||||
var choise = best_candidate.pick_random()
|
||||
var new_chunk = choise.scene.instantiate()
|
||||
add_child(new_chunk)
|
||||
new_chunk.position = Vector3(grid_pos.x * chunk_size, 0, grid_pos.y * chunk_size)
|
||||
new_chunk.rotation.y = choise.rotation * (-PI / 2.0)
|
||||
add_child(new_chunk)
|
||||
|
||||
var new_list: Array[Node] = []
|
||||
collect_all_chunkinfo(new_chunk, new_list)
|
||||
var info_new = new_list[0] if new_list.size() > 0 else null
|
||||
var info_new = _get_cached_chunk_info(new_chunk, choise.scene)
|
||||
|
||||
var have_lamppost = false
|
||||
if info_new != null and "have_lamppost" in new_chunk:
|
||||
if info_new != null and "have_lamppost" in info_new:
|
||||
have_lamppost = info_new.have_lamppost
|
||||
|
||||
board[grid_pos] = {
|
||||
@@ -300,16 +481,14 @@ func _add_compatible_biome(grid_pos: Vector2i) -> void:
|
||||
}
|
||||
|
||||
if have_lamppost:
|
||||
_connect_lamppost_wires(grid_pos)
|
||||
_queue_lamppost_wire_connection(grid_pos)
|
||||
|
||||
else:
|
||||
var backup = zone_catalogue[0].instantiate()
|
||||
add_child(backup)
|
||||
backup.position = Vector3(grid_pos.x * chunk_size, 0, grid_pos.y * chunk_size)
|
||||
add_child(backup)
|
||||
|
||||
var backup_list: Array[Node] = []
|
||||
collect_all_chunkinfo(backup, backup_list)
|
||||
var info_backup = backup_list[0] if backup_list.size() > 0 else null
|
||||
var info_backup = _get_cached_chunk_info(backup, zone_catalogue[0])
|
||||
|
||||
var safe_heights = {
|
||||
"north": req_height_north if req_height_north != -1 else height_target,
|
||||
@@ -351,8 +530,6 @@ func _train_radar() -> void:
|
||||
|
||||
var current_progress = rail_path.train_progress
|
||||
var total_length = rail_path.curve.get_baked_length()
|
||||
#var exchange_distance = 0.0
|
||||
#var next_biome = ""
|
||||
|
||||
for step in range(1, 31):
|
||||
var next_progress = wrapf(current_progress + (step * chunk_size), 0.0, total_length)
|
||||
@@ -364,44 +541,18 @@ func _train_radar() -> void:
|
||||
var future_biome = _get_procedural_biome_name(noise_generator.get_noise_2d(f_x, f_z))
|
||||
|
||||
if future_biome != current_biome:
|
||||
#exchange_distance = step * chunk_size
|
||||
#next_biome = future_biome
|
||||
break
|
||||
|
||||
func _clean_far_chunks(centro_attuale: Vector2i) -> void:
|
||||
var cells_to_remove = []
|
||||
var safe_margin = 2
|
||||
|
||||
for grid_pos in board.keys():
|
||||
var cell = board[grid_pos]
|
||||
if cell["type"] == "obstacle": continue
|
||||
|
||||
var dist_x = abs(grid_pos.x - centro_attuale.x)
|
||||
var dist_z = abs(grid_pos.y - centro_attuale.y)
|
||||
|
||||
if dist_x > eye_line + safe_margin or dist_z > eye_line + safe_margin:
|
||||
if cell.has("node") and is_instance_valid(cell["node"]):
|
||||
cell["node"].queue_free()
|
||||
cells_to_remove.append(grid_pos)
|
||||
|
||||
for pos in cells_to_remove:
|
||||
board.erase(pos)
|
||||
|
||||
|
||||
func _get_lampposts(info_node: Node, side: String) -> Array[Node3D]:
|
||||
var lampposts: Array[Node3D] = []
|
||||
if side == "sx":
|
||||
if "connection_left" in info_node and info_node.connection_left != null:
|
||||
for p in info_node.connection_left:
|
||||
if is_instance_valid(p): lampposts.append(p)
|
||||
#if lampposts.is_empty() and "nodo_attacco_sx" in nodo_info and is_instance_valid(nodo_info.get("nodo_attacco_sx")):
|
||||
# lampposts.append(nodo_info.get("nodo_attacco_sx"))
|
||||
else:
|
||||
if "connection_right" in info_node and info_node.connection_right != null:
|
||||
for p in info_node.connection_right:
|
||||
if is_instance_valid(p): lampposts.append(p)
|
||||
#if lampposts.is_empty() and "nodo_attacco_dx" in nodo_info and is_instance_valid(nodo_info.get("nodo_attacco_dx")):
|
||||
# lampposts.append(nodo_info.get("nodo_attacco_dx"))
|
||||
return lampposts
|
||||
|
||||
func _connect_lamppost_wires(new_board_pos: Vector2i) -> void:
|
||||
@@ -471,7 +622,7 @@ func _connect_lamppost_wires(new_board_pos: Vector2i) -> void:
|
||||
if board.has(closest_pos) and board[closest_pos].get("have_lamppost", false):
|
||||
var closest_root = board[closest_pos]["node"]
|
||||
var closest_info = board[closest_pos]["info"]
|
||||
|
||||
|
||||
if not is_instance_valid(closest_root) or closest_root == new_root or closest_info == null: continue
|
||||
|
||||
if closest_info is Node3D: closest_info.force_update_transform()
|
||||
|
||||
@@ -4,6 +4,7 @@ extends Node3D
|
||||
const NOISE_TEXTURE: Texture2D = preload("res://core/daynight/noise.tres")
|
||||
const WEATHER_SHADER: Material = preload("res://core/daynight/weather_overlay.tres")
|
||||
const WEATHER_PLAIN_SHADER: Material = preload("res://core/daynight/weather_plain_shader.tres")
|
||||
const DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME: int = 2 #how many update of the environment (apply materials) will be done per frame
|
||||
|
||||
@export var environment_config: EnvironmentConfig
|
||||
|
||||
@@ -35,6 +36,7 @@ var weather_controller: WeatherController
|
||||
|
||||
var day_tween: Tween
|
||||
var day_time: float = 0.0
|
||||
var pending_environment_nodes: Dictionary = {}
|
||||
|
||||
func _ready() -> void:
|
||||
|
||||
@@ -76,9 +78,50 @@ func _ready() -> void:
|
||||
weather_controller.name = "WeatherController"
|
||||
add_child(weather_controller)
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
_process_pending_environment_nodes()
|
||||
|
||||
func _on_tree_node_added(node: Node) -> void:
|
||||
if node.is_in_group("wind_node") or node.is_in_group("weather_node") or node.is_in_group("weather_vegetables_node"):
|
||||
call_deferred("_apply_dynamic_environment_materials", node)
|
||||
_queue_dynamic_environment_node(node)
|
||||
|
||||
func _queue_dynamic_environment_node(node: Node) -> void:
|
||||
if not is_instance_valid(node):
|
||||
return
|
||||
|
||||
var ancestor = node.get_parent()
|
||||
while ancestor != null:
|
||||
if pending_environment_nodes.has(ancestor.get_instance_id()):
|
||||
return
|
||||
ancestor = ancestor.get_parent()
|
||||
|
||||
var stale_ids: Array[int] = []
|
||||
for node_id in pending_environment_nodes.keys():
|
||||
var pending_node = pending_environment_nodes[node_id]
|
||||
if not is_instance_valid(pending_node):
|
||||
stale_ids.append(node_id)
|
||||
continue
|
||||
if node.is_ancestor_of(pending_node):
|
||||
stale_ids.append(node_id)
|
||||
|
||||
for node_id in stale_ids:
|
||||
pending_environment_nodes.erase(node_id)
|
||||
|
||||
pending_environment_nodes[node.get_instance_id()] = node
|
||||
|
||||
func _process_pending_environment_nodes() -> void:
|
||||
var processed = 0
|
||||
for node_id in pending_environment_nodes.keys():
|
||||
if processed >= DYNAMIC_ENVIRONMENT_UPDATES_PER_FRAME:
|
||||
break
|
||||
|
||||
var node = pending_environment_nodes[node_id]
|
||||
pending_environment_nodes.erase(node_id)
|
||||
if not is_instance_valid(node):
|
||||
continue
|
||||
|
||||
_apply_dynamic_environment_materials(node)
|
||||
processed += 1
|
||||
|
||||
func _apply_dynamic_environment_materials(node: Node) -> void:
|
||||
if not is_instance_valid(node):
|
||||
|
||||
Reference in New Issue
Block a user