Skip to content

Commit

Permalink
Added support for WangSets (#226)
Browse files Browse the repository at this point in the history
Closes #112
  • Loading branch information
josebaMdeL committed Aug 5, 2022
1 parent 672b5ca commit 1a10faf
Show file tree
Hide file tree
Showing 9 changed files with 413 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
### Added
- Support for Wang sets.

## [0.10.2]
### Added
- Map-wrapped chunks: `ChunkWrapper`.
Expand Down
28 changes: 28 additions & 0 deletions assets/tiled_csv_wangsets.tmx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<map version="1.8" tiledversion="1.8.5" orientation="orthogonal" renderorder="right-down" width="30" height="20" tilewidth="32" tileheight="32" infinite="0" nextlayerid="3" nextobjectid="1">
<tileset firstgid="1" source="tilesheet_wangsets.tsx"/>
<layer id="1" name="Layer 1" width="30" height="20">
<data encoding="csv">
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,
47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47,47
</data>
</layer>
</map>
112 changes: 112 additions & 0 deletions assets/tilesheet_wangsets.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?xml version="1.0" encoding="UTF-8"?>
<tileset version="1.8" tiledversion="1.8.5" name="tilesheet_wangsets" tilewidth="32" tileheight="32" tilecount="84" columns="14">
<image source="tilesheet.png" width="448" height="192"/>
<wangsets>
<wangset name="Void" type="mixed" tile="-1">
<wangcolor name="" color="#ff0000" tile="-1" probability="1"/>
<wangtile tileid="0" wangid="1,1,0,0,0,0,0,1"/>
<wangtile tileid="1" wangid="0,0,0,1,1,1,0,0"/>
<wangtile tileid="14" wangid="0,0,0,0,0,1,1,1"/>
<wangtile tileid="15" wangid="0,1,1,1,0,0,0,0"/>
<wangtile tileid="16" wangid="1,1,1,1,1,1,1,1"/>
<wangtile tileid="17" wangid="1,1,1,1,1,1,1,1"/>
<wangtile tileid="28" wangid="1,1,0,0,0,0,0,1"/>
<wangtile tileid="29" wangid="1,1,0,0,0,0,0,1"/>
<wangtile tileid="56" wangid="1,1,0,0,0,0,0,1"/>
<wangtile tileid="57" wangid="0,0,0,1,1,1,0,0"/>
<wangtile tileid="70" wangid="0,0,0,0,0,1,1,1"/>
<wangtile tileid="71" wangid="0,1,1,1,0,0,0,0"/>
</wangset>
<wangset name="Wall" type="mixed" tile="-1">
<wangcolor name="Light" color="#00ff00" tile="-1" probability="1"/>
<wangcolor name="Dark" color="#006f00" tile="-1" probability="1"/>
<wangtile tileid="4" wangid="2,2,2,2,2,2,2,2"/>
<wangtile tileid="5" wangid="2,2,0,0,0,2,2,2"/>
<wangtile tileid="6" wangid="2,2,0,0,0,0,0,2"/>
<wangtile tileid="7" wangid="2,2,2,2,0,0,0,2"/>
<wangtile tileid="8" wangid="0,0,0,2,0,0,0,0"/>
<wangtile tileid="9" wangid="0,0,0,0,0,2,0,0"/>
<wangtile tileid="10" wangid="2,2,0,2,0,2,2,2"/>
<wangtile tileid="11" wangid="2,2,2,2,0,2,0,2"/>
<wangtile tileid="12" wangid="2,2,0,2,0,2,0,2"/>
<wangtile tileid="13" wangid="0,2,2,2,0,2,0,2"/>
<wangtile tileid="19" wangid="0,0,0,0,0,2,2,2"/>
<wangtile tileid="21" wangid="0,2,2,2,0,0,0,0"/>
<wangtile tileid="22" wangid="0,2,2,0,0,0,0,0"/>
<wangtile tileid="23" wangid="0,0,0,0,0,0,0,2"/>
<wangtile tileid="24" wangid="0,2,0,2,2,2,2,2"/>
<wangtile tileid="25" wangid="0,2,2,2,2,2,0,2"/>
<wangtile tileid="26" wangid="0,2,0,2,0,2,2,2"/>
<wangtile tileid="27" wangid="0,2,0,2,2,2,0,2"/>
<wangtile tileid="31" wangid="0,0,2,2,2,2,2,0"/>
<wangtile tileid="33" wangid="0,0,0,2,2,2,2,2"/>
<wangtile tileid="34" wangid="0,0,0,2,2,2,0,0"/>
<wangtile tileid="35" wangid="0,2,2,2,1,2,0,0"/>
<wangtile tileid="36" wangid="0,0,0,2,0,2,0,0"/>
<wangtile tileid="37" wangid="0,0,0,0,0,2,0,2"/>
<wangtile tileid="38" wangid="0,2,0,0,0,0,0,2"/>
<wangtile tileid="39" wangid="0,2,0,2,0,0,0,0"/>
<wangtile tileid="40" wangid="1,1,0,1,0,1,0,1"/>
<wangtile tileid="41" wangid="0,1,1,1,0,1,0,1"/>
<wangtile tileid="45" wangid="2,2,2,2,2,2,2,2"/>
<wangtile tileid="46" wangid="1,1,1,1,1,1,1,1"/>
<wangtile tileid="47" wangid="1,1,0,0,0,1,1,1"/>
<wangtile tileid="48" wangid="1,1,0,0,0,0,0,1"/>
<wangtile tileid="49" wangid="1,1,1,1,0,0,0,1"/>
<wangtile tileid="50" wangid="0,0,0,1,0,0,0,0"/>
<wangtile tileid="51" wangid="0,0,0,0,0,1,0,0"/>
<wangtile tileid="52" wangid="1,1,0,1,0,1,1,1"/>
<wangtile tileid="53" wangid="1,1,1,1,0,1,0,1"/>
<wangtile tileid="54" wangid="0,1,0,1,0,1,1,1"/>
<wangtile tileid="55" wangid="0,1,0,1,1,1,0,1"/>
<wangtile tileid="59" wangid="0,0,1,1,1,1,1,0"/>
<wangtile tileid="61" wangid="0,0,0,0,0,1,1,1"/>
<wangtile tileid="63" wangid="0,1,1,1,0,0,0,0"/>
<wangtile tileid="64" wangid="0,1,0,0,0,0,0,0"/>
<wangtile tileid="65" wangid="0,0,0,0,0,0,0,1"/>
<wangtile tileid="66" wangid="0,1,0,1,1,1,1,1"/>
<wangtile tileid="67" wangid="0,1,1,1,1,1,0,1"/>
<wangtile tileid="73" wangid="1,1,2,2,2,2,2,1"/>
<wangtile tileid="75" wangid="0,0,0,1,1,1,1,1"/>
<wangtile tileid="76" wangid="0,0,0,1,1,1,0,0"/>
<wangtile tileid="77" wangid="0,1,1,1,1,1,0,0"/>
<wangtile tileid="78" wangid="0,0,0,1,0,1,0,0"/>
<wangtile tileid="79" wangid="0,0,0,0,0,1,0,1"/>
<wangtile tileid="80" wangid="0,1,0,0,0,0,0,1"/>
<wangtile tileid="81" wangid="0,1,0,1,0,0,0,0"/>
</wangset>
<wangset name="Floor" type="mixed" tile="-1">
<wangcolor name="" color="#ff0000" tile="-1" probability="1">
<properties>
<property name="Damage" type="float" value="0"/>
</properties>
</wangcolor>
<wangcolor name="Trap" color="#00ff00" tile="-1" probability="1">
<properties>
<property name="Damage" type="float" value="32.1"/>
</properties>
</wangcolor>
<wangtile tileid="5" wangid="0,0,1,1,1,0,0,0"/>
<wangtile tileid="6" wangid="0,0,1,1,1,1,1,0"/>
<wangtile tileid="7" wangid="0,0,0,0,1,1,1,0"/>
<wangtile tileid="19" wangid="1,1,1,1,1,0,0,0"/>
<wangtile tileid="20" wangid="1,1,1,1,1,1,1,1"/>
<wangtile tileid="21" wangid="1,0,0,0,1,1,1,1"/>
<wangtile tileid="33" wangid="1,1,1,0,0,0,0,0"/>
<wangtile tileid="34" wangid="1,1,1,0,0,0,1,1"/>
<wangtile tileid="35" wangid="1,0,0,0,0,0,1,1"/>
<wangtile tileid="47" wangid="0,0,1,1,1,0,0,0"/>
<wangtile tileid="48" wangid="0,0,1,1,1,1,1,0"/>
<wangtile tileid="49" wangid="0,0,0,0,1,1,1,0"/>
<wangtile tileid="61" wangid="1,1,1,1,1,0,0,0"/>
<wangtile tileid="62" wangid="2,2,2,2,2,2,2,2"/>
<wangtile tileid="63" wangid="1,0,0,0,1,1,1,1"/>
<wangtile tileid="75" wangid="1,1,1,0,0,0,0,0"/>
<wangtile tileid="76" wangid="1,1,1,0,0,0,1,1"/>
<wangtile tileid="77" wangid="1,0,0,0,0,0,1,1"/>
<properties>
<property name="Movement Cost" type="int" value="1"/>
</properties>
</wangset>
</wangsets>
</tileset>
7 changes: 7 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,11 @@ pub enum Error {
/// Supported types are `string`, `int`, `float`, `bool`, `color`, `file` and `object`.
type_name: String,
},
/// Found a WangId that was not properly formatted.
InvalidWangIdEncoding {
/// Stores the wrongly parsed String.
read_string: String,
},
}

