From 6077ff47af622503d990772607e514d109799169 Mon Sep 17 00:00:00 2001 From: LawnCable Date: Fri, 15 Apr 2022 08:37:07 +0200 Subject: make name, tile_count and columns optional so it does not fail parsing older/invalid maps also add the log crate to still print warnings in these cases --- src/lowlevel/macros.rs | 15 +++++++++++ src/lowlevel/tileset.rs | 69 ++++++++++++++++++++++++++----------------------- 2 files changed, 52 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/lowlevel/macros.rs b/src/lowlevel/macros.rs index 29c4511..b14ae13 100644 --- a/src/lowlevel/macros.rs +++ b/src/lowlevel/macros.rs @@ -17,6 +17,21 @@ macro_rules! get_attribute { }}; } +#[macro_export] +macro_rules! get_recommended_attribute { + ($node:expr, $attribute_name:expr) => {{ + let node: &roxmltree::Node = &$node; + let attribute_name: &str = $attribute_name; + match node.attribute(attribute_name) { + None => { + warn!("{} attribute missing", attribute_name); + None + } + Some(v) => Some(v.to_owned()), + } + }}; +} + #[macro_export] macro_rules! ensure_element { ($node:expr) => { diff --git a/src/lowlevel/tileset.rs b/src/lowlevel/tileset.rs index 5a13cba..5804138 100644 --- a/src/lowlevel/tileset.rs +++ b/src/lowlevel/tileset.rs @@ -1,5 +1,6 @@ -use crate::{ensure_element, ensure_tag_name, get_attribute}; -use anyhow::{anyhow, bail, Context}; +use crate::{ensure_element, ensure_tag_name, get_attribute, get_recommended_attribute}; +use anyhow::{anyhow, Context}; +use log::warn; use super::image::Image; use super::property::Properties; @@ -541,7 +542,7 @@ pub struct TileSet { pub version: Option, /// The name of this tileset. - pub name: String, + pub name: Option, /// The (maximum) width of the tiles in this tileset. pub tile_width: usize, @@ -554,11 +555,11 @@ pub struct TileSet { pub margin: usize, /// The number of tiles in this tileset (since 0.13) - pub tile_count: usize, + pub tile_count: Option, /// The number of tile columns in the tileset. /// For image collection tilesets it is editable and is used when displaying the tileset. (since 0.15) - pub columns: usize, + pub columns: Option, /// Controls the alignment for tile objects. /// Valid values are unspecified, topleft, top, topright, left, center, right, bottomleft, bottom and bottomright. @@ -672,69 +673,73 @@ impl TileSet { let tile_width = get_attribute!(node, "tilewidth")?.parse()?; let tile_height = get_attribute!(node, "tileheight")?.parse()?; - let tile_count: usize = match get_attribute!(node, "tilecount") { - Ok(tc_string) => tc_string.parse()?, + let tile_count: Option = match get_attribute!(node, "tilecount") { + Ok(tc_string) => Some(tc_string.parse()?), Err(err) => { if let Some(img) = &image { // there is no tilecount, but an image so we can guess/calculate the tilecount // TODO TEST for this if spacing != 0 { - bail!("tilecount not set, and calculationg it with spacing enabled is not implemented yet."); - } - - if let Some(image_width) = img.width { + warn!("tilecount not set, and calculationg it with spacing enabled is not implemented yet."); + None + } else if let Some(image_width) = img.width { if let Some(image_heigth) = img.height { let real_tile_with = tile_width + (margin * 2); let real_tile_height = tile_height + (margin * 2); let columns = image_width / real_tile_with; let rows = image_heigth / real_tile_height; - columns * rows + Some(columns * rows) } else { - bail!("tilecount not set, calculating failed: image has no height"); + warn!("tilecount not set, calculating failed: image has no height"); + None } } else { - bail!("tilecount not set, calculating failed: image has no width"); + warn!("tilecount not set, calculating failed: image has no width"); + None } } else { - return Err(err); + warn!("tilecount not set, calculating failed: no image"); + None } } }; - let columns: usize = match get_attribute!(node, "columns") { - Ok(c) => c.parse()?, + let columns: Option = match get_attribute!(node, "columns") { + Ok(c) => Some(c.parse()?), Err(err) => { if let Some(img) = &image { // there is no columns attribute, but an image so we can guess/calculate the columns // TODO TEST for this if spacing != 0 { - bail!("columns not set, and calculationg it with spacing enabled is not implemented yet."); - } - - if let Some(image_width) = img.width { + warn!("columns not set, and calculationg it with spacing enabled is not implemented yet."); + None + } else if let Some(image_width) = img.width { if let Some(image_heigth) = img.height { let real_tile_with = tile_width + (margin * 2); let real_tile_height = tile_height + (margin * 2); let columns = image_width / real_tile_with; let rows = image_heigth / real_tile_height; - columns * rows + Some(columns * rows) } else { - bail!("columns not set, calculating failed: image has no height"); + warn!("columns not set, calculating failed: image has no height"); + None } } else { - bail!("columns not set, calculating failed: image has no width"); + warn!("columns not set, calculating failed: image has no width"); + None } } else { - return Err(err); + warn!("columns not set, calculating failed: image has no width"); + None } } }; Ok(TileSet { version, - name: get_attribute!(node, "name")?.to_owned(), + name: get_recommended_attribute!(node, "name"), tile_width, tile_height, spacing, @@ -770,13 +775,13 @@ mod test_tileset { tile_set, TileSet { version: None, - name: "beach_tileset".to_owned(), + name: Some("beach_tileset".to_owned()), tile_width: 16, tile_height: 16, spacing: 0, margin: 0, - tile_count: 936, - columns: 36, + tile_count: Some(936), + columns: Some(36), object_alignment: ObjectAlignment::Unspecified, tile: vec![ Tile { @@ -894,7 +899,7 @@ mod test_tileset_element { first_gid: 1, tileset: TileSet { version: None, - name: "hex mini".to_owned(), + name: Some("hex mini".to_owned()), tile_width: 18, tile_height: 18, tile_offset: TileOffset { x: 0, y: 1 }, @@ -902,8 +907,8 @@ mod test_tileset_element { wangsets: vec![], spacing: 0, margin: 0, - tile_count: 20, - columns: 5, + tile_count: Some(20), + columns: Some(5), object_alignment: ObjectAlignment::default(), tile: vec![], image: Some(Image { -- cgit v1.2.3-60-g2f50