Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add group layer support #146

Merged
merged 10 commits into from
Feb 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 64 additions & 0 deletions assets/tiled_group_layers.tmx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.5" tiledversion="1.7.0" orientation="orthogonal" renderorder="right-down" width="8" height="8" tilewidth="32" tileheight="32" infinite="0" nextlayerid="10" nextobjectid="1">
<tileset firstgid="1" source="tilesheet.tsx"/>
<layer id="1" name="tile-1" width="8" height="8">
<properties>
<property name="key" value="value1"/>
</properties>
<data encoding="csv">
6,7,8,0,0,0,0,0,
20,21,22,0,0,0,0,0,
34,35,36,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
</data>
</layer>
<group id="3" name="group-1">
<properties>
<property name="key" value="value4"/>
</properties>
<layer id="5" name="tile-2" width="8" height="8">
<properties>
<property name="key" value="value2"/>
</properties>
<data encoding="csv">
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,6,7,8,0,0,
0,0,0,20,21,22,0,0,
0,0,0,34,35,36,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
</data>
</layer>
</group>
<group id="6" name="group-2">
<properties>
<property name="key" value="value5"/>
</properties>
<group id="8" name="group-3">
<properties>
<property name="key" value="value6"/>
</properties>
<layer id="9" name="tile-3" width="8" height="8">
<properties>
<property name="key" value="value3"/>
</properties>
<data encoding="csv">
0,0,0,48,49,50,0,0,
0,0,0,62,63,64,0,0,
0,0,0,76,77,78,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
</data>
</layer>
</group>
</group>
</map>
10 changes: 7 additions & 3 deletions examples/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,9 @@ fn main() {
println!("Infinite tile layer with {} chunks", data.chunks.len())
}
},

tiled::LayerType::ObjectLayer(layer) => {
println!("Object layer with {} objects", layer.data().objects.len())
}

},
tiled::LayerType::ImageLayer(layer) => {
println!(
"Image layer with {}",
Expand All @@ -44,6 +42,12 @@ fn main() {
None => "no image".to_owned(),
}
)
},
tiled::LayerType::GroupLayer(layer) => {
println!(
"Group layer with {} sublayers",
layer.layers().len()
)
}
}
}
Expand Down
121 changes: 121 additions & 0 deletions src/layers/group.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
use std::path::Path;
use std::collections::HashMap;

use crate:: {
layers::{LayerData, LayerTag},
error::TiledError,
properties::{parse_properties, Properties},
map::MapTilesetGid,
util::*,
MapWrapper, Layer, 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],
) -> Result<(Self, Properties), TiledError> {
let mut properties = HashMap::new();
let mut layers = Vec::new();
parse_tag!(parser, "group", {
"layer" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::TileLayer,
infinite,
map_path,
&tilesets,
)?);
Ok(())
},
"imagelayer" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::ImageLayer,
infinite,
map_path,
&tilesets,
)?);
Ok(())
},
"objectgroup" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::ObjectLayer,
infinite,
map_path,
&tilesets,
)?);
Ok(())
},
"group" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::GroupLayer,
infinite,
map_path,
&tilesets,
)?);
Ok(())
},
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
},
});
Ok((
Self { layers },
properties,
))
}
}

pub type GroupLayer<'map> = MapWrapper<'map, GroupLayerData>;

impl<'map> GroupLayer<'map> {
pub fn layers(&self) -> GroupLayerIter {
GroupLayerIter::new(self.map(), self.data())
}
pub fn get_layer(&self, index: usize) -> Option<Layer> {
self.data().layers.get(index).map(|data| Layer::new(self.map(), data))
}
}

/// An iterator that iterates over all the layers in a group layer, obtained via [`GroupLayer::layers`].
pub struct GroupLayerIter<'map> {
map: &'map Map,
group: &'map GroupLayerData,
index: usize,
}

impl<'map> GroupLayerIter<'map> {
fn new(map: &'map Map, group: &'map GroupLayerData) -> Self {
Self { map, group, index: 0 }
}
}

