use crate::{SpriteCatalog, SpriteModeMap};
pub fn validate_sprite_mode_maps(
owner_label: &str,
tile_id: Option<&str>,
sprite_modes: &SpriteModeMap,
catalog: &SpriteCatalog,
) -> Vec<String> {
let mut errors = Vec::new();
let Some(tile_id) = tile_id.filter(|s| !s.is_empty()) else {
if !sprite_modes.is_empty() {
errors.push(format!(
"{owner_label}: sprite_modes set but tile_id is missing"
));
}
return errors;
};
if sprite_modes.is_empty() {
return errors;
}
let sheet_modes = catalog.mode_ids(tile_id);
if sheet_modes.is_empty() {
errors.push(format!(
"{owner_label}: tile_id '{tile_id}' not found in sprite catalog or has no modes"
));
return errors;
}
for (key, mode) in sprite_modes {
if !mode_exists_on_sheet(mode, &sheet_modes) {
errors.push(format!(
"{owner_label}: sprite_modes.{key} = '{mode}' not on sheet '{tile_id}' (have: {})",
sheet_modes.join(", ")
));
}
}
errors
}
pub fn mode_exists_on_sheet(mode: &str, sheet_modes: &[String]) -> bool {
if sheet_modes.iter().any(|m| m == mode) {
return true;
}
let prefix = format!("{mode}_");
sheet_modes.iter().any(|m| m.starts_with(&prefix))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::catalog::{load_sprite_catalog, SpriteSheetModes};
use std::collections::HashMap;
#[test]
fn catches_unknown_mode() {
let dir = crate::catalog::default_sprites_dir().expect("sprites dir");
let catalog = load_sprite_catalog(&dir).expect("load");
let mut map = SpriteModeMap::new();
map.insert("available".into(), "bogus_mode_xyz".into());
let errs = validate_sprite_mode_maps("item.test", Some("resource.oak_log"), &map, &catalog);
assert_eq!(errs.len(), 1);
assert!(errs[0].contains("bogus_mode_xyz"));
}
#[test]
fn accepts_directional_prefix_for_base_mode() {
let sheet_modes = vec!["idle_north".into(), "walk_south".into(), "combat".into()];
assert!(mode_exists_on_sheet("idle", &sheet_modes));
assert!(mode_exists_on_sheet("walk", &sheet_modes));
assert!(mode_exists_on_sheet("combat", &sheet_modes));
assert!(!mode_exists_on_sheet("run", &sheet_modes));
}
}