1 2 3 4 5 6 7 8 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 64 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 133 134 135 136 137 138
use std::{collections::HashMap, path::Path, sync::Arc};
use crate::{
error::Result,
layers::{LayerData, LayerTag},
properties::{parse_properties, Properties},
util::*,
Error, Layer, MapTilesetGid, ResourceCache, ResourceReader, Tileset,
};
/// The raw data of a [`GroupLayer`]. Does not include a reference to its parent [`Map`](crate::Map).
#[derive(Debug, PartialEq, Clone)]
pub struct GroupLayerData {
layers: Vec<LayerData>,
}
impl GroupLayerData {
pub(crate) fn new(
parser: &mut impl Iterator<Item = XmlEventResult>,
infinite: bool,
map_path: &Path,
tilesets: &[MapTilesetGid],
for_tileset: Option<Arc<Tileset>>,
reader: &mut impl ResourceReader,
cache: &mut impl ResourceCache,
) -> Result<(Self, Properties)> {
let mut properties = HashMap::new();
let mut layers = Vec::new();
parse_tag!(parser, "group", {
"layer" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::Tiles,
infinite,
map_path,
tilesets,
for_tileset.as_ref().cloned(),reader,
cache
)?);
Ok(())
},
"imagelayer" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::Image,
infinite,
map_path,
tilesets,
for_tileset.as_ref().cloned(),reader,
cache
)?);
Ok(())
},
"objectgroup" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::Objects,
infinite,
map_path,
tilesets,
for_tileset.as_ref().cloned(),reader,
cache
)?);
Ok(())
},
"group" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::Group,
infinite,
map_path,
tilesets,
for_tileset.as_ref().cloned(),reader,
cache
)?);
Ok(())
},
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
},
});
Ok((Self { layers }, properties))
}
}
map_wrapper!(
#[doc = "A group layer, used to organize the layers of the map in a hierarchy."]
#[doc = "\nAlso see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#group)."]
#[doc = "## Note"]
#[doc = "In Tiled, the properties of the group layer recursively affect child layers.
Implementing this behavior is left up to the user of this library."]
GroupLayer => GroupLayerData
);
impl<'map> GroupLayer<'map> {
/// Returns an iterator over the layers present in this group in display order.
/// ## Example
/// ```
/// use tiled::Layer;
/// # use tiled::Loader;
///
/// # fn main() {
/// # let map = Loader::new()
/// # .load_tmx_map("assets/tiled_group_layers.tmx")
/// # .unwrap();
/// #
/// let nested_layers: Vec<Layer> = map
/// .layers()
/// .filter_map(|layer| match layer.layer_type() {
/// tiled::LayerType::Group(layer) => Some(layer),
/// _ => None,
/// })
/// .flat_map(|layer| layer.layers())
/// .collect();
///
/// dbg!(nested_layers);
/// # }
/// ```
pub fn layers(&self) -> impl ExactSizeIterator<Item = Layer<'map>> + 'map {
let map: &'map crate::Map = self.map;
self.data
.layers
.iter()
.map(move |layer| Layer::new(map, layer))
}
/// Gets a specific layer from the group by index.
pub fn get_layer(&self, index: usize) -> Option<Layer> {
self.data
.layers
.get(index)
.map(|data| Layer::new(self.map, data))
}
}