From 9c2c3ae927c4c485db555dca2571bc195ea21ff4 Mon Sep 17 00:00:00 2001 From: Doug Reeves <guodman@gmail.com> Date: Fri, 9 Jun 2017 21:12:16 -0500 Subject: [PATCH] Added a function that will parse just a tileset (tsx) file. --- src/lib.rs | 47 ++++++++++++++++++++++++++++++----------------- tests/lib.rs | 9 ++++++++- 2 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index eae2b31..7f1d4b8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -325,11 +325,11 @@ pub struct Tileset { impl Tileset { fn new<R: Read>(parser: &mut EventReader<R>, attrs: Vec<OwnedAttribute>, map_path: Option<&Path>) -> Result<Tileset, TiledError> { Tileset::new_internal(parser, &attrs) - .or_else(|_| { Tileset::new_external(&attrs, map_path) }) + .or_else(|_| { Tileset::new_reference(&attrs, map_path) }) } fn new_internal<R: Read>(parser: &mut EventReader<R>, attrs: &Vec<OwnedAttribute>) -> Result<Tileset, TiledError> { - let ((s, m), (g, n, w, h)) = get_attrs!( + let ((spacing, margin), (first_gid, name, width, height)) = get_attrs!( attrs, optionals: [("spacing", spacing, |v:String| v.parse().ok()), ("margin", margin, |v:String| v.parse().ok())], @@ -351,17 +351,17 @@ impl Tileset { Ok(()) }); - Ok(Tileset {first_gid: g, - name: n, - tile_width: w, tile_height: h, - spacing: s.unwrap_or(0), - margin: m.unwrap_or(0), + Ok(Tileset {first_gid: first_gid, + name: name, + tile_width: width, tile_height: height, + spacing: spacing.unwrap_or(0), + margin: margin.unwrap_or(0), images: images, tiles: tiles}) } - fn new_external(attrs: &Vec<OwnedAttribute>, map_path: Option<&Path>) -> Result<Tileset, TiledError> { - let ((), (g, source)) = get_attrs!( + fn new_reference(attrs: &Vec<OwnedAttribute>, map_path: Option<&Path>) -> Result<Tileset, TiledError> { + let ((), (first_gid, source)) = get_attrs!( attrs, optionals: [], required: [("firstgid", first_gid, |v:String| v.parse().ok()), @@ -370,12 +370,16 @@ impl Tileset { let tileset_path = map_path.ok_or(TiledError::Other("Maps with external tilesets must know their file location. See parse_with_path(Path).".to_string()))?.with_file_name(source); let file = File::open(&tileset_path).map_err(|_| TiledError::Other(format!("External tileset file not found: {:?}", tileset_path)))?; + Tileset::new_external(file, first_gid) + } + + fn new_external<R: Read>(file: R, first_gid: u32) -> Result<Tileset, TiledError> { let mut tileset_parser = EventReader::new(file); loop { match try!(tileset_parser.next().map_err(TiledError::XmlDecodingError)) { XmlEvent::StartElement {name, attributes, ..} => { if name.local_name == "tileset" { - return Tileset::parse_external_tileset(g, &mut tileset_parser, &attributes) + return Tileset::parse_external_tileset(first_gid, &mut tileset_parser, &attributes) } } XmlEvent::EndDocument => return Err(TiledError::PrematureEnd("Tileset Document ended before map was parsed".to_string())), @@ -384,8 +388,8 @@ impl Tileset { } } - fn parse_external_tileset<R: Read>(g: u32, parser: &mut EventReader<R>, attrs: &Vec<OwnedAttribute>) -> Result<Tileset, TiledError> { - let ((s, m), (n, w, h)) = get_attrs!( + fn parse_external_tileset<R: Read>(first_gid: u32, parser: &mut EventReader<R>, attrs: &Vec<OwnedAttribute>) -> Result<Tileset, TiledError> { + let ((spacing, margin), (name, width, height)) = get_attrs!( attrs, optionals: [("spacing", spacing, |v:String| v.parse().ok()), ("margin", margin, |v:String| v.parse().ok())], @@ -406,11 +410,11 @@ impl Tileset { Ok(()) }); - Ok(Tileset {first_gid: g, - name: n, - tile_width: w, tile_height: h, - spacing: s.unwrap_or(0), - margin: m.unwrap_or(0), + Ok(Tileset {first_gid: first_gid, + name: name, + tile_width: width, tile_height: height, + spacing: spacing.unwrap_or(0), + margin: margin.unwrap_or(0), images: images, tiles: tiles}) } @@ -800,3 +804,12 @@ pub fn parse_file(path: &Path) -> Result<Map, TiledError> { pub fn parse<R: Read>(reader: R) -> Result<Map, TiledError> { parse_impl(reader, None) } + +/// Parse a buffer hopefully containing the contents of a Tiled tileset. +/// +/// External tilesets do not have a firstgid attribute. That lives in the +/// map. You must pass in `first_gid`. If you do not need to use gids for anything, +/// passing in 1 will work fine. +pub fn parse_tileset<R: Read>(reader: R, first_gid: u32) -> Result<Tileset, TiledError> { + Tileset::new_external(reader, first_gid) +} diff --git a/tests/lib.rs b/tests/lib.rs index 233ba7f..6ac8a99 100644 --- a/tests/lib.rs +++ b/tests/lib.rs @@ -2,7 +2,7 @@ extern crate tiled; use std::path::Path; use std::fs::File; -use tiled::{Map, TiledError, parse, parse_file}; +use tiled::{Map, TiledError, parse, parse_file, parse_tileset}; fn read_from_file(p: &Path) -> Result<Map, TiledError> { let file = File::open(p).unwrap(); @@ -30,3 +30,10 @@ fn test_external_tileset() { let e = read_from_file_with_path(&Path::new("assets/tiled_base64_external.tmx")).unwrap(); assert_eq!(r, e); } + +#[test] +fn test_just_tileset() { + let r = read_from_file(&Path::new("assets/tiled_base64.tmx")).unwrap(); + let t = parse_tileset(File::open(Path::new("assets/tilesheet.tsx")).unwrap(), 1).unwrap(); + assert_eq!(r.tilesets[0], t); +} -- GitLab