Newer
Older
use std::collections::HashMap;
use xml::attribute::OwnedAttribute;
use crate::{
parse_properties,
util::{get_attrs, parse_tag, XmlEventResult},
Gid, Map, MapTilesetGid, Properties, Tile, TileId, TiledError, Tileset,
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
};
mod finite;
mod infinite;
mod util;
pub use finite::*;
pub use infinite::*;
/// Stores the internal tile gid about a layer tile, along with how it is flipped.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub(crate) struct LayerTileData {
/// The index of the tileset this tile's in, relative to the tile's map.
pub(crate) tileset_index: usize,
/// The local ID of the tile in the tileset it's in.
pub(crate) id: TileId,
pub flip_h: bool,
pub flip_v: bool,
pub flip_d: bool,
}
impl LayerTileData {
const FLIPPED_HORIZONTALLY_FLAG: u32 = 0x80000000;
const FLIPPED_VERTICALLY_FLAG: u32 = 0x40000000;
const FLIPPED_DIAGONALLY_FLAG: u32 = 0x20000000;
const ALL_FLIP_FLAGS: u32 = Self::FLIPPED_HORIZONTALLY_FLAG
| Self::FLIPPED_VERTICALLY_FLAG
| Self::FLIPPED_DIAGONALLY_FLAG;
/// Creates a new [`LayerTileData`] from a [`GID`] plus its flipping bits.
pub(crate) fn from_bits(bits: u32, tilesets: &[MapTilesetGid]) -> Option<Self> {
let flags = bits & Self::ALL_FLIP_FLAGS;
let gid = Gid(bits & !Self::ALL_FLIP_FLAGS);
let flip_d = flags & Self::FLIPPED_DIAGONALLY_FLAG == Self::FLIPPED_DIAGONALLY_FLAG; // Swap x and y axis (anti-diagonally) [flips over y = -x line]
let flip_h = flags & Self::FLIPPED_HORIZONTALLY_FLAG == Self::FLIPPED_HORIZONTALLY_FLAG; // Flip tile over y axis
let flip_v = flags & Self::FLIPPED_VERTICALLY_FLAG == Self::FLIPPED_VERTICALLY_FLAG; // Flip tile over x axis
if gid == Gid::EMPTY {
None
} else {
let (tileset_index, tileset) = crate::util::get_tileset_for_gid(tilesets, gid)?;
let id = gid.0 - tileset.first_gid.0;
Some(Self {
tileset_index,
id,
flip_h,
flip_v,
flip_d,
})
}
}
}
#[derive(Debug, PartialEq, Clone)]
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
Finite(FiniteTileLayerData),
Infinite(InfiniteTileLayerData),
}
impl TileLayerData {
pub(crate) fn new(
parser: &mut impl Iterator<Item = XmlEventResult>,
attrs: Vec<OwnedAttribute>,
infinite: bool,
tilesets: &[MapTilesetGid],
) -> Result<(Self, Properties), TiledError> {
let ((), (width, height)) = get_attrs!(
attrs,
optionals: [
],
required: [
("width", width, |v: String| v.parse().ok()),
("height", height, |v: String| v.parse().ok()),
],
TiledError::MalformedAttributes("layer parsing error, width and height attributes required".to_string())
);
let mut result = Self::Finite(Default::default());
let mut properties = HashMap::new();
parse_tag!(parser, "layer", {
"data" => |attrs| {
if infinite {
result = Self::Infinite(InfiniteTileLayerData::new(parser, attrs, tilesets)?);
} else {
result = Self::Finite(FiniteTileLayerData::new(parser, attrs, width, height, tilesets)?);
}
Ok(())
},
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
},
});
Ok((result, properties))
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct LayerTile<'map> {
pub tileset: &'map Tileset,
pub id: TileId,
pub flip_h: bool,
pub flip_v: bool,
pub flip_d: bool,
}
impl<'map> LayerTile<'map> {
pub(crate) fn from_data(data: &LayerTileData, map: &'map Map) -> Self {
Self {
tileset: &*map.tilesets()[data.tileset_index],
id: data.id,
flip_h: data.flip_h,
flip_v: data.flip_v,
flip_d: data.flip_d,
}
}
/// Get a reference to the layer tile's referenced tile, if it exists.
pub fn get_tile(&self) -> Option<&'map Tile> {
self.tileset.get_tile(self.id)
}
}
pub enum TileLayer<'map> {
Finite(FiniteTileLayer<'map>),
Infinite(InfiniteTileLayer<'map>),
}
pub(crate) fn new(map: &'map Map, data: &'map TileLayerData) -> Self {
match data {
TileLayerData::Finite(data) => Self::Finite(FiniteTileLayer::new(map, data)),
TileLayerData::Infinite(data) => Self::Infinite(InfiniteTileLayer::new(map, data)),
}
}
pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> {
match self {
TileLayer::Finite(finite) => finite.get_tile(x, y),
TileLayer::Infinite(infinite) => infinite.get_tile(x, y),
}