/// A result with an error variant of [`crate::Error`].
Expand Down Expand Up @@ -93,6 +98,8 @@ impl fmt::Display for Error {
write!(fmt, "Invalid property value: {}", description),
Error::UnknownPropertyType { type_name } =>
write!(fmt, "Unknown property value type '{}'", type_name),
Error::InvalidWangIdEncoding{read_string} =>
write!(fmt, "\"{}\" is not a valid WangId format", read_string),
}
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/tileset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use crate::properties::{parse_properties, Properties};
use crate::tile::TileData;
use crate::{util::*, Gid, Tile, TileId};

mod wangset;
pub use wangset::{WangColor, WangId, WangSet, WangTile};

/// 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).
Expand Down Expand Up @@ -53,6 +56,9 @@ pub struct Tileset {
/// All the tiles present in this tileset, indexed by their local IDs.
tiles: HashMap<TileId, TileData>,

/// All the wangsets present in this tileset.
pub wang_sets: Vec<WangSet>,

/// The custom properties of the tileset.
pub properties: Properties,
}
Expand Down Expand Up @@ -235,6 +241,7 @@ impl Tileset {
let mut image = Option::None;
let mut tiles = HashMap::with_capacity(prop.tilecount as usize);
let mut properties = HashMap::new();
let mut wang_sets = Vec::new();

parse_tag!(parser, "tileset", {
"image" => |attrs| {
Expand All @@ -250,6 +257,11 @@ impl Tileset {
tiles.insert(id, tile);
Ok(())
},
"wangset" => |attrs| {
let set = WangSet::new(parser, attrs)?;
wang_sets.push(set);
Ok(())
},
});

// A tileset is considered an image collection tileset if there is no image attribute (because its tiles do).
Expand Down Expand Up @@ -278,6 +290,7 @@ impl Tileset {
tilecount: prop.tilecount,
image,
tiles,
wang_sets,
properties,
})
}
Expand Down
101 changes: 101 additions & 0 deletions src/tileset/wangset.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
use std::collections::HashMap;

