1use crate::{reader::AseReader, tilemap::TileBitmaskHeader, Result};
2use std::{io::Read, ops::Index};
3
4#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5pub(crate) struct TileId(pub u32);
6
7#[derive(Debug, Clone)]
13#[allow(unused)]
14pub struct Tile {
15 pub(crate) id: TileId,
16 pub(crate) flip_x: bool,
18 pub(crate) flip_y: bool,
19 pub(crate) rotate_90cw: bool,
20}
21
22pub(crate) static EMPTY_TILE: Tile = Tile {
23 id: TileId(0),
24 flip_x: false,
25 flip_y: false,
26 rotate_90cw: false,
27};
28
29impl Tile {
30 pub fn id(&self) -> u32 {
32 self.id.0
33 }
34
35 pub(crate) fn new(chunk: &[u8], header: &TileBitmaskHeader) -> Result<Self> {
36 AseReader::new(chunk)
37 .dword()
38 .map(|bits| Self::parse(bits, header))
39 }
40
41 fn parse(bits: u32, header: &TileBitmaskHeader) -> Self {
42 Self {
43 id: TileId(bits & header.tile_id),
44 flip_x: as_bool(bits & header.x_flip),
45 flip_y: as_bool(bits & header.y_flip),
46 rotate_90cw: as_bool(bits & header.rotate_90cw),
47 }
48 }
49}
50
51#[derive(Debug)]
52pub(crate) struct Tiles(Vec<Tile>);
53
54impl Tiles {
55 pub(crate) fn unzip<T: Read>(
56 reader: AseReader<T>,
57 expected_tile_count: usize,
58 header: &TileBitmaskHeader,
59 ) -> Result<Self> {
60 let expected_output_size = 4 * expected_tile_count;
62 let bytes = reader.unzip(expected_output_size)?;
63 let tiles: Result<Vec<Tile>> = bytes
64 .chunks_exact(4)
65 .map(|bytes| Tile::new(bytes, header))
66 .collect();
67 Ok(Self(tiles?))
68 }
69}
70
71impl Index<usize> for Tiles {
72 type Output = Tile;
73
74 fn index(&self, index: usize) -> &Self::Output {
75 &self.0[index]
76 }
77}
78
79fn as_bool(bitwise_and: u32) -> bool {
80 bitwise_and != 0
81}