use serde::{Deserialize, Serialize};
use crate::error::{MeshError, Result};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ImageBlock {
#[serde(default)]
pub name: String,
pub atlas: SpriteAtlas,
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SpriteAtlas {
pub width: u32,
pub height: u32,
pub frame_width: u32,
pub frame_height: u32,
pub frame_count: u32,
pub rgba: Vec<u8>,
}
impl SpriteAtlas {
pub fn validate(&self) -> Result<()> {
let expected = self.width as usize * self.height as usize * 4;
if self.rgba.len() != expected {
return Err(MeshError::InvalidBlock(format!(
"atlas {}x{} expects {expected} RGBA bytes, got {}",
self.width,
self.height,
self.rgba.len()
)));
}
if self.frame_width == 0 || self.frame_height == 0 {
return Err(MeshError::InvalidBlock(
"frame dimensions must be non-zero".into(),
));
}
if self.frame_width > self.width || self.frame_height > self.height {
return Err(MeshError::InvalidBlock(format!(
"frame {}x{} exceeds atlas {}x{}",
self.frame_width, self.frame_height, self.width, self.height
)));
}
let capacity = (self.width / self.frame_width) * (self.height / self.frame_height);
if self.frame_count == 0 || self.frame_count > capacity {
return Err(MeshError::InvalidBlock(format!(
"frame_count {} does not fit {} frames in atlas",
self.frame_count, capacity
)));
}
Ok(())
}
}