use xml::attribute::OwnedAttribute;

use crate::{
error::Error,
properties::{parse_properties, Properties},
util::{get_attrs, parse_tag, XmlEventResult},
Result, TileId,
};

mod wang_color;
pub use wang_color::WangColor;
mod wang_tile;
pub use wang_tile::{WangId, WangTile};

/// Wang set's terrain brush connection type.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum WangSetType {
Corner,
Edge,
Mixed,
}

impl Default for WangSetType {
fn default() -> Self {
WangSetType::Mixed
}
}

/// Raw data belonging to a WangSet.
#[derive(Debug, PartialEq, Clone)]
pub struct WangSet {
/// The name of the Wang set.
pub name: String,
/// Type of Wang set.
pub wang_set_type: WangSetType,
/// The tile ID of the tile representing this Wang set.
pub tile: Option<TileId>,
/// The colors color that can be used to define the corner and/or edge of each Wang tile.
pub wang_colors: Vec<WangColor>,
/// All the Wang tiles present in this Wang set, indexed by their local IDs.
pub wang_tiles: HashMap<TileId, WangTile>,
/// The custom properties of this Wang set.
pub properties: Properties,
}

impl WangSet {
/// Reads data from XML parser to create a WangSet.
pub fn new(
parser: &mut impl Iterator<Item = XmlEventResult>,
attrs: Vec<OwnedAttribute>,
) -> Result<WangSet> {
// Get common data
let (name, wang_set_type, tile) = get_attrs!(
for v in attrs {
"name" => name ?= v.parse::<String>(),
"type" => wang_set_type ?= v.parse::<String>(),
"tile" => tile ?= v.parse::<i64>(),
}
(name, wang_set_type, tile)
);

let wang_set_type = match wang_set_type.as_str() {
"corner" => WangSetType::Corner,
"edge" => WangSetType::Edge,
_ => WangSetType::default(),
};
let tile = if tile >= 0 { Some(tile as u32) } else { None };

// Gather variable data
let mut wang_colors = Vec::new();
let mut wang_tiles = HashMap::new();
let mut properties = HashMap::new();
parse_tag!(parser, "wangset", {
"wangcolor" => |attrs| {
let color = WangColor::new(parser, attrs)?;
wang_colors.push(color);
Ok(())
},
"wangtile" => |attrs| {
let (id, t) = WangTile::new(parser, attrs)?;
wang_tiles.insert(id, t);
Ok(())
},
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
},
});

Ok(WangSet {
name,
wang_set_type,
tile,
wang_colors,
wang_tiles,
properties,
})
}
}
63 changes: 63 additions & 0 deletions src/tileset/wangset/wang_color.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use std::collections::HashMap;

