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 --- Cargo.lock | 53 ------------------------------------- Cargo.toml | 3 ++- src/lowlevel/macros.rs | 15 +++++++++++ src/lowlevel/tileset.rs | 69 ++++++++++++++++++++++++++----------------------- 4 files changed, 54 insertions(+), 86 deletions(-) delete mode 100644 Cargo.lock diff --git a/Cargo.lock b/Cargo.lock deleted file mode 100644 index 3df5c0d..0000000 --- a/Cargo.lock +++ /dev/null @@ -1,53 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "anyhow" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" - -[[package]] -name = "bytemuck" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bed57e2090563b83ba8f83366628ce535a7584c9afa4c9fc0612a03925c6df58" - -[[package]] -name = "fast-tiled" -version = "0.1.0" -dependencies = [ - "anyhow", - "read_color", - "rgb", - "roxmltree", -] - -[[package]] -name = "read_color" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f4c8858baa4ad3c8bcc156ae91a0ffe22b76a3975c40c49b4f04c15c6bce0da" - -[[package]] -name = "rgb" -version = "0.8.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fddb3b23626145d1776addfc307e1a1851f60ef6ca64f376bcb889697144cf0" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "roxmltree" -version = "0.14.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "921904a62e410e37e215c40381b7117f830d9d89ba60ab5236170541dd25646b" -dependencies = [ - "xmlparser", -] - -[[package]] -name = "xmlparser" -version = "0.13.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "114ba2b24d2167ef6d67d7d04c8cc86522b87f490025f39f0303b7db5bf5e3d8" diff --git a/Cargo.toml b/Cargo.toml index f4267e6..62a0304 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,5 @@ edition = "2018" anyhow = "1.0.40" rgb = "0.8.27" roxmltree = "0.14.1" -read_color = "1.0.0" \ No newline at end of file +read_color = "1.0.0" +log = "0.4.16" 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