summaryrefslogtreecommitdiff
path: root/src/sprite_loader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/sprite_loader.rs')
-rw-r--r--src/sprite_loader.rs79
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)
+ }
+ }
+}