Skip to content
Snippets Groups Projects
Commit 3563f0f4 authored by Jengamon's avatar Jengamon
Browse files

Fix tile flipping code

parent f7bda672
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="1.2.5" orientation="orthogonal" renderorder="right-down" width="2" height="2" tilewidth="32" tileheight="32" infinite="0" nextlayerid="2" nextobjectid="1">
<tileset firstgid="1" source="tilesheet.tsx"/>
<layer id="1" name="Tile Layer 1" width="2" height="2">
<data encoding="csv">
3758096387,1073741827,
2147483651,536870915
</data>
</layer>
</map>
...@@ -511,8 +511,6 @@ impl Tileset { ...@@ -511,8 +511,6 @@ impl Tileset {
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Tile { pub struct Tile {
pub id: u32, pub id: u32,
pub flip_h: bool,
pub flip_v: bool,
pub images: Vec<Image>, pub images: Vec<Image>,
pub properties: Properties, pub properties: Properties,
pub objectgroup: Option<ObjectGroup>, pub objectgroup: Option<ObjectGroup>,
...@@ -521,12 +519,6 @@ pub struct Tile { ...@@ -521,12 +519,6 @@ pub struct Tile {
pub probability: f32, pub probability: f32,
} }
const FLIPPED_HORIZONTALLY_FLAG: u32 = 0x8;
const FLIPPED_VERTICALLY_FLAG: u32 = 0x4;
const FLIPPED_DIAGONALLY_FLAG: u32 = 0x2;
const ALL_FLIP_FLAGS: u32 =
FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG;
impl Tile { impl Tile {
fn new<R: Read>( fn new<R: Read>(
parser: &mut EventReader<R>, parser: &mut EventReader<R>,
...@@ -544,12 +536,6 @@ impl Tile { ...@@ -544,12 +536,6 @@ impl Tile {
TiledError::MalformedAttributes("tile must have an id with the correct type".to_string()) TiledError::MalformedAttributes("tile must have an id with the correct type".to_string())
); );
let flags = (id & ALL_FLIP_FLAGS) >> 28;
let id: u32 = id & !ALL_FLIP_FLAGS;
let diagon = flags & FLIPPED_DIAGONALLY_FLAG == FLIPPED_DIAGONALLY_FLAG;
let flip_h = (flags & FLIPPED_HORIZONTALLY_FLAG == FLIPPED_HORIZONTALLY_FLAG) ^ diagon;
let flip_v = (flags & FLIPPED_VERTICALLY_FLAG == FLIPPED_VERTICALLY_FLAG) ^ diagon;
let mut images = Vec::new(); let mut images = Vec::new();
let mut properties = HashMap::new(); let mut properties = HashMap::new();
let mut objectgroup = None; let mut objectgroup = None;
...@@ -574,8 +560,6 @@ impl Tile { ...@@ -574,8 +560,6 @@ impl Tile {
}); });
Ok(Tile { Ok(Tile {
id, id,
flip_h,
flip_v,
images, images,
properties, properties,
objectgroup, objectgroup,
...@@ -623,6 +607,39 @@ impl Image { ...@@ -623,6 +607,39 @@ impl Image {
} }
} }
/// Stores the proper tile gid, along with how it is flipped.
// Maybe PartialEq and Eq should be custom, so that it ignores tile-flipping?
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct LayerTile {
pub gid: u32,
pub flip_h: bool,
pub flip_v: bool,
pub flip_d: bool,
}
const FLIPPED_HORIZONTALLY_FLAG: u32 = 0x80000000;
const FLIPPED_VERTICALLY_FLAG: u32 = 0x40000000;
const FLIPPED_DIAGONALLY_FLAG: u32 = 0x20000000;
const ALL_FLIP_FLAGS: u32 =
FLIPPED_HORIZONTALLY_FLAG | FLIPPED_VERTICALLY_FLAG | FLIPPED_DIAGONALLY_FLAG;
impl LayerTile {
pub fn new(id: u32) -> LayerTile {
let flags = id & ALL_FLIP_FLAGS;
let gid = id & !ALL_FLIP_FLAGS;
let flip_d = flags & FLIPPED_DIAGONALLY_FLAG == FLIPPED_DIAGONALLY_FLAG; // Swap x and y axis (anti-diagonally) [flips over y = -x line]
let flip_h = flags & FLIPPED_HORIZONTALLY_FLAG == FLIPPED_HORIZONTALLY_FLAG; // Flip tile over y axis
let flip_v = flags & FLIPPED_VERTICALLY_FLAG == FLIPPED_VERTICALLY_FLAG; // Flip tile over x axis
LayerTile {
gid,
flip_h,
flip_v,
flip_d,
}
}
}
#[derive(Debug, PartialEq, Clone)] #[derive(Debug, PartialEq, Clone)]
pub struct Layer { pub struct Layer {
pub name: String, pub name: String,
...@@ -630,7 +647,7 @@ pub struct Layer { ...@@ -630,7 +647,7 @@ pub struct Layer {
pub visible: bool, pub visible: bool,
/// The tiles are arranged in rows. Each tile is a number which can be used /// 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. /// to find which tileset it belongs to and can then be rendered.
pub tiles: Vec<Vec<u32>>, pub tiles: Vec<Vec<LayerTile>>,
pub properties: Properties, pub properties: Properties,
pub layer_index: u32, pub layer_index: u32,
} }
...@@ -971,7 +988,7 @@ fn parse_data<R: Read>( ...@@ -971,7 +988,7 @@ fn parse_data<R: Read>(
parser: &mut EventReader<R>, parser: &mut EventReader<R>,
attrs: Vec<OwnedAttribute>, attrs: Vec<OwnedAttribute>,
width: u32, width: u32,
) -> Result<Vec<Vec<u32>>, TiledError> { ) -> Result<Vec<Vec<LayerTile>>, TiledError> {
let ((e, c), ()) = get_attrs!( let ((e, c), ()) = get_attrs!(
attrs, attrs,
optionals: [ optionals: [
...@@ -989,7 +1006,7 @@ fn parse_data<R: Read>( ...@@ -989,7 +1006,7 @@ fn parse_data<R: Read>(
)) ))
} }
(Some(e), None) => match e.as_ref() { (Some(e), None) => match e.as_ref() {
"base64" => return parse_base64(parser).map(|v| convert_to_u32(&v, width)), "base64" => return parse_base64(parser).map(|v| convert_to_tile(&v, width)),
"csv" => return decode_csv(parser), "csv" => return decode_csv(parser),
e => return Err(TiledError::Other(format!("Unknown encoding format {}", e))), e => return Err(TiledError::Other(format!("Unknown encoding format {}", e))),
}, },
...@@ -997,12 +1014,12 @@ fn parse_data<R: Read>( ...@@ -997,12 +1014,12 @@ fn parse_data<R: Read>(
("base64", "zlib") => { ("base64", "zlib") => {
return parse_base64(parser) return parse_base64(parser)
.and_then(decode_zlib) .and_then(decode_zlib)
.map(|v| convert_to_u32(&v, width)) .map(|v| convert_to_tile(&v, width))
} }
("base64", "gzip") => { ("base64", "gzip") => {
return parse_base64(parser) return parse_base64(parser)
.and_then(decode_gzip) .and_then(decode_gzip)
.map(|v| convert_to_u32(&v, width)) .map(|v| convert_to_tile(&v, width))
} }
(e, c) => { (e, c) => {
return Err(TiledError::Other(format!( return Err(TiledError::Other(format!(
...@@ -1054,11 +1071,11 @@ fn decode_gzip(data: Vec<u8>) -> Result<Vec<u8>, TiledError> { ...@@ -1054,11 +1071,11 @@ fn decode_gzip(data: Vec<u8>) -> Result<Vec<u8>, TiledError> {
Ok(data) Ok(data)
} }
fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, TiledError> { fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<LayerTile>>, TiledError> {
loop { loop {
match try!(parser.next().map_err(TiledError::XmlDecodingError)) { match try!(parser.next().map_err(TiledError::XmlDecodingError)) {
XmlEvent::Characters(s) => { XmlEvent::Characters(s) => {
let mut rows: Vec<Vec<u32>> = Vec::new(); let mut rows: Vec<Vec<LayerTile>> = Vec::new();
for row in s.split('\n') { for row in s.split('\n') {
if row.trim() == "" { if row.trim() == "" {
continue; continue;
...@@ -1067,6 +1084,7 @@ fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, Til ...@@ -1067,6 +1084,7 @@ fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, Til
row.split(',') row.split(',')
.filter(|v| v.trim() != "") .filter(|v| v.trim() != "")
.map(|v| v.replace('\r', "").parse().unwrap()) .map(|v| v.replace('\r', "").parse().unwrap())
.map(|id| LayerTile::new(id))
.collect(), .collect(),
); );
} }
...@@ -1082,7 +1100,7 @@ fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, Til ...@@ -1082,7 +1100,7 @@ fn decode_csv<R: Read>(parser: &mut EventReader<R>) -> Result<Vec<Vec<u32>>, Til
} }
} }
fn convert_to_u32(all: &Vec<u8>, width: u32) -> Vec<Vec<u32>> { fn convert_to_tile(all: &Vec<u8>, width: u32) -> Vec<Vec<LayerTile>> {
let mut data = Vec::new(); let mut data = Vec::new();
for chunk in all.chunks((width * 4) as usize) { for chunk in all.chunks((width * 4) as usize) {
let mut row = Vec::new(); let mut row = Vec::new();
...@@ -1092,6 +1110,7 @@ fn convert_to_u32(all: &Vec<u8>, width: u32) -> Vec<Vec<u32>> { ...@@ -1092,6 +1110,7 @@ fn convert_to_u32(all: &Vec<u8>, width: u32) -> Vec<Vec<u32>> {
+ ((chunk[start + 2] as u32) << 16) + ((chunk[start + 2] as u32) << 16)
+ ((chunk[start + 1] as u32) << 8) + ((chunk[start + 1] as u32) << 8)
+ chunk[start] as u32; + chunk[start] as u32;
let n = LayerTile::new(n);
row.push(n); row.push(n);
} }
data.push(row); data.push(row);
......
...@@ -79,3 +79,27 @@ fn test_object_group_property() { ...@@ -79,3 +79,27 @@ fn test_object_group_property() {
}; };
assert!(prop_value); assert!(prop_value);
} }
#[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);
}
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