Skip to content
Snippets Groups Projects
Commit 6da58bd0 authored by Victor Sergienko's avatar Victor Sergienko
Browse files

There is only one image per Tile OR per Tileset. Added columns field.

parent 9fc0b742
No related branches found
No related tags found
No related merge requests found
...@@ -14,7 +14,7 @@ use crate::{ ...@@ -14,7 +14,7 @@ use crate::{
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Tile { pub struct Tile {
pub id: u32, pub id: u32,
pub images: Vec<Image>, pub image: Option<Image>,
pub properties: Properties, pub properties: Properties,
pub objectgroup: Option<ObjectGroup>, pub objectgroup: Option<ObjectGroup>,
pub animation: Option<Vec<Frame>>, pub animation: Option<Vec<Frame>>,
...@@ -39,13 +39,13 @@ impl Tile { ...@@ -39,13 +39,13 @@ impl Tile {
TiledError::MalformedAttributes("tile must have an id with the correct type".to_string()) TiledError::MalformedAttributes("tile must have an id with the correct type".to_string())
); );
let mut images = Vec::new(); let mut image = Option::None;
let mut properties = HashMap::new(); let mut properties = HashMap::new();
let mut objectgroup = None; let mut objectgroup = None;
let mut animation = None; let mut animation = None;
parse_tag!(parser, "tile", { parse_tag!(parser, "tile", {
"image" => |attrs| { "image" => |attrs| {
images.push(Image::new(parser, attrs)?); image = Some(Image::new(parser, attrs)?);
Ok(()) Ok(())
}, },
"properties" => |_| { "properties" => |_| {
...@@ -63,7 +63,7 @@ impl Tile { ...@@ -63,7 +63,7 @@ impl Tile {
}); });
Ok(Tile { Ok(Tile {
id, id,
images, image: image,
properties, properties,
objectgroup, objectgroup,
animation, animation,
......
...@@ -24,9 +24,14 @@ pub struct Tileset { ...@@ -24,9 +24,14 @@ pub struct Tileset {
pub spacing: u32, pub spacing: u32,
pub margin: u32, pub margin: u32,
pub tilecount: Option<u32>, pub tilecount: Option<u32>,
/// The Tiled spec says that a tileset can have mutliple images so a `Vec` pub columns: u32,
/// is used. Usually you will only use one. /// A tileset can either:
pub images: Vec<Image>, /// * have a single spritesheet `image` in `tileset` ("regular" tileset);
/// * have zero images in `tileset` and one `image` per `tile` ("image collection" tileset).
///
/// - Source: [tiled issue #2117](https://github.com/mapeditor/tiled/issues/2117)
/// - Source: [`columns` documentation](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tileset)
pub image: Option<Image>,
pub tiles: Vec<Tile>, pub tiles: Vec<Tile>,
pub properties: Properties, pub properties: Properties,
} }
...@@ -54,12 +59,13 @@ impl Tileset { ...@@ -54,12 +59,13 @@ impl Tileset {
parser: &mut EventReader<R>, parser: &mut EventReader<R>,
attrs: &Vec<OwnedAttribute>, attrs: &Vec<OwnedAttribute>,
) -> Result<Tileset, TiledError> { ) -> Result<Tileset, TiledError> {
let ((spacing, margin, tilecount), (first_gid, name, width, height)) = get_attrs!( let ((spacing, margin, tilecount, columns), (first_gid, name, width, height)) = get_attrs!(
attrs, attrs,
optionals: [ optionals: [
("spacing", spacing, |v:String| v.parse().ok()), ("spacing", spacing, |v:String| v.parse().ok()),
("margin", margin, |v:String| v.parse().ok()), ("margin", margin, |v:String| v.parse().ok()),
("tilecount", tilecount, |v:String| v.parse().ok()), ("tilecount", tilecount, |v:String| v.parse().ok()),
("columns", columns, |v:String| v.parse().ok()),
], ],
required: [ required: [
("firstgid", first_gid, |v:String| v.parse().ok()), ("firstgid", first_gid, |v:String| v.parse().ok()),
...@@ -70,12 +76,12 @@ impl Tileset { ...@@ -70,12 +76,12 @@ impl Tileset {
TiledError::MalformedAttributes("tileset must have a firstgid, name tile width and height with correct types".to_string()) TiledError::MalformedAttributes("tileset must have a firstgid, name tile width and height with correct types".to_string())
); );
let mut images = Vec::new(); let mut image = Option::None;
let mut tiles = Vec::new(); let mut tiles = Vec::new();
let mut properties = HashMap::new(); let mut properties = HashMap::new();
parse_tag!(parser, "tileset", { parse_tag!(parser, "tileset", {
"image" => |attrs| { "image" => |attrs| {
images.push(Image::new(parser, attrs)?); image = Some(Image::new(parser, attrs)?);
Ok(()) Ok(())
}, },
"properties" => |_| { "properties" => |_| {
...@@ -88,6 +94,15 @@ impl Tileset { ...@@ -88,6 +94,15 @@ impl Tileset {
}, },
}); });
let columns = match columns {
Some(col) => col,
None => match &image {
None => return Err(TiledError::MalformedAttributes(
"No <image> and no <columns> in <tileset>".to_string())),
Some(image) => image.width as u32 / width,
},
};
Ok(Tileset { Ok(Tileset {
tile_width: width, tile_width: width,
tile_height: height, tile_height: height,
...@@ -96,7 +111,8 @@ impl Tileset { ...@@ -96,7 +111,8 @@ impl Tileset {
first_gid, first_gid,
name, name,
tilecount, tilecount,
images, columns,
image,
tiles, tiles,
properties, properties,
}) })
...@@ -159,12 +175,13 @@ impl Tileset { ...@@ -159,12 +175,13 @@ impl Tileset {
parser: &mut EventReader<R>, parser: &mut EventReader<R>,
attrs: &Vec<OwnedAttribute>, attrs: &Vec<OwnedAttribute>,
) -> Result<Tileset, TiledError> { ) -> Result<Tileset, TiledError> {
let ((spacing, margin, tilecount), (name, width, height)) = get_attrs!( let ((spacing, margin, tilecount, columns), (name, width, height)) = get_attrs!(
attrs, attrs,
optionals: [ optionals: [
("spacing", spacing, |v:String| v.parse().ok()), ("spacing", spacing, |v:String| v.parse().ok()),
("margin", margin, |v:String| v.parse().ok()), ("margin", margin, |v:String| v.parse().ok()),
("tilecount", tilecount, |v:String| v.parse().ok()), ("tilecount", tilecount, |v:String| v.parse().ok()),
("columns", columns, |v:String| v.parse().ok()),
], ],
required: [ required: [
("name", name, |v| Some(v)), ("name", name, |v| Some(v)),
...@@ -174,24 +191,33 @@ impl Tileset { ...@@ -174,24 +191,33 @@ impl Tileset {
TiledError::MalformedAttributes("tileset must have a firstgid, name tile width and height with correct types".to_string()) TiledError::MalformedAttributes("tileset must have a firstgid, name tile width and height with correct types".to_string())
); );
let mut images = Vec::new(); let mut image = Option::None;
let mut tiles = Vec::new(); let mut tiles = Vec::new();
let mut properties = HashMap::new(); let mut properties = HashMap::new();
parse_tag!(parser, "tileset", { parse_tag!(parser, "tileset", {
"image" => |attrs| { "image" => |attrs| {
images.push(Image::new(parser, attrs)?); image = Some(Image::new(parser, attrs)?);
Ok(())
},
"tile" => |attrs| {
tiles.push(Tile::new(parser, attrs)?);
Ok(()) Ok(())
}, },
"properties" => |_| { "properties" => |_| {
properties = parse_properties(parser)?; properties = parse_properties(parser)?;
Ok(()) Ok(())
}, },
"tile" => |attrs| {
tiles.push(Tile::new(parser, attrs)?);
Ok(())
},
}); });
let columns = match columns {
Some(col) => col,
None => match &image {
None => return Err(TiledError::MalformedAttributes(
"No <image> and no <columns> in <tileset>".to_string())),
Some(image) => image.width as u32 / width,
},
};
Ok(Tileset { Ok(Tileset {
first_gid: first_gid, first_gid: first_gid,
name: name, name: name,
...@@ -199,8 +225,9 @@ impl Tileset { ...@@ -199,8 +225,9 @@ impl Tileset {
tile_height: height, tile_height: height,
spacing: spacing.unwrap_or(0), spacing: spacing.unwrap_or(0),
margin: margin.unwrap_or(0), margin: margin.unwrap_or(0),
tilecount: tilecount, columns,
images: images, tilecount,
image,
tiles: tiles, tiles: tiles,
properties, properties,
}) })
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment