use serde::Deserialize; use std::{collections::HashMap, error::Error, fs::File, io::BufReader, path::Path}; use crate::{content::materials::MaterialId, sim::cell::Cell}; fn load_img(path: &Path) -> Result<(Vec, u32, u32), Box> { let mut decoder = png::Decoder::new(BufReader::new(File::open(path)?)); decoder.set_transformations(png::Transformations::IDENTITY); let mut reader = decoder.read_info()?; // only None if it's too big for memory let mut buf = vec![0; reader.output_buffer_size().unwrap()]; let info = reader.next_frame(&mut buf)?; if info.color_type != png::ColorType::Indexed { return Err(format!("{:#?}: not indexed", path.to_str()).into()); } if info.bit_depth != png::BitDepth::Eight { return Err(format!( "{:#?}: expected 8-bit, got {:?}", path.to_str(), info.bit_depth ) .into()); } buf.truncate(info.buffer_size()); Ok((buf, info.width, info.height)) } #[derive(Deserialize)] struct PaletteEntry { material: MaterialId, } #[derive(Deserialize)] struct SpriteManifest { palette: HashMap, } fn load_manifest(path: &Path) -> Result> { Ok(toml::from_str(&std::fs::read_to_string(path)?)?) } pub struct SpriteCells { pub cells: Vec, pub width: u32, pub height: u32, } pub fn load_sprite_to_cells(path: &str) -> SpriteCells { let img_result = load_img(&Path::join(Path::new(path), Path::new("img.png"))); match img_result { Ok((indices, width, height)) => { let manifest_result = load_manifest(&Path::join(Path::new(path), Path::new("manifest.toml"))); match manifest_result { Ok(SpriteManifest { palette }) => { let cells: Vec = indices .iter() .map(|i| { Cell::from_material( palette.get(i).map_or(MaterialId::Void, |v| v.material), ) }) .collect(); SpriteCells { cells, width, height, } } Err(e) => { panic!("Couldn't load sprite: {}", e) } } } Err(e) => { panic!("Couldn't load sprite: {}", e) } } }