use xml::attribute::OwnedAttribute;

use crate::{
error::Error,
properties::{parse_properties, Color, Properties},
util::{get_attrs, parse_tag, XmlEventResult},
Result, TileId,
};

/// Stores the data of the Wang color.
#[derive(Debug, PartialEq, Clone)]
pub struct WangColor {
/// The name of this color.
pub name: String,
#[allow(missing_docs)]
pub color: Color,
/// The tile ID of the tile representing this color.
pub tile: Option<TileId>,
/// The relative probability that this color is chosen over others in case of multiple options. (defaults to 0)
pub probability: f32,
/// The custom properties of this color.
pub properties: Properties,
}

impl WangColor {
/// Reads data from XML parser to create a WangColor.
pub fn new(
parser: &mut impl Iterator<Item = XmlEventResult>,
attrs: Vec<OwnedAttribute>,
) -> Result<WangColor> {
// Get common data
let (name, color, tile, probability) = get_attrs!(
for v in attrs {
"name" => name ?= v.parse::<String>(),
"color" => color ?= v.parse(),
"tile" => tile ?= v.parse::<i64>(),
"probability" => probability ?= v.parse::<f32>(),
}
(name, color, tile, probability)
);

let tile = if tile >= 0 { Some(tile as u32) } else { None };

// Gather variable data
let mut properties = HashMap::new();
parse_tag!(parser, "wangcolor", {
"properties" => |_| {
properties = parse_properties(parser)?;
Ok(())
},
});

Ok(WangColor {
name,
color,
tile,
probability,
properties,
})
}
}
Loading

0 comments on commit 1a10faf

Please sign in to comment.