diff options
Diffstat (limited to 'src/sprite_loader.rs')
| -rw-r--r-- | src/sprite_loader.rs | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/sprite_loader.rs b/src/sprite_loader.rs new file mode 100644 index 0000000..eccf066 --- /dev/null +++ b/src/sprite_loader.rs @@ -0,0 +1,79 @@ +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<u8>, u32, u32), Box<dyn Error>> { + 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<u8, PaletteEntry>, +} + +fn load_manifest(path: &Path) -> Result<SpriteManifest, Box<dyn Error>> { + Ok(toml::from_str(&std::fs::read_to_string(path)?)?) +} + +pub struct SpriteCells { + pub cells: Vec<Cell>, + 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<Cell> = indices + .iter() + .map(|i| Cell::from_material(palette.get(i).unwrap().material)) + .collect(); + + SpriteCells { + cells, + width, + height, + } + } + Err(e) => { + panic!("Couldn't load sprite: {}", e) + } + } + } + Err(e) => { + panic!("Couldn't load sprite: {}", e) + } + } +} |
