fix(terrain): preserve opaque shade lookup keys
This commit is contained in:
@@ -27,7 +27,7 @@ use fparkan_assets::{
|
||||
use fparkan_corpus::{discover, render_report_json, report, DiscoverOptions};
|
||||
use fparkan_inspection::{
|
||||
inspect_archive_file, inspect_land_msh_bounds_file, inspect_model_from_root,
|
||||
load_land_msh_from_path, ArchiveInspection, ModelInspection,
|
||||
inspect_wear_from_root, load_land_msh_from_path, ArchiveInspection, ModelInspection,
|
||||
};
|
||||
use fparkan_path::{normalize_relative, PathPolicy};
|
||||
use fparkan_prototype::build_prototype_graph_report;
|
||||
@@ -46,6 +46,7 @@ const MISSION_GRAPH_SCHEMA: &str = "fparkan-mission-graph-v1";
|
||||
const MISSION_INSPECT_SCHEMA: &str = "fparkan-mission-inspect-v1";
|
||||
const TERRAIN_INSPECT_SCHEMA: &str = "fparkan-terrain-inspect-v1";
|
||||
const MODEL_INSPECT_SCHEMA: &str = "fparkan-model-inspect-v1";
|
||||
const WEAR_INSPECT_SCHEMA: &str = "fparkan-wear-inspect-v1";
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ArchiveInspectOutput<'a> {
|
||||
@@ -128,11 +129,11 @@ struct TerrainInspectOutput {
|
||||
faces: usize,
|
||||
slots: usize,
|
||||
material_tags: Vec<TerrainMaterialTagCount>,
|
||||
shade_material_pairs: usize,
|
||||
shade_pairs: usize,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
shade_material_lookup_min: Option<u16>,
|
||||
shade_lookup_key_min: Option<u16>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
shade_material_lookup_max: Option<u16>,
|
||||
shade_lookup_key_max: Option<u16>,
|
||||
shade_batch_boundaries: usize,
|
||||
}
|
||||
|
||||
@@ -142,6 +143,19 @@ struct TerrainMaterialTagCount {
|
||||
faces: usize,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct WearInspectOutput {
|
||||
schema_version: &'static str,
|
||||
archive: String,
|
||||
resource: String,
|
||||
materials: usize,
|
||||
lightmaps: usize,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
first_material: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
last_material: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct ModelInspectOutput<'a> {
|
||||
schema_version: &'static str,
|
||||
@@ -238,6 +252,10 @@ fn run(args: &[String]) -> Result<(), String> {
|
||||
let rest = strip_format_json(rest)?;
|
||||
inspect_terrain(&rest)
|
||||
}
|
||||
[domain, command, rest @ ..] if domain == "wear" && command == "inspect" => {
|
||||
let rest = strip_format_json(rest)?;
|
||||
inspect_wear(&rest)
|
||||
}
|
||||
[domain, command, rest @ ..] if domain == "model" && command == "inspect" => {
|
||||
let rest = strip_format_json(rest)?;
|
||||
inspect_model(&rest)
|
||||
@@ -479,19 +497,13 @@ fn inspect_terrain(args: &[String]) -> Result<(), String> {
|
||||
.map(|(tag, faces)| TerrainMaterialTagCount { tag, faces })
|
||||
.collect::<Vec<_>>();
|
||||
material_tags.sort_unstable_by_key(|entry| entry.tag);
|
||||
let shade_material_pairs = (0..terrain.slots.slots_raw.len())
|
||||
let shade_pairs = (0..terrain.slots.slots_raw.len())
|
||||
.filter_map(|slot_index| terrain.slot_material_pairs(slot_index))
|
||||
.flatten()
|
||||
.collect::<Vec<_>>();
|
||||
let shade_material_lookup_min = shade_material_pairs
|
||||
.iter()
|
||||
.map(|pair| pair.shade_selection().material_index)
|
||||
.min();
|
||||
let shade_material_lookup_max = shade_material_pairs
|
||||
.iter()
|
||||
.map(|pair| pair.shade_selection().material_index)
|
||||
.max();
|
||||
let shade_batch_boundaries = shade_material_pairs
|
||||
let shade_lookup_key_min = shade_pairs.iter().map(|pair| pair.shade_lookup_key()).min();
|
||||
let shade_lookup_key_max = shade_pairs.iter().map(|pair| pair.shade_lookup_key()).max();
|
||||
let shade_batch_boundaries = shade_pairs
|
||||
.iter()
|
||||
.filter(|pair| pair.flags & 0x0010 != 0)
|
||||
.count();
|
||||
@@ -506,15 +518,35 @@ fn inspect_terrain(args: &[String]) -> Result<(), String> {
|
||||
faces: terrain.faces.len(),
|
||||
slots: terrain.slots.slots_raw.len(),
|
||||
material_tags,
|
||||
shade_material_pairs: shade_material_pairs.len(),
|
||||
shade_material_lookup_min,
|
||||
shade_material_lookup_max,
|
||||
shade_pairs: shade_pairs.len(),
|
||||
shade_lookup_key_min,
|
||||
shade_lookup_key_max,
|
||||
shade_batch_boundaries,
|
||||
})?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn inspect_wear(args: &[String]) -> Result<(), String> {
|
||||
let root = parse_root_alias(args)?;
|
||||
let archive = parse_required(args, &["--archive"], "--archive")?;
|
||||
let resource = parse_required(args, &["--resource"], "--resource")?;
|
||||
let inspection = inspect_wear_from_root(&root, &archive, &resource)?;
|
||||
println!(
|
||||
"{}",
|
||||
serialize_json(&WearInspectOutput {
|
||||
schema_version: WEAR_INSPECT_SCHEMA,
|
||||
archive,
|
||||
resource,
|
||||
materials: inspection.materials,
|
||||
lightmaps: inspection.lightmaps,
|
||||
first_material: inspection.first_material,
|
||||
last_material: inspection.last_material,
|
||||
})?
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn inspect_model(args: &[String]) -> Result<(), String> {
|
||||
let root = parse_root_alias(args)?;
|
||||
let archive = parse_required(args, &["--archive"], "--archive")?;
|
||||
@@ -632,7 +664,7 @@ fn prototype_graph_requiredness_label(
|
||||
}
|
||||
|
||||
fn usage() -> String {
|
||||
"usage: fparkan corpus discover|validate --root <path> [--format json] | archive inspect <file> [--format json] | terrain inspect <Land.msh> [--format json] | model inspect --root <path> --archive <archive> --resource <model.msh> [--format json] | prototype inspect --root <path> --key <key> [--format json] | mission graph|inspect --root <path> --mission <path> [--format json]".to_string()
|
||||
"usage: fparkan corpus discover|validate --root <path> [--format json] | archive inspect <file> [--format json] | terrain inspect <Land.msh> [--format json] | wear inspect --root <path> --archive <archive> --resource <wear.wea> [--format json] | model inspect --root <path> --archive <archive> --resource <model.msh> [--format json] | prototype inspect --root <path> --key <key> [--format json] | mission graph|inspect --root <path> --mission <path> [--format json]".to_string()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -759,16 +791,35 @@ mod tests {
|
||||
TerrainMaterialTagCount { tag: 0, faces: 1 },
|
||||
TerrainMaterialTagCount { tag: 3, faces: 1 },
|
||||
],
|
||||
shade_material_pairs: 2,
|
||||
shade_material_lookup_min: Some(1),
|
||||
shade_material_lookup_max: Some(2),
|
||||
shade_pairs: 2,
|
||||
shade_lookup_key_min: Some(1),
|
||||
shade_lookup_key_max: Some(2),
|
||||
shade_batch_boundaries: 1,
|
||||
})
|
||||
.expect("serialize terrain inspection");
|
||||
|
||||
assert_eq!(
|
||||
json,
|
||||
"{\"schema_version\":\"fparkan-terrain-inspect-v1\",\"path\":\"DATA/MAPS/AutoMAP/Land.msh\",\"positions\":3,\"min\":[-1.0,-2.0,-3.0],\"max\":[4.0,5.0,6.0],\"faces\":2,\"slots\":4,\"material_tags\":[{\"tag\":0,\"faces\":1},{\"tag\":3,\"faces\":1}],\"shade_material_pairs\":2,\"shade_material_lookup_min\":1,\"shade_material_lookup_max\":2,\"shade_batch_boundaries\":1}"
|
||||
"{\"schema_version\":\"fparkan-terrain-inspect-v1\",\"path\":\"DATA/MAPS/AutoMAP/Land.msh\",\"positions\":3,\"min\":[-1.0,-2.0,-3.0],\"max\":[4.0,5.0,6.0],\"faces\":2,\"slots\":4,\"material_tags\":[{\"tag\":0,\"faces\":1},{\"tag\":3,\"faces\":1}],\"shade_pairs\":2,\"shade_lookup_key_min\":1,\"shade_lookup_key_max\":2,\"shade_batch_boundaries\":1}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn wear_inspect_output_retains_material_bounds() {
|
||||
let json = serialize_json(&WearInspectOutput {
|
||||
schema_version: WEAR_INSPECT_SCHEMA,
|
||||
archive: "system.rlb".to_string(),
|
||||
resource: "SHADE.WEA".to_string(),
|
||||
materials: 1,
|
||||
lightmaps: 0,
|
||||
first_material: Some("LIGHT1".to_string()),
|
||||
last_material: Some("LIGHT1".to_string()),
|
||||
})
|
||||
.expect("serialize wear inspection");
|
||||
|
||||
assert_eq!(
|
||||
json,
|
||||
"{\"schema_version\":\"fparkan-wear-inspect-v1\",\"archive\":\"system.rlb\",\"resource\":\"SHADE.WEA\",\"materials\":1,\"lightmaps\":0,\"first_material\":\"LIGHT1\",\"last_material\":\"LIGHT1\"}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user