refactor(M03): extract WMO placement registry

This commit is contained in:
2026-07-17 00:33:09 +04:00
parent 79bc4e6ffc
commit c5900368d4
10 changed files with 561 additions and 53 deletions
+46 -39
View File
@@ -12,6 +12,9 @@ const WMO_BUILDER_SCRIPT := preload("res://addons/mpq_extractor/loaders/wmo_buil
const WMO_PLACEMENT_RESOLVER_SCRIPT := preload(
"res://src/render/wmo/wmo_placement_resolver.gd"
)
const WMO_PLACEMENT_REGISTRY_SCRIPT := preload(
"res://src/render/wmo/wmo_placement_registry.gd"
)
const M2_BUILDER_SCRIPT := preload("res://addons/mpq_extractor/loaders/m2_builder.gd")
const M2_NATIVE_ANIMATED_BUILDER_SCRIPT := preload("res://addons/mpq_extractor/loaders/m2_native_animated_builder.gd")
const M2_NATIVE_ANIMATOR_SCRIPT := preload("res://src/scenes/streaming/m2_native_animator.gd")
@@ -286,7 +289,8 @@ var _m2_animated_scene_cache: Dictionary = {}
var _m2_static_animation_cache: Dictionary = {}
var _m2_missing_cache: Dictionary = {}
var _world_wmo_root: Node3D
var _wmo_registry: Dictionary = {}
var _wmo_placement_registry := WMO_PLACEMENT_REGISTRY_SCRIPT.new()
var _wmo_instance_nodes_by_unique_key: Dictionary = {}
func _ready() -> void:
@@ -1031,7 +1035,7 @@ func render_baseline_snapshot() -> Dictionary:
},
"cache_entries": _tile_mesh_cache.size(),
"m2_active_unique_ids": _m2_unique_placement_registry.active_count(),
"wmo_instances": _wmo_registry.size(),
"wmo_instances": _wmo_placement_registry.active_count(),
}
@@ -1313,7 +1317,7 @@ func _tick_runtime_stats(delta: float) -> void:
m2_tiles,
m2_multimeshes,
m2_instances,
_wmo_registry.size(),
_wmo_placement_registry.active_count(),
])
@@ -3363,7 +3367,7 @@ func _wdt_has_global_wmo() -> bool:
func _place_global_wmo() -> void:
if not _wdt_has_global_wmo():
return
if _wmo_registry.has("global"):
if _wmo_placement_registry.contains("global"):
return
_ensure_world_wmo_root()
@@ -3387,10 +3391,7 @@ func _place_global_wmo() -> void:
_world_wmo_root.add_child(instance)
_set_editor_owner_recursive(instance)
_wmo_registry["global"] = {
"node": instance,
"refs": {"__global__": true},
}
_register_wmo_instance_reference("global", "__global__", instance)
func _sync_detail_assets(state: Dictionary, focus_pos: Vector3) -> Dictionary:
@@ -3566,10 +3567,8 @@ func _process_wmo_build_jobs() -> void:
tile_key,
index
)
if _wmo_registry.has(unique_key):
var entry: Dictionary = _wmo_registry[unique_key]
var entry_refs: Dictionary = entry["refs"]
entry_refs[tile_key] = true
if _wmo_placement_registry.contains(unique_key):
_wmo_placement_registry.add_reference(unique_key, tile_key)
refs.append(unique_key)
else:
var rel_path: String = str(wmo_names[name_id]).replace("\\", "/")
@@ -3579,10 +3578,7 @@ func _process_wmo_build_jobs() -> void:
if instance != null:
_world_wmo_root.add_child(instance)
_set_editor_owner_recursive(instance)
_wmo_registry[unique_key] = {
"node": instance,
"refs": {tile_key: true},
}
_register_wmo_instance_reference(unique_key, tile_key, instance)
refs.append(unique_key)
_start_wmo_render_build(unique_key, instance, render_resource)
else:
@@ -3602,10 +3598,11 @@ func _process_wmo_build_jobs() -> void:
_prepare_runtime_wmo_instance(live_instance)
_world_wmo_root.add_child(live_instance)
_set_editor_owner_recursive(live_instance)
_wmo_registry[unique_key] = {
"node": live_instance,
"refs": {tile_key: true},
}
_register_wmo_instance_reference(
unique_key,
tile_key,
live_instance
)
refs.append(unique_key)
else:
var scene_instance := _instantiate_wmo_scene(rel_path, scene, placement)
@@ -3613,10 +3610,11 @@ func _process_wmo_build_jobs() -> void:
_prepare_runtime_wmo_instance(scene_instance)
_world_wmo_root.add_child(scene_instance)
_set_editor_owner_recursive(scene_instance)
_wmo_registry[unique_key] = {
"node": scene_instance,
"refs": {tile_key: true},
}
_register_wmo_instance_reference(
unique_key,
tile_key,
scene_instance
)
refs.append(unique_key)
if advance_job:
job["refs"] = refs
@@ -3994,6 +3992,17 @@ func _cancel_wmo_build_job(tile_key: String) -> void:
_wmo_build_queue.erase(tile_key)
func _register_wmo_instance_reference(
placement_key: String,
reference_key: String,
instance: Node3D
) -> void:
if placement_key.is_empty() or reference_key.is_empty() or instance == null:
return
_wmo_instance_nodes_by_unique_key[placement_key] = instance
_wmo_placement_registry.add_reference(placement_key, reference_key)
func _unregister_tile_wmos(state: Dictionary) -> void:
var refs: Array = state.get("wmo_refs", [])
var tile_key: String = String(state.get("key", ""))
@@ -4003,18 +4012,16 @@ func _unregister_tile_wmos(state: Dictionary) -> void:
state["wmo_building"] = false
return
for unique_key in refs:
if not _wmo_registry.has(unique_key):
for unique_key_variant in refs:
var unique_key := String(unique_key_variant)
if not _wmo_placement_registry.contains(unique_key):
continue
var entry: Dictionary = _wmo_registry[unique_key]
var entry_refs: Dictionary = entry["refs"]
entry_refs.erase(tile_key)
if entry_refs.is_empty():
if _wmo_placement_registry.release_reference(unique_key, tile_key):
_cancel_wmo_render_build_job(String(unique_key))
var node: Node = entry.get("node", null)
if node:
var node: Node = _wmo_instance_nodes_by_unique_key.get(unique_key, null)
if node != null and is_instance_valid(node):
node.queue_free()
_wmo_registry.erase(unique_key)
_wmo_instance_nodes_by_unique_key.erase(unique_key)
state["wmo_refs"] = []
state["wmo_building"] = false
@@ -4023,14 +4030,14 @@ func _unregister_tile_wmos(state: Dictionary) -> void:
func _clear_wmo_registry() -> void:
_wmo_render_build_jobs.clear()
_wmo_render_build_queue.clear()
for entry_variant in _wmo_registry.values():
if not (entry_variant is Dictionary):
for node_variant in _wmo_instance_nodes_by_unique_key.values():
if not (node_variant is Node):
continue
var entry: Dictionary = entry_variant
var node: Node = entry.get("node", null)
if node and is_instance_valid(node):
var node := node_variant as Node
if is_instance_valid(node):
_queue_free_streamed_node(node)
_wmo_registry.clear()
_wmo_instance_nodes_by_unique_key.clear()
_wmo_placement_registry.clear()
if _world_wmo_root and is_instance_valid(_world_wmo_root):
_queue_free_streamed_node(_world_wmo_root)
_world_wmo_root = null