use std::{collections::HashMap, path::Path, sync::Arc};
use xml::attribute::OwnedAttribute;
use crate::{
parse_properties,
util::{get_attrs, map_wrapper, parse_tag, XmlEventResult},
Color, Error, MapTilesetGid, Object, ObjectData, Properties, ResourceCache, ResourceReader,
Result, Tileset,
};
#[derive(Debug, PartialEq, Clone)]
pub struct ObjectLayerData {
objects: Vec<ObjectData>,
pub colour: Option<Color>,
}
impl ObjectLayerData {
pub(crate) fn new(
parser: &mut impl Iterator<Item = XmlEventResult>,
attrs: Vec<OwnedAttribute>,
tilesets: Option<&[MapTilesetGid]>,
for_tileset: Option<Arc<Tileset>>,
path_relative_to: &Path,
reader: &mut impl ResourceReader,
cache: &mut impl ResourceCache,
) -> Result<(ObjectLayerData, Properties)> {
let c = get_attrs!(
for v in attrs {
Some("color") => color ?= v.parse(),
}
color
);
let mut objects = Vec::new();
let mut properties = HashMap::new();
parse_tag!(parser, "objectgroup", {
"object" => |attrs| {
objects.push(ObjectData::new(parser, attrs, tilesets, for_tileset.as_ref().cloned(), path_relative_to, reader, cache)?);
Ok(())
},
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
},
});
Ok((ObjectLayerData { objects, colour: c }, properties))
}
#[inline]
pub fn object_data(&self) -> &[ObjectData] {
self.objects.as_ref()
}
}
map_wrapper!(
#[doc = "Also called an \"object group\". Used for storing [`Object`]s in a map."]
ObjectLayer => ObjectLayerData);
impl<'map> ObjectLayer<'map> {
pub fn get_object(&self, idx: usize) -> Option<Object<'map>> {
self.data
.objects
.get(idx)
.map(|data| Object::new(self.map, data))
}
#[inline]
pub fn objects(&self) -> impl ExactSizeIterator<Item = Object<'map>> + 'map {
let map: &'map crate::Map = self.map;
self.data
.objects
.iter()
.map(move |object| Object::new(map, object))
}
}