diff --git a/CHANGELOG.md b/CHANGELOG.md index 83a04f3f62dae193e9ff485f06556b1f254dd64e..fbbe474b8760890f3f2b37efae481686c0fc9a76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - `Tileset::source` for obtaining where the tileset actually came from. - `Tileset::columns`. +- `Color::alpha`. - `Layer::id`, `Layer::width`, `Layer::height`, `Layer::parallax_x` and `Layer::parallax_y`. - Support for 'object'-type properties. - Support for multiline string properties. @@ -39,6 +40,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bumped `zstd` to `0.9`. - Fixed markdown formatting in the `CONTRIBUTORS` file. +### Fixed +- `Color` parsing. + + ## [0.9.5] - 2021-05-02 ### Added - Support for file properties. diff --git a/assets/tiled_image_layers.tmx b/assets/tiled_image_layers.tmx index 6ee077b43fe7a1044a738347f995040f72f6c034..6c3128ffc854273fa71b16f90d56996cc97fb0b9 100644 --- a/assets/tiled_image_layers.tmx +++ b/assets/tiled_image_layers.tmx @@ -3,8 +3,8 @@ <tileset firstgid="1" name="tilesheet" tilewidth="32" tileheight="32" tilecount="84" columns="14"> <image source="tilesheet.png" width="448" height="192"/> </tileset> - <imagelayer id="1" name="Image Layer 1"/> - <imagelayer id="2" name="Image Layer 2"> + <imagelayer id="1" name="Image Layer 1" tintcolor="#12345678"/> + <imagelayer id="2" name="Image Layer 2" tintcolor="123456"> <image source="tilesheet.png" width="448" height="192"/> </imagelayer> </map> diff --git a/src/layers.rs b/src/layers.rs index b5c0b653a8064a0029a1731567b63abd66370ad8..e75f345759ddf3f182f9b8195167c3a4f3b11ba9 100644 --- a/src/layers.rs +++ b/src/layers.rs @@ -68,6 +68,7 @@ pub struct Layer { pub parallax_x: f32, pub parallax_y: f32, pub opacity: f32, + pub tint_color: Option<Color>, pub properties: Properties, pub layer_type: LayerType, } @@ -80,10 +81,14 @@ impl Layer { infinite: bool, path_relative_to: Option<&Path>, ) -> Result<Self, TiledError> { - let ((opacity, visible, offset_x, offset_y, parallax_x, parallax_y, name, id), ()) = get_attrs!( + let ( + (opacity, tint_color, visible, offset_x, offset_y, parallax_x, parallax_y, name, id), + (), + ) = get_attrs!( attrs, optionals: [ ("opacity", opacity, |v:String| v.parse().ok()), + ("tintcolor", tint_color, |v:String| v.parse().ok()), ("visible", visible, |v:String| v.parse().ok().map(|x:i32| x == 1)), ("offsetx", offset_x, |v:String| v.parse().ok()), ("offsety", offset_y, |v:String| v.parse().ok()), @@ -120,6 +125,7 @@ impl Layer { parallax_x: parallax_x.unwrap_or(1.0), parallax_y: parallax_y.unwrap_or(1.0), opacity: opacity.unwrap_or(1.0), + tint_color, name: name.unwrap_or_default(), id: id.unwrap_or(0), properties, diff --git a/src/properties.rs b/src/properties.rs index 7e8c0bd995e5675785f61216a2f3b1bd739ab481..949046c9d9054e63294287d447802dfbfcadbf4b 100644 --- a/src/properties.rs +++ b/src/properties.rs @@ -1,38 +1,57 @@ use std::{collections::HashMap, io::Read, str::FromStr}; -use xml::{EventReader, attribute::OwnedAttribute, reader::XmlEvent}; +use xml::{attribute::OwnedAttribute, reader::XmlEvent, EventReader}; use crate::{ - error::{ParseTileError, TiledError}, + error::TiledError, util::{get_attrs, parse_tag}, }; #[derive(Debug, PartialEq, Eq, Copy, Clone)] pub struct Color { + pub alpha: u8, pub red: u8, pub green: u8, pub blue: u8, } impl FromStr for Color { - type Err = ParseTileError; + type Err = (); - fn from_str(s: &str) -> Result<Color, ParseTileError> { + fn from_str(s: &str) -> Result<Color, Self::Err> { let s = if s.starts_with("#") { &s[1..] } else { s }; - if s.len() != 6 { - return Err(ParseTileError::ColorError); - } - let r = u8::from_str_radix(&s[0..2], 16); - let g = u8::from_str_radix(&s[2..4], 16); - let b = u8::from_str_radix(&s[4..6], 16); - if r.is_ok() && g.is_ok() && b.is_ok() { - return Ok(Color { - red: r.unwrap(), - green: g.unwrap(), - blue: b.unwrap(), - }); + match s.len() { + 6 => { + let r = u8::from_str_radix(&s[0..2], 16); + let g = u8::from_str_radix(&s[2..4], 16); + let b = u8::from_str_radix(&s[4..6], 16); + match (r, g, b) { + (Ok(red), Ok(green), Ok(blue)) => Ok(Color { + alpha: 0xFF, + red, + green, + blue, + }), + _ => Err(()), + } + } + 8 => { + let a = u8::from_str_radix(&s[0..2], 16); + let r = u8::from_str_radix(&s[2..4], 16); + let g = u8::from_str_radix(&s[4..6], 16); + let b = u8::from_str_radix(&s[6..8], 16); + match (a, r, g, b) { + (Ok(alpha), Ok(red), Ok(green), Ok(blue)) => Ok(Color { + alpha, + red, + green, + blue, + }), + _ => Err(()), + } + } + _ => Err(()), } - Err(ParseTileError::ColorError) } } @@ -105,7 +124,7 @@ pub(crate) fn parse_properties<R: Read>( TiledError::MalformedAttributes("property must have a name and a value".to_string()) ); let t = t.unwrap_or("string".into()); - + let v = match v_attr { Some(val) => val, None => { diff --git a/tests/lib.rs b/tests/lib.rs index 4954b84a8bc2ba2b4d41567b43a4888b8c89738f..ad8839f7095501b142a87ee101979ee4fdf38d3d 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -1,6 +1,6 @@ use std::path::Path; use std::{fs::File, path::PathBuf}; -use tiled::{LayerData, Map, PropertyValue, TiledError, Tileset}; +use tiled::{Color, LayerData, Map, PropertyValue, TiledError, Tileset}; use tiled::{LayerType, ObjectLayer, TileLayer}; fn as_tile_layer(layer: &LayerType) -> &TileLayer { @@ -256,3 +256,26 @@ fn test_object_property() { }; assert_eq!(3, prop_value); } + +#[test] +fn test_tint_color() { + let r = Map::parse_file("assets/tiled_image_layers.tmx").unwrap(); + assert_eq!( + r.layers[0].tint_color, + Some(Color { + alpha: 0x12, + red: 0x34, + green: 0x56, + blue: 0x78 + }) + ); + assert_eq!( + r.layers[1].tint_color, + Some(Color { + alpha: 0xFF, + red: 0x12, + green: 0x34, + blue: 0x56 + }) + ); +}