From 8906685876bf644cce25d4bfc45ff4674d7142d8 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 24 Oct 2023 23:55:08 +0200 Subject: [PATCH 01/13] removed need for flutter sdk (dart:ui) --> replaced dart:ui Color with color_model package --> custom Rect instead of dart:ui --> replaced flutter_test with test package --- packages/tiled/lib/src/common/rect.dart | 17 +++++++++++++++++ packages/tiled/lib/src/layer.dart | 2 +- packages/tiled/test/parser_test.dart | 8 ++++---- 3 files changed, 22 insertions(+), 5 deletions(-) create mode 100644 packages/tiled/lib/src/common/rect.dart diff --git a/packages/tiled/lib/src/common/rect.dart b/packages/tiled/lib/src/common/rect.dart new file mode 100644 index 0000000..f42b620 --- /dev/null +++ b/packages/tiled/lib/src/common/rect.dart @@ -0,0 +1,17 @@ +class Rect { + final double x; + final double y; + final double width; + final double height; + + Rect.fromLTWH(this.x, this.y, this.width, this.height); + + @override + bool operator ==(Object other) { + if (other is! Rect) return false; + return x == other.x && y == other.y && width == other.width && height == other.height; + } + + @override + int get hashCode => Object.hash(x, y, width, height); +} \ No newline at end of file diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index dd25967..bf09582 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -425,7 +425,7 @@ class TileLayer extends Layer { } class ObjectGroup extends Layer { - static const defaultColor = ColorData.rgb(160, 160, 164); + static const defaultColor = ColorData.rgb(160, 160, 164, 255); static const defaultColorHex = '%a0a0a4'; /// topdown (default) or index (indexOrder). diff --git a/packages/tiled/test/parser_test.dart b/packages/tiled/test/parser_test.dart index 3ec9f5e..11f2f7b 100644 --- a/packages/tiled/test/parser_test.dart +++ b/packages/tiled/test/parser_test.dart @@ -88,10 +88,10 @@ void main() { equals('test_value'), ); expect( - properties.getValue('multiline string'), - Platform.isWindows - ? equals('Hello,\r\nWorld') - : equals('Hello,\nWorld'), + properties + .getValue('multiline string') + ?.replaceAll('\r\n', '\n'), + equals('Hello,\nWorld'), ); expect( properties.getValue('integer property'), From 1527e7be84af426b3440a6aad3615e8edd520e7e Mon Sep 17 00:00:00 2001 From: benni-tec Date: Sat, 28 Oct 2023 15:58:15 +0200 Subject: [PATCH 02/13] replaced custom rect in favor of Rectangle from dart:math --- packages/tiled/lib/src/common/rect.dart | 17 ----------------- packages/tiled/pubspec.yaml | 2 +- 2 files changed, 1 insertion(+), 18 deletions(-) delete mode 100644 packages/tiled/lib/src/common/rect.dart diff --git a/packages/tiled/lib/src/common/rect.dart b/packages/tiled/lib/src/common/rect.dart deleted file mode 100644 index f42b620..0000000 --- a/packages/tiled/lib/src/common/rect.dart +++ /dev/null @@ -1,17 +0,0 @@ -class Rect { - final double x; - final double y; - final double width; - final double height; - - Rect.fromLTWH(this.x, this.y, this.width, this.height); - - @override - bool operator ==(Object other) { - if (other is! Rect) return false; - return x == other.x && y == other.y && width == other.width && height == other.height; - } - - @override - int get hashCode => Object.hash(x, y, width, height); -} \ No newline at end of file diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index abdb17b..f4fb5c5 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -1,5 +1,5 @@ name: tiled -version: 0.10.2 +version: 0.11.0 description: A Dart Tiled library. Parse your TMX files into useful representations. Compatible with Flame. homepage: https://github.com/flame-engine/tiled.dart From 54038eeb31c6b4d904bef808a16dbb8489ae7b8a Mon Sep 17 00:00:00 2001 From: benni-tec Date: Wed, 17 Jan 2024 11:44:43 +0100 Subject: [PATCH 03/13] reversed version change (done automagically by melos) --- packages/tiled/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index f4fb5c5..ce870e2 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -1,5 +1,5 @@ name: tiled -version: 0.11.0 +version: 0.10.1 description: A Dart Tiled library. Parse your TMX files into useful representations. Compatible with Flame. homepage: https://github.com/flame-engine/tiled.dart From b4e32cdca9e3fd9c39f10ccfb8ec4be972ad9a85 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Fri, 20 Dec 2024 09:56:11 +0100 Subject: [PATCH 04/13] fixed merge --- packages/tiled/lib/src/layer.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index bf09582..f872cd9 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -333,7 +333,7 @@ abstract class Layer { decompressed = const ZLibDecoder().decodeBytes(decodedString); break; case Compression.gzip: - decompressed = const GZipDecoder().decodeBytes(decodedString); + decompressed = GZipDecoder().decodeBytes(decodedString); break; case Compression.zstd: throw UnsupportedError('zstd is an unsupported compression'); From 6f659ece26f10698d3551799ec1bb2ab198976f9 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Sat, 28 Oct 2023 17:23:22 +0200 Subject: [PATCH 05/13] added TsxProviderBase and updatet TsxProvider to not break existing contracts // corrected and extended README.md --- README.md | 27 ++++++++++++++-- packages/tiled/lib/src/tile_map_parser.dart | 2 +- packages/tiled/lib/src/tiled_map.dart | 4 +-- packages/tiled/lib/src/tileset/tileset.dart | 6 ++-- packages/tiled/lib/src/tsx_provider.dart | 34 ++++++++++++++++++--- 5 files changed, 61 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a2f8002..41b163f 100644 --- a/README.md +++ b/README.md @@ -29,9 +29,15 @@ Load a TMX file into a string by any means, and then pass the string to TileMapP final TiledMap mapTmx = TileMapParser.parseTmx(tmxBody); ``` -If your tmx file includes a external tsx reference, you have to add a CustomParser +If your tmx file includes a external tsx reference, you have to add a CustomParser. This can either be done by using extending the TsxProviderBase, which can match multiple files, or by extending TsxProvider, which only matches on file by its name. ```dart -class CustomTsxProvider extends TsxProvider { +class MultipleTsxProvider extends TsxProviderBase { + @override + bool checkProvidable(String filename) => ["external1.tsx", "external2.tsx"].contains(filename); + + @override + Parser? getCachedSource(String filename) => null; + @override Parser getSource(String fileName) { final xml = File(fileName).readAsStringSync(); @@ -40,6 +46,23 @@ class CustomTsxProvider extends TsxProvider { } } ``` + +```dart +class SingleTsxProvider extends TsxProvider { + @override + String get filename => "external.tsx"; + + @override + Parser? getCachedSource() => null; + + @override + Parser getSource(String _) { + final xml = File(filename).readAsStringSync(); + final node = XmlDocument.parse(xml).rootElement; + return XmlParser(node); + } +} +``` And use it in the parseTmx method ```dart final String tmxBody = /* ... */; diff --git a/packages/tiled/lib/src/tile_map_parser.dart b/packages/tiled/lib/src/tile_map_parser.dart index 534747c..59d0b05 100644 --- a/packages/tiled/lib/src/tile_map_parser.dart +++ b/packages/tiled/lib/src/tile_map_parser.dart @@ -13,7 +13,7 @@ class TileMapParser { /// /// Accepts an optional list of external TsxProviders for external tilesets /// referenced in the map file. - static TiledMap parseTmx(String xml, {List? tsxList}) { + static TiledMap parseTmx(String xml, {List? tsxList}) { final xmlElement = XmlDocument.parse(xml).rootElement; if (xmlElement.name.local != 'map') { throw 'XML is not in TMX format'; diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index 1a11973..e944136 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -315,7 +315,7 @@ class TiledMap { ); } - factory TiledMap.parse(Parser parser, {List? tsxList}) { + factory TiledMap.parse(Parser parser, {List? tsxList}) { final backgroundColorHex = parser.getStringOrNull('backgroundcolor'); final backgroundColor = parser.getColorOrNull('backgroundcolor'); final compressionLevel = parser.getInt('compressionlevel', defaults: -1); @@ -346,7 +346,7 @@ class TiledMap { return Tileset.parse(tilesetData); } final matchingTsx = tsxList.where( - (tsx) => tsx.filename == tilesetSource, + (tsx) => tsx.checkProvidable(tilesetSource), ); return Tileset.parse( diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 0f1ac92..16ee4d9 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -105,7 +105,7 @@ class Tileset { tileCount = this.tiles.length; } - factory Tileset.parse(Parser parser, {TsxProvider? tsx}) { + factory Tileset.parse(Parser parser, {TsxProviderBase? tsx}) { final backgroundColor = parser.getStringOrNull('backgroundcolor'); final columns = parser.getIntOrNull('columns'); final firstGid = parser.getIntOrNull('firstgid'); @@ -171,10 +171,10 @@ class Tileset { return result; } - void _checkIfExternalTsx(String? source, TsxProvider? tsx) { + void _checkIfExternalTsx(String? source, TsxProviderBase? tsx) { if (tsx != null && source != null) { final tileset = Tileset.parse( - tsx.getCachedSource() ?? tsx.getSource(source), + tsx.getCachedSourceBase(source) ?? tsx.getSourceBase(source), ); // Copy attributes if not null backgroundColor = tileset.backgroundColor ?? backgroundColor; diff --git a/packages/tiled/lib/src/tsx_provider.dart b/packages/tiled/lib/src/tsx_provider.dart index bc5a84b..8bf996b 100644 --- a/packages/tiled/lib/src/tsx_provider.dart +++ b/packages/tiled/lib/src/tsx_provider.dart @@ -1,18 +1,44 @@ import 'package:tiled/tiled.dart'; /// abstract class to be implemented for an external tileset data provider. -abstract class TsxProvider { +abstract class TsxProviderBase { + /// Given a filename this function should check whether this Provider + /// can provide this source. + bool checkProvidable(String filename); + + /// Retrieves the external tileset data given the tileset filename. + Parser getSourceBase(String filename); + + /// Used when provider implementations cache the data. Returns the cached + /// data for the external tileset by filename. + Parser? getCachedSourceBase(String filename); +} + +/// abstract convenience class to be implemented for an external tileset data +/// provider, which only provides one file and can therefore be matched by the +/// filename alone. +abstract class TsxProvider extends TsxProviderBase { /// Unique filename for the tileset to be loaded. This should match the - /// 'source' property in the map.tmx file. + /// 'source' property in the map.tmx file. This is used to check if this + /// Provider can provide a source! String get filename; - /// Retrieves the external tileset data given the tileset filename. - Parser getSource(String filename); + @override + bool checkProvidable(String filename) => filename == this.filename; /// Used when provider implementations cache the data. Returns the cached /// data for the exernal tileset. Parser? getCachedSource(); + @override + Parser? getCachedSourceBase(String _) => getCachedSource(); + + /// Retrieves the external tileset data given the tileset filename. + Parser getSource(String filename); + + @override + Parser getSourceBase(String filename) => getSource(filename); + /// Parses a file returning a [TsxProvider]. static Future parse(String key) { throw UnimplementedError(); From 118b6e99b527394abfcf1c000bc246682a2f4962 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Mon, 30 Oct 2023 09:08:35 +0100 Subject: [PATCH 06/13] Clarification of TsxProvider behaviour in README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 41b163f..874776a 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,10 @@ class SingleTsxProvider extends TsxProvider { } } ``` -And use it in the parseTmx method +And use it in the parseTmx method. Keep in mind that the first TsxProvider that can provide a source is used! ```dart final String tmxBody = /* ... */; - final TiledMap mapTmx = TileMapParser.parseTmx(tmxBody, tsx: CustomTsxProvider()); + final TiledMap mapTmx = TileMapParser.parseTmx(tmxBody, tsxProviders: [SingleTsxProvider(), MultipleTsxProvider()]); ``` From 7ddcb0467ce4b5c80d39a4d33a580263938a76c3 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 14:11:21 +0100 Subject: [PATCH 07/13] generalized provider (ready for templates) --- packages/tiled/lib/src/parser.dart | 7 ++ packages/tiled/lib/src/provider.dart | 11 +++ packages/tiled/lib/src/tile_map_parser.dart | 24 ----- packages/tiled/lib/src/tiled_map.dart | 88 ++++++++++++------ packages/tiled/lib/src/tileset/tileset.dart | 6 +- packages/tiled/lib/src/tsx_provider.dart | 46 --------- packages/tiled/pubspec.yaml | 1 + .../tiled/test/complexmap_infinite_test.dart | 2 +- packages/tiled/test/image_layer_test.dart | 2 +- .../tiled/test/isometric_staggered_test.dart | 4 +- packages/tiled/test/isometric_test.dart | 2 +- packages/tiled/test/layer_test.dart | 4 +- packages/tiled/test/object_group_test.dart | 2 +- packages/tiled/test/overflow_bug_test.dart | 6 +- packages/tiled/test/parser_compare_test.dart | 22 ++--- packages/tiled/test/parser_test.dart | 93 +++++++++++-------- packages/tiled/test/rectangle_map_test.dart | 2 +- packages/tiled/test/tmx_object_test.dart | 2 +- 18 files changed, 160 insertions(+), 164 deletions(-) create mode 100644 packages/tiled/lib/src/provider.dart delete mode 100644 packages/tiled/lib/src/tile_map_parser.dart delete mode 100644 packages/tiled/lib/src/tsx_provider.dart diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index 7716eca..7bb0808 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -5,13 +5,18 @@ class ParsingException implements Exception { final String name; final String? valueFound; final String reason; + ParsingException(this.name, this.valueFound, this.reason); } class XmlParser extends Parser { final XmlElement element; + XmlParser(this.element); + factory XmlParser.fromString(String string) => + XmlParser(XmlDocument.parse(string).rootElement); + @override String? getInnerTextOrNull() => element.innerText.isEmpty ? null : element.innerText; @@ -49,7 +54,9 @@ class XmlParser extends Parser { class JsonParser extends Parser { final Map json; + JsonParser(this.json); + factory JsonParser.fromString(String string) => JsonParser(jsonDecode(string) as Map); @override String? getInnerTextOrNull() => null; diff --git a/packages/tiled/lib/src/provider.dart b/packages/tiled/lib/src/provider.dart new file mode 100644 index 0000000..ecd1b3b --- /dev/null +++ b/packages/tiled/lib/src/provider.dart @@ -0,0 +1,11 @@ +part of tiled; + +abstract class Provider { + bool canProvide(String filename); + + T getSource(String filename); + T? getCachedSource(String filename); +} + +typedef ParserProvider = Provider; +typedef ImagePathProvider = Provider; \ No newline at end of file diff --git a/packages/tiled/lib/src/tile_map_parser.dart b/packages/tiled/lib/src/tile_map_parser.dart deleted file mode 100644 index 59d0b05..0000000 --- a/packages/tiled/lib/src/tile_map_parser.dart +++ /dev/null @@ -1,24 +0,0 @@ -import 'dart:convert'; - -import 'package:tiled/tiled.dart'; -import 'package:xml/xml.dart'; - -class TileMapParser { - static TiledMap parseJson(String json) { - final parser = JsonParser(jsonDecode(json) as Map); - return TiledMap.parse(parser); - } - - /// Parses the provided map xml. - /// - /// Accepts an optional list of external TsxProviders for external tilesets - /// referenced in the map file. - static TiledMap parseTmx(String xml, {List? tsxList}) { - final xmlElement = XmlDocument.parse(xml).rootElement; - if (xmlElement.name.local != 'map') { - throw 'XML is not in TMX format'; - } - final parser = XmlParser(xmlElement); - return TiledMap.parse(parser, tsxList: tsxList); - } -} diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index e944136..cecb854 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -132,28 +132,31 @@ class TiledMap { /// the [TsxProvider]s returned from the [tsxProviderFunction]. /// The [tsxProviderFunction] is most commonly your static [TsxProvider.parse] /// implementation. - static Future fromString( - String contents, - Future Function(String key) tsxProviderFunction, - ) async { - final tsxSourcePaths = XmlDocument.parse(contents) - .rootElement - .children - .whereType() - .where((element) => element.name.local == 'tileset') - .map((e) => e.getAttribute('source')); - - final tsxProviders = await Future.wait( - tsxSourcePaths - .where((key) => key != null) - .map((key) async => tsxProviderFunction(key!)), - ); - - return TileMapParser.parseTmx( - contents, - tsxList: tsxProviders.isEmpty ? null : tsxProviders, - ); - } + // TODO: why is this here? same as parseTmx??? + // static Future fromString( + // String contents, { + // List? tsxProviders, + // List? templateProviders, + // List? imageProviders, + // }) async { + // final tsxSourcePaths = XmlDocument.parse(contents) + // .rootElement + // .children + // .whereType() + // .where((element) => element.name.local == 'tileset') + // .map((e) => e.getAttribute('source')); + // + // final tsxProviders = await Future.wait( + // tsxSourcePaths + // .where((key) => key != null) + // .map((key) async => tsxProviderFunction(key!)), + // ); + // + // return TileMapParser.parseTmx( + // contents, + // tsxList: tsxProviders.isEmpty ? null : tsxProviders, + // ); + // } // Convenience Methods Tile? tileByGid(int tileGid) { @@ -315,7 +318,40 @@ class TiledMap { ); } - factory TiledMap.parse(Parser parser, {List? tsxList}) { + static TiledMap parseJson(String json) { + final parser = JsonParser(jsonDecode(json) as Map); + return TiledMap.parse(parser); + } + + /// Parses the provided map xml. + /// + /// Accepts an optional list of external TsxProviders for external tilesets + /// referenced in the map file. + static TiledMap parseTmx( + String xml, { + List? tsxProviders, + List? templateProviders, + List? imageProviders, + }) { + final xmlElement = XmlDocument.parse(xml).rootElement; + if (xmlElement.name.local != 'map') { + throw 'XML is not in TMX format'; + } + final parser = XmlParser(xmlElement); + return TiledMap.parse( + parser, + tsxProviders: tsxProviders, + templateProviders: templateProviders, + imageProviders: imageProviders, + ); + } + + factory TiledMap.parse( + Parser parser, { + List? tsxProviders, + List? templateProviders, + List? imageProviders, + }) { final backgroundColorHex = parser.getStringOrNull('backgroundcolor'); final backgroundColor = parser.getColorOrNull('backgroundcolor'); final compressionLevel = parser.getInt('compressionlevel', defaults: -1); @@ -342,11 +378,11 @@ class TiledMap { 'tileset', (tilesetData) { final tilesetSource = tilesetData.getStringOrNull('source'); - if (tilesetSource == null || tsxList == null) { + if (tilesetSource == null || tsxProviders == null) { return Tileset.parse(tilesetData); } - final matchingTsx = tsxList.where( - (tsx) => tsx.checkProvidable(tilesetSource), + final matchingTsx = tsxProviders.where( + (tsx) => tsx.canProvide(tilesetSource), ); return Tileset.parse( diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 16ee4d9..82c0033 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -105,7 +105,7 @@ class Tileset { tileCount = this.tiles.length; } - factory Tileset.parse(Parser parser, {TsxProviderBase? tsx}) { + factory Tileset.parse(Parser parser, {ParserProvider? tsx}) { final backgroundColor = parser.getStringOrNull('backgroundcolor'); final columns = parser.getIntOrNull('columns'); final firstGid = parser.getIntOrNull('firstgid'); @@ -171,10 +171,10 @@ class Tileset { return result; } - void _checkIfExternalTsx(String? source, TsxProviderBase? tsx) { + void _checkIfExternalTsx(String? source, ParserProvider? tsx) { if (tsx != null && source != null) { final tileset = Tileset.parse( - tsx.getCachedSourceBase(source) ?? tsx.getSourceBase(source), + tsx.getCachedSource(source) ?? tsx.getSource(source), ); // Copy attributes if not null backgroundColor = tileset.backgroundColor ?? backgroundColor; diff --git a/packages/tiled/lib/src/tsx_provider.dart b/packages/tiled/lib/src/tsx_provider.dart deleted file mode 100644 index 8bf996b..0000000 --- a/packages/tiled/lib/src/tsx_provider.dart +++ /dev/null @@ -1,46 +0,0 @@ -import 'package:tiled/tiled.dart'; - -/// abstract class to be implemented for an external tileset data provider. -abstract class TsxProviderBase { - /// Given a filename this function should check whether this Provider - /// can provide this source. - bool checkProvidable(String filename); - - /// Retrieves the external tileset data given the tileset filename. - Parser getSourceBase(String filename); - - /// Used when provider implementations cache the data. Returns the cached - /// data for the external tileset by filename. - Parser? getCachedSourceBase(String filename); -} - -/// abstract convenience class to be implemented for an external tileset data -/// provider, which only provides one file and can therefore be matched by the -/// filename alone. -abstract class TsxProvider extends TsxProviderBase { - /// Unique filename for the tileset to be loaded. This should match the - /// 'source' property in the map.tmx file. This is used to check if this - /// Provider can provide a source! - String get filename; - - @override - bool checkProvidable(String filename) => filename == this.filename; - - /// Used when provider implementations cache the data. Returns the cached - /// data for the exernal tileset. - Parser? getCachedSource(); - - @override - Parser? getCachedSourceBase(String _) => getCachedSource(); - - /// Retrieves the external tileset data given the tileset filename. - Parser getSource(String filename); - - @override - Parser getSourceBase(String filename) => getSource(filename); - - /// Parses a file returning a [TsxProvider]. - static Future parse(String key) { - throw UnimplementedError(); - } -} diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index ce870e2..4fc2027 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -16,3 +16,4 @@ dev_dependencies: dartdoc: ^8.3.1 flame_lint: ^1.1.2 test: ^1.24.8 + path: ^1.8.3 diff --git a/packages/tiled/test/complexmap_infinite_test.dart b/packages/tiled/test/complexmap_infinite_test.dart index ca5bf49..feaf67b 100644 --- a/packages/tiled/test/complexmap_infinite_test.dart +++ b/packages/tiled/test/complexmap_infinite_test.dart @@ -10,7 +10,7 @@ void main() { return File('./test/fixtures/complexmap_infinite.tmx') .readAsString() .then((xml) { - complexMapInfinite = TileMapParser.parseTmx(xml); + complexMapInfinite = TiledMap.parseTmx(xml); }); }); diff --git a/packages/tiled/test/image_layer_test.dart b/packages/tiled/test/image_layer_test.dart index 8996c45..a5f703d 100644 --- a/packages/tiled/test/image_layer_test.dart +++ b/packages/tiled/test/image_layer_test.dart @@ -7,7 +7,7 @@ void main() { late TiledMap map; setUp(() { return File('./test/fixtures/imagelayer.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx(xml); + map = TiledMap.parseTmx(xml); }); }); diff --git a/packages/tiled/test/isometric_staggered_test.dart b/packages/tiled/test/isometric_staggered_test.dart index 4e13832..59dc4ed 100644 --- a/packages/tiled/test/isometric_staggered_test.dart +++ b/packages/tiled/test/isometric_staggered_test.dart @@ -11,14 +11,14 @@ void main() { return File('./test/fixtures/isometric_staggered_grass_and_water.json') .readAsString() .then((xml) { - mapIsoStaggeredJson = TileMapParser.parseJson(xml); + mapIsoStaggeredJson = TiledMap.parseJson(xml); }); }); setUp(() { return File('./test/fixtures/isometric_staggered_grass_and_water.tmx') .readAsString() .then((xml) { - mapIsoStaggeredTmx = TileMapParser.parseTmx(xml); + mapIsoStaggeredTmx = TiledMap.parseTmx(xml); }); }); diff --git a/packages/tiled/test/isometric_test.dart b/packages/tiled/test/isometric_test.dart index 9c28c6a..ba885b4 100644 --- a/packages/tiled/test/isometric_test.dart +++ b/packages/tiled/test/isometric_test.dart @@ -10,7 +10,7 @@ void main() { return File('./test/fixtures/isometric_grass_and_water.tmx') .readAsString() .then((xml) { - mapIso = TileMapParser.parseTmx(xml); + mapIso = TiledMap.parseTmx(xml); }); }); diff --git a/packages/tiled/test/layer_test.dart b/packages/tiled/test/layer_test.dart index d967704..b3e3061 100644 --- a/packages/tiled/test/layer_test.dart +++ b/packages/tiled/test/layer_test.dart @@ -9,11 +9,11 @@ void main() { setUp(() { final f1 = File('./test/fixtures/test.tmx').readAsString().then((xml) { - mapTmx = TileMapParser.parseTmx(xml); + mapTmx = TiledMap.parseTmx(xml); }); final f2 = File('./test/fixtures/test_base64_gzip.tmx').readAsString().then((xml) { - mapTmxBase64Gzip = TileMapParser.parseTmx(xml); + mapTmxBase64Gzip = TiledMap.parseTmx(xml); }); return Future.wait([f1, f2]); diff --git a/packages/tiled/test/object_group_test.dart b/packages/tiled/test/object_group_test.dart index 0287622..432768b 100644 --- a/packages/tiled/test/object_group_test.dart +++ b/packages/tiled/test/object_group_test.dart @@ -7,7 +7,7 @@ void main() { late TiledMap map; setUp(() { return File('./test/fixtures/objectgroup.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx(xml); + map = TiledMap.parseTmx(xml); }); }); diff --git a/packages/tiled/test/overflow_bug_test.dart b/packages/tiled/test/overflow_bug_test.dart index 27e62b7..71b73be 100644 --- a/packages/tiled/test/overflow_bug_test.dart +++ b/packages/tiled/test/overflow_bug_test.dart @@ -11,11 +11,7 @@ void main() { setUp(() { return File('./test/fixtures/testoverflow_csv.tmx').readAsString().then( (mapString) { - return TiledMap.fromString(mapString, TsxProvider.parse).then( - (parsedMap) { - map = parsedMap; - }, - ); + map = TiledMap.parseTmx(mapString); }, ); }); diff --git a/packages/tiled/test/parser_compare_test.dart b/packages/tiled/test/parser_compare_test.dart index 4e8b421..961307c 100644 --- a/packages/tiled/test/parser_compare_test.dart +++ b/packages/tiled/test/parser_compare_test.dart @@ -7,28 +7,28 @@ void main() { late TiledMap oldMap; setUp(() { return File('./test/fixtures/test_old.tmx').readAsString().then((xml) { - oldMap = TileMapParser.parseTmx(xml); + oldMap = TiledMap.parseTmx(xml); }); }); late TiledMap map; setUp(() { return File('./test/fixtures/testcsv.json').readAsString().then((xml) { - map = TileMapParser.parseJson(xml); + map = TiledMap.parseJson(xml); }); }); late TiledMap map2; setUp(() { return File('./test/fixtures/testzlib.json').readAsString().then((xml) { - map2 = TileMapParser.parseJson(xml); + map2 = TiledMap.parseJson(xml); }); }); late TiledMap map3; setUp(() { return File('./test/fixtures/testgzip.json').readAsString().then((xml) { - map3 = TileMapParser.parseJson(xml); + map3 = TiledMap.parseJson(xml); }); }); @@ -37,49 +37,49 @@ void main() { return File('./test/fixtures/testbase64only.json') .readAsString() .then((xml) { - map4 = TileMapParser.parseJson(xml); + map4 = TiledMap.parseJson(xml); }); }); late TiledMap tileMapCsv; setUp(() { return File('./test/fixtures/test_csv.tmx').readAsString().then((xml) { - tileMapCsv = TileMapParser.parseTmx(xml); + tileMapCsv = TiledMap.parseTmx(xml); }); }); late TiledMap tileMap; setUp(() { return File('./test/fixtures/test.tmx').readAsString().then((xml) { - tileMap = TileMapParser.parseTmx(xml); + tileMap = TiledMap.parseTmx(xml); }); }); late TiledMap tileMapEllipse; setUp(() { return File('./test/fixtures/map.tmx').readAsString().then((xml) { - tileMapEllipse = TileMapParser.parseTmx(xml); + tileMapEllipse = TiledMap.parseTmx(xml); }); }); late TiledMap map5; setUp(() { return File('./test/fixtures/complexmap.json').readAsString().then((xml) { - map5 = TileMapParser.parseJson(xml); + map5 = TiledMap.parseJson(xml); }); }); late TiledMap map6; setUp(() { return File('./test/fixtures/complexmap.tmx').readAsString().then((xml) { - map6 = TileMapParser.parseTmx(xml); + map6 = TiledMap.parseTmx(xml); }); }); late TiledMap tileMapComplex; setUp(() { return File('./test/fixtures/complexmap.tmx').readAsString().then((xml) { - tileMapComplex = TileMapParser.parseTmx(xml); + tileMapComplex = TiledMap.parseTmx(xml); }); }); diff --git a/packages/tiled/test/parser_test.dart b/packages/tiled/test/parser_test.dart index 11f2f7b..d09672b 100644 --- a/packages/tiled/test/parser_test.dart +++ b/packages/tiled/test/parser_test.dart @@ -2,6 +2,7 @@ import 'dart:io'; import 'dart:math' show Rectangle; import 'package:collection/collection.dart'; +import 'package:path/path.dart' as paths; import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; @@ -10,14 +11,14 @@ void main() { late TiledMap map; setUp(() { return File('./test/fixtures/test.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx(xml); + map = TiledMap.parseTmx(xml); }); }); test('Parser.parse raises an error when the XML is empty', () { const wrongXml = ''; expect( - () => TileMapParser.parseTmx(wrongXml), + () => TiledMap.parseTmx(wrongXml), throwsA(const TypeMatcher()), ); }); @@ -25,7 +26,7 @@ void main() { test('Parser.parse raises an error when the XML is not in TMX format', () { const wrongXml = ''; expect( - () => TileMapParser.parseTmx(wrongXml), + () => TiledMap.parseTmx(wrongXml), throwsA('XML is not in TMX format'), ); }); @@ -209,7 +210,7 @@ void main() { group('Parser.parse populates Map with objectgroups', () { setUp(() { return File('./test/fixtures/objectgroup.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx(xml); + map = TiledMap.parseTmx(xml); }); }); @@ -252,9 +253,9 @@ void main() { group('Parser.parse fills Map with tileset & different img configs', () { setUp(() { return File('./test/fixtures/map_images.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx( + map = TiledMap.parseTmx( xml, - tsxList: [CustomTsxProvider.parse('tileset.tsx')], + tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], ); }); }); @@ -313,9 +314,9 @@ void main() { return File('./test/fixtures/external_tileset_map.tmx') .readAsString() .then((xml) { - final map = TileMapParser.parseTmx( + final map = TiledMap.parseTmx( xml, - tsxList: [CustomTsxProvider.parse('tileid_over_tilecount.tsx')], + tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], ); expect(map.tilesets[0].tileCount, 137); final tile = map.tileByGid(1)!; @@ -328,9 +329,9 @@ void main() { group('Parser.parse with tsx provider', () { test('it loads external tsx', () { return File('./test/fixtures/map_images.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx( + map = TiledMap.parseTmx( xml, - tsxList: [CustomTsxProvider.parse('tileset.tsx')], + tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], ); expect( map.tilesetByName('external').image!.source, @@ -343,9 +344,9 @@ void main() { group('Parser.parse with multiple layers', () { test('it has 2 layers', () { return File('./test/fixtures/map_images.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx( + map = TiledMap.parseTmx( xml, - tsxList: [CustomTsxProvider.parse('tileset.tsx')], + tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], ); expect(map.layers.length, equals(2)); }); @@ -358,19 +359,9 @@ void main() { return File('./test/fixtures/map_with_multiple_tilesets.tmx') .readAsString() .then((xml) { - final tilemapXml = XmlDocument.parse(xml).rootElement; - final tsxSourcePaths = tilemapXml.children - .whereType() - .where((element) => element.name.local == 'tileset') - .map((tsx) => tsx.getAttribute('source')); - - final tsxProviders = tsxSourcePaths - .where((key) => key != null) - .map((key) => CustomTsxProvider.parse(key!)); - - map = TileMapParser.parseTmx( + map = TiledMap.parseTmx( xml, - tsxList: tsxProviders.isEmpty ? null : tsxProviders.toList(), + tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], ); return; }); @@ -428,7 +419,7 @@ void main() { test('support empty terrain values', () { final xml = File('./test/fixtures/map_with_empty_terrains.tmx') .readAsStringSync(); - final tiledMap = TileMapParser.parseTmx(xml); + final tiledMap = TiledMap.parseTmx(xml); final tileset = tiledMap.tilesets.first; final tile = tileset.tiles.first; @@ -437,28 +428,52 @@ void main() { }); } -class CustomTsxProvider extends TsxProvider { - final String _filename; - final String data; +class FixtureTsxProvider extends ParserProvider { + final List files; + final String root; + + FixtureTsxProvider(this.root, this.files); + + factory FixtureTsxProvider.all(String directory) { + final dir = Directory(directory); + if (!dir.existsSync()) { + throw '[FixtureTsxProvider] Supplied directory does not exist!'; + } + + final names = dir + .listSync() + .whereType() + .where((e) => e.path.endsWith('.tsx')) + .map((e) => paths.basename(e.path)) + .toList(); - CustomTsxProvider._(this.data, this._filename); + return FixtureTsxProvider(directory, names); + } + + factory FixtureTsxProvider.file(String path) { + final file = File(path); + if (!file.existsSync()) { + throw '[FixtureTsxProvider] Supplied path does not match any file!'; + } - factory CustomTsxProvider.parse(String filename) { - final xml = File('./test/fixtures/$filename').readAsStringSync(); - return CustomTsxProvider._(xml, filename); + return FixtureTsxProvider(paths.dirname(path), [paths.basename(path)]); } + final Map cache = {}; + @override - String get filename => _filename; + bool canProvide(String filename) => true; @override - Parser getSource(String key) { - final node = XmlDocument.parse(data).rootElement; - return XmlParser(node); - } + Parser? getCachedSource(String filename) => cache.containsKey(filename) + ? XmlParser.fromString(cache[filename]!) + : null; @override - Parser? getCachedSource() { - return getSource(''); + Parser getSource(String filename) { + final content = File(paths.join(root, filename)).readAsStringSync(); + cache[filename] = content; + + return XmlParser.fromString(content); } } diff --git a/packages/tiled/test/rectangle_map_test.dart b/packages/tiled/test/rectangle_map_test.dart index 797bb5b..45b154b 100644 --- a/packages/tiled/test/rectangle_map_test.dart +++ b/packages/tiled/test/rectangle_map_test.dart @@ -8,7 +8,7 @@ void main() { setUp(() { return File('./test/fixtures/rectangle.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx(xml); + map = TiledMap.parseTmx(xml); }); }); diff --git a/packages/tiled/test/tmx_object_test.dart b/packages/tiled/test/tmx_object_test.dart index 8579ed6..594f05d 100644 --- a/packages/tiled/test/tmx_object_test.dart +++ b/packages/tiled/test/tmx_object_test.dart @@ -7,7 +7,7 @@ void main() { late TiledMap map; setUp(() { return File('./test/fixtures/objectgroup.tmx').readAsString().then((xml) { - map = TileMapParser.parseTmx(xml); + map = TiledMap.parseTmx(xml); }); }); From 2698055fa78e3891f979edaef73e695090705f74 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 15:33:57 +0100 Subject: [PATCH 08/13] added providers to Parser // implemented provider for templates // adjusted tests --- packages/tiled/lib/src/layer.dart | 7 ++- .../tiled/lib/src/objects/tiled_object.dart | 23 +++++++- packages/tiled/lib/src/parser.dart | 53 +++++++++++++++---- packages/tiled/lib/src/provider.dart | 6 +-- packages/tiled/lib/src/template.dart | 4 ++ packages/tiled/lib/src/tiled_map.dart | 34 ++++++------ packages/tiled/lib/src/tileset/tile.dart | 8 +-- packages/tiled/test/parser_test.dart | 35 ++++++------ 8 files changed, 115 insertions(+), 55 deletions(-) diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index f872cd9..9bbfb90 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -117,7 +117,7 @@ abstract class Layer { this.properties = CustomProperties.empty, }); - static Layer parse(Parser parser) { + static Layer parse(Parser parser, {List? templateProviders}) { final type = parser.formatSpecificParsing( (json) => json.getLayerType('type'), (xml) => LayerTypeExtension.parseFromTmx(xml.element.name.toString()), @@ -277,7 +277,10 @@ abstract class Layer { static List parseLayers(Parser parser) { return parser.formatSpecificParsing( - (json) => json.getChildrenAs('layers', Layer.parse), + (json) => json.getChildrenAs( + 'layers', + Layer.parse, + ), (xml) { // It's very important not change the order of the layers // during parsing! diff --git a/packages/tiled/lib/src/objects/tiled_object.dart b/packages/tiled/lib/src/objects/tiled_object.dart index 0bee7a1..954bfcd 100644 --- a/packages/tiled/lib/src/objects/tiled_object.dart +++ b/packages/tiled/lib/src/objects/tiled_object.dart @@ -59,7 +59,9 @@ class TiledObject { bool point; bool rectangle; + String? templatePath; Template? template; + Text? text; bool visible; @@ -84,6 +86,7 @@ class TiledObject { this.ellipse = false, this.point = false, this.rectangle = false, + this.templatePath, this.template, this.text, this.visible = true, @@ -93,12 +96,17 @@ class TiledObject { }); bool get isPolyline => polyline.isNotEmpty; + bool get isPolygon => polygon.isNotEmpty; + bool get isPoint => point; + bool get isEllipse => ellipse; + bool get isRectangle => rectangle; - factory TiledObject.parse(Parser parser) { + factory TiledObject.parse( + Parser parser) { final x = parser.getDouble('x', defaults: 0); final y = parser.getDouble('y', defaults: 0); final height = parser.getDouble('height', defaults: 0); @@ -126,7 +134,17 @@ class TiledObject { (xml) => xml.getChildren('point').isNotEmpty, ); final text = parser.getSingleChildOrNullAs('text', Text.parse); - final template = parser.getSingleChildOrNullAs('template', Template.parse); + final templatePath = parser.getStringOrNull('template'); + final templateProvider = templatePath == null + ? null + : parser.templateProviders?.firstWhere((e) => e.canProvide(templatePath)); + final template = templateProvider == null + ? null + : Template.parse( + templateProvider.getCachedSource(templatePath!) ?? + templateProvider.getSource(templatePath), + ); + final properties = parser.getProperties(); final polygon = parsePointList(parser, 'polygon'); @@ -147,6 +165,7 @@ class TiledObject { ellipse: ellipse, point: point, rectangle: rectangle, + templatePath: templatePath, template: template, text: text, visible: visible, diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index 7bb0808..80a75a5 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -12,10 +12,18 @@ class ParsingException implements Exception { class XmlParser extends Parser { final XmlElement element; - XmlParser(this.element); - - factory XmlParser.fromString(String string) => - XmlParser(XmlDocument.parse(string).rootElement); + XmlParser(this.element, {super.tsxProviders, super.templateProviders}); + + factory XmlParser.fromString( + String string, { + List? tsxProviders, + List? templateProviders, + }) => + XmlParser( + XmlDocument.parse(string).rootElement, + tsxProviders: tsxProviders, + templateProviders: templateProviders, + ); @override String? getInnerTextOrNull() => @@ -31,7 +39,11 @@ class XmlParser extends Parser { return element.children .whereType() .where((e) => e.name.local == name) - .map(XmlParser.new) + .map((e) => XmlParser( + e, + templateProviders: templateProviders, + tsxProviders: tsxProviders, + )) .toList(); } @@ -39,7 +51,11 @@ class XmlParser extends Parser { return element.children .whereType() .where((e) => names.contains(e.name.local)) - .map(XmlParser.new) + .map((e) => XmlParser( + e, + tsxProviders: tsxProviders, + templateProviders: templateProviders, + )) .toList(); } @@ -55,8 +71,18 @@ class XmlParser extends Parser { class JsonParser extends Parser { final Map json; - JsonParser(this.json); - factory JsonParser.fromString(String string) => JsonParser(jsonDecode(string) as Map); + JsonParser(this.json, {super.tsxProviders, super.templateProviders}); + + factory JsonParser.fromString( + String string, { + List? tsxProviders, + List? templateProviders, + }) => + JsonParser( + jsonDecode(string) as Map, + tsxProviders: tsxProviders, + templateProviders: templateProviders, + ); @override String? getInnerTextOrNull() => null; @@ -72,7 +98,11 @@ class JsonParser extends Parser { return []; } return (json[name] as List) - .map((dynamic e) => JsonParser(e as Map)) + .map((dynamic e) => JsonParser( + e as Map, + templateProviders: templateProviders, + tsxProviders: tsxProviders, + )) .toList(); } @@ -90,6 +120,11 @@ class JsonParser extends Parser { } abstract class Parser { + final List? templateProviders; + final List? tsxProviders; + + Parser({this.tsxProviders, this.templateProviders}); + String? getInnerTextOrNull(); String? getStringOrNull(String name, {String? defaults}); diff --git a/packages/tiled/lib/src/provider.dart b/packages/tiled/lib/src/provider.dart index ecd1b3b..99b8dd0 100644 --- a/packages/tiled/lib/src/provider.dart +++ b/packages/tiled/lib/src/provider.dart @@ -1,10 +1,10 @@ part of tiled; abstract class Provider { - bool canProvide(String filename); + bool canProvide(String path); - T getSource(String filename); - T? getCachedSource(String filename); + T getSource(String path); + T? getCachedSource(String path); } typedef ParserProvider = Provider; diff --git a/packages/tiled/lib/src/template.dart b/packages/tiled/lib/src/template.dart index ea7a983..d6b55e8 100644 --- a/packages/tiled/lib/src/template.dart +++ b/packages/tiled/lib/src/template.dart @@ -34,3 +34,7 @@ class Template { object: parser.getSingleChildOrNullAs('object', TiledObject.parse), ); } + +class TemplateReference { + +} \ No newline at end of file diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index cecb854..a26b41b 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -318,8 +318,16 @@ class TiledMap { ); } - static TiledMap parseJson(String json) { - final parser = JsonParser(jsonDecode(json) as Map); + static TiledMap parseJson( + String json, { + List? tsxProviders, + List? templateProviders, + }) { + final parser = JsonParser( + jsonDecode(json) as Map, + templateProviders: templateProviders, + tsxProviders: tsxProviders, + ); return TiledMap.parse(parser); } @@ -327,31 +335,24 @@ class TiledMap { /// /// Accepts an optional list of external TsxProviders for external tilesets /// referenced in the map file. - static TiledMap parseTmx( + factory TiledMap.parseTmx( String xml, { List? tsxProviders, List? templateProviders, - List? imageProviders, }) { final xmlElement = XmlDocument.parse(xml).rootElement; if (xmlElement.name.local != 'map') { throw 'XML is not in TMX format'; } - final parser = XmlParser(xmlElement); - return TiledMap.parse( - parser, + final parser = XmlParser( + xmlElement, tsxProviders: tsxProviders, templateProviders: templateProviders, - imageProviders: imageProviders, ); + return TiledMap.parse(parser); } - factory TiledMap.parse( - Parser parser, { - List? tsxProviders, - List? templateProviders, - List? imageProviders, - }) { + factory TiledMap.parse(Parser parser) { final backgroundColorHex = parser.getStringOrNull('backgroundcolor'); final backgroundColor = parser.getColorOrNull('backgroundcolor'); final compressionLevel = parser.getInt('compressionlevel', defaults: -1); @@ -378,10 +379,11 @@ class TiledMap { 'tileset', (tilesetData) { final tilesetSource = tilesetData.getStringOrNull('source'); - if (tilesetSource == null || tsxProviders == null) { + if (tilesetSource == null || parser.tsxProviders == null) { return Tileset.parse(tilesetData); } - final matchingTsx = tsxProviders.where( + + final matchingTsx = parser.tsxProviders!.where( (tsx) => tsx.canProvide(tilesetSource), ); diff --git a/packages/tiled/lib/src/tileset/tile.dart b/packages/tiled/lib/src/tileset/tile.dart index 2c4b11a..a91f961 100644 --- a/packages/tiled/lib/src/tileset/tile.dart +++ b/packages/tiled/lib/src/tileset/tile.dart @@ -52,7 +52,7 @@ class Tile { /// Will be same as [type]. String? get class_ => type; - Tile.parse(Parser parser) + Tile.parse(Parser parser, {List? templateProviders}) : this( localId: parser.getInt('id'), @@ -74,8 +74,10 @@ class Tile { parser.getDoubleOrNull('width') ?? 0, parser.getDoubleOrNull('height') ?? 0, ), - objectGroup: - parser.getSingleChildOrNullAs('objectgroup', Layer.parse), + objectGroup: parser.getSingleChildOrNullAs( + 'objectgroup', + (e) => Layer.parse(e, templateProviders: templateProviders), + ), animation: parser.formatSpecificParsing( (json) => json.getChildrenAs('animation', Frame.parse), (xml) => diff --git a/packages/tiled/test/parser_test.dart b/packages/tiled/test/parser_test.dart index d09672b..588d967 100644 --- a/packages/tiled/test/parser_test.dart +++ b/packages/tiled/test/parser_test.dart @@ -255,7 +255,7 @@ void main() { return File('./test/fixtures/map_images.tmx').readAsString().then((xml) { map = TiledMap.parseTmx( xml, - tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], + tsxProviders: [FixtureTsxProvider.all()], ); }); }); @@ -316,7 +316,7 @@ void main() { .then((xml) { final map = TiledMap.parseTmx( xml, - tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], + tsxProviders: [FixtureTsxProvider.all()], ); expect(map.tilesets[0].tileCount, 137); final tile = map.tileByGid(1)!; @@ -331,7 +331,7 @@ void main() { return File('./test/fixtures/map_images.tmx').readAsString().then((xml) { map = TiledMap.parseTmx( xml, - tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], + tsxProviders: [FixtureTsxProvider.all()], ); expect( map.tilesetByName('external').image!.source, @@ -346,7 +346,7 @@ void main() { return File('./test/fixtures/map_images.tmx').readAsString().then((xml) { map = TiledMap.parseTmx( xml, - tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], + tsxProviders: [FixtureTsxProvider.all()], ); expect(map.layers.length, equals(2)); }); @@ -361,7 +361,7 @@ void main() { .then((xml) { map = TiledMap.parseTmx( xml, - tsxProviders: [FixtureTsxProvider.all('./test/fixtures')], + tsxProviders: [FixtureTsxProvider.all()], ); return; }); @@ -434,7 +434,7 @@ class FixtureTsxProvider extends ParserProvider { FixtureTsxProvider(this.root, this.files); - factory FixtureTsxProvider.all(String directory) { + factory FixtureTsxProvider.all([String directory = './test/fixtures']) { final dir = Directory(directory); if (!dir.existsSync()) { throw '[FixtureTsxProvider] Supplied directory does not exist!'; @@ -447,27 +447,22 @@ class FixtureTsxProvider extends ParserProvider { .map((e) => paths.basename(e.path)) .toList(); - return FixtureTsxProvider(directory, names); - } - - factory FixtureTsxProvider.file(String path) { - final file = File(path); - if (!file.existsSync()) { - throw '[FixtureTsxProvider] Supplied path does not match any file!'; - } - - return FixtureTsxProvider(paths.dirname(path), [paths.basename(path)]); + return FixtureTsxProvider(paths.absolute(directory), names); } final Map cache = {}; @override - bool canProvide(String filename) => true; + bool canProvide(String filename) { + return files.contains(filename); + } @override - Parser? getCachedSource(String filename) => cache.containsKey(filename) - ? XmlParser.fromString(cache[filename]!) - : null; + Parser? getCachedSource(String filename) { + return cache.containsKey(filename) + ? XmlParser.fromString(cache[filename]!) + : null; + } @override Parser getSource(String filename) { From 4bb6dedf58a311abde734750f4716e961aa1af97 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Sat, 21 Dec 2024 09:52:01 +0100 Subject: [PATCH 09/13] rebased and some fine tuning --- README.md | 69 ++++++++++++++++++++------- packages/tiled/lib/src/parser.dart | 29 ++++------- packages/tiled/lib/src/template.dart | 4 -- packages/tiled/lib/src/tiled_map.dart | 36 ++------------ 4 files changed, 65 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 874776a..f12fb70 100644 --- a/README.md +++ b/README.md @@ -26,14 +26,19 @@ Load a TMX file into a string by any means, and then pass the string to TileMapP ```dart final String tmxBody = /* ... */; - final TiledMap mapTmx = TileMapParser.parseTmx(tmxBody); + final TiledMap mapTmx = TiledMap.parseTmx(tmxBody); ``` -If your tmx file includes a external tsx reference, you have to add a CustomParser. This can either be done by using extending the TsxProviderBase, which can match multiple files, or by extending TsxProvider, which only matches on file by its name. +If your tmx file includes external reference, e.g. for .tsx files, you have to add providers. +These providers are then used to find these files and load their contents as a string, +as well as maybe caching them. + +To construct a provider for tsx files for example you can just extend the Provider +or ParserProvider class, which is just a type alias. ```dart -class MultipleTsxProvider extends TsxProviderBase { +class MultipleTsxProvider extends ParserProvider { @override - bool checkProvidable(String filename) => ["external1.tsx", "external2.tsx"].contains(filename); + bool canProvide(String filename) => ["external1.tsx", "external2.tsx"].contains(filename); @override Parser? getCachedSource(String filename) => null; @@ -47,34 +52,64 @@ class MultipleTsxProvider extends TsxProviderBase { } ``` +If, for example, all your tsx files are in one directory, +adding only one RelativeTsxProvider can allow the Parser to find all of them. + ```dart -class SingleTsxProvider extends TsxProvider { +class RelativeTsxProvider extends TsxProviderBase { + final String root; + + RelativeTsxProvider(this.root); + @override - String get filename => "external.tsx"; - + bool canProvide(String filename) { + if (cache.containsKey(filename)) return true; + + final exists = File(paths.join(root, filename)).existsSync(); + if (exists) cache[filename] = null; + + return exists; + } + + Map cache = {}; + @override - Parser? getCachedSource() => null; - + Parser? getCachedSource(String filename) => cache[filename]; + @override - Parser getSource(String _) { - final xml = File(filename).readAsStringSync(); - final node = XmlDocument.parse(xml).rootElement; - return XmlParser(node); + Parser getSource(String filename) { + final xml = XmlDocument.parse(File(paths.join(root, filename)).readAsStringSync()); + final element = xml.getElement("tileset"); + if (element == null) { + throw ParsingException( + "tileset", + null, + "This tsx file does not seem to contain a top-level tileset tag", + ); + } + + cache[filename] = XmlParser(element); + return cache[filename]!; } } ``` -And use it in the parseTmx method. Keep in mind that the first TsxProvider that can provide a source is used! + +These providers are passed to the parseTmx or parseJson method. +Keep in mind that the first Provider that can provide a source is used! + ```dart final String tmxBody = /* ... */; - final TiledMap mapTmx = TileMapParser.parseTmx(tmxBody, tsxProviders: [SingleTsxProvider(), MultipleTsxProvider()]); - + final TiledMap mapTmx = TiledMap.parseTmx( + tmxBody, + tsxProviders: [SingleTsxProvider(), MultipleTsxProvider()], + ); ``` ### Load Json Files Alternatively load a json file. ```dart final String jsonBody = /* ... */; - final TiledMap mapTmx = TileMapParser.parseJson(jsonBody); + final TiledMap mapTmx = TiledMap.parseJson(jsonBody); ``` ### Implementation diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index 80a75a5..4934d7f 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -14,16 +14,10 @@ class XmlParser extends Parser { XmlParser(this.element, {super.tsxProviders, super.templateProviders}); - factory XmlParser.fromString( - String string, { - List? tsxProviders, - List? templateProviders, - }) => - XmlParser( - XmlDocument.parse(string).rootElement, - tsxProviders: tsxProviders, - templateProviders: templateProviders, - ); + XmlParser.fromString(String string, { + super.tsxProviders, + super.templateProviders, + }) : element = XmlDocument.parse(string).rootElement; @override String? getInnerTextOrNull() => @@ -62,7 +56,7 @@ class XmlParser extends Parser { @override T formatSpecificParsing( T Function(JsonParser) json, - T Function(XmlParser) xml, + T Function(XmlParser) xml ) { return xml(this); } @@ -73,16 +67,9 @@ class JsonParser extends Parser { JsonParser(this.json, {super.tsxProviders, super.templateProviders}); - factory JsonParser.fromString( - String string, { - List? tsxProviders, - List? templateProviders, - }) => - JsonParser( - jsonDecode(string) as Map, - tsxProviders: tsxProviders, - templateProviders: templateProviders, - ); + JsonParser.fromString(String string, { + super.tsxProviders, super.templateProviders, + }) : json = jsonDecode(string) as Map; @override String? getInnerTextOrNull() => null; diff --git a/packages/tiled/lib/src/template.dart b/packages/tiled/lib/src/template.dart index d6b55e8..ea7a983 100644 --- a/packages/tiled/lib/src/template.dart +++ b/packages/tiled/lib/src/template.dart @@ -34,7 +34,3 @@ class Template { object: parser.getSingleChildOrNullAs('object', TiledObject.parse), ); } - -class TemplateReference { - -} \ No newline at end of file diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index a26b41b..fcb7fa1 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -128,36 +128,6 @@ class TiledMap { this.properties = CustomProperties.empty, }); - /// Takes a string [contents] and converts it to a [TiledMap] with the help of - /// the [TsxProvider]s returned from the [tsxProviderFunction]. - /// The [tsxProviderFunction] is most commonly your static [TsxProvider.parse] - /// implementation. - // TODO: why is this here? same as parseTmx??? - // static Future fromString( - // String contents, { - // List? tsxProviders, - // List? templateProviders, - // List? imageProviders, - // }) async { - // final tsxSourcePaths = XmlDocument.parse(contents) - // .rootElement - // .children - // .whereType() - // .where((element) => element.name.local == 'tileset') - // .map((e) => e.getAttribute('source')); - // - // final tsxProviders = await Future.wait( - // tsxSourcePaths - // .where((key) => key != null) - // .map((key) async => tsxProviderFunction(key!)), - // ); - // - // return TileMapParser.parseTmx( - // contents, - // tsxList: tsxProviders.isEmpty ? null : tsxProviders, - // ); - // } - // Convenience Methods Tile? tileByGid(int tileGid) { if (tileGid == 0) { @@ -318,7 +288,11 @@ class TiledMap { ); } - static TiledMap parseJson( + /// Parses the provided json. + /// + /// Accepts an optional list of external TsxProviders for external tilesets + /// referenced in the map file. + factory TiledMap.parseJson( String json, { List? tsxProviders, List? templateProviders, From 7f08edf7d7a506357b3845ba94a99cdf9cfc2f38 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 28 Dec 2024 21:29:12 +0100 Subject: [PATCH 10/13] Re-trigger check From 80d09014f233dd8b963303df832283921c3160ab Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 28 Dec 2024 21:48:49 +0100 Subject: [PATCH 11/13] Fix up rebase --- packages/tiled/lib/src/parser.dart | 15 +++++++++------ packages/tiled/lib/src/provider.dart | 4 ++-- packages/tiled/lib/src/tiled_map.dart | 1 + packages/tiled/lib/tiled.dart | 3 +-- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index 4934d7f..72c4ac4 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; @@ -14,7 +16,8 @@ class XmlParser extends Parser { XmlParser(this.element, {super.tsxProviders, super.templateProviders}); - XmlParser.fromString(String string, { + XmlParser.fromString( + String string, { super.tsxProviders, super.templateProviders, }) : element = XmlDocument.parse(string).rootElement; @@ -55,9 +58,7 @@ class XmlParser extends Parser { @override T formatSpecificParsing( - T Function(JsonParser) json, - T Function(XmlParser) xml - ) { + T Function(JsonParser) json, T Function(XmlParser) xml) { return xml(this); } } @@ -67,8 +68,10 @@ class JsonParser extends Parser { JsonParser(this.json, {super.tsxProviders, super.templateProviders}); - JsonParser.fromString(String string, { - super.tsxProviders, super.templateProviders, + JsonParser.fromString( + String string, { + super.tsxProviders, + super.templateProviders, }) : json = jsonDecode(string) as Map; @override diff --git a/packages/tiled/lib/src/provider.dart b/packages/tiled/lib/src/provider.dart index 99b8dd0..fd122ba 100644 --- a/packages/tiled/lib/src/provider.dart +++ b/packages/tiled/lib/src/provider.dart @@ -1,4 +1,4 @@ -part of tiled; +import 'package:tiled/tiled.dart'; abstract class Provider { bool canProvide(String path); @@ -8,4 +8,4 @@ abstract class Provider { } typedef ParserProvider = Provider; -typedef ImagePathProvider = Provider; \ No newline at end of file +typedef ImagePathProvider = Provider; diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index fcb7fa1..177475d 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -1,4 +1,5 @@ import 'dart:collection'; +import 'dart:convert'; import 'package:collection/collection.dart'; import 'package:tiled/tiled.dart'; diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index e0a7f2f..4bd636b 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -14,8 +14,8 @@ export 'src/layer.dart'; export 'src/objects/text.dart'; export 'src/objects/tiled_object.dart'; export 'src/parser.dart'; +export 'src/provider.dart'; export 'src/template.dart'; -export 'src/tile_map_parser.dart'; export 'src/tiled_map.dart'; export 'src/tileset/grid.dart'; export 'src/tileset/terrain.dart'; @@ -25,4 +25,3 @@ export 'src/tileset/tileset.dart'; export 'src/tileset/wang/wang_color.dart'; export 'src/tileset/wang/wang_set.dart'; export 'src/tileset/wang/wang_tile.dart'; -export 'src/tsx_provider.dart'; From dadb9c1a649d5a8894eb1ee4765d31a8e15184cb Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 28 Dec 2024 21:50:12 +0100 Subject: [PATCH 12/13] Fix formatting --- packages/tiled/lib/src/objects/tiled_object.dart | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/tiled/lib/src/objects/tiled_object.dart b/packages/tiled/lib/src/objects/tiled_object.dart index 954bfcd..16f8b0e 100644 --- a/packages/tiled/lib/src/objects/tiled_object.dart +++ b/packages/tiled/lib/src/objects/tiled_object.dart @@ -105,8 +105,7 @@ class TiledObject { bool get isRectangle => rectangle; - factory TiledObject.parse( - Parser parser) { + factory TiledObject.parse(Parser parser) { final x = parser.getDouble('x', defaults: 0); final y = parser.getDouble('y', defaults: 0); final height = parser.getDouble('height', defaults: 0); @@ -137,7 +136,8 @@ class TiledObject { final templatePath = parser.getStringOrNull('template'); final templateProvider = templatePath == null ? null - : parser.templateProviders?.firstWhere((e) => e.canProvide(templatePath)); + : parser.templateProviders + ?.firstWhere((e) => e.canProvide(templatePath)); final template = templateProvider == null ? null : Template.parse( From 6ddbfdc9145a83d691f2e9247992eaa41722fcd0 Mon Sep 17 00:00:00 2001 From: Lukas Klingsbo Date: Sat, 28 Dec 2024 21:51:02 +0100 Subject: [PATCH 13/13] Fix analyzer --- packages/tiled/lib/src/layer.dart | 4 +-- packages/tiled/lib/src/parser.dart | 40 ++++++++++++++++++------------ packages/tiled/pubspec.yaml | 2 +- 3 files changed, 27 insertions(+), 19 deletions(-) diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 9bbfb90..d544d22 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -336,7 +336,7 @@ abstract class Layer { decompressed = const ZLibDecoder().decodeBytes(decodedString); break; case Compression.gzip: - decompressed = GZipDecoder().decodeBytes(decodedString); + decompressed = const GZipDecoder().decodeBytes(decodedString); break; case Compression.zstd: throw UnsupportedError('zstd is an unsupported compression'); @@ -428,7 +428,7 @@ class TileLayer extends Layer { } class ObjectGroup extends Layer { - static const defaultColor = ColorData.rgb(160, 160, 164, 255); + static const defaultColor = ColorData.rgb(160, 160, 164); static const defaultColorHex = '%a0a0a4'; /// topdown (default) or index (indexOrder). diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index 72c4ac4..2f6d64b 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -36,11 +36,13 @@ class XmlParser extends Parser { return element.children .whereType() .where((e) => e.name.local == name) - .map((e) => XmlParser( - e, - templateProviders: templateProviders, - tsxProviders: tsxProviders, - )) + .map( + (e) => XmlParser( + e, + templateProviders: templateProviders, + tsxProviders: tsxProviders, + ), + ) .toList(); } @@ -48,17 +50,21 @@ class XmlParser extends Parser { return element.children .whereType() .where((e) => names.contains(e.name.local)) - .map((e) => XmlParser( - e, - tsxProviders: tsxProviders, - templateProviders: templateProviders, - )) + .map( + (e) => XmlParser( + e, + tsxProviders: tsxProviders, + templateProviders: templateProviders, + ), + ) .toList(); } @override T formatSpecificParsing( - T Function(JsonParser) json, T Function(XmlParser) xml) { + T Function(JsonParser) json, + T Function(XmlParser) xml, + ) { return xml(this); } } @@ -88,11 +94,13 @@ class JsonParser extends Parser { return []; } return (json[name] as List) - .map((dynamic e) => JsonParser( - e as Map, - templateProviders: templateProviders, - tsxProviders: tsxProviders, - )) + .map( + (dynamic e) => JsonParser( + e as Map, + templateProviders: templateProviders, + tsxProviders: tsxProviders, + ), + ) .toList(); } diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index 4fc2027..14b3833 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -15,5 +15,5 @@ dependencies: dev_dependencies: dartdoc: ^8.3.1 flame_lint: ^1.1.2 - test: ^1.24.8 path: ^1.8.3 + test: ^1.24.8