From 2d0ded231b6995bbdebbc62d69e37d015f1b96a2 Mon Sep 17 00:00:00 2001 From: Valentin Popov Date: Sat, 18 Jul 2026 20:26:15 +0400 Subject: [PATCH] feat(assets): preserve unit component asset provenance --- crates/fparkan-assets/src/lib.rs | 46 ++++++++++++++++++++++++++++++-- docs/tomes/03-resources.md | 4 +++ 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/crates/fparkan-assets/src/lib.rs b/crates/fparkan-assets/src/lib.rs index 35380ef..2dc9ef5 100644 --- a/crates/fparkan-assets/src/lib.rs +++ b/crates/fparkan-assets/src/lib.rs @@ -1251,6 +1251,8 @@ pub fn extend_graph_report_with_visual_dependencies_with_progress, + unit_component_index: Option, resource: &ResourceKey, ) -> PrototypeGraphProvenance { PrototypeGraphProvenance { root_index, parent_edge, - unit_component_index: None, + unit_component_index, archive: Some(resource.archive.display_lossy().to_string()), resource: Some(resource.name.0.clone()), span: None, @@ -2011,6 +2018,8 @@ fn push_visual_failure( ) { let root_index = root_index_for_prototype(graph, prototype_index); let parent_edge = parent_edge_for_failure(graph, prototype_index, edge); + let unit_component_index = + parent_edge.and_then(|value| unit_component_index_for_edge(graph, value)); let dependency = mesh_dependency_resource(graph, prototype_index); report.failures.push(PrototypeGraphFailure { root_index, @@ -2021,7 +2030,7 @@ fn push_visual_failure( provenance: Some(PrototypeGraphProvenance { root_index, parent_edge, - unit_component_index: None, + unit_component_index, archive: dependency.map(|resource| resource.archive.as_str().to_string()), resource: Some(resource_raw), span: None, @@ -2038,6 +2047,18 @@ fn root_index_for_prototype(graph: &PrototypeGraph, prototype_index: usize) -> u 0 } +fn unit_component_index_for_edge( + graph: &PrototypeGraph, + edge_id: fparkan_prototype::PrototypeGraphEdgeId, +) -> Option { + graph + .edges + .iter() + .find(|edge| edge.id == edge_id) + .and_then(|edge| edge.provenance.as_ref()) + .and_then(|provenance| provenance.unit_component_index) +} + fn parent_edge_for_failure( graph: &PrototypeGraph, prototype_index: usize, @@ -2726,6 +2747,19 @@ mod tests { dependencies: Vec::new(), }; let mut graph = prototype_graph_for_mesh(&prototype); + graph + .edges + .iter_mut() + .find(|edge| edge.kind == fparkan_prototype::PrototypeGraphEdgeKind::PrototypeToMesh) + .expect("mesh edge") + .provenance = Some(PrototypeGraphProvenance { + root_index: 0, + parent_edge: Some(fparkan_prototype::PrototypeGraphEdgeId(0)), + unit_component_index: Some(3), + archive: Some("static.rlb".to_string()), + resource: Some(b"tree.msh".to_vec()), + span: None, + }); let mut report = PrototypeGraphReport { root_count: 1, direct_reference_count: 1, @@ -2799,6 +2833,14 @@ mod tests { .iter() .filter_map(|edge| edge.provenance.as_ref()) .all(|provenance| provenance.root_index == 0)); + for edge in [wear_edge, material_edge, texture_edge, lightmap_edge] { + assert_eq!( + edge.provenance + .as_ref() + .and_then(|provenance| provenance.unit_component_index), + Some(3) + ); + } } #[test] diff --git a/docs/tomes/03-resources.md b/docs/tomes/03-resources.md index a2386ba..29fef77 100644 --- a/docs/tomes/03-resources.md +++ b/docs/tomes/03-resources.md @@ -480,6 +480,10 @@ dependency также несёт `unit_component_index`. Это индекс и порядке файла, а не тип компонента; по нему diagnostics и будущие consumers могут однозначно вернуться к raw 112-byte record. +Visual dependency expansion наследует этот индекс на edges к WEAR, MAT0, +diffuse texture и lightmap. Поэтому ошибка или asset в любой из этих фаз +сохраняет путь до конкретной записи unit DAT, а не только до миссионного object. + ## Вспомогательные форматы MSH, материал и текстура отвечают за видимую форму. Полноценный прототип