refactor(M03): extract M2 runtime mesh finalizer
Work-Package: M03-RND-M2-RUNTIME-MESH-FINALIZER-001 Agent: sindo-main-codex Tests: 37 headless renderer/coordinate contracts pass; checkpoint dry-run 7/7; documentation and coordination gates pass Fidelity: preserves refresh version 2, classifier, rebuild and fallback transitions; no visual parity claim
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
class_name M2RuntimeMeshFinalizer
|
||||
extends RefCounted
|
||||
|
||||
## Finalizes stale cached M2 Meshes using caller-supplied raw data. The caller
|
||||
## owns raw-file I/O, cache adoption, missing state and materialization.
|
||||
|
||||
const M2_BUILDER_SCRIPT := preload("res://addons/mpq_extractor/loaders/m2_builder.gd")
|
||||
const M2_RUNTIME_MESH_REBUILD_CLASSIFIER_SCRIPT := preload(
|
||||
"res://src/render/m2/m2_runtime_mesh_rebuild_classifier.gd"
|
||||
)
|
||||
const M2_MESH_RESOURCE_EXTRACTOR_SCRIPT := preload(
|
||||
"res://src/render/m2/m2_mesh_resource_extractor.gd"
|
||||
)
|
||||
|
||||
const MATERIAL_REFRESH_VERSION := 2
|
||||
const MATERIAL_REFRESH_VERSION_META := "wow_m2_material_refresh_version"
|
||||
|
||||
var _runtime_mesh_rebuild_classifier := M2_RUNTIME_MESH_REBUILD_CLASSIFIER_SCRIPT.new()
|
||||
var _mesh_resource_extractor := M2_MESH_RESOURCE_EXTRACTOR_SCRIPT.new()
|
||||
|
||||
|
||||
## Returns whether one Mesh is stale and the caller should load raw M2 data.
|
||||
func requires_raw_data_for_refresh(mesh: Mesh) -> bool:
|
||||
return (
|
||||
mesh != null
|
||||
and int(mesh.get_meta(MATERIAL_REFRESH_VERSION_META, 0)) < MATERIAL_REFRESH_VERSION
|
||||
)
|
||||
|
||||
|
||||
## Marks, rebuilds or falls back one stale Mesh using already-loaded raw M2
|
||||
## data. Current Meshes return unchanged and never inspect raw data.
|
||||
func finalize_mesh(
|
||||
normalized_relative_path: String,
|
||||
mesh: Mesh,
|
||||
raw_m2_data: Dictionary,
|
||||
extracted_directory: String) -> Mesh:
|
||||
if mesh == null:
|
||||
return null
|
||||
if not requires_raw_data_for_refresh(mesh):
|
||||
return mesh
|
||||
if raw_m2_data.is_empty() or not _runtime_mesh_rebuild_classifier.needs_runtime_mesh_rebuild(
|
||||
normalized_relative_path,
|
||||
raw_m2_data):
|
||||
_mark_mesh_current(mesh)
|
||||
return mesh
|
||||
var rebuilt_mesh := _rebuild_mesh(raw_m2_data, extracted_directory)
|
||||
if rebuilt_mesh != null:
|
||||
return rebuilt_mesh
|
||||
_mark_mesh_current(mesh)
|
||||
return mesh
|
||||
|
||||
|
||||
## Clears memoized per-path rebuild decisions at the existing map/shutdown sites.
|
||||
func clear() -> void:
|
||||
_runtime_mesh_rebuild_classifier.clear()
|
||||
|
||||
|
||||
## Returns the memoized rebuild-decision count for diagnostics and verification.
|
||||
func cached_rebuild_decision_count() -> int:
|
||||
return _runtime_mesh_rebuild_classifier.cached_path_count()
|
||||
|
||||
|
||||
func _mark_mesh_current(mesh: Mesh) -> void:
|
||||
mesh.set_meta(MATERIAL_REFRESH_VERSION_META, MATERIAL_REFRESH_VERSION)
|
||||
|
||||
|
||||
func _rebuild_mesh(raw_m2_data: Dictionary, extracted_directory: String) -> Mesh:
|
||||
var temporary_prototype: Node3D = M2_BUILDER_SCRIPT.build(
|
||||
raw_m2_data,
|
||||
extracted_directory
|
||||
)
|
||||
if temporary_prototype == null:
|
||||
return null
|
||||
var rebuilt_mesh := _mesh_resource_extractor.find_first_mesh_in_subtree(
|
||||
temporary_prototype
|
||||
)
|
||||
temporary_prototype.free()
|
||||
return rebuilt_mesh
|
||||
Reference in New Issue
Block a user