tmx/
map.rs

1use super::*;
2
3/// A tiled map loaded from a .tmx file.
4pub struct Map {
5    /// Custom properties.
6    pub properties: HashMap<String, Property>,
7    /// Tilesets used in the map.
8    pub tilesets: Vec<Arc<Tileset>>,
9    /// Layers contained in the map.
10    pub layers: Vec<Layer>,
11
12    /// The total width of the map, measured in tiles.
13    pub width: u32,
14    /// The total height of the map, measured in tiles.
15    pub height: u32,
16    /// The rendering type of the map.
17    pub tile_type: TileType,
18
19    /// Background color of the map.
20    pub background: [u8; 4],
21}
22
23pub struct Objects<'a> {
24    l: &'a [Layer],
25    i: usize,
26    z: f32,
27
28    sub: Option<Box<Objects<'a>>>,
29}
30
31impl Map {
32    /// Retrieve the tileset associated with the global tile id (gid).
33    /// If no tileset is associated with the gid, `None` is returned.
34    pub fn get_tileset(&self, gid: u32) -> Option<Arc<Tileset>> {
35        for tileset in self.tilesets.iter().rev() {
36            if gid >= tileset.first_gid {
37                return Some(tileset.clone());
38            }
39        }
40        None
41    }
42
43    /// Retrieve the tile metadata associated with the global tile id (gid).
44    /// If no tile metadata is associated with the gid, `None` is returned.
45    pub fn get_tile(&self, gid: u32) -> Option<&Tile> {
46        for tileset in self.tilesets.iter().rev() {
47            if gid >= tileset.first_gid {
48                let id = gid - tileset.first_gid;
49                return if let Some(&Some(ref tile)) = tileset.tiles.get(id as usize) {
50                    Some(&tile)
51                } else {
52                    None
53                };
54            }
55        }
56        None
57    }
58
59    /// Iterate over all the objects in the map
60    pub fn objects(&self) -> Objects {
61        Objects {
62            l: self.layers.as_slice(),
63            i: 0,
64            z: 0.0,
65            sub: None,
66        }
67    }
68}
69
70impl<'a> Iterator for Objects<'a> {
71    type Item = (f32, &'a Object);
72
73    fn next(&mut self) -> Option<(f32, &'a Object)> {
74        if let Some(sub) = self.sub.as_mut().and_then(|s| s.next()) {
75            return Some(sub);
76        } else if self.sub.is_some() {
77            self.z = self.sub.take().unwrap().z + 1.0;
78            self.sub = None;
79        }
80
81        if !self.l.is_empty() {
82            match &self.l[0] {
83                Layer::Group { layers, .. } => {
84                    self.sub = Some(Box::new(Objects {
85                        l: layers.as_slice(),
86                        i: 0,
87                        z: self.z,
88                        sub: None,
89                    }));
90                }
91
92                Layer::ObjectLayer { objects, .. } => {
93                    if self.i < objects.len() {
94                        self.i += 1;
95                        return Some((self.z, &objects[self.i - 1]));
96                    }
97                }
98
99                _ => {}
100            }
101
102            self.l = &self.l[1..];
103            self.i = 0;
104            self.z += 1.0;
105            return self.next();
106        }
107
108        None
109    }
110}