impl<'map> Iterator for GroupLayerIter<'map> {
type Item = Layer<'map>;
fn next(&mut self) -> Option<Self::Item> {
let layer_data = self.group.layers.get(self.index)?;
self.index += 1;
Some(Layer::new(self.map, layer_data))
}
}

impl<'map> ExactSizeIterator for GroupLayerIter<'map> {
fn len(&self) -> usize {
self.group.layers.len() - self.index
}
}
12 changes: 10 additions & 2 deletions src/layers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,23 @@ mod object;
pub use object::*;
mod tile;
pub use tile::*;
mod group;
pub use group::*;

#[derive(Clone, PartialEq, Debug)]
pub enum LayerDataType {
TileLayer(TileLayerData),
ObjectLayer(ObjectLayerData),
ImageLayer(ImageLayerData),
// TODO: Support group layers
GroupLayer(GroupLayerData),
}

#[derive(Clone, Copy)]
pub(crate) enum LayerTag {
TileLayer,
ObjectLayer,
ImageLayer,
GroupLayer,
}

#[derive(Clone, PartialEq, Debug)]
Expand Down Expand Up @@ -85,6 +88,10 @@ impl LayerData {
let (ty, properties) = ImageLayerData::new(parser, map_path)?;
(LayerDataType::ImageLayer(ty), properties)
}
LayerTag::GroupLayer => {
let (ty, properties) = GroupLayerData::new(parser, infinite, map_path, tilesets)?;
(LayerDataType::GroupLayer(ty), properties)
}
};

Ok(Self {
Expand Down Expand Up @@ -116,7 +123,7 @@ pub enum LayerType<'map> {
TileLayer(TileLayer<'map>),
ObjectLayer(ObjectLayer<'map>),
ImageLayer(ImageLayer<'map>),
// TODO: Support group layers
GroupLayer(GroupLayer<'map>),
}

impl<'map> LayerType<'map> {
Expand All @@ -125,6 +132,7 @@ impl<'map> LayerType<'map> {
LayerDataType::TileLayer(data) => Self::TileLayer(TileLayer::new(map, data)),
LayerDataType::ObjectLayer(data) => Self::ObjectLayer(ObjectLayer::new(map, data)),
LayerDataType::ImageLayer(data) => Self::ImageLayer(ImageLayer::new(map, data)),
LayerDataType::GroupLayer(data) => Self::GroupLayer(GroupLayer::new(map, data)),
}
}
}
23 changes: 17 additions & 6 deletions src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,8 @@ impl Map {
}

/// Get an iterator over all the layers in the map in ascending order of their layer index.
pub fn layers(&self) -> LayerIter {
LayerIter::new(self)
pub fn layers(&self) -> MapLayerIter {
MapLayerIter::new(self)
}

/// Returns the layer that has the specified index, if it exists.
Expand All @@ -114,18 +114,18 @@ impl Map {
}

/// An iterator that iterates over all the layers in a map, obtained via [`Map::layers`].
pub struct LayerIter<'map> {
pub struct MapLayerIter<'map> {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed name to disambiguate from new GroupLayerIter

map: &'map Map,
index: usize,
}

impl<'map> LayerIter<'map> {
impl<'map> MapLayerIter<'map> {
fn new(map: &'map Map) -> Self {
Self { map, index: 0 }
}
}

impl<'map> Iterator for LayerIter<'map> {
impl<'map> Iterator for MapLayerIter<'map> {
type Item = Layer<'map>;

fn next(&mut self) -> Option<Self::Item> {
Expand All @@ -135,7 +135,7 @@ impl<'map> Iterator for LayerIter<'map> {
}
}

impl<'map> ExactSizeIterator for LayerIter<'map> {
impl<'map> ExactSizeIterator for MapLayerIter<'map> {
fn len(&self) -> usize {
self.map.layers.len() - self.index
}
Expand Down Expand Up @@ -222,6 +222,17 @@ impl Map {
)?);
Ok(())
},
"group" => |attrs| {
layers.push(LayerData::new(
parser,
attrs,
LayerTag::GroupLayer,
infinite,
map_path,
&tilesets,
)?);
Ok(())
},
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
Expand Down
Loading