add loading and saving support to BlendMap

This commit is contained in:
Gered 2022-07-20 16:32:19 -04:00
parent d6e05c7e3a
commit c4e0a11259

View file

@ -1,12 +1,24 @@
use std::fs::File;
use std::io::{BufReader, BufWriter};
use std::path::Path;
use byteorder::{ReadBytesExt, WriteBytesExt};
use thiserror::Error;
use crate::graphics::*;
use crate::math::*;
use crate::utils::bytes::ReadFixedLengthByteArray;
#[derive(Error, Debug)]
pub enum BlendMapError {
#[error("Source color {0} is out of range for this BlendMap")]
InvalidSourceColor(u8),
#[error("Bad or unsupported BlendMap file: {0}")]
BadFile(String),
#[error("BlendMap I/O error")]
IOError(#[from] std::io::Error),
}
/// A lookup table used by [`BlendMap`]s. This table stores destination color to blend color
@ -226,11 +238,57 @@ impl BlendMap {
None
}
}
pub fn load_from_file(path: &Path) -> Result<Self, BlendMapError> {
let f = File::open(path)?;
let mut reader = BufReader::new(f);
Self::load_from_bytes(&mut reader)
}
pub fn load_from_bytes<T: ReadBytesExt>(reader: &mut T) -> Result<Self, BlendMapError> {
let ident: [u8; 4] = reader.read_bytes()?;
if ident != *b"BMap" {
return Err(BlendMapError::BadFile(String::from("Unrecognized header")));
}
let start_color = reader.read_u8()?;
let end_color = reader.read_u8()?;
let num_maps = (end_color - start_color + 1) as usize;
let mut maps = Vec::with_capacity(num_maps);
for _ in 0..num_maps {
let map: BlendMapping = reader.read_bytes()?;
maps.push(map);
}
Ok(BlendMap {
start_color,
end_color,
mapping: maps.into_boxed_slice()
})
}
pub fn to_file(&self, path: &Path) -> Result<(), BlendMapError> {
let f = File::create(path)?;
let mut writer = BufWriter::new(f);
self.to_bytes(&mut writer)
}
pub fn to_bytes<T: WriteBytesExt>(&self, writer: &mut T) -> Result<(), BlendMapError> {
writer.write_all(b"BMap")?;
writer.write_u8(self.start_color)?;
writer.write_u8(self.end_color)?;
for map in self.mapping.iter() {
writer.write_all(map)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use claim::*;
use tempfile::TempDir;
use super::*;
@ -324,6 +382,25 @@ mod tests {
);
Ok(())
}
#[test]
fn load_and_save() -> Result<(), BlendMapError> {
let tmp_dir = TempDir::new()?;
let mut blend_map = BlendMap::new(2, 3);
for i in 0..=255 {
blend_map.set_mapping(2, i, i)?;
blend_map.set_mapping(3, i, 255 - i)?;
}
let save_path = tmp_dir.path().join("test_blend_map.blendmap");
blend_map.to_file(&save_path)?;
let loaded_blend_map = BlendMap::load_from_file(&save_path)?;
assert!(blend_map == loaded_blend_map, "loaded BlendMap is not the same as the original");
Ok(())
}
}