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