Skip to content
Snippets Groups Projects
Unverified Commit 6682c54b authored by BlockCat's avatar BlockCat Committed by GitHub
Browse files

Merge pull request #1 from BlockCat/infinite

add infinite map
parents 688dcf9d 8366cf89
No related branches found
No related tags found
No related merge requests found
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.2" tiledversion="2020.05.20" orientation="orthogonal" renderorder="right-down" width="100" height="100" tilewidth="32" tileheight="32" infinite="1" backgroundcolor="#ff00ff" nextlayerid="6" nextobjectid="5">
<editorsettings>
<chunksize width="32" height="32"/>
</editorsettings>
<tileset firstgid="1" name="tilesheet" tilewidth="32" tileheight="32" tilecount="84" columns="14">
<image source="tilesheet.png" width="448" height="192"/>
<tile id="1">
<properties>
<property name="a tile property" value="123"/>
</properties>
</tile>
</tileset>
<tileset firstgid="85" source="tilesheet.tsx"/>
<layer id="3" name="Background" width="100" height="100">
<data encoding="base64" compression="zlib">
<chunk x="-32" y="0" width="32" height="32">
eJztzTENAAAMw7BiGH+wg9CjryPldrJ142t8Pp/P5/P5fD6fz+fz+w/olSQB
</chunk>
<chunk x="0" y="0" width="32" height="32">
eJztwwEJAAAMBKHL8P3DrsdQcNVUVVXV1w/BwEgB
</chunk>
<chunk x="-32" y="32" width="32" height="32">
eJztzcEJAAAIA7HO4P7DOkRBEBK49yWdKWv5+/v7+/v73/8BgH8WAIoSAQ==
</chunk>
<chunk x="0" y="32" width="32" height="32">
eJztwwEJAAAAAqA29H9sQ1KwSaqqXgUA/gxxUCQB
</chunk>
</data>
</layer>
<layer id="4" name="Ground" width="100" height="100" locked="1">
<data encoding="base64" compression="zlib">
<chunk x="0" y="0" width="32" height="32">
eJztVLsOwjAQi4Af6MAnIBb4AgRiRUKw8+hMS2fg87mInGSdLk0ThgyNJYtXajvxBWMKCgoK4nAhXom3TN4dsSE+XY5/s/B+NErdB/FOfANryJKSw2o2HrYiZ+e+q4AvkSM2Az/PXMD7j5KzFc9jjlr5PYRKcCI+h/xRx66JPQN7rivi2r0ujd4/+/fpp5yB1Z0Dff3jnODsS3aBjJq/1ZRzLfvnvflmtW92Q/4zRzkL2D/efS0r34EU/yHr8fzlHWTKNUP9D6a/U+6V9/5RldL9pyau10pVSvPn/58NUOtWm0mfVmgdgrvbmd/92xu9W20mfVqhdRrQPwfG7n8knomnTP4W24zexX9c/l+dHlQo
</chunk>
<chunk x="0" y="32" width="32" height="32">
eJzt0KESABAQRdH9IwlJIlH8/9fYQKJ66Z6ZV5S7w+xWHm9Kpx99w5fE/by70xdM/x+nV/cdTdzv4h4AAAAA4L8FOaQDyA==
</chunk>
</data>
</layer>
<layer id="5" name="Overlay" width="100" height="100">
<data encoding="base64" compression="zlib">
<chunk x="0" y="0" width="32" height="32">
eJztwzENAAAIA7A5wb9L3hkgPG3SBAB+TQUA4MYCfd0AXg==
</chunk>
</data>
</layer>
<objectgroup id="2" name="Object group">
<object id="1" x="14" y="9" width="285" height="135"/>
<object id="2" x="329" y="217" width="102" height="109">
<ellipse/>
</object>
<object id="3" x="314" y="376">
<polyline points="0,0 -111,-63 -203,27 -205,-130 -78,-150 -6,-6"/>
</object>
<object id="4" x="479" y="84">
<polygon points="0,0 139,128 -55,64 -37,-49 159,47 138,126"/>
</object>
</objectgroup>
</map>
......@@ -236,6 +236,7 @@ pub struct Map {
pub object_groups: Vec<ObjectGroup>,
pub properties: Properties,
pub background_colour: Option<Colour>,
pub infinite: bool,
}
impl Map {
......@@ -244,10 +245,11 @@ impl Map {
attrs: Vec<OwnedAttribute>,
map_path: Option<&Path>,
) -> Result<Map, TiledError> {
let (c, (v, o, w, h, tw, th)) = get_attrs!(
let ((c, infinite), (v, o, w, h, tw, th)) = get_attrs!(
attrs,
optionals: [
("backgroundcolor", colour, |v:String| v.parse().ok()),
("infinite", infinite, |v:String| Some(v == "1")),
],
required: [
("version", version, |v| Some(v)),
......@@ -272,7 +274,7 @@ impl Map {
Ok(())
},
"layer" => |attrs| {
layers.push(Layer::new(parser, attrs, w, layer_index)?);
layers.push(Layer::new(parser, attrs, w, layer_index, infinite.unwrap_or(false))?);
layer_index += 1;
Ok(())
},
......@@ -304,6 +306,7 @@ impl Map {
object_groups,
properties,
background_colour: c,
infinite: infinite.unwrap_or(false)
})
}
......@@ -666,7 +669,7 @@ pub struct Layer {
pub visible: bool,
/// The tiles are arranged in rows. Each tile is a number which can be used
/// to find which tileset it belongs to and can then be rendered.
pub tiles: Vec<Vec<LayerTile>>,
pub tiles: LayerData,
pub properties: Properties,
pub layer_index: u32,
}
......@@ -677,6 +680,7 @@ impl Layer {
attrs: Vec<OwnedAttribute>,
width: u32,
layer_index: u32,
infinite: bool,
) -> Result<Layer, TiledError> {
let ((o, v), n) = get_attrs!(
attrs,
......@@ -689,11 +693,15 @@ impl Layer {
],
TiledError::MalformedAttributes("layer must have a name".to_string())
);
let mut tiles = Vec::new();
let mut tiles: LayerData = LayerData::Finite(Default::default());
let mut properties = HashMap::new();
parse_tag!(parser, "layer", {
"data" => |attrs| {
tiles = parse_data(parser, attrs, width)?;
if infinite {
tiles = parse_infinite_data(parser, attrs, width)?;
} else {
tiles = parse_data(parser, attrs, width)?;
}
Ok(())
},
"properties" => |_| {
......@@ -712,6 +720,55 @@ impl Layer {
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum LayerData {
Finite(Vec<Vec<LayerTile>>),
Infinite(HashMap<(i32, i32), Chunk>)
}
#[derive(Debug, PartialEq, Clone)]
pub struct Chunk {
pub x: i32,
pub y: i32,
pub width: u32,
pub height: u32,
pub tiles: Vec<Vec<LayerTile>>,
}
impl Chunk {
pub(crate) fn new<R: Read>(
parser: &mut EventReader<R>,
attrs: Vec<OwnedAttribute>,
encoding: Option<String>,
compression: Option<String>,
) -> Result<Chunk, TiledError> {
let ((), (x, y, width, height)) = get_attrs!(
attrs,
optionals: [],
required: [
("x", x, |v: String| v.parse().ok()),
("y", y, |v: String| v.parse().ok()),
("width", width, |v: String| v.parse().ok()),
("height", height, |v: String| v.parse().ok()),
],
TiledError::MalformedAttributes("layer must have a name".to_string())
);
let tiles = parse_data_line(encoding, compression, parser, width)?;
Ok(Chunk {
x,
y,
width,
height,
tiles,
})
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct ImageLayer {
......@@ -1007,11 +1064,38 @@ fn parse_animation<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Frame>, T
Ok(animation)
}
fn parse_infinite_data<R: Read>(
parser: &mut EventReader<R>,
attrs: Vec<OwnedAttribute>,
width: u32,
) -> Result<LayerData, TiledError> {
let ((e, c), ()) = get_attrs!(
attrs,
optionals: [
("encoding", encoding, |v| Some(v)),
("compression", compression, |v| Some(v)),
],
required: [],
TiledError::MalformedAttributes("data must have an encoding and a compression".to_string())
);
let mut chunks = HashMap::<(i32, i32), Chunk>::new();
parse_tag!(parser, "data", {
"chunk" => |attrs| {
let chunk = Chunk::new(parser, attrs, e.clone(), c.clone())?;
chunks.insert((chunk.x, chunk.y), chunk);
Ok(())
}
});
Ok(LayerData::Infinite(chunks))
}
fn parse_data<R: Read>(
parser: &mut EventReader<R>,
attrs: Vec<OwnedAttribute>,
width: u32,
) -> Result<Vec<Vec<LayerTile>>, TiledError> {
) -> Result<LayerData, TiledError> {
let ((e, c), ()) = get_attrs!(
attrs,
optionals: [
......@@ -1022,7 +1106,13 @@ fn parse_data<R: Read>(
TiledError::MalformedAttributes("data must have an encoding and a compression".to_string())
);
match (e, c) {
let tiles = parse_data_line(e, c, parser, width)?;
Ok(LayerData::Finite(tiles))
}
fn parse_data_line<R: Read>(encoding: Option<String>, compression: Option<String>, parser: &mut EventReader<R>, width: u32) -> Result<Vec<Vec<LayerTile>>, TiledError> {
match (encoding, compression) {
(None, None) => {
return Err(TiledError::Other(
"XML format is currently not supported".to_string(),
......
use std::fs::File;
use std::path::Path;
use tiled::{parse, parse_file, parse_tileset, Map, PropertyValue, TiledError};
use tiled::{parse, parse_file, parse_tileset, Map, PropertyValue, TiledError, LayerData};
fn read_from_file(p: &Path) -> Result<Map, TiledError> {
let file = File::open(p).unwrap();
......@@ -36,6 +36,24 @@ fn test_just_tileset() {
assert_eq!(r.tilesets[0], t);
}
#[test]
fn test_infinite_tileset() {
let r = read_from_file_with_path(&Path::new("assets/tiled_base64_zlib_infinite.tmx")).unwrap();
if let LayerData::Infinite(chunks) = &r.layers[0].tiles {
assert_eq!(chunks.len(), 4);
assert_eq!(chunks[&(0, 0)].width, 32);
assert_eq!(chunks[&(0, 0)].height, 32);
assert_eq!(chunks[&(-32, 0)].width, 32);
assert_eq!(chunks[&(0, 32)].height, 32);
assert_eq!(chunks[&(-32, 32)].height, 32);
} else {
assert!(false, "It is wrongly recognized as a finite map");
}
}
#[test]
fn test_image_layers() {
let r = read_from_file(&Path::new("assets/tiled_image_layers.tmx")).unwrap();
......@@ -104,23 +122,29 @@ fn test_tileset_property() {
#[test]
fn test_flipped_gid() {
let r = read_from_file_with_path(&Path::new("assets/tiled_flipped.tmx")).unwrap();
let t1 = r.layers[0].tiles[0][0];
let t2 = r.layers[0].tiles[0][1];
let t3 = r.layers[0].tiles[1][0];
let t4 = r.layers[0].tiles[1][1];
assert_eq!(t1.gid, t2.gid);
assert_eq!(t2.gid, t3.gid);
assert_eq!(t3.gid, t4.gid);
assert!(t1.flip_d);
assert!(t1.flip_h);
assert!(t1.flip_v);
assert!(!t2.flip_d);
assert!(!t2.flip_h);
assert!(t2.flip_v);
assert!(!t3.flip_d);
assert!(t3.flip_h);
assert!(!t3.flip_v);
assert!(t4.flip_d);
assert!(!t4.flip_h);
assert!(!t4.flip_v);
if let LayerData::Finite(tiles) = &r.layers[0].tiles {
let t1 = tiles[0][0];
let t2 = tiles[0][1];
let t3 = tiles[1][0];
let t4 = tiles[1][1];
assert_eq!(t1.gid, t2.gid);
assert_eq!(t2.gid, t3.gid);
assert_eq!(t3.gid, t4.gid);
assert!(t1.flip_d);
assert!(t1.flip_h);
assert!(t1.flip_v);
assert!(!t2.flip_d);
assert!(!t2.flip_h);
assert!(t2.flip_v);
assert!(!t3.flip_d);
assert!(t3.flip_h);
assert!(!t3.flip_v);
assert!(t4.flip_d);
assert!(!t4.flip_h);
assert!(!t4.flip_v);
} else {
assert!(false, "It is wrongly recognized as an infinite map");
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment