mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-30 04:57:54 -06:00
model: try the complete texture name before its final token
This commit is contained in:
@@ -22,12 +22,12 @@ fn sibling_name(name: &str) -> Option<&str> {
|
||||
(!file.is_empty() && file.len() < name.len()).then_some(file)
|
||||
}
|
||||
|
||||
/// A material reference resolved against the model's folder: the name as written (options are
|
||||
/// part of it, `-bm 1 file.png`), the whole value (a name containing spaces), then its file name
|
||||
/// (an absolute path from another machine, #1274).
|
||||
/// A material reference resolved against the model's folder: the name as written (a name
|
||||
/// containing spaces is one name), then its file name (an absolute path from another machine,
|
||||
/// #1274), then the final token (the options convention, `-bm 1 file.png`).
|
||||
fn resolve_reference(resolve: &dyn Fn(&str) -> Option<Vec<u8>>, name: &str) -> Option<Vec<u8>> {
|
||||
let mut tried: Vec<&str> = vec![];
|
||||
for candidate in [name.split_whitespace().last().unwrap_or(name), name, sibling_name(name).unwrap_or(name)] {
|
||||
for candidate in [name, sibling_name(name).unwrap_or(name), name.split_whitespace().last().unwrap_or(name)] {
|
||||
if tried.contains(&candidate) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -167,6 +167,46 @@ fn obj_textures_from_another_machine_find_the_file_next_to_the_model() {
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn obj_texture_prefers_the_complete_name_over_its_final_token() {
|
||||
// Two textures sit beside the model: `Map.png` (the final whitespace token of the reference)
|
||||
// and `Diffuse Map.png` (the complete name). The complete name must win, its basename next,
|
||||
// the final token last (the `-bm 1 file.png` options convention).
|
||||
let d = std::env::temp_dir().join(format!("ec-obj-full-name-{}", std::process::id()));
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
std::fs::create_dir_all(&d).unwrap();
|
||||
let png = |w: u32| {
|
||||
let img = image::RgbaImage::from_fn(w, 2, |_, _| image::Rgba([255, 0, 0, 255]));
|
||||
let mut out = std::io::Cursor::new(Vec::new());
|
||||
img.write_to(&mut out, image::ImageFormat::Png).unwrap();
|
||||
out.into_inner()
|
||||
};
|
||||
std::fs::write(d.join("Map.png"), png(2)).unwrap();
|
||||
std::fs::write(d.join("Diffuse Map.png"), png(4)).unwrap();
|
||||
let mtl = "newmtl Spaced\nmap_Kd Diffuse Map.png\n\
|
||||
newmtl Absolute\nmap_Kd C:\\tex\\Diffuse Map.png\n\
|
||||
newmtl Options\nmap_Kd -bm 1 Map.png\n";
|
||||
let obj = "mtllib quad.mtl\nv -1 -1 0\nv 1 -1 0\nv 1 1 0\nv -1 1 0\nvt 0 0\nvt 1 0\nvt 1 1\nvt 0 1\n\
|
||||
usemtl Spaced\nf 1/1 2/2 3/3\nf 1/1 3/3 4/4\n";
|
||||
// Like the media layer's resolver: a relative name joins the model's folder; an absolute
|
||||
// path is only looked up where it points (here: nowhere else).
|
||||
let resolve = |uri: &str| -> Option<Vec<u8>> {
|
||||
let p = std::path::Path::new(uri);
|
||||
if p.is_absolute() { return None; }
|
||||
std::fs::read(d.join(p)).ok()
|
||||
};
|
||||
let resolver = |uri: &str| -> Option<Vec<u8>> {
|
||||
if uri == "quad.mtl" { Some(mtl.as_bytes().to_vec()) } else { resolve(uri) }
|
||||
};
|
||||
let m = obj::parse(obj.as_bytes(), &resolver).unwrap();
|
||||
assert_eq!(m.materials.len(), 3);
|
||||
let size = |mat: &Material| mat.base_color_tex.map(|t| (m.textures[t.texture].width, m.textures[t.texture].height));
|
||||
assert_eq!(size(&m.materials[0]), Some((4, 2)), "the complete `Diffuse Map.png` wins over its final token `Map.png`");
|
||||
assert_eq!(size(&m.materials[1]), Some((4, 2)), "an absolute path's spaced basename beats its final token");
|
||||
assert_eq!(size(&m.materials[2]), Some((2, 2)), "the `-bm 1 file.png` options convention still finds the final token");
|
||||
let _ = std::fs::remove_dir_all(&d);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn channel_interpolation_modes() {
|
||||
let mut c = Channel { node: 0, path: ChannelPath::Translation, interp: Interp::Step, times: vec![0.0, 1.0], values: vec![0.0, 0.0, 0.0, 10.0, 0.0, 0.0] };
|
||||
|
||||
Reference in New Issue
Block a user