aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-07-18 16:39:52 +0300
committerValentin Popov <valentin@popov.link>2026-07-18 16:39:52 +0300
commite9c1a83c51070c4f8da76540c17c2393922b6fcc (patch)
tree5cf115fc25aa4df24848e9488bdaa919890bf7f7 /crates
parent575124830b678d0c4d5b37a708bba9692a4e47ef (diff)
downloadfparkan-e9c1a83c51070c4f8da76540c17c2393922b6fcc.tar.xz
fparkan-e9c1a83c51070c4f8da76540c17c2393922b6fcc.zip
fix(terrain): preserve opaque shade lookup keys
Diffstat (limited to 'crates')
-rw-r--r--crates/fparkan-inspection/src/lib.rs41
-rw-r--r--crates/fparkan-terrain-format/src/lib.rs24
-rw-r--r--crates/fparkan-terrain/src/lib.rs4
3 files changed, 51 insertions, 18 deletions
diff --git a/crates/fparkan-inspection/src/lib.rs b/crates/fparkan-inspection/src/lib.rs
index e2b9068..be1f098 100644
--- a/crates/fparkan-inspection/src/lib.rs
+++ b/crates/fparkan-inspection/src/lib.rs
@@ -146,6 +146,19 @@ pub struct WearMaterialTexture {
pub image: fparkan_texm::RgbaImage,
}
+/// Compact inspection summary of a WEAR resource stored in an archive.
+#[derive(Clone, Debug, Eq, PartialEq)]
+pub struct WearInspection {
+ /// Number of material rows.
+ pub materials: usize,
+ /// Number of lightmap rows.
+ pub lightmaps: usize,
+ /// First material resource name, when present.
+ pub first_material: Option<String>,
+ /// Last material resource name, when present.
+ pub last_material: Option<String>,
+}
+
/// Land map/msh inspection payload.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct MapInspection {
@@ -374,6 +387,34 @@ pub fn inspect_model_from_root(
})
}
+/// Inspects a WEAR resource through repository-backed lookup.
+///
+/// # Errors
+///
+/// Returns a string error when the resource cannot be resolved or parsed as a
+/// valid WEAR payload.
+pub fn inspect_wear_from_root(
+ root: &Path,
+ archive: &str,
+ resource: &str,
+) -> Result<WearInspection, String> {
+ let bytes = read_resource_bytes_diagnostic(root, archive, resource)
+ .map_err(|err| render_human(&err))?;
+ let wear = decode_wear(&bytes).map_err(|err| err.to_string())?;
+ Ok(WearInspection {
+ materials: wear.entries.len(),
+ lightmaps: wear.lightmaps.len(),
+ first_material: wear
+ .entries
+ .first()
+ .map(|entry| String::from_utf8_lossy(&entry.material.0).into_owned()),
+ last_material: wear
+ .entries
+ .last()
+ .map(|entry| String::from_utf8_lossy(&entry.material.0).into_owned()),
+ })
+}
+
/// Loads and validates a model resource through repository-backed lookup.
///
/// # Errors
diff --git a/crates/fparkan-terrain-format/src/lib.rs b/crates/fparkan-terrain-format/src/lib.rs
index 764de09..54bd3f4 100644
--- a/crates/fparkan-terrain-format/src/lib.rs
+++ b/crates/fparkan-terrain-format/src/lib.rs
@@ -212,18 +212,15 @@ pub struct TerrainMaterialPair {
}
impl TerrainMaterialPair {
- /// Returns the material-manager selection used by `GetShade`.
+ /// Returns the opaque lookup key supplied to `GetShade`.
///
- /// `GetShade` owns a manager loaded only with `Shade.wea`, so its
- /// 16-bit lookup occupies row bits of that manager's table zero. It is
- /// deliberately separate from the `Land1.wea`/`Land2.wea` selections
- /// carried by [`TerrainMaterialLayers`].
+ /// This is deliberately separate from the `Land1.wea`/`Land2.wea`
+ /// selectors carried by [`TerrainMaterialLayers`]. Although `GetShade`
+ /// owns a manager loaded from `Shade.wea`, this key is not a WEAR row:
+ /// observed map values exceed that table's row count.
#[must_use]
- pub const fn shade_selection(self) -> TerrainMaterialSelection {
- TerrainMaterialSelection {
- table_index: 0,
- material_index: self.material_lookup,
- }
+ pub const fn shade_lookup_key(self) -> u16 {
+ self.material_lookup
}
}
@@ -1586,11 +1583,8 @@ mod tests {
])
);
assert_eq!(
- document.slot_material_pairs(0).expect("material pairs")[0].shade_selection(),
- TerrainMaterialSelection {
- table_index: 0,
- material_index: 0x0102,
- }
+ document.slot_material_pairs(0).expect("material pairs")[0].shade_lookup_key(),
+ 0x0102
);
assert_eq!(document.slot_material_pairs(1), None);
diff --git a/crates/fparkan-terrain/src/lib.rs b/crates/fparkan-terrain/src/lib.rs
index a69df2a..4eef871 100644
--- a/crates/fparkan-terrain/src/lib.rs
+++ b/crates/fparkan-terrain/src/lib.rs
@@ -27,9 +27,7 @@ use std::collections::VecDeque;
///
/// Applications access this semantic terrain API through this terrain crate
/// rather than taking a direct dependency on the binary-format parser.
-pub use fparkan_terrain_format::{
- TerrainMaterialLayers, TerrainMaterialPair, TerrainMaterialSelection,
-};
+pub use fparkan_terrain_format::{TerrainMaterialLayers, TerrainMaterialSelection};
/// Terrain world.
#[derive(Clone, Debug, Default)]