Skip to content

Commit

Permalink
Merge pull request #3 from kornellapacz/master
Browse files Browse the repository at this point in the history
Added typed properties support and properties for TileMap and Layer
  • Loading branch information
luanpotter committed May 22, 2020
2 parents 4c8f7e1 + 4547fef commit 4dc2630
Show file tree
Hide file tree
Showing 8 changed files with 94 additions and 45 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## [next]

* Added typed properties support and properties for TileMap and Layer

## 0.3.0

* `Layer` using 2d list store layer's `_tiles`,useful for get tile by coordinate `x,y`
Expand Down
4 changes: 4 additions & 0 deletions lib/src/layer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ class Layer {
int height;
bool visible;

Map<String, dynamic> properties = {};

TileMap map;
List<List<int>> tileMatrix;

Expand Down Expand Up @@ -49,6 +51,8 @@ class Layer {

assembleTileMatrix(inflatedString);
}

properties = TileMapParser._parsePropertiesFromElement(element);
}

// TMX data format documented here: https://github.com/bjorn/tiled/wiki/TMX-Map-Format#data
Expand Down
17 changes: 11 additions & 6 deletions lib/src/object_group.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ class ObjectGroup {

TileMap map;

Map<String, String> properties = {};
Map<String, dynamic> properties = {};
List<TmxObject> tmxObjects = [];

ObjectGroup.fromXML(XmlElement element) {
if (element == null) { throw 'arg "element" cannot be null'; }
if (element == null) {
throw 'arg "element" cannot be null';
}

NodeDSL.on(element, (dsl) {
name = dsl.strOr('name', name);
Expand All @@ -22,12 +24,15 @@ class ObjectGroup {
visible = dsl.boolOr('visible', visible);
});

properties = TileMapParser._parseProperties(TileMapParser._getPropertyNodes(element));
properties = TileMapParser._parsePropertiesFromElement(element);

var objectNodes = element.children
.where((node) => node is XmlElement)
.where((node) => (node as XmlElement).name.local == 'object');
tmxObjects = objectNodes.map((objectNode)
=> new TmxObject.fromXML(objectNode)).toList();
.cast<XmlElement>()
.where((node) => node.name.local == 'object');

tmxObjects = objectNodes
.map((objectNode) => new TmxObject.fromXML(objectNode))
.toList();
}
}
6 changes: 3 additions & 3 deletions lib/src/tile.dart
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ class Tile {
margin = tileset.margin;
gid = tileId + tileset.firstgid;
properties = tileset.tileProperties[gid];
if (properties == null) {
properties = {};
}

properties ??= {};

_image = tileset.tileImage[gid];
}

Expand Down
17 changes: 12 additions & 5 deletions lib/src/tile_map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class TileMap {
List<Tileset> tilesets = new List<Tileset>();
List<Layer> layers = new List<Layer>();
List<ObjectGroup> objectGroups = [];
Map<String, dynamic> properties = {};

/**
* Retrieve a tile based on its GID
Expand All @@ -20,16 +21,17 @@ class TileMap {
* A GID of 0 is always an "empty" tile
*/
Tile getTileByGID(int gid) {
if (gid == 0) { return new Tile.emptyTile(); }
if (gid == 0) {
return new Tile.emptyTile();
}
var ts = tilesets.lastWhere((tileset) => tileset.firstgid <= gid);
return new Tile(gid - ts.firstgid, ts);
}

// Returns a tileset based on its name
Tileset getTileset(String name) {
return tilesets.firstWhere((tileset) => tileset.name == name,
orElse: () => throw new ArgumentError('Tileset $name not found')
);
orElse: () => throw new ArgumentError('Tileset $name not found'));
}

/**
Expand All @@ -54,11 +56,16 @@ class TileMap {
*/
Tile getTileByPhrase(String tilePhrase) {
var split = tilePhrase.split('|');
if (split.length != 2) { throw new ArgumentError("$tilePhrase not in the format of 'TilesetName|LocalTileID"); }
if (split.length != 2) {
throw new ArgumentError(
'$tilePhrase not in the format of "TilesetName|LocalTileID"',
);
}

var tilesetName = split.first;
var tileId = int.parse(split.last,
onError: (src) => throw new ArgumentError('Local tile ID $src is not an integer.') );
onError: (src) =>
throw new ArgumentError('Local tile ID $src is not an integer.'));

return getTileByLocalID(tilesetName, tileId);
}
Expand Down
66 changes: 48 additions & 18 deletions lib/src/tile_map_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ class TileMapParser {
TileMapParser();

TileMap parse(String xml, {TsxProvider tsx}) {

var xmlElement = _parseXml(xml).rootElement;

if (xmlElement.name.local != 'map') {
Expand All @@ -17,12 +16,11 @@ class TileMapParser {
map.width = int.parse(xmlElement.getAttribute('width'));
map.height = int.parse(xmlElement.getAttribute('height'));

xmlElement.children.where((node) => node is XmlNode).forEach( (XmlNode node) {
if (!(node is XmlElement)) {
return;
}
var element = node as XmlElement;
switch(element.name.local) {
xmlElement.children
.where((node) => node is XmlElement)
.cast<XmlElement>()
.forEach((XmlElement element) {
switch (element.name.local) {
case 'tileset':
map.tilesets.add(new Tileset.fromXML(element, tsx: tsx)..map = map);
break;
Expand All @@ -35,19 +33,49 @@ class TileMapParser {
}
});

map.properties = TileMapParser._parsePropertiesFromElement(xmlElement);

return map;
}

static Image _parseImage(XmlElement node) {
var attrs = node.getAttribute;
return new Image(attrs('source'), int.parse(attrs('width')), int.parse(attrs('height')));

return new Image(
attrs('source'),
int.parse(attrs('width')),
int.parse(attrs('height')),
);
}

static Map<String, dynamic> _parsePropertiesFromElement(XmlElement element) {
return TileMapParser._parseProperties(
TileMapParser._getPropertyNodes(element),
);
}

static Map<String, String> _parseProperties(nodes) {
var map = new Map<String, String>();
nodes.forEach( (property) {
var attrs = property.getAttribute;
map[attrs('name')] = attrs('value');
static Map<String, dynamic> _parseProperties(nodes) {
final map = <String, dynamic>{};

nodes.forEach((property) {
final attrs = property.getAttribute;
final value = attrs('value');
final name = attrs('name');

switch (attrs('type')) {
case 'bool':
map[name] = value == 'true';
break;
case 'int':
map[name] = int.parse(value);
break;
case 'float':
map[name] = double.parse(value);
break;
default: // for types file, color (returns ARGB), string
map[name] = value;
break;
}
});

return map;
Expand All @@ -67,8 +95,11 @@ class TileMapParser {
static Iterable<XmlElement> _getPropertyNodes(XmlElement node) {
var propertyNode = node.children
.where((node) => node is XmlElement)
.firstWhere((node) => (node as XmlElement).name.local == 'properties', orElse: () => null) as XmlElement;
if (propertyNode == null) { return []; }
.cast<XmlElement>()
.firstWhere((element) => element.name.local == 'properties', orElse: () => null);
if (propertyNode == null) {
return [];
}
return propertyNode.findElements('property');
}

Expand All @@ -83,17 +114,16 @@ class TileMapParser {
}

static Function _getDecoder(String encodingType) {
switch(encodingType) {
switch (encodingType) {
case 'base64':
return _decodeBase64;
default:
throw 'Incompatible encoding found: $encodingType';
}

}

static Function _getDecompressor(String compressionType) {
switch(compressionType) {
switch (compressionType) {
case 'zlib':
return new ZLibDecoder().decodeBytes;
case 'gzip':
Expand Down
10 changes: 4 additions & 6 deletions lib/src/tileset.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ class Tileset {

Image image;
List<Image> images = new List<Image>();
Map<String, String> properties = new Map<String, String>();
Map<int, Map<String, String>> tileProperties = new Map();
Map<String, dynamic> properties = {};
Map<int, Map<String, dynamic>> tileProperties = {};
Map<int, Image> tileImage = new Map();

Tileset(this.firstgid);
Expand All @@ -27,15 +27,13 @@ class Tileset {
image = _findImage(element);
_addImage(image);

properties = TileMapParser._parseProperties(
TileMapParser._getPropertyNodes(element));
properties = TileMapParser._parsePropertiesFromElement(element);

// Parse tile properties, if present.
element.findElements('tile').forEach((XmlElement tileNode) {
int tileId = int.parse(tileNode.getAttribute('id'));
int tileGid = tileId + firstgid;
tileProperties[tileGid] = TileMapParser._parseProperties(
TileMapParser._getPropertyNodes(tileNode));
tileProperties[tileGid] = TileMapParser._parsePropertiesFromElement(tileNode);
var image = _findImage(tileNode);
tileImage[tileGid] = image;
_addImage(image);
Expand Down
15 changes: 8 additions & 7 deletions lib/src/tmx_object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ class TmxObject {
bool isPolyline = false;

List<Point> points = [];
Map<String, String> properties = {};

Map<String, dynamic> properties = {};

TmxObject.fromXML(XmlElement element) {
if (element == null) { throw 'arg "element" cannot be null'; }
if (element == null) {
throw 'arg "element" cannot be null';
}

NodeDSL.on(element, (dsl) {
name = dsl.strOr('name', name);
Expand All @@ -36,19 +37,19 @@ class TmxObject {
visible = dsl.boolOr('visible', visible);
});

properties = TileMapParser._parseProperties(TileMapParser._getPropertyNodes(element));
properties = TileMapParser._parsePropertiesFromElement(element);

// TODO: it is implied by the spec that there are only two children to
// an object node: an optional <properties /> and an optional <ellipse />,
// <polygon />, or <polyline />
var xmlElements = element.children
.where((node) => node is XmlElement)
.where((node) => (node as XmlElement).name.local != 'properties');
.where((node) => node is XmlElement)
.where((node) => (node as XmlElement).name.local != 'properties');

if (xmlElements.length > 0) {
var node = xmlElements.first as XmlElement;

switch(node.name.local) {
switch (node.name.local) {
case 'ellipse':
isEllipse = true;
break;
Expand Down

0 comments on commit 4dc2630

Please sign in to comment.