add support for loading and saving BitmapAtlas "descriptor" json files
as well as support for directly instantiating a BitmapAtlas from such a descriptor. saving a BitmapAtlas to a descriptor file directly is not added (yet?) as my gut feeling is that these files would probably be hand-written? saving from a BitmapAtlas directly would (in a simple/naive impl) always result in a long-ish list of "tiles" anyway, since grids are turned into tiles. this further reinforces me feeling that you'd either write these files by hand, or at the very least, just construct a descriptor instance in code somehow and save that
This commit is contained in:
parent
afa7a92709
commit
f5291a4d60
|
@ -16,6 +16,8 @@ num-traits = "0.2.15"
|
||||||
bitflags = "2.1.0"
|
bitflags = "2.1.0"
|
||||||
flate2 = "1.0.25"
|
flate2 = "1.0.25"
|
||||||
crc32fast = "1.3.2"
|
crc32fast = "1.3.2"
|
||||||
|
serde = { version = "1.0.136", features = ["derive"] }
|
||||||
|
serde_json = "1.0.79"
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dependencies]
|
[target.'cfg(not(windows))'.dependencies]
|
||||||
sdl2 = { git = "https://github.com/Rust-SDL2/rust-sdl2/", rev = "819ab438ac971a922d6ee1da558822002d343b4e", features = ["static-link", "bundled", "use-pkgconfig", "unsafe_textures"] }
|
sdl2 = { git = "https://github.com/Rust-SDL2/rust-sdl2/", rev = "819ab438ac971a922d6ee1da558822002d343b4e", features = ["static-link", "bundled", "use-pkgconfig", "unsafe_textures"] }
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
|
use std::fs::File;
|
||||||
|
use std::io::{BufReader, BufWriter, Read, Write};
|
||||||
use std::ops::Index;
|
use std::ops::Index;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
@ -15,6 +18,9 @@ pub enum BitmapAtlasError {
|
||||||
|
|
||||||
#[error("Invalid dimensions for region")]
|
#[error("Invalid dimensions for region")]
|
||||||
InvalidDimensions,
|
InvalidDimensions,
|
||||||
|
|
||||||
|
#[error("No bitmap atlas entries in the descriptor")]
|
||||||
|
NoEntries,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
@ -40,6 +46,27 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_descriptor(descriptor: &BitmapAtlasDescriptor, bitmap: BitmapType) -> Result<Self, BitmapAtlasError> {
|
||||||
|
if descriptor.tiles.is_empty() {
|
||||||
|
return Err(BitmapAtlasError::NoEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut atlas = BitmapAtlas::new(bitmap);
|
||||||
|
for entry in descriptor.tiles.iter() {
|
||||||
|
use BitmapAtlasDescriptorEntry::*;
|
||||||
|
match entry {
|
||||||
|
Tile { x, y, width, height } => {
|
||||||
|
atlas.add(Rect::new(*x as i32, *y as i32, *width, *height))?;
|
||||||
|
}
|
||||||
|
Autogrid { x, y, tile_width, tile_height, num_tiles_x, num_tiles_y, border } => {
|
||||||
|
atlas.add_custom_grid(*x, *y, *tile_width, *tile_height, *num_tiles_x, *num_tiles_y, *border)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(atlas)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add(&mut self, rect: Rect) -> Result<usize, BitmapAtlasError> {
|
pub fn add(&mut self, rect: Rect) -> Result<usize, BitmapAtlasError> {
|
||||||
if rect.width == 0 || rect.height == 0 {
|
if rect.width == 0 || rect.height == 0 {
|
||||||
return Err(BitmapAtlasError::InvalidDimensions);
|
return Err(BitmapAtlasError::InvalidDimensions);
|
||||||
|
@ -158,6 +185,70 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum BitmapAtlasDescriptorError {
|
||||||
|
#[error("Serde Json serialization/deserialization error: {0}")]
|
||||||
|
SerdeJsonError(String),
|
||||||
|
|
||||||
|
#[error("I/O error")]
|
||||||
|
IOError(#[from] std::io::Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
#[serde(rename_all = "lowercase")]
|
||||||
|
pub enum BitmapAtlasDescriptorEntry {
|
||||||
|
Tile {
|
||||||
|
x: u32, //
|
||||||
|
y: u32,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
},
|
||||||
|
Autogrid {
|
||||||
|
x: u32, //
|
||||||
|
y: u32,
|
||||||
|
tile_width: u32,
|
||||||
|
tile_height: u32,
|
||||||
|
num_tiles_x: u32,
|
||||||
|
num_tiles_y: u32,
|
||||||
|
border: u32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, serde::Deserialize, serde::Serialize)]
|
||||||
|
pub struct BitmapAtlasDescriptor {
|
||||||
|
pub bitmap: String,
|
||||||
|
pub tiles: Vec<BitmapAtlasDescriptorEntry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BitmapAtlasDescriptor {
|
||||||
|
pub fn load_from_file(path: &Path) -> Result<Self, BitmapAtlasDescriptorError> {
|
||||||
|
let f = File::open(path)?;
|
||||||
|
let mut reader = BufReader::new(f);
|
||||||
|
Self::load_from_bytes(&mut reader)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_from_bytes<T: Read>(reader: &mut T) -> Result<Self, BitmapAtlasDescriptorError> {
|
||||||
|
match serde_json::from_reader(reader) {
|
||||||
|
Ok(desc) => Ok(desc),
|
||||||
|
Err(error) => Err(BitmapAtlasDescriptorError::SerdeJsonError(error.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_file(&self, path: &Path) -> Result<(), BitmapAtlasDescriptorError> {
|
||||||
|
let f = File::create(path)?;
|
||||||
|
let mut writer = BufWriter::new(f);
|
||||||
|
self.to_bytes(&mut writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn to_bytes<T: Write>(&self, writer: &mut T) -> Result<(), BitmapAtlasDescriptorError> {
|
||||||
|
if let Err(error) = serde_json::to_writer_pretty(writer, &self) {
|
||||||
|
Err(BitmapAtlasDescriptorError::SerdeJsonError(error.to_string()))
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use claim::*;
|
use claim::*;
|
||||||
|
|
Loading…
Reference in a new issue