diff --git a/README.md b/README.md index 33eae93c5ffbe0fa7d458733bbb624f2c79d86d5..05157f14a27fe70d08f3400d7515dc15dc94746d 100644 --- a/README.md +++ b/README.md @@ -1,36 +1,39 @@ # rs-tiled +```toml +tiled = "0.9.5" +``` [](https://github.com/mapeditor/rs-tiled/actions/workflows/rust.yml) [](https://crates.io/crates/tiled) -Read maps from the [Tiled Map Editor](http://www.mapeditor.org/) into rust for use in video games. It is game engine agnostic and pretty barebones at the moment. Documentation is available [on docs.rs](https://docs.rs/tiled/). - -Code contributions are welcome as are bug reports, documentation, suggestions and criticism. - -[There is a package on crates.io](https://crates.io/crates/tiled), to use simply add: +A crate for reading TMX (map) and TSX (tileset) files from the [Tiled Map Editor](http://www.mapeditor.org/) into Rust. +It provides a huge set of features as well as a strong wrapper over internal features such as GIDs. -``` -tiled = "0.9.5" -``` +Documentation is available [on docs.rs](https://docs.rs/tiled/). -to the dependencies section of your Cargo.toml. +Code contributions are welcome as are bug reports, documentation, suggestions and criticism. The minimum supported TMX version is 0.13. ### Example ```rust -use tiled::Map; +use tiled::{FilesystemResourceCache, Map}; fn main() { - let map = Map::parse_file("assets/tiled_base64_zlib.tmx").unwrap(); + let map = Map::parse_file( + "assets/tiled_base64_zlib.tmx", + &mut FilesystemResourceCache::new(), + ) + .unwrap(); println!("{:?}", map); - println!("{:?}", map.tileset_by_gid(22)); + println!("{:?}", map.tilesets()[0].get_tile(0).unwrap().probability()); } + ``` ### Licences -assets/tilesheet.png by Buch (https://opengameart.org/content/sci-fi-interior-tiles) +assets/tilesheet.png by [Buch](https://opengameart.org/content/sci-fi-interior-tiles) Licenced under MIT diff --git a/src/animation.rs b/src/animation.rs index 691b53196a603350fb8974594f361b6b16bbf996..cb8d55e3b0088b88e2460ae202d746fee1e59119 100644 --- a/src/animation.rs +++ b/src/animation.rs @@ -1,10 +1,21 @@ +//! Structures related to tile animations. + use xml::attribute::OwnedAttribute; -use crate::{error::TiledError, util::{get_attrs, XmlEventResult, parse_tag}}; +use crate::{ + error::TiledError, + util::{get_attrs, parse_tag, XmlEventResult}, +}; +/// A structure describing a [frame] of a [TMX tile animation]. +/// +/// [frame]: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-frame +/// [TMX tile animation]: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#animation #[derive(Debug, PartialEq, Clone, Copy)] pub struct Frame { + /// The local ID of a tile within the parent tileset. pub tile_id: u32, + /// How long (in milliseconds) this frame should be displayed before advancing to the next frame. pub duration: u32, } @@ -26,7 +37,6 @@ impl Frame { } } - pub(crate) fn parse_animation( parser: &mut impl Iterator<Item = XmlEventResult>, ) -> Result<Vec<Frame>, TiledError> { @@ -38,4 +48,4 @@ pub(crate) fn parse_animation( }, }); Ok(animation) -} \ No newline at end of file +} diff --git a/src/cache.rs b/src/cache.rs index a193a1ae070074f69223431086829bd0c4d54ba4..5c4a3303a922e253efd60d8e9e46ddf36e19f422 100644 --- a/src/cache.rs +++ b/src/cache.rs @@ -6,11 +6,37 @@ use std::{ use crate::Tileset; +/// A reference type that is used to refer to a resource. For the owned variant, see [`ResourcePathBuf`]. pub type ResourcePath = Path; +/// An owned type that is used to refer to a resource. For the non-owned variant, see [`ResourcePath`]. pub type ResourcePathBuf = PathBuf; +/// A trait identifying a data type that holds resources (such as tilesets) and maps them to a +/// [`ResourcePath`] to prevent loading them more than once. pub trait ResourceCache { + /// Obtains a tileset from the cache, if it exists. + /// + /// # Example + /// ``` + /// use std::fs::File; + /// use tiled::{FilesystemResourceCache, ResourceCache, Tileset}; + /// # use tiled::TiledError; + /// # fn main() -> Result<(), TiledError> { + /// let mut cache = FilesystemResourceCache::new(); + /// let path = "assets/tilesheet.tsx"; + /// + /// assert!(cache.get_tileset(path).is_none()); + /// cache.get_or_try_insert_tileset_with(path.to_owned().into(), || Tileset::parse_reader(File::open(path).unwrap(), path))?; + /// assert!(cache.get_tileset(path).is_some()); + /// # Ok(()) + /// # } + /// ``` fn get_tileset(&self, path: impl AsRef<ResourcePath>) -> Option<Arc<Tileset>>; + + /// Returns the tileset mapped to `path` if it exists, otherwise calls `f` and, depending on its + /// result, it will: + /// - Insert the object into the cache, if the result was [`Ok`]. + /// - Return the error and leave the cache intact, if the result was [`Err`]. fn get_or_try_insert_tileset_with<F, E>( &mut self, path: ResourcePathBuf, @@ -27,6 +53,7 @@ pub struct FilesystemResourceCache { } impl FilesystemResourceCache { + /// Creates an empty [`FilesystemResourceCache`]. pub fn new() -> Self { Self { tilesets: HashMap::new(), diff --git a/src/error.rs b/src/error.rs index 3a4e83462723af021122b7211a6cd6f9d057c334..1848dbfba3f9509fa4718ce72994a109a3373c28 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,30 +10,44 @@ pub enum TiledError { /// An error occured when decompressing using the /// [flate2](https://github.com/alexcrichton/flate2-rs) crate. DecompressingError(std::io::Error), + /// An error occured when decoding a base64 encoded dataset. Base64DecodingError(base64::DecodeError), + /// An error occured when parsing a XML file, such as a TMX or TSX file. XmlDecodingError(xml::reader::Error), + /// The XML stream ended before the document was fully parsed. PrematureEnd(String), /// The path given is invalid because it isn't contained in any folder. PathIsNotFile, + /// Could not open some file due to an I/O error. CouldNotOpenFile { + /// The path to the file that was unable to be opened. path: PathBuf, + /// The error that occured when trying to open the file. err: std::io::Error, }, /// There was an invalid tile in the map parsed. InvalidTileFound, /// Unknown encoding or compression format or invalid combination of both (for tile layers) InvalidEncodingFormat { + /// The `encoding` attribute of the tile layer data, if any. encoding: Option<String>, + /// The `compression` attribute of the tile layer data, if any. compression: Option<String>, }, /// There was an error parsing the value of a [`PropertyValue`]. /// /// [`PropertyValue`]: crate::PropertyValue - InvalidPropertyValue{description: String}, + InvalidPropertyValue { + /// A description of the error that occured. + description: String + }, /// Found an unknown property value type while parsing a [`PropertyValue`]. /// /// [`PropertyValue`]: crate::PropertyValue - UnknownPropertyType{name: String}, + UnknownPropertyType { + /// The name of the property whose value type is unknown. + name: String + }, } impl fmt::Display for TiledError { diff --git a/src/image.rs b/src/image.rs index 7399f380e8d2dfdb1921a2b9ec2d8d9e4ba73737..c22b57ad70215f4b71e603aac77ecdd08b8a29fe 100644 --- a/src/image.rs +++ b/src/image.rs @@ -4,6 +4,7 @@ use xml::attribute::OwnedAttribute; use crate::{error::TiledError, properties::Color, util::*}; +/// A reference to an image stored somewhere within the filesystem. #[derive(Debug, PartialEq, Eq, Clone)] pub struct Image { /// The filepath of the image. @@ -15,8 +16,11 @@ pub struct Image { /// [source]: https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#image // TODO: Embedded images pub source: PathBuf, + /// The width in pixels of the image. pub width: i32, + /// The height in pixels of the image. pub height: i32, + /// A color that should be interpreted as transparent (0 alpha), if any. pub transparent_colour: Option<Color>, } diff --git a/src/layers/group.rs b/src/layers/group.rs index f4d135d260c8894591baf99c532945310e14dcf9..0a4d8d25f6b936165f066c9ebdafc7fc8cacd64e 100644 --- a/src/layers/group.rs +++ b/src/layers/group.rs @@ -78,12 +78,21 @@ impl GroupLayerData { } } -map_wrapper!(GroupLayer => GroupLayerData); +map_wrapper!( + #[doc = "A group layer, used to organize the layers of the map in a hierarchy."] + #[doc = "\nAlso see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#group)."] + #[doc = "## Note"] + #[doc = "In Tiled, the properties of the group layer recursively affect child layers. + Implementing this behavior is left up to the user of this library."] + GroupLayer => GroupLayerData +); impl<'map> GroupLayer<'map> { + /// Returns an iterator over the layers present in this group in display order. pub fn layers(&self) -> GroupLayerIter { GroupLayerIter::new(self.map, self.data) } + /// Gets a specific layer from the group by index. pub fn get_layer(&self, index: usize) -> Option<Layer> { self.data .layers diff --git a/src/layers/image.rs b/src/layers/image.rs index e75a92b0d367bca11591e9d09726bbcc49107b38..d8c8ae8d515e5fa4c3b0a34615f6bd84bd914cb2 100644 --- a/src/layers/image.rs +++ b/src/layers/image.rs @@ -35,7 +35,11 @@ impl ImageLayerData { } } -map_wrapper!(ImageLayer => ImageLayerData); +map_wrapper!( + #[doc = "A layer consisting of a single image."] + #[doc = "\nAlso see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#imagelayer)."] + ImageLayer => ImageLayerData +); impl<'map> ImageLayer<'map> { /// Get a reference to the image layer's image. diff --git a/src/layers/mod.rs b/src/layers/mod.rs index b0b006907f5ff85a39a7e035fea76c1a095825df..56db87e61b06901892d9553c9ba3459f9a220870 100644 --- a/src/layers/mod.rs +++ b/src/layers/mod.rs @@ -110,7 +110,10 @@ impl LayerData { } } -map_wrapper!(Layer => LayerData); +map_wrapper!( + #[doc = "A generic map layer, accessed via [`Map::layers()`]."] + Layer => LayerData +); impl<'map> Layer<'map> { /// Get a reference to the layer's name. @@ -180,11 +183,16 @@ impl<'map> Layer<'map> { } } +/// Represents some kind of map layer. #[derive(Debug)] pub enum LayerType<'map> { + /// A tile layer; Also see [`TileLayer`]. TileLayer(TileLayer<'map>), + /// An object layer (also called object group); Also see [`ObjectLayer`]. ObjectLayer(ObjectLayer<'map>), + /// An image layer; Also see [`ImageLayer`]. ImageLayer(ImageLayer<'map>), + /// A group layer; Also see [`GroupLayer`]. GroupLayer(GroupLayer<'map>), } diff --git a/src/layers/object.rs b/src/layers/object.rs index c7265956286abdf340c24971ab5b34cc8b3ef3b3..500c7f6f4b039d530d658fdd3cbaf035827d148c 100644 --- a/src/layers/object.rs +++ b/src/layers/object.rs @@ -11,7 +11,9 @@ use crate::{ /// Raw data referring to a map object layer or tile collision data. #[derive(Debug, PartialEq, Clone)] pub struct ObjectLayerData { + /// The objects present in this layer. pub objects: Vec<ObjectData>, + /// The color used in the editor to display objects in this layer. pub colour: Option<Color>, } @@ -48,9 +50,12 @@ impl ObjectLayerData { } } -map_wrapper!(ObjectLayer => ObjectLayerData); +map_wrapper!( + #[doc = "Also called an \"object group\". Used for storing [`Object`]s in a map."] + ObjectLayer => ObjectLayerData); impl<'map> ObjectLayer<'map> { + /// Obtains the object corresponding to the index given. pub fn get_object(&self, idx: usize) -> Option<Object<'map>> { self.data .objects @@ -58,9 +63,16 @@ impl<'map> ObjectLayer<'map> { .map(|data| Object::new(self.map, data)) } + /// Returns an iterator over the objects present in this layer, in the order they were declared + /// in in the TMX file. pub fn objects(&self) -> Objects<'map> { Objects::new(self.map, self.data) } + + /// Get a reference to the object layer's colour. + pub fn colour(&self) -> Option<Color> { + self.data.colour + } } /// An iterator that iterates over all the objects in an object layer, obtained via [`ObjectLayer::objects`]. diff --git a/src/layers/tile/finite.rs b/src/layers/tile/finite.rs index 2e2c0cc30d987973ab4a829f58ad88ca6a166437..e76eabe8fa241b63c03a2de7aa54d45cb2cf8353 100644 --- a/src/layers/tile/finite.rs +++ b/src/layers/tile/finite.rs @@ -60,9 +60,15 @@ impl FiniteTileLayerData { } } -map_wrapper!(FiniteTileLayer => FiniteTileLayerData); +map_wrapper!( + #[doc = "A [`TileLayer`](super::TileLayer) with a defined bound (width and height)."] + FiniteTileLayer => FiniteTileLayerData +); impl<'map> FiniteTileLayer<'map> { + /// Obtains the tile present at the position given. + /// + /// If the position given is invalid or the position is empty, this function will return [`None`]. pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> { self.data .get_tile(x, y) diff --git a/src/layers/tile/infinite.rs b/src/layers/tile/infinite.rs index 96c8f67b552d10e91dc3d72f755eba98e7d09ca0..f7d70fcdddc1499f90ef70aa94d51ce36d969d01 100644 --- a/src/layers/tile/infinite.rs +++ b/src/layers/tile/infinite.rs @@ -4,7 +4,7 @@ use xml::attribute::OwnedAttribute; use crate::{ util::{floor_div, get_attrs, map_wrapper, parse_tag, XmlEventResult}, - LayerTile, LayerTileData, MapTilesetGid, TiledError, + LayerTile, LayerTileData, MapTilesetGid, TiledError, }; use super::util::parse_data_line; @@ -81,14 +81,21 @@ fn tile_to_chunk_pos(x: i32, y: i32) -> (i32, i32) { ) } +/// Part of an infinite tile layer. #[derive(Debug, PartialEq, Clone)] pub struct Chunk { tiles: Box<[Option<LayerTileData>; Self::TILE_COUNT]>, } impl Chunk { + /// Internal infinite layer chunk width. Do not rely on this value as it might change between + /// versions. pub const WIDTH: u32 = 16; + /// Internal infinite layer chunk height. Do not rely on this value as it might change between + /// versions. pub const HEIGHT: u32 = 16; + /// Internal infinite layer chunk tile count. Do not rely on this value as it might change + /// between versions. pub const TILE_COUNT: usize = Self::WIDTH as usize * Self::HEIGHT as usize; pub(crate) fn new() -> Self { @@ -143,9 +150,15 @@ impl InternalChunk { } } -map_wrapper!(InfiniteTileLayer => InfiniteTileLayerData); +map_wrapper!( + #[doc = "A [`TileLayer`](super::TileLayer) with no bounds, internally stored using [`Chunk`]s."] + InfiniteTileLayer => InfiniteTileLayerData +); impl<'map> InfiniteTileLayer<'map> { + /// Obtains the tile present at the position given. + /// + /// If the position is empty, this function will return [`None`]. pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> { self.data .get_tile(x, y) diff --git a/src/layers/tile/mod.rs b/src/layers/tile/mod.rs index 5c3d27aa8d30d78f557f68afae36553035be418c..02577527dc9c6181c76e0431a46c31d1227aee76 100644 --- a/src/layers/tile/mod.rs +++ b/src/layers/tile/mod.rs @@ -106,7 +106,10 @@ impl TileLayerData { } } -map_wrapper!(LayerTile => LayerTileData); +map_wrapper!( + #[doc = "An instance of a [`Tile`] present in a [`TileLayer`]."] + LayerTile => LayerTileData +); impl<'map> LayerTile<'map> { /// Get a reference to the layer tile's referenced tile, if it exists. @@ -155,9 +158,12 @@ impl<'map> LayerTile<'map> { } } +/// A map layer containing tiles in some way. May be finite or infinite. #[derive(Debug)] pub enum TileLayer<'map> { + /// An finite tile layer; Also see [`FiniteTileLayer`]. Finite(FiniteTileLayer<'map>), + /// An infinite tile layer; Also see [`InfiniteTileLayer`]. Infinite(InfiniteTileLayer<'map>), } @@ -169,6 +175,9 @@ impl<'map> TileLayer<'map> { } } + /// Obtains the tile present at the position given. + /// + /// If the position given is invalid or the position is empty, this function will return [`None`]. pub fn get_tile(&self, x: i32, y: i32) -> Option<LayerTile> { match self { TileLayer::Finite(finite) => finite.get_tile(x, y), diff --git a/src/lib.rs b/src/lib.rs index 0ec71af99d21dc2329c78bc14c52b511b50ad32c..306008646a16dba8e897ee78d70c0349c0d7c338 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,6 @@ +#![doc = include_str!("../README.md")] +#![deny(missing_docs)] +#![deny(rustdoc::broken_intra_doc_links)] #![deny(unsafe_code)] #![deny(missing_copy_implementations)] #![deny(missing_debug_implementations)] diff --git a/src/map.rs b/src/map.rs index dcedbb2a0988004b0e6cc3c0b8296e67225ba09e..96dc9f064b41cf94746f72c8f28f24b208bed5d9 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,3 +1,5 @@ +//! Structures related to Tiled maps. + use std::{collections::HashMap, fmt, fs::File, io::Read, path::Path, str::FromStr, sync::Arc}; use xml::{attribute::OwnedAttribute, reader::XmlEvent, EventReader}; @@ -21,6 +23,7 @@ pub(crate) struct MapTilesetGid { pub struct Map { /// The TMX format version this map was saved to. pub version: String, + /// The way tiles are laid out in the map. pub orientation: Orientation, /// Width of the map, in tiles. pub width: u32, @@ -38,6 +41,8 @@ pub struct Map { pub properties: Properties, /// The background color of this map, if any. pub background_color: Option<Color>, + /// Whether this map is infinite. An infinite map has no fixed size and can grow in all + /// directions. Its layer data is stored in chunks. pub infinite: bool, } @@ -263,6 +268,7 @@ impl Map { /// Represents the way tiles are laid out in a map. #[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[allow(missing_docs)] pub enum Orientation { Orthogonal, Isometric, diff --git a/src/objects.rs b/src/objects.rs index 062270a5784867468e07cdbe4de2e10b8068fd54..55c5a7032fa9a0293c05595f0085e622a2e6a9c8 100644 --- a/src/objects.rs +++ b/src/objects.rs @@ -9,7 +9,11 @@ use crate::{ LayerTile, LayerTileData, MapTilesetGid, }; +/// A structure describing an [`Object`]'s shape. +/// +/// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-object). #[derive(Debug, PartialEq, Clone)] +#[allow(missing_docs)] pub enum ObjectShape { Rect { width: f32, height: f32 }, Ellipse { width: f32, height: f32 }, @@ -19,19 +23,40 @@ pub enum ObjectShape { } /// Raw data belonging to an object. Used internally and for tile collisions. +/// +/// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-object). #[derive(Debug, PartialEq, Clone)] pub struct ObjectData { + /// ID of the object, which is unique per map since Tiled 0.11. + /// + /// On older versions this value is defaulted to 0. pub id: u32, tile: Option<LayerTileData>, + /// The name of the object, which is arbitrary and set by the user. pub name: String, + /// The type of the object, which is arbitrary and set by the user. pub obj_type: String, + /// The width of the object, if applicable. This refers to the attribute in `object`. + /// Since it is duplicate or irrelevant information in all cases, use the equivalent + /// member in [`ObjectShape`] instead. + #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")] pub width: f32, + /// The height of the object, if applicable. This refers to the attribute in `object`. + /// Since it is duplicate or irrelevant information in all cases, use the equivalent + /// member in [`ObjectShape`] instead. + #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")] pub height: f32, + /// The X coordinate of this object in pixels. pub x: f32, + /// The Y coordinate of this object in pixels. pub y: f32, + /// The clockwise rotation of this object around (x,y) in degrees. pub rotation: f32, + /// Whether the object is shown or hidden. pub visible: bool, + /// The object's shape. pub shape: ObjectShape, + /// The object's custom properties set by the user. pub properties: Properties, } @@ -100,6 +125,7 @@ impl ObjectData { let shape = shape.unwrap_or(ObjectShape::Rect { width, height }); + #[allow(deprecated)] Ok(ObjectData { id, tile, @@ -168,10 +194,16 @@ impl ObjectData { } } -map_wrapper!(Object => ObjectData); +map_wrapper!( + #[doc = "Wrapper over an [`ObjectData`] that contains both a reference to the data as well as + to the map it is contained in."] + Object => ObjectData +); impl<'map> Object<'map> { - /// Get the object's id. + /// ID of the object, which is unique per map since Tiled 0.11. + /// + /// On older versions this value is defaulted to 0. #[inline] pub fn id(&self) -> u32 { self.data.id @@ -185,61 +217,69 @@ impl<'map> Object<'map> { .map(|tile| LayerTile::new(self.map, tile)) } - /// Get a reference to the object's name. + /// The name of the object, which is arbitrary and set by the user. #[inline] pub fn name(&self) -> &str { self.data.name.as_ref() } - /// Get a reference to the object's type. + /// The type of the object, which is arbitrary and set by the user. #[inline] pub fn obj_type(&self) -> &str { self.data.obj_type.as_ref() } - /// Get the object's width. + /// The width of the object, if applicable. This refers to the attribute in `object`. + /// Since it is duplicate or irrelevant information in all cases, use the equivalent + /// member in [`ObjectShape`] instead. + #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")] #[inline] pub fn width(&self) -> f32 { + #[allow(deprecated)] self.data.width } - /// Get the object's height. + /// The height of the object, if applicable. This refers to the attribute in `object`. + /// Since it is duplicate or irrelevant information in all cases, use the equivalent + /// member in [`ObjectShape`] instead. + #[deprecated(since = "0.10.0", note = "Use [`ObjectShape`] members instead")] #[inline] pub fn height(&self) -> f32 { + #[allow(deprecated)] self.data.height } - /// Get the object's x. + /// The X coordinate of this object in pixels. #[inline] pub fn x(&self) -> f32 { self.data.x } - /// Get object's y. + /// The Y coordinate of this object in pixels. #[inline] pub fn y(&self) -> f32 { self.data.y } - /// Get a reference to the object's rotation. + /// The clockwise rotation of this object around (x,y) in degrees. #[inline] pub fn rotation(&self) -> f32 { self.data.rotation } - /// Whether the object should be visible or not. + /// Whether the object is shown or hidden. #[inline] pub fn visible(&self) -> bool { self.data.visible } - /// Get a reference to the object's shape. + /// The object's shape. #[inline] pub fn shape(&self) -> &ObjectShape { &self.data.shape } - /// Get a reference to the object's properties. + /// The object's custom properties set by the user. #[inline] pub fn properties(&self) -> &Properties { &self.data.properties diff --git a/src/properties.rs b/src/properties.rs index 0625c2093a22148dac04fff1eab5a6aea76b0f38..7fda017f11d3fda1ec741a2915d468fe52e7b533 100644 --- a/src/properties.rs +++ b/src/properties.rs @@ -7,7 +7,9 @@ use crate::{ util::{get_attrs, parse_tag, XmlEventResult}, }; +/// Represents a RGBA color with 8-bit depth on each channel. #[derive(Debug, PartialEq, Eq, Copy, Clone)] +#[allow(missing_docs)] pub struct Color { pub alpha: u8, pub red: u8, @@ -55,16 +57,26 @@ impl FromStr for Color { } } +/// Represents a custom property's value. +/// +/// Also read the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tmx-properties). #[derive(Debug, PartialEq, Clone)] pub enum PropertyValue { + /// A boolean value. Corresponds to the `bool` property type. BoolValue(bool), + /// A floating point value. Corresponds to the `float` property type. FloatValue(f32), + /// A signed integer value. Corresponds to the `int` property type. IntValue(i32), + /// A color value. Corresponds to the `color` property type. ColorValue(u32), + /// A string value. Corresponds to the `string` property type. StringValue(String), - /// Holds the path relative to the map or tileset + /// A filepath value. Corresponds to the `file` property type. + /// Holds the path relative to the map or tileset. FileValue(String), - /// Holds the id of a referenced object, or 0 if unset + /// An object ID value. Corresponds to the `object` property type. + /// Holds the id of a referenced object, or 0 if unset. ObjectValue(u32), } @@ -111,6 +123,7 @@ impl PropertyValue { } } +/// A custom property container. pub type Properties = HashMap<String, PropertyValue>; pub(crate) fn parse_properties( diff --git a/src/tile.rs b/src/tile.rs index 4ef80dbc39f58cdc536b35fc36953a401044304e..5563d647a3ae72b290bc5917cc90aa9a7306aef1 100644 --- a/src/tile.rs +++ b/src/tile.rs @@ -12,6 +12,7 @@ use crate::{ Tileset, }; +/// A tile ID, local to a tileset. pub type TileId = u32; #[derive(Debug, PartialEq, Clone, Default)] @@ -24,6 +25,7 @@ pub(crate) struct TileData { probability: f32, } +/// Points to a tile belonging to a tileset. #[derive(Debug)] pub struct Tile<'tileset> { pub(crate) tileset: &'tileset Tileset, diff --git a/src/tileset.rs b/src/tileset.rs index 8745a80066b47d6e8d9ea88e298094b0980aa80a..3c6a3edeb4298cea598512429c1f427065d68c19 100644 --- a/src/tileset.rs +++ b/src/tileset.rs @@ -12,15 +12,35 @@ use crate::properties::{parse_properties, Properties}; use crate::tile::TileData; use crate::{util::*, Gid, Tile}; -/// A tileset, usually the tilesheet image. +/// A collection of tiles for usage in maps and template objects. +/// +/// Also see the [TMX docs](https://doc.mapeditor.org/en/stable/reference/tmx-map-format/#tileset). #[derive(Debug, PartialEq, Clone)] pub struct Tileset { + /// 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] + /// tilesets. + /// + /// [image collection]: Self::image pub tile_width: u32, + /// The (maximum) height in pixels of the tiles in this tileset. Irrelevant for [image collection] + /// tilesets. + /// + /// [image collection]: Self::image pub tile_height: u32, + /// The spacing in pixels between the tiles in this tileset (applies to the tileset image). + /// Irrelevant for image collection tilesets. pub spacing: u32, + /// The margin around the tiles in this tileset (applies to the tileset image). + /// Irrelevant for image collection tilesets. pub margin: u32, + /// The number of tiles in this tileset. Note that tile IDs don't always have a connection with + /// the tile count, and as such there may be tiles with an ID bigger than the tile count. pub tilecount: u32, + /// The number of tile columns in the tileset. Editable for image collection tilesets, otherwise + /// calculated using [image](Self::image) width, [tile width](Self::tile_width), + /// [spacing](Self::spacing) and [margin](Self::margin). pub columns: u32, /// A tileset can either: diff --git a/src/util.rs b/src/util.rs index dadad0cf58523561fc5e9ef5125a76b0bdddd9be..8ea280300b7ea24900705dd7e498bd5df6bb7e2a 100644 --- a/src/util.rs +++ b/src/util.rs @@ -54,8 +54,9 @@ macro_rules! parse_tag { /// Creates a new type that wraps an internal data type over along with a map. macro_rules! map_wrapper { - ($name:ident => $data_ty:ty) => { + ($(#[$attrs:meta])* $name:ident => $data_ty:ty) => { #[derive(Clone, Copy, PartialEq, Debug)] + $(#[$attrs])* pub struct $name<'map> { pub(crate) map: &'map $crate::Map, pub(crate) data: &'map $data_ty,