diff --git a/CHANGELOG.md b/CHANGELOG.md index 591a71d..237872e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased (0.12.2)] +## [0.13.0] +### Added +- Added a `source` member to `Tileset`, `Map` and `Template`, which stores the resource path they have been loaded from. (#303) +- Add `hex_side_length` member to `Map`. (#313) + ### Fixed - Fixed template instance size and position overrides in `ObjectData::shape`. (#309) diff --git a/Cargo.toml b/Cargo.toml index 2555d4b..d7ee648 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tiled" -version = "0.12.1" +version = "0.13.0" description = "A rust crate for loading maps created by the Tiled editor" categories = ["game-development"] keywords = ["gamedev", "tiled", "tmx", "map"] diff --git a/README.md b/README.md index e473b3d..62fb65b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # rs-tiled ```toml -tiled = "0.12.1" +tiled = "0.13.0" ``` [![Rust](https://github.com/mapeditor/rs-tiled/actions/workflows/rust.yml/badge.svg)](https://github.com/mapeditor/rs-tiled/actions/workflows/rust.yml) @@ -24,7 +24,7 @@ use tiled::Loader; fn main() { let mut loader = Loader::new(); - let map = loader.load_tmx_map("assets/tiled_base64_zlib.tmx").unwrap(); + let map = loader.load_tmx_map("assets/tiled_base64_external.tmx").unwrap(); println!("{:?}", map); println!("{:?}", map.tilesets()[0].get_tile(0).unwrap().probability); diff --git a/src/map.rs b/src/map.rs index 37b2503..d983dce 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,12 @@ //! Structures related to Tiled maps. -use std::{collections::HashMap, fmt, path::Path, str::FromStr, sync::Arc}; +use std::{ + collections::HashMap, + fmt, + path::{Path, PathBuf}, + str::FromStr, + sync::Arc, +}; use xml::attribute::OwnedAttribute; @@ -22,6 +28,8 @@ pub(crate) struct MapTilesetGid { #[derive(PartialEq, Clone)] pub struct Map { version: String, + /// The path first used in a [`ResourceReader`] to load this map. + pub source: PathBuf, /// The way tiles are laid out in the map. pub orientation: Orientation, /// Width of the map, in tiles. @@ -48,6 +56,8 @@ pub struct Map { /// individual tiles may have different sizes. As such, there is no guarantee that this value /// will be the same as the one from the tilesets the map is using. pub tile_height: u32, + /// The length of the side of a hexagonal tile in pixels (used by tile layers on hexagonal maps). + pub hex_side_length: Option, /// The stagger axis of Hexagonal/Staggered map. pub stagger_axis: StaggerAxis, /// The stagger index of Hexagonal/Staggered map. @@ -157,7 +167,7 @@ impl Map { cache: &mut impl ResourceCache, ) -> Result { let ( - (c, infinite, user_type, user_class, stagger_axis, stagger_index), + (c, infinite, user_type, user_class, stagger_axis, stagger_index, hex_side_length), (v, o, w, h, tw, th), ) = get_attrs!( for v in attrs { @@ -167,6 +177,7 @@ impl Map { Some("class") => user_class ?= v.parse(), Some("staggeraxis") => stagger_axis ?= v.parse::(), Some("staggerindex") => stagger_index ?= v.parse::(), + Some("hexsidelength") => hex_side_length ?= v.parse(), "version" => version = v, "orientation" => orientation ?= v.parse::(), "width" => width ?= v.parse::(), @@ -174,7 +185,7 @@ impl Map { "tilewidth" => tile_width ?= v.parse::(), "tileheight" => tile_height ?= v.parse::(), } - ((colour, infinite, user_type, user_class, stagger_axis, stagger_index), (version, orientation, width, height, tile_width, tile_height)) + ((colour, infinite, user_type, user_class, stagger_axis, stagger_index, hex_side_length), (version, orientation, width, height, tile_width, tile_height)) ); let infinite = infinite.unwrap_or(false); @@ -277,11 +288,13 @@ impl Map { Ok(Map { version: v, + source: map_path.to_owned(), orientation: o, width: w, height: h, tile_width: tw, tile_height: th, + hex_side_length, stagger_axis, stagger_index, tilesets, diff --git a/src/template.rs b/src/template.rs index 104178a..e774b9a 100644 --- a/src/template.rs +++ b/src/template.rs @@ -1,4 +1,4 @@ -use std::path::Path; +use std::path::{Path, PathBuf}; use std::sync::Arc; use xml::EventReader; @@ -15,6 +15,8 @@ use crate::{ /// maps. #[derive(Clone, Debug)] pub struct Template { + /// The path first used in a [`ResourceReader`] to load this template. + pub source: PathBuf, /// The tileset this template contains a reference to pub tileset: Option>, /// The object data for this template @@ -102,6 +104,10 @@ impl Template { let object = object.ok_or(Error::TemplateHasNoObject)?; - Ok(Arc::new(Template { tileset, object })) + Ok(Arc::new(Template { + source: template_path.to_owned(), + tileset, + object, + })) } } diff --git a/src/tileset.rs b/src/tileset.rs index 4218ba5..c478943 100644 --- a/src/tileset.rs +++ b/src/tileset.rs @@ -17,6 +17,10 @@ pub use wangset::*; /// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tileset). #[derive(Debug, PartialEq, Clone)] pub struct Tileset { + /// The path first used in a [`ResourceReader`] to load this tileset. + /// + /// For embedded tilesets, this path will be the same as the template or map's source. + pub source: PathBuf, /// The name of the tileset, set by the user. pub name: String, /// The (maximum) width in pixels of the tiles in this tileset. Irrelevant for [image collection] @@ -157,6 +161,7 @@ impl Tileset { Self::finish_parsing_xml( parser, + path.to_owned(), TilesetProperties { spacing, margin, @@ -227,6 +232,7 @@ impl Tileset { Self::finish_parsing_xml( parser, + path.to_owned(), TilesetProperties { spacing, margin, @@ -245,6 +251,7 @@ impl Tileset { fn finish_parsing_xml( parser: &mut impl Iterator, + container_path: PathBuf, prop: TilesetProperties, reader: &mut impl ResourceReader, cache: &mut impl ResourceCache, @@ -303,6 +310,7 @@ impl Tileset { .unwrap_or_else(|| Self::calculate_columns(&image, prop.tile_width, margin, spacing))?; Ok(Tileset { + source: container_path, name: prop.name, user_type: prop.user_type, tile_width: prop.tile_width, diff --git a/tests/lib.rs b/tests/lib.rs index f190049..a07c66a 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -12,7 +12,7 @@ fn as_finite<'map>(data: TileLayer<'map>) -> FiniteTileLayer<'map> { } } -fn compare_everything_but_tileset_sources(r: &Map, e: &Map) { +fn compare_everything_but_sources(r: &Map, e: &Map) { assert_eq!(r.version(), e.version()); assert_eq!(r.orientation, e.orientation); assert_eq!(r.width, e.width); @@ -39,10 +39,10 @@ fn test_gzip_and_zlib_encoded_and_raw_are_the_same() { .load_tmx_map("assets/tiled_base64_zstandard.tmx") .unwrap(); let c = Loader::new().load_tmx_map("assets/tiled_csv.tmx").unwrap(); - compare_everything_but_tileset_sources(&z, &g); - compare_everything_but_tileset_sources(&z, &r); - compare_everything_but_tileset_sources(&z, &c); - compare_everything_but_tileset_sources(&z, &zstd); + compare_everything_but_sources(&z, &g); + compare_everything_but_sources(&z, &r); + compare_everything_but_sources(&z, &c); + compare_everything_but_sources(&z, &zstd); let layer = as_finite(c.get_layer(0).unwrap().as_tile_layer().unwrap()); { @@ -65,11 +65,11 @@ fn test_external_tileset() { let e = loader .load_tmx_map("assets/tiled_base64_external.tmx") .unwrap(); - compare_everything_but_tileset_sources(&r, &e); + compare_everything_but_sources(&r, &e); } #[test] -fn test_sources() { +fn test_cache() { let mut loader = Loader::new(); let e = loader .load_tmx_map("assets/tiled_base64_external.tmx") @@ -84,6 +84,40 @@ fn test_sources() { ); } +#[test] +fn test_external_sources() { + let mut loader = Loader::new(); + let e = loader + .load_tmx_map("assets/tiled_base64_external.tmx") + .unwrap(); + assert_eq!(e.source, PathBuf::from("assets/tiled_base64_external.tmx")); + assert_eq!( + e.tilesets()[0].source, + PathBuf::from("assets/tilesheet.tsx") + ); + + let e = loader + .load_tmx_map("assets/tiled_object_template.tmx") + .unwrap(); + assert_eq!(e.source, PathBuf::from("assets/tiled_object_template.tmx")); + assert_eq!( + loader.cache().templates.values().next().unwrap().source, + PathBuf::from("assets/tiled_object_template.tx") + ); +} + +#[test] +fn test_embedded_sources() { + let mut loader = Loader::new(); + let e = loader.load_tmx_map("assets/tiled_base64_gzip.tmx").unwrap(); + + assert_eq!(e.source, PathBuf::from("assets/tiled_base64_gzip.tmx")); + assert_eq!( + e.tilesets()[0].source, + PathBuf::from("assets/tiled_base64_gzip.tmx") + ); +} + #[test] fn test_just_tileset() { let mut loader = Loader::new();