use super::*;
use crate::traits::check_wang4x4;
use image::{GenericImage, ImageResult};
use serde::{de::Visitor, Deserialize, Deserializer};
use std::fmt::Formatter;
struct VisitorGridAtlas;
impl<'de> Deserialize<'de> for GridCornerAtlas {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_map(VisitorGridAtlas)
}
}
impl<'de> Visitor<'de> for VisitorGridAtlas {
type Value = GridCornerAtlas;
fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
formatter.write_str("except TileAtlas4x6 {width, height, image}")
}
}
impl GridCornerAtlas {
pub fn from_wang(wang: &RgbaImage) -> ImageResult<Self> {
let cell_size = check_wang4x4(wang)?;
let mut out = Self { image: RgbaImage::new(cell_size * 16, cell_size), count: [1; 16] };
for i in 0..16 {
let view = make_wing_cell(wang, i, cell_size);
out.image.copy_from(&view.to_image(), i * cell_size, 0)?;
}
Ok(out)
}
}
fn make_wing_cell(raw: &RgbaImage, id: u32, s: u32) -> SubImage<&RgbaImage> {
match id {
0b0000 => raw.view(0 * s, 3 * s, s, s),
0b0001 => raw.view(3 * s, 3 * s, s, s),
0b0010 => raw.view(0 * s, 2 * s, s, s),
0b0011 => raw.view(1 * s, 2 * s, s, s),
0b0100 => raw.view(0 * s, 0 * s, s, s),
0b0101 => raw.view(3 * s, 2 * s, s, s),
0b0110 => raw.view(2 * s, 3 * s, s, s),
0b0111 => raw.view(3 * s, 1 * s, s, s),
0b1000 => raw.view(1 * s, 3 * s, s, s),
0b1001 => raw.view(0 * s, 1 * s, s, s),
0b1010 => raw.view(1 * s, 0 * s, s, s),
0b1011 => raw.view(2 * s, 2 * s, s, s),
0b1100 => raw.view(3 * s, 0 * s, s, s),
0b1101 => raw.view(2 * s, 0 * s, s, s),
0b1110 => raw.view(1 * s, 1 * s, s, s),
0b1111 => raw.view(2 * s, 1 * s, s, s),
_ => unreachable!(),
}
}
impl GridCornerAtlas {
pub fn from_rpg_maker_xp(rpg: &RgbaImage) -> ImageResult<Self> {
assert_eq!(rpg.width() % 4, 0, "image width {} does not divide by 4", rpg.width());
assert_eq!(rpg.height() % 6, 0, "image height {} does not divide by 6", rpg.height());
let half_cell = rpg.width() / 4;
let mut out = Self { image: RgbaImage::new(half_cell * 16 * 2, half_cell * 2), count: [1; 16] };
for i in 0..16 {
let view = make_rpg4x6_cell(rpg, i, half_cell)?;
out.image.copy_from(&view, i * half_cell * 2, 0)?;
}
Ok(out)
}
}
fn make_rpg4x6_cell(raw: &RgbaImage, id: u32, hs: u32) -> ImageResult<RgbaImage> {
let xs = match id {
0b0000 => [(0, 0), (1, 0), (0, 1), (1, 1)],
0b0001 => [(3, 5), (1, 0), (0, 1), (1, 1)],
0b0010 => [(0, 0), (0, 5), (0, 1), (1, 1)],
0b0011 => [(1, 5), (2, 5), (0, 1), (1, 1)],
0b0100 => [(0, 0), (1, 0), (3, 2), (1, 1)],
0b0101 => [(3, 3), (1, 0), (3, 4), (1, 1)],
0b0110 => [(0, 0), (0, 5), (3, 2), (1, 1)],
0b0111 => [(3, 1), (2, 5), (3, 4), (1, 1)],
0b1000 => [(0, 0), (1, 0), (0, 1), (0, 2)],
0b1001 => [(3, 5), (1, 0), (0, 1), (0, 2)],
0b1010 => [(0, 0), (0, 3), (0, 1), (0, 4)],
0b1011 => [(1, 5), (2, 1), (0, 1), (0, 4)],
0b1100 => [(0, 0), (1, 0), (1, 2), (2, 2)],
0b1101 => [(3, 3), (1, 0), (3, 0), (2, 2)],
0b1110 => [(0, 0), (0, 3), (1, 2), (2, 0)],
0b1111 => [(1, 3), (2, 3), (1, 4), (2, 4)],
_ => unreachable!(),
};
let mut out = RgbaImage::new(hs * 2, hs * 2);
for (i, (x, y)) in xs.iter().enumerate() {
let view = raw.view(*x * hs, *y * hs, hs, hs);
let x = (i as u32 % 2) * hs;
let y = (i as u32 / 2) * hs;
out.copy_from(&view.to_image(), x, y)?;
}
Ok(out)
}