From c37b7cf7ff2267299e20dc8de082d0571abf4952 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 24 Oct 2023 23:55:08 +0200 Subject: [PATCH 01/17] 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/color.dart | 9 +++++++++ packages/tiled/lib/src/common/property.dart | 4 ++-- packages/tiled/lib/src/common/rect.dart | 17 +++++++++++++++++ packages/tiled/lib/src/layer.dart | 8 ++++---- packages/tiled/lib/src/parser.dart | 4 ++-- packages/tiled/lib/src/tiled_map.dart | 2 +- packages/tiled/lib/tiled.dart | 4 +++- packages/tiled/pubspec.yaml | 7 ++----- .../tiled/test/complexmap_infinite_test.dart | 2 +- packages/tiled/test/image_layer_test.dart | 2 +- .../tiled/test/isometric_staggered_test.dart | 2 +- packages/tiled/test/isometric_test.dart | 2 +- packages/tiled/test/layer_test.dart | 4 ++-- packages/tiled/test/map_test.dart | 2 +- packages/tiled/test/object_group_test.dart | 4 ++-- packages/tiled/test/overflow_bug_test.dart | 2 +- packages/tiled/test/parser_compare_test.dart | 2 +- packages/tiled/test/parser_test.dart | 8 ++++---- packages/tiled/test/rectangle_map_test.dart | 2 +- packages/tiled/test/tile_test.dart | 16 ++++++++-------- packages/tiled/test/tileset_test.dart | 2 +- packages/tiled/test/tmx_object_test.dart | 2 +- 22 files changed, 66 insertions(+), 41 deletions(-) create mode 100644 packages/tiled/lib/src/common/color.dart create mode 100644 packages/tiled/lib/src/common/rect.dart diff --git a/packages/tiled/lib/src/common/color.dart b/packages/tiled/lib/src/common/color.dart new file mode 100644 index 0000000..913f101 --- /dev/null +++ b/packages/tiled/lib/src/common/color.dart @@ -0,0 +1,9 @@ +import 'package:color_models/color_models.dart'; + +const _mask = 0xff; +int _sub(int hex, int index) => (hex & (_mask << index * 8)) >> index * 8; + +class Color extends RgbColor { + /// Format: aarrggbb + Color(int hex) : super(_sub(hex, 2), _sub(hex, 1), _sub(hex, 0), _sub(hex, 3)); +} diff --git a/packages/tiled/lib/src/common/property.dart b/packages/tiled/lib/src/common/property.dart index b52e9ac..840fb8e 100644 --- a/packages/tiled/lib/src/common/property.dart +++ b/packages/tiled/lib/src/common/property.dart @@ -37,7 +37,7 @@ class Property { case PropertyType.color: return ColorProperty( name: name, - value: parser.getColor('value', defaults: const Color(0x00000000)), + value: parser.getColor('value', defaults: Color(0x00000000)), hexValue: parser.getString('value', defaults: '#00000000'), ); @@ -156,7 +156,7 @@ class ObjectProperty extends Property { } /// [value] is the color -class ColorProperty extends Property { +class ColorProperty extends Property { final String hexValue; ColorProperty({ 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 ccff08d..c5a14d3 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -81,7 +81,7 @@ abstract class Layer { /// child layers (optional). /// /// Parsed from [tintColorHex], will be null if parsing fails for any reason. - Color? tintColor; + ColorModel? tintColor; /// The opacity of the layer as a value from 0 to 1. Defaults to 1. double opacity; @@ -420,7 +420,7 @@ class TileLayer extends Layer { } class ObjectGroup extends Layer { - static const defaultColor = Color.fromARGB(255, 160, 160, 164); + static const defaultColor = RgbColor(160, 160, 164, 255); static const defaultColorHex = '%a0a0a4'; /// topdown (default) or index (indexOrder). @@ -438,7 +438,7 @@ class ObjectGroup extends Layer { /// /// Parsed from [colorHex], will be fallback to [defaultColor] if parsing /// fails for any reason. - Color color; + ColorModel color; ObjectGroup({ super.id, @@ -478,7 +478,7 @@ class ImageLayer extends Layer { /// /// Parsed from [transparentColorHex], will be null if parsing fails for any /// reason. - Color? transparentColor; + ColorModel? transparentColor; /// Whether or not to repeat the image on the X-axis bool repeatX; diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index 3cd278a..f6416cd 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -197,7 +197,7 @@ abstract class Parser { return result; } - Color? getColorOrNull(String name, {Color? defaults}) { + ColorModel? getColorOrNull(String name, {ColorModel? defaults}) { final tiledColor = getStringOrNull(name); // Tiled colors are stored as either ARGB or RGB hex values, so we can @@ -218,7 +218,7 @@ abstract class Parser { } } - Color getColor(String name, {Color? defaults}) { + ColorModel getColor(String name, {ColorModel? defaults}) { final result = getColorOrNull(name, defaults: defaults); if (result == null) { throw ParsingException(name, null, 'Missing required color field'); diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index f976762..8576d1b 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -79,7 +79,7 @@ class TiledMap { /// /// Parsed from [backgroundColorHex], will be null if parsing fails for any /// reason. - Color? backgroundColor; + ColorModel? backgroundColor; int compressionLevel; diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index 4907cc5..ffe3c0c 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -4,11 +4,13 @@ import 'dart:collection'; import 'dart:convert'; import 'dart:math' show Rectangle; import 'dart:typed_data'; -import 'dart:ui'; import 'package:archive/archive.dart'; import 'package:collection/collection.dart'; +import 'package:color_models/color_models.dart'; import 'package:meta/meta.dart'; +import 'package:tiled/src/common/color.dart'; +import 'package:tiled/src/common/rect.dart'; import 'package:xml/xml.dart'; part 'src/chunk.dart'; diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index ca1c5c8..5fa1ce0 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -8,13 +8,10 @@ environment: dependencies: archive: ^3.3.0 collection: ^1.16.0 - flutter: - sdk: flutter meta: ^1.7.0 xml: ^6.1.0 + color_models: ^1.3.3 dev_dependencies: dartdoc: ^6.0.1 - flame_lint: ^0.2.0 - flutter_test: - sdk: flutter + test: ^1.24.8 diff --git a/packages/tiled/test/complexmap_infinite_test.dart b/packages/tiled/test/complexmap_infinite_test.dart index 5ab581c..ca5bf49 100644 --- a/packages/tiled/test/complexmap_infinite_test.dart +++ b/packages/tiled/test/complexmap_infinite_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/image_layer_test.dart b/packages/tiled/test/image_layer_test.dart index da3a9c6..3b52721 100644 --- a/packages/tiled/test/image_layer_test.dart +++ b/packages/tiled/test/image_layer_test.dart @@ -1,7 +1,7 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; import 'package:tiled/tiled.dart'; +import 'package:test/test.dart'; void main() { late TiledMap map; diff --git a/packages/tiled/test/isometric_staggered_test.dart b/packages/tiled/test/isometric_staggered_test.dart index 00e9e33..4e13832 100644 --- a/packages/tiled/test/isometric_staggered_test.dart +++ b/packages/tiled/test/isometric_staggered_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/isometric_test.dart b/packages/tiled/test/isometric_test.dart index 66c61bc..9c28c6a 100644 --- a/packages/tiled/test/isometric_test.dart +++ b/packages/tiled/test/isometric_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/layer_test.dart b/packages/tiled/test/layer_test.dart index 984b46f..974c31b 100644 --- a/packages/tiled/test/layer_test.dart +++ b/packages/tiled/test/layer_test.dart @@ -1,7 +1,7 @@ import 'dart:io'; -import 'dart:ui'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; +import 'package:tiled/src/common/color.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/map_test.dart b/packages/tiled/test/map_test.dart index fd86eed..2288cc5 100644 --- a/packages/tiled/test/map_test.dart +++ b/packages/tiled/test/map_test.dart @@ -1,4 +1,4 @@ -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/object_group_test.dart b/packages/tiled/test/object_group_test.dart index d0692cf..eeccc8f 100644 --- a/packages/tiled/test/object_group_test.dart +++ b/packages/tiled/test/object_group_test.dart @@ -1,7 +1,7 @@ import 'dart:io'; -import 'dart:ui'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; +import 'package:tiled/src/common/color.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/overflow_bug_test.dart b/packages/tiled/test/overflow_bug_test.dart index 481c888..27e62b7 100644 --- a/packages/tiled/test/overflow_bug_test.dart +++ b/packages/tiled/test/overflow_bug_test.dart @@ -2,7 +2,7 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/parser_compare_test.dart b/packages/tiled/test/parser_compare_test.dart index ab052d0..4e8b421 100644 --- a/packages/tiled/test/parser_compare_test.dart +++ b/packages/tiled/test/parser_compare_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/parser_test.dart b/packages/tiled/test/parser_test.dart index 519d5b7..4c0bcb9 100644 --- a/packages/tiled/test/parser_test.dart +++ b/packages/tiled/test/parser_test.dart @@ -1,8 +1,8 @@ import 'dart:io'; import 'dart:math' show Rectangle; -import 'dart:ui'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; +import 'package:tiled/src/common/color.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; @@ -89,7 +89,7 @@ void main() { ); expect( properties.getValue('multiline string'), - equals('Hello,\nWorld'), + equals('Hello,\r\nWorld'), ); expect( properties.getValue('integer property'), @@ -101,7 +101,7 @@ void main() { ); expect( properties.getValue('color property'), - equals(const Color(0x00112233)), + equals(Color(0x00112233)), ); expect( properties.getValue('float property'), diff --git a/packages/tiled/test/rectangle_map_test.dart b/packages/tiled/test/rectangle_map_test.dart index 7e70418..797bb5b 100644 --- a/packages/tiled/test/rectangle_map_test.dart +++ b/packages/tiled/test/rectangle_map_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/tile_test.dart b/packages/tiled/test/tile_test.dart index db85d8e..076a0db 100644 --- a/packages/tiled/test/tile_test.dart +++ b/packages/tiled/test/tile_test.dart @@ -1,7 +1,7 @@ import 'dart:io'; -import 'dart:ui'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; +import 'package:tiled/src/common/rect.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; @@ -58,8 +58,8 @@ void main() { final tile1 = tileset1.tiles.firstWhere((t) => t.localId == 0); final tile2 = tileset1.tiles.firstWhere((t) => t.localId == 1); - expect(tile1.imageRect, const Rect.fromLTWH(64, 96, 32, 32)); - expect(tile2.imageRect, const Rect.fromLTWH(0, 0, 20, 20)); + expect(tile1.imageRect, Rect.fromLTWH(64, 96, 32, 32)); + expect(tile2.imageRect, Rect.fromLTWH(0, 0, 20, 20)); }); test( @@ -70,10 +70,10 @@ void main() { final tile3 = tileset2.tiles.firstWhere((t) => t.localId == 129); final tile4 = tileset2.tiles.firstWhere((t) => t.localId == 11); - expect(tile1.imageRect, const Rect.fromLTWH(112, 48, 16, 16)); - expect(tile2.imageRect, const Rect.fromLTWH(64, 96, 16, 16)); - expect(tile3.imageRect, const Rect.fromLTWH(160, 112, 16, 16)); - expect(tile4.imageRect, const Rect.fromLTWH(176, 0, 16, 16)); + expect(tile1.imageRect, Rect.fromLTWH(112, 48, 16, 16)); + expect(tile2.imageRect, Rect.fromLTWH(64, 96, 16, 16)); + expect(tile3.imageRect, Rect.fromLTWH(160, 112, 16, 16)); + expect(tile4.imageRect, Rect.fromLTWH(176, 0, 16, 16)); }, ); }, diff --git a/packages/tiled/test/tileset_test.dart b/packages/tiled/test/tileset_test.dart index 756709b..d5bed4e 100644 --- a/packages/tiled/test/tileset_test.dart +++ b/packages/tiled/test/tileset_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; diff --git a/packages/tiled/test/tmx_object_test.dart b/packages/tiled/test/tmx_object_test.dart index f58d90a..8579ed6 100644 --- a/packages/tiled/test/tmx_object_test.dart +++ b/packages/tiled/test/tmx_object_test.dart @@ -1,6 +1,6 @@ import 'dart:io'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; void main() { From e389a087a020af0c6da7f737daf3caf7b07edf29 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Sat, 28 Oct 2023 15:58:15 +0200 Subject: [PATCH 02/17] replaced custom rect in favor of Rectangle from dart:math --- packages/tiled/lib/src/common/color.dart | 2 +- packages/tiled/lib/src/common/rect.dart | 17 ----------------- packages/tiled/lib/src/tileset/tile.dart | 4 ++-- packages/tiled/lib/src/tileset/tileset.dart | 4 ++-- packages/tiled/lib/tiled.dart | 3 +-- packages/tiled/pubspec.yaml | 2 +- packages/tiled/test/layer_test.dart | 1 - packages/tiled/test/object_group_test.dart | 1 - packages/tiled/test/parser_test.dart | 1 - packages/tiled/test/tile_test.dart | 14 +++++++------- 10 files changed, 14 insertions(+), 35 deletions(-) delete mode 100644 packages/tiled/lib/src/common/rect.dart diff --git a/packages/tiled/lib/src/common/color.dart b/packages/tiled/lib/src/common/color.dart index 913f101..9911ac7 100644 --- a/packages/tiled/lib/src/common/color.dart +++ b/packages/tiled/lib/src/common/color.dart @@ -1,4 +1,4 @@ -import 'package:color_models/color_models.dart'; +part of tiled; const _mask = 0xff; int _sub(int hex, int index) => (hex & (_mask << index * 8)) >> index * 8; 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/lib/src/tileset/tile.dart b/packages/tiled/lib/src/tileset/tile.dart index c2c1c74..a10a2e3 100644 --- a/packages/tiled/lib/src/tileset/tile.dart +++ b/packages/tiled/lib/src/tileset/tile.dart @@ -27,7 +27,7 @@ class Tile { List terrain; TiledImage? image; - Rect? imageRect; + Rectangle? imageRect; Layer? objectGroup; List animation; CustomProperties properties; @@ -66,7 +66,7 @@ class Tile { .toList() ?? [], image: parser.getSingleChildOrNullAs('image', TiledImage.parse), - imageRect: Rect.fromLTWH( + imageRect: Rectangle( parser.getDoubleOrNull('x') ?? 0, parser.getDoubleOrNull('y') ?? 0, parser.getDoubleOrNull('width') ?? 0, diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index b26584e..49d64f3 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -230,7 +230,7 @@ class Tileset { final tiles = []; for (var i = 0; i < tileCount; ++i) { - Rect? imageRect; + Rectangle? imageRect; if (columns != null && columns != 0 && @@ -239,7 +239,7 @@ class Tileset { final x = (i % columns) * tileWidth; final y = i ~/ columns * tileHeight; - imageRect = Rect.fromLTWH( + imageRect = Rectangle( x.toDouble(), y.toDouble(), tileWidth.toDouble(), diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index ffe3c0c..5d33d4a 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -9,8 +9,6 @@ import 'package:archive/archive.dart'; import 'package:collection/collection.dart'; import 'package:color_models/color_models.dart'; import 'package:meta/meta.dart'; -import 'package:tiled/src/common/color.dart'; -import 'package:tiled/src/common/rect.dart'; import 'package:xml/xml.dart'; part 'src/chunk.dart'; @@ -21,6 +19,7 @@ part 'src/common/gid.dart'; part 'src/common/point.dart'; part 'src/common/property.dart'; part 'src/common/tiled_image.dart'; +part 'src/common/color.dart'; part 'src/editor_setting/chunk_size.dart'; part 'src/editor_setting/editor_setting.dart'; part 'src/editor_setting/export.dart'; diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index 5fa1ce0..280a58f 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -1,5 +1,5 @@ name: tiled -version: 0.10.1 +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 diff --git a/packages/tiled/test/layer_test.dart b/packages/tiled/test/layer_test.dart index 974c31b..73a7ae5 100644 --- a/packages/tiled/test/layer_test.dart +++ b/packages/tiled/test/layer_test.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:test/test.dart'; -import 'package:tiled/src/common/color.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/object_group_test.dart b/packages/tiled/test/object_group_test.dart index eeccc8f..8acd54a 100644 --- a/packages/tiled/test/object_group_test.dart +++ b/packages/tiled/test/object_group_test.dart @@ -1,7 +1,6 @@ import 'dart:io'; import 'package:test/test.dart'; -import 'package:tiled/src/common/color.dart'; import 'package:tiled/tiled.dart'; void main() { diff --git a/packages/tiled/test/parser_test.dart b/packages/tiled/test/parser_test.dart index 4c0bcb9..bf7ebd4 100644 --- a/packages/tiled/test/parser_test.dart +++ b/packages/tiled/test/parser_test.dart @@ -2,7 +2,6 @@ import 'dart:io'; import 'dart:math' show Rectangle; import 'package:test/test.dart'; -import 'package:tiled/src/common/color.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; diff --git a/packages/tiled/test/tile_test.dart b/packages/tiled/test/tile_test.dart index 076a0db..c75ae19 100644 --- a/packages/tiled/test/tile_test.dart +++ b/packages/tiled/test/tile_test.dart @@ -1,7 +1,7 @@ import 'dart:io'; +import 'dart:math'; import 'package:test/test.dart'; -import 'package:tiled/src/common/rect.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; @@ -58,8 +58,8 @@ void main() { final tile1 = tileset1.tiles.firstWhere((t) => t.localId == 0); final tile2 = tileset1.tiles.firstWhere((t) => t.localId == 1); - expect(tile1.imageRect, Rect.fromLTWH(64, 96, 32, 32)); - expect(tile2.imageRect, Rect.fromLTWH(0, 0, 20, 20)); + expect(tile1.imageRect, Rectangle(64, 96, 32, 32)); + expect(tile2.imageRect, Rectangle(0, 0, 20, 20)); }); test( @@ -70,10 +70,10 @@ void main() { final tile3 = tileset2.tiles.firstWhere((t) => t.localId == 129); final tile4 = tileset2.tiles.firstWhere((t) => t.localId == 11); - expect(tile1.imageRect, Rect.fromLTWH(112, 48, 16, 16)); - expect(tile2.imageRect, Rect.fromLTWH(64, 96, 16, 16)); - expect(tile3.imageRect, Rect.fromLTWH(160, 112, 16, 16)); - expect(tile4.imageRect, Rect.fromLTWH(176, 0, 16, 16)); + expect(tile1.imageRect, Rectangle(112, 48, 16, 16)); + expect(tile2.imageRect, Rectangle(64, 96, 16, 16)); + expect(tile3.imageRect, Rectangle(160, 112, 16, 16)); + expect(tile4.imageRect, Rectangle(176, 0, 16, 16)); }, ); }, From 8f38c1c93050cfb750e3a51d7cf99732859c80dc Mon Sep 17 00:00:00 2001 From: benni-tec Date: Sun, 29 Oct 2023 16:28:43 +0100 Subject: [PATCH 03/17] removed color_models dependency in favor of a basic data class in color.dart --- packages/tiled/lib/src/common/color.dart | 26 ++++++++++++++++++--- packages/tiled/lib/src/common/property.dart | 4 ++-- packages/tiled/lib/src/layer.dart | 8 +++---- packages/tiled/lib/src/parser.dart | 6 ++--- packages/tiled/lib/src/tiled_map.dart | 2 +- packages/tiled/lib/tiled.dart | 1 - packages/tiled/pubspec.yaml | 1 - packages/tiled/test/layer_test.dart | 2 +- packages/tiled/test/object_group_test.dart | 2 +- packages/tiled/test/parser_test.dart | 4 ++-- 10 files changed, 37 insertions(+), 19 deletions(-) diff --git a/packages/tiled/lib/src/common/color.dart b/packages/tiled/lib/src/common/color.dart index 9911ac7..f1e077c 100644 --- a/packages/tiled/lib/src/common/color.dart +++ b/packages/tiled/lib/src/common/color.dart @@ -1,9 +1,29 @@ part of tiled; const _mask = 0xff; -int _sub(int hex, int index) => (hex & (_mask << index * 8)) >> index * 8; -class Color extends RgbColor { +int _sub(int hex, int index) { + final value = (hex & (_mask << index * 8)) >> index * 8; + assert(value >= 0 && value < 256); + return value; +} + +class Color { + final int red; + final int green; + final int blue; + final int alpha; + /// Format: aarrggbb - Color(int hex) : super(_sub(hex, 2), _sub(hex, 1), _sub(hex, 0), _sub(hex, 3)); + Color.hex(int hex) + : alpha = _sub(hex, 3), + red = _sub(hex, 2), + green = _sub(hex, 1), + blue = _sub(hex, 0); + + const Color.rgb(this.red, this.green, this.blue, [this.alpha = 255]) + : assert(red >= 0 && red <= 255), + assert(green >= 0 && green <= 255), + assert(blue >= 0 && blue <= 255), + assert(alpha >= 0 && alpha <= 255); } diff --git a/packages/tiled/lib/src/common/property.dart b/packages/tiled/lib/src/common/property.dart index 840fb8e..5fadae3 100644 --- a/packages/tiled/lib/src/common/property.dart +++ b/packages/tiled/lib/src/common/property.dart @@ -37,7 +37,7 @@ class Property { case PropertyType.color: return ColorProperty( name: name, - value: parser.getColor('value', defaults: Color(0x00000000)), + value: parser.getColor('value', defaults: Color.hex(0x00000000)), hexValue: parser.getString('value', defaults: '#00000000'), ); @@ -156,7 +156,7 @@ class ObjectProperty extends Property { } /// [value] is the color -class ColorProperty extends Property { +class ColorProperty extends Property { final String hexValue; ColorProperty({ diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index c5a14d3..9e4b683 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -81,7 +81,7 @@ abstract class Layer { /// child layers (optional). /// /// Parsed from [tintColorHex], will be null if parsing fails for any reason. - ColorModel? tintColor; + Color? tintColor; /// The opacity of the layer as a value from 0 to 1. Defaults to 1. double opacity; @@ -420,7 +420,7 @@ class TileLayer extends Layer { } class ObjectGroup extends Layer { - static const defaultColor = RgbColor(160, 160, 164, 255); + static const defaultColor = Color.rgb(160, 160, 164, 255); static const defaultColorHex = '%a0a0a4'; /// topdown (default) or index (indexOrder). @@ -438,7 +438,7 @@ class ObjectGroup extends Layer { /// /// Parsed from [colorHex], will be fallback to [defaultColor] if parsing /// fails for any reason. - ColorModel color; + Color color; ObjectGroup({ super.id, @@ -478,7 +478,7 @@ class ImageLayer extends Layer { /// /// Parsed from [transparentColorHex], will be null if parsing fails for any /// reason. - ColorModel? transparentColor; + Color? transparentColor; /// Whether or not to repeat the image on the X-axis bool repeatX; diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index f6416cd..2fe6201 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -197,7 +197,7 @@ abstract class Parser { return result; } - ColorModel? getColorOrNull(String name, {ColorModel? defaults}) { + Color? getColorOrNull(String name, {Color? defaults}) { final tiledColor = getStringOrNull(name); // Tiled colors are stored as either ARGB or RGB hex values, so we can @@ -212,13 +212,13 @@ abstract class Parser { } if (colorValue != null) { - return Color(colorValue); + return Color.hex(colorValue); } else { return defaults; } } - ColorModel getColor(String name, {ColorModel? defaults}) { + Color getColor(String name, {Color? defaults}) { final result = getColorOrNull(name, defaults: defaults); if (result == null) { throw ParsingException(name, null, 'Missing required color field'); diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index 8576d1b..f976762 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -79,7 +79,7 @@ class TiledMap { /// /// Parsed from [backgroundColorHex], will be null if parsing fails for any /// reason. - ColorModel? backgroundColor; + Color? backgroundColor; int compressionLevel; diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index 5d33d4a..c658c47 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -7,7 +7,6 @@ import 'dart:typed_data'; import 'package:archive/archive.dart'; import 'package:collection/collection.dart'; -import 'package:color_models/color_models.dart'; import 'package:meta/meta.dart'; import 'package:xml/xml.dart'; diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index 280a58f..636356b 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -10,7 +10,6 @@ dependencies: collection: ^1.16.0 meta: ^1.7.0 xml: ^6.1.0 - color_models: ^1.3.3 dev_dependencies: dartdoc: ^6.0.1 diff --git a/packages/tiled/test/layer_test.dart b/packages/tiled/test/layer_test.dart index 73a7ae5..ff200b1 100644 --- a/packages/tiled/test/layer_test.dart +++ b/packages/tiled/test/layer_test.dart @@ -74,7 +74,7 @@ void main() { expect(layer.tintColorHex, equals('#ffaabb')); expect( layer.tintColor, - equals(Color(int.parse('0xffffaabb'))), + equals(Color.hex(int.parse('0xffffaabb'))), ); }); }); diff --git a/packages/tiled/test/object_group_test.dart b/packages/tiled/test/object_group_test.dart index 8acd54a..98d5ac0 100644 --- a/packages/tiled/test/object_group_test.dart +++ b/packages/tiled/test/object_group_test.dart @@ -30,7 +30,7 @@ void main() { expect(objectGroup.colorHex, equals('#555500')); expect( objectGroup.color, - equals(Color(int.parse('0xff555500'))), + equals(Color.hex(int.parse('0xff555500'))), ); }); diff --git a/packages/tiled/test/parser_test.dart b/packages/tiled/test/parser_test.dart index bf7ebd4..2e05c24 100644 --- a/packages/tiled/test/parser_test.dart +++ b/packages/tiled/test/parser_test.dart @@ -43,7 +43,7 @@ void main() { expect(map.backgroundColorHex, equals('#ccddaaff')); expect( map.backgroundColor, - equals(Color(int.parse('0xccddaaff'))), + equals(Color.hex(int.parse('0xccddaaff'))), ); }); @@ -100,7 +100,7 @@ void main() { ); expect( properties.getValue('color property'), - equals(Color(0x00112233)), + equals(Color.hex(0x00112233)), ); expect( properties.getValue('float property'), From f6978009ce53532a8ad30990a144a3e26dd3de85 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 19:42:56 +0100 Subject: [PATCH 04/17] renamed Color to ColorData to make conversion easier in flame_tiled // added tests for hex decoding in ColorData --- packages/tiled/lib/src/common/color.dart | 14 ++++-------- packages/tiled/lib/src/common/property.dart | 4 ++-- packages/tiled/lib/src/layer.dart | 14 ++++++------ packages/tiled/lib/src/parser.dart | 6 ++--- packages/tiled/lib/src/tiled_map.dart | 4 ++-- packages/tiled/test/color.dart | 25 +++++++++++++++++++++ packages/tiled/test/layer_test.dart | 2 +- packages/tiled/test/object_group_test.dart | 2 +- packages/tiled/test/parser_test.dart | 6 ++--- 9 files changed, 48 insertions(+), 29 deletions(-) create mode 100644 packages/tiled/test/color.dart diff --git a/packages/tiled/lib/src/common/color.dart b/packages/tiled/lib/src/common/color.dart index f1e077c..f5cda41 100644 --- a/packages/tiled/lib/src/common/color.dart +++ b/packages/tiled/lib/src/common/color.dart @@ -1,27 +1,21 @@ part of tiled; -const _mask = 0xff; +class ColorData { + static int _sub(int hex, int index) => (hex >> index * 8) & 0x000000ff; -int _sub(int hex, int index) { - final value = (hex & (_mask << index * 8)) >> index * 8; - assert(value >= 0 && value < 256); - return value; -} - -class Color { final int red; final int green; final int blue; final int alpha; /// Format: aarrggbb - Color.hex(int hex) + ColorData.hex(int hex) : alpha = _sub(hex, 3), red = _sub(hex, 2), green = _sub(hex, 1), blue = _sub(hex, 0); - const Color.rgb(this.red, this.green, this.blue, [this.alpha = 255]) + const ColorData.rgb(this.red, this.green, this.blue, [this.alpha = 255]) : assert(red >= 0 && red <= 255), assert(green >= 0 && green <= 255), assert(blue >= 0 && blue <= 255), diff --git a/packages/tiled/lib/src/common/property.dart b/packages/tiled/lib/src/common/property.dart index 5fadae3..b14e03d 100644 --- a/packages/tiled/lib/src/common/property.dart +++ b/packages/tiled/lib/src/common/property.dart @@ -37,7 +37,7 @@ class Property { case PropertyType.color: return ColorProperty( name: name, - value: parser.getColor('value', defaults: Color.hex(0x00000000)), + value: parser.getColor('value', defaults: ColorData.hex(0x00000000)), hexValue: parser.getString('value', defaults: '#00000000'), ); @@ -156,7 +156,7 @@ class ObjectProperty extends Property { } /// [value] is the color -class ColorProperty extends Property { +class ColorProperty extends Property { final String hexValue; ColorProperty({ diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 9e4b683..1169251 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -77,11 +77,11 @@ abstract class Layer { /// any graphics drawn by this layer or any child layers (optional). String? tintColorHex; - /// [Color] that is multiplied with any graphics drawn by this layer or any + /// [ColorData] that is multiplied with any graphics drawn by this layer or any /// child layers (optional). /// /// Parsed from [tintColorHex], will be null if parsing fails for any reason. - Color? tintColor; + ColorData? tintColor; /// The opacity of the layer as a value from 0 to 1. Defaults to 1. double opacity; @@ -420,7 +420,7 @@ class TileLayer extends Layer { } class ObjectGroup extends Layer { - static const defaultColor = Color.rgb(160, 160, 164, 255); + static const defaultColor = ColorData.rgb(160, 160, 164, 255); static const defaultColorHex = '%a0a0a4'; /// topdown (default) or index (indexOrder). @@ -433,12 +433,12 @@ class ObjectGroup extends Layer { /// this group. (defaults to gray (“#a0a0a4”)) String colorHex; - /// [Color] used to display the objects in this group. + /// [ColorData] used to display the objects in this group. /// (defaults to gray (“#a0a0a4”)) /// /// Parsed from [colorHex], will be fallback to [defaultColor] if parsing /// fails for any reason. - Color color; + ColorData color; ObjectGroup({ super.id, @@ -474,11 +474,11 @@ class ImageLayer extends Layer { /// (optional). String? transparentColorHex; - /// [Color] to be rendered as transparent (optional). + /// [ColorData] to be rendered as transparent (optional). /// /// Parsed from [transparentColorHex], will be null if parsing fails for any /// reason. - Color? transparentColor; + ColorData? transparentColor; /// Whether or not to repeat the image on the X-axis bool repeatX; diff --git a/packages/tiled/lib/src/parser.dart b/packages/tiled/lib/src/parser.dart index 2fe6201..2bbafd5 100644 --- a/packages/tiled/lib/src/parser.dart +++ b/packages/tiled/lib/src/parser.dart @@ -197,7 +197,7 @@ abstract class Parser { return result; } - Color? getColorOrNull(String name, {Color? defaults}) { + ColorData? getColorOrNull(String name, {ColorData? defaults}) { final tiledColor = getStringOrNull(name); // Tiled colors are stored as either ARGB or RGB hex values, so we can @@ -212,13 +212,13 @@ abstract class Parser { } if (colorValue != null) { - return Color.hex(colorValue); + return ColorData.hex(colorValue); } else { return defaults; } } - Color getColor(String name, {Color? defaults}) { + ColorData getColor(String name, {ColorData? defaults}) { final result = getColorOrNull(name, defaults: defaults); if (result == null) { throw ParsingException(name, null, 'Missing required color field'); diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index f976762..19dbeac 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -74,12 +74,12 @@ class TiledMap { /// behind all other layers (optional). String? backgroundColorHex; - /// [Color] to be rendered as a solid color behind all other layers + /// [ColorData] to be rendered as a solid color behind all other layers /// (optional). /// /// Parsed from [backgroundColorHex], will be null if parsing fails for any /// reason. - Color? backgroundColor; + ColorData? backgroundColor; int compressionLevel; diff --git a/packages/tiled/test/color.dart b/packages/tiled/test/color.dart new file mode 100644 index 0000000..d7a87ca --- /dev/null +++ b/packages/tiled/test/color.dart @@ -0,0 +1,25 @@ +import 'dart:math'; + +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; +import 'package:tiled/tiled.dart'; + +void main() { + group("ColorData.hex", () { + test("parse", () { + final random = Random(); + final red = random.nextInt(256); + final green = random.nextInt(256); + final blue = random.nextInt(256); + final alpha = random.nextInt(256); + + final hex = alpha << 24 | red << 16 | green << 8 | blue << 0; + final data = ColorData.hex(hex); + + expect(data.alpha, equals(alpha)); + expect(data.red, equals(red)); + expect(data.green, equals(green)); + expect(data.blue, equals(blue)); + }); + }); +} \ No newline at end of file diff --git a/packages/tiled/test/layer_test.dart b/packages/tiled/test/layer_test.dart index ff200b1..d967704 100644 --- a/packages/tiled/test/layer_test.dart +++ b/packages/tiled/test/layer_test.dart @@ -74,7 +74,7 @@ void main() { expect(layer.tintColorHex, equals('#ffaabb')); expect( layer.tintColor, - equals(Color.hex(int.parse('0xffffaabb'))), + equals(ColorData.hex(int.parse('0xffffaabb'))), ); }); }); diff --git a/packages/tiled/test/object_group_test.dart b/packages/tiled/test/object_group_test.dart index 98d5ac0..0287622 100644 --- a/packages/tiled/test/object_group_test.dart +++ b/packages/tiled/test/object_group_test.dart @@ -30,7 +30,7 @@ void main() { expect(objectGroup.colorHex, equals('#555500')); expect( objectGroup.color, - equals(Color.hex(int.parse('0xff555500'))), + equals(ColorData.hex(int.parse('0xff555500'))), ); }); diff --git a/packages/tiled/test/parser_test.dart b/packages/tiled/test/parser_test.dart index 2e05c24..442d783 100644 --- a/packages/tiled/test/parser_test.dart +++ b/packages/tiled/test/parser_test.dart @@ -43,7 +43,7 @@ void main() { expect(map.backgroundColorHex, equals('#ccddaaff')); expect( map.backgroundColor, - equals(Color.hex(int.parse('0xccddaaff'))), + equals(ColorData.hex(int.parse('0xccddaaff'))), ); }); @@ -99,8 +99,8 @@ void main() { equals('#00112233'), ); expect( - properties.getValue('color property'), - equals(Color.hex(0x00112233)), + properties.getValue('color property'), + equals(ColorData.hex(0x00112233)), ); expect( properties.getValue('float property'), From e104efdd2ea68560817a541087a4edf835aa6627 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 20:27:41 +0100 Subject: [PATCH 05/17] added dartdocs to color and tests --- packages/tiled/lib/src/common/color.dart | 4 +++- packages/tiled/test/color.dart | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/tiled/lib/src/common/color.dart b/packages/tiled/lib/src/common/color.dart index f5cda41..135bf22 100644 --- a/packages/tiled/lib/src/common/color.dart +++ b/packages/tiled/lib/src/common/color.dart @@ -1,5 +1,7 @@ part of tiled; +/// Basic data class holding a Color in ARGB format. +/// This can be converted to dart:ui's Color using the flame_tiled package class ColorData { static int _sub(int hex, int index) => (hex >> index * 8) & 0x000000ff; @@ -8,7 +10,7 @@ class ColorData { final int blue; final int alpha; - /// Format: aarrggbb + /// Parses the Color from an int using the lower 32-bits and tiled's format: 0xaarrggbb ColorData.hex(int hex) : alpha = _sub(hex, 3), red = _sub(hex, 2), diff --git a/packages/tiled/test/color.dart b/packages/tiled/test/color.dart index d7a87ca..c39c834 100644 --- a/packages/tiled/test/color.dart +++ b/packages/tiled/test/color.dart @@ -22,4 +22,4 @@ void main() { expect(data.blue, equals(blue)); }); }); -} \ No newline at end of file +} From 6b60e922a807fd461ff1ac8ba0e1fff43b1b19bd Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 20:32:20 +0100 Subject: [PATCH 06/17] added back flame_lint --- packages/tiled/pubspec.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/tiled/pubspec.yaml b/packages/tiled/pubspec.yaml index 636356b..b61f9ab 100644 --- a/packages/tiled/pubspec.yaml +++ b/packages/tiled/pubspec.yaml @@ -13,4 +13,5 @@ dependencies: dev_dependencies: dartdoc: ^6.0.1 + flame_lint: ^1.1.1 test: ^1.24.8 From 54c387820ae7a2106e53a337b4a9e48911c9649a Mon Sep 17 00:00:00 2001 From: benni-tec Date: Sun, 29 Oct 2023 19:15:26 +0100 Subject: [PATCH 07/17] transfer --- packages/tiled/lib/src/common/gid.dart | 32 ++++++----- packages/tiled/lib/src/common/map.dart | 3 ++ packages/tiled/lib/src/exportable.dart | 75 ++++++++++++++++++++++++++ packages/tiled/lib/src/exporter.dart | 73 +++++++++++++++++++++++++ packages/tiled/lib/src/layer.dart | 45 +++++++++++----- packages/tiled/lib/src/tiled_map.dart | 31 ++++++----- packages/tiled/lib/tiled.dart | 3 ++ 7 files changed, 221 insertions(+), 41 deletions(-) create mode 100644 packages/tiled/lib/src/common/map.dart create mode 100644 packages/tiled/lib/src/exportable.dart create mode 100644 packages/tiled/lib/src/exporter.dart diff --git a/packages/tiled/lib/src/common/gid.dart b/packages/tiled/lib/src/common/gid.dart index 69fdd34..3dafdc3 100644 --- a/packages/tiled/lib/src/common/gid.dart +++ b/packages/tiled/lib/src/common/gid.dart @@ -32,12 +32,15 @@ part of tiled; /// When rendering a tile, the order of operation matters. The diagonal flip /// (x/y axis swap) is done first, followed by the horizontal and vertical /// flips. -class Gid { +class Gid extends UnaryExportable { static const int flippedHorizontallyFlag = 0x80000000; static const int flippedVerticallyFlag = 0x40000000; static const int flippedDiagonallyFlag = 0x20000000; static const int flippedAntiDiagonallyFlag = 0x10000000; + static const int flagBits = + flippedHorizontallyFlag | flippedVerticallyFlag | flippedDiagonallyFlag | flippedAntiDiagonallyFlag; + final int tile; final Flips flips; @@ -45,20 +48,13 @@ class Gid { factory Gid.fromInt(int gid) { // get flips from id - final flippedHorizontally = - (gid & flippedHorizontallyFlag) == flippedHorizontallyFlag; - final flippedVertically = - (gid & flippedVerticallyFlag) == flippedVerticallyFlag; - final flippedDiagonally = - (gid & flippedDiagonallyFlag) == flippedDiagonallyFlag; - final flippedAntiDiagonally = - gid & flippedAntiDiagonallyFlag == flippedAntiDiagonallyFlag; + final flippedHorizontally = (gid & flippedHorizontallyFlag) == flippedHorizontallyFlag; + final flippedVertically = (gid & flippedVerticallyFlag) == flippedVerticallyFlag; + final flippedDiagonally = (gid & flippedDiagonallyFlag) == flippedDiagonallyFlag; + final flippedAntiDiagonally = gid & flippedAntiDiagonallyFlag == flippedAntiDiagonallyFlag; // clear id from flips - final tileId = gid & - ~(flippedHorizontallyFlag | - flippedVerticallyFlag | - flippedDiagonallyFlag | - flippedAntiDiagonallyFlag); + final tileId = + gid & ~(flippedHorizontallyFlag | flippedVerticallyFlag | flippedDiagonallyFlag | flippedAntiDiagonallyFlag); final flip = Flips( flippedHorizontally, flippedVertically, @@ -86,4 +82,12 @@ class Gid { }); }); } + + @override + String export() => ((tile & ~flagBits) | + (flips.horizontally ? flippedHorizontallyFlag : 0) | + (flips.vertically ? flippedVerticallyFlag : 0) | + (flips.diagonally ? flippedDiagonallyFlag : 0) | + (flips.antiDiagonally ? flippedAntiDiagonallyFlag : 0)) + .toString(); } diff --git a/packages/tiled/lib/src/common/map.dart b/packages/tiled/lib/src/common/map.dart new file mode 100644 index 0000000..87be32b --- /dev/null +++ b/packages/tiled/lib/src/common/map.dart @@ -0,0 +1,3 @@ +extension Null on Map { + Map nonNulls() => {for (final e in entries.where((e) => e.value is V)) e.key : e.value as V}; +} \ No newline at end of file diff --git a/packages/tiled/lib/src/exportable.dart b/packages/tiled/lib/src/exportable.dart new file mode 100644 index 0000000..73d0309 --- /dev/null +++ b/packages/tiled/lib/src/exportable.dart @@ -0,0 +1,75 @@ +part of tiled; + +abstract class Exportable { + const Exportable(); + + String xml(); + String json(); +} + +abstract class UnaryExportable extends Exportable { + const UnaryExportable(); + + String export(); + + @override + String json() => export(); + + @override + String xml() => export(); +} + +class PassThroughExportable extends Exportable { + final Object value; + + const PassThroughExportable(this.value); + + @override + String json() => value.toString(); + + @override + String xml() => value.toString(); +} + +extension ExportableString on String { + Exportable toExport() => PassThroughExportable(this); +} + +extension ExportableNum on num { + Exportable toExport() => PassThroughExportable(this); +} + +extension ExportableBool on bool { + Exportable toExport() => PassThroughExportable(this); +} + +class _ExportableColor extends UnaryExportable { + final Color color; + + const _ExportableColor(this.color); + + static String _hex(int value) { + final str = value.toRadixString(16).padLeft(2, '0'); + return str.substring(str.length - 2, str.length - 1); + } + + @override + String export() => '#${_hex(color.alpha)}${_hex(color.red)}${_hex(color.green)}${_hex(color.blue)}'; +} + +extension ExportableColor on Color { + Exportable toExport() => _ExportableColor(this); +} + +class FormatSpecificExportable extends Exportable { + final String Function() xmlF; + final String Function() jsonF; + + const FormatSpecificExportable({required this.xmlF, required this.jsonF}); + + @override + String json() => jsonF(); + + @override + String xml() => xmlF(); +} diff --git a/packages/tiled/lib/src/exporter.dart b/packages/tiled/lib/src/exporter.dart new file mode 100644 index 0000000..bd2c417 --- /dev/null +++ b/packages/tiled/lib/src/exporter.dart @@ -0,0 +1,73 @@ +part of tiled; + +abstract class Exporter { + T exportValue(Exportable value); + + T exportElement(String name, Map attributes, Map> children); + + E formatSpecificExporting( + E Function(XmlExporter) xml, + E Function(JsonExporter) json, + ); +} + +class XmlExporter extends Exporter { + @override + XmlNode exportValue(Exportable value) => XmlText(value.xml()); + + @override + XmlNode exportElement( + String name, + Map attributes, + Map> children, + ) { + final element = XmlElement( + XmlName(name), + attributes.entries.map( + (e) => XmlAttribute( + XmlName(e.key), + e.value.xml(), + ), + ), + children.values.flattened, + ); + + return element; + } + + @override + E formatSpecificExporting( + E Function(XmlExporter p1) xml, + E Function(JsonExporter p1) json, + ) { + return xml(this); + } +} + +class JsonExporter extends Exporter { + @override + dynamic exportValue(dynamic value) => value; + + @override + Map exportElement( + String name, + Map attributes, + Map> children, + ) => + { + ...attributes, + ...children, + }; + + @override + E formatSpecificExporting( + E Function(XmlExporter p1) xml, + E Function(JsonExporter p1) json, + ) { + return json(this); + } +} + +extension DataExport on List { + +} diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 1169251..00a83b7 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -112,6 +112,8 @@ abstract class Layer { this.properties = CustomProperties.empty, }); + T export(Exporter exporter); + static Layer parse(Parser parser) { final type = parser.formatSpecificParsing( (json) => json.getLayerType('type'), @@ -144,17 +146,13 @@ abstract class Layer { (json) => null, // data is just a string or list of int on JSON (xml) => xml.getSingleChildOrNull('data'), ); - final compression = parser.getCompressionOrNull('compression') ?? - dataNode?.getCompressionOrNull('compression'); - final encoding = parser.getFileEncodingOrNull('encoding') ?? - dataNode?.getFileEncodingOrNull('encoding') ?? - FileEncoding.csv; + final compression = parser.getCompressionOrNull('compression') ?? dataNode?.getCompressionOrNull('compression'); + final encoding = + parser.getFileEncodingOrNull('encoding') ?? dataNode?.getFileEncodingOrNull('encoding') ?? FileEncoding.csv; Chunk parseChunk(Parser e) => Chunk.parse(e, encoding, compression); - final chunks = parser.getChildrenAs('chunks', parseChunk) + - (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); - final data = dataNode != null - ? parseLayerData(dataNode, encoding, compression) - : null; + final chunks = + parser.getChildrenAs('chunks', parseChunk) + (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); + final data = dataNode != null ? parseLayerData(dataNode, encoding, compression) : null; layer = TileLayer( id: id, name: name, @@ -185,10 +183,8 @@ abstract class Layer { 'draworder', defaults: DrawOrder.topDown, ); - final colorHex = - parser.getString('color', defaults: ObjectGroup.defaultColorHex); - final color = - parser.getColor('color', defaults: ObjectGroup.defaultColor); + final colorHex = parser.getString('color', defaults: ObjectGroup.defaultColorHex); + final color = parser.getColor('color', defaults: ObjectGroup.defaultColor); final objects = parser.getChildrenAs('object', TiledObject.parse); layer = ObjectGroup( id: id, @@ -417,6 +413,27 @@ class TileLayer extends Layer { } return Gid.generate(data, width, height); } + + @override + T export(Exporter exporter, {Compression compression = Compression.zlib, FileEncoding encoding = FileEncoding.base64}) => exporter.exportElement( + 'layer', + { + 'class': class_?.toExport(), + 'name': name.toExport(), + 'height': height.toExport(), + 'width': width.toExport(), + 'x': x.toExport(), + 'y': y.toExport(), + 'opacity': opacity.toExport(), + 'type': type.name.toExport(), + 'visible': visible.toExport(), + 'compression': (data == null ? compression : null)?.name.toExport(), + }.nonNulls(), + { + 'chunks': chunks?.map((e) => e.export(exporter, compression: compression, encoding: encoding)), + 'data': da + }.nonNulls(), + ); } class ObjectGroup extends Layer { diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index 19dbeac..50b6cdb 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -137,9 +137,7 @@ class TiledMap { .map((e) => e.getAttribute('source')); final tsxProviders = await Future.wait( - tsxSourcePaths - .where((key) => key != null) - .map((key) async => tsxProviderFunction(key!)), + tsxSourcePaths.where((key) => key != null).map((key) async => tsxProviderFunction(key!)), ); return TileMapParser.parseTmx( @@ -216,10 +214,7 @@ class TiledMap { } } imageSet.addAll( - layers - .whereType() - .map((e) => e.image) - .where((e) => e.source != null), + layers.whereType().map((e) => e.image).where((e) => e.source != null), ); return imageSet.toList(); } @@ -232,17 +227,13 @@ class TiledMap { } else if (layer is TileLayer) { const emptyTile = 0; final rows = layer.tileData ?? >[]; - final gids = rows - .expand((row) => row.map((gid) => gid.tile)) - .where((gid) => gid != emptyTile) - .toSet(); + final gids = rows.expand((row) => row.map((gid) => gid.tile)).where((gid) => gid != emptyTile).toSet(); return gids .map(tilesetByTileGId) .toSet() // The different gid can be in the same tileset .expand( - (tileset) => - [tileset.image, ...tileset.tiles.map((tile) => tile.image)], + (tileset) => [tileset.image, ...tileset.tiles.map((tile) => tile.image)], ) .whereNotNull() .toList(); @@ -358,4 +349,18 @@ class TiledMap { properties: properties, ); } + + T export(Exporter exporter, {bool embedTilesets = true}) => exporter.exportElement( + 'map', + { + 'backgroundColor': backgroundColor?.toExport(), + 'compressionlevel': compressionLevel.toExport(), + 'height': height.toExport(), + 'hexsidelength': hexSideLength?.toExport(), + 'infinite': infinite.toExport(), + }.nonNulls(), + { + 'layers': layers.map((e) => e.export()), + }, + ); } diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index c658c47..7da69de 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -8,9 +8,12 @@ import 'dart:typed_data'; import 'package:archive/archive.dart'; import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; +import 'package:tiled/src/common/map.dart'; import 'package:xml/xml.dart'; part 'src/chunk.dart'; +part 'src/exportable.dart'; +part 'src/exporter.dart'; part 'src/common/enums.dart'; part 'src/common/flips.dart'; part 'src/common/frame.dart'; From 50025a03cfecab5d370f1d3f805ea3377f1f738b Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 31 Oct 2023 16:24:00 +0100 Subject: [PATCH 08/17] added exports to I think everything --- packages/tiled/lib/src/chunk.dart | 20 +++- packages/tiled/lib/src/common/frame.dart | 8 +- packages/tiled/lib/src/common/gid.dart | 9 +- packages/tiled/lib/src/common/iterable.dart | 17 +++ packages/tiled/lib/src/common/map.dart | 2 + packages/tiled/lib/src/common/property.dart | 15 +++ .../tiled/lib/src/common/tiled_image.dart | 17 ++- packages/tiled/lib/src/data.dart | 72 ++++++++++++ packages/tiled/lib/src/exportable.dart | 75 ------------ packages/tiled/lib/src/exporter.dart | 73 ------------ .../lib/src/exporter/export_element.dart | 110 ++++++++++++++++++ .../lib/src/exporter/export_settings.dart | 15 +++ .../tiled/lib/src/exporter/export_value.dart | 93 +++++++++++++++ .../tiled/lib/src/exporter/exportable.dart | 5 + packages/tiled/lib/src/exporter/json.dart | 24 ++++ packages/tiled/lib/src/layer.dart | 108 ++++++++++++++--- packages/tiled/lib/src/objects/text.dart | 20 +++- .../tiled/lib/src/objects/tiled_object.dart | 64 +++++++++- packages/tiled/lib/src/tiled_map.dart | 43 +++++-- packages/tiled/lib/src/tileset/grid.dart | 13 ++- packages/tiled/lib/src/tileset/tile.dart | 48 +++++++- .../tiled/lib/src/tileset/tile_offset.dart | 12 +- packages/tiled/lib/src/tileset/tileset.dart | 68 ++++++++++- .../lib/src/tileset/wang/wang_color.dart | 16 ++- .../tiled/lib/src/tileset/wang/wang_set.dart | 20 +++- .../tiled/lib/src/tileset/wang/wang_tile.dart | 29 ++++- packages/tiled/lib/tiled.dart | 11 +- 27 files changed, 819 insertions(+), 188 deletions(-) create mode 100644 packages/tiled/lib/src/common/iterable.dart create mode 100644 packages/tiled/lib/src/data.dart delete mode 100644 packages/tiled/lib/src/exportable.dart delete mode 100644 packages/tiled/lib/src/exporter.dart create mode 100644 packages/tiled/lib/src/exporter/export_element.dart create mode 100644 packages/tiled/lib/src/exporter/export_settings.dart create mode 100644 packages/tiled/lib/src/exporter/export_value.dart create mode 100644 packages/tiled/lib/src/exporter/exportable.dart create mode 100644 packages/tiled/lib/src/exporter/json.dart diff --git a/packages/tiled/lib/src/chunk.dart b/packages/tiled/lib/src/chunk.dart index e306604..bab4331 100644 --- a/packages/tiled/lib/src/chunk.dart +++ b/packages/tiled/lib/src/chunk.dart @@ -17,7 +17,7 @@ part of tiled; /// The data inside is a compressed (encoded) representation of a list /// (that sequentially represents a matrix) of integers representing /// [Gid]s. -class Chunk { +class Chunk extends Exportable { List data; int x; @@ -59,4 +59,22 @@ class Chunk { return Chunk(data: data, x: x, y: y, width: width, height: height); } + + @override + ExportElement export(ExportSettings settings) { + final common = { + 'x': x.toExport(), + 'y': y.toExport(), + 'width': width.toExport(), + 'height': height.toExport(), + }; + + return ExportElement( + 'chunk', + common, + { + 'data': TileData(data).export(settings), + }, + ); + } } diff --git a/packages/tiled/lib/src/common/frame.dart b/packages/tiled/lib/src/common/frame.dart index 72e4633..a543eca 100644 --- a/packages/tiled/lib/src/common/frame.dart +++ b/packages/tiled/lib/src/common/frame.dart @@ -8,7 +8,7 @@ part of tiled; /// * tileid: The local ID of a tile within the parent . /// * duration: How long (in milliseconds) this frame should be displayed /// before advancing to the next frame. -class Frame { +class Frame extends Exportable { int tileId; int duration; @@ -22,4 +22,10 @@ class Frame { tileId: parser.getInt('tileid'), duration: parser.getInt('duration'), ); + + @override + ExportResolver export(ExportSettings settings) => ExportElement('frame', { + 'tileid': tileId.toExport(), + 'duration': duration.toExport(), + }, {}); } diff --git a/packages/tiled/lib/src/common/gid.dart b/packages/tiled/lib/src/common/gid.dart index 3dafdc3..1d32817 100644 --- a/packages/tiled/lib/src/common/gid.dart +++ b/packages/tiled/lib/src/common/gid.dart @@ -32,7 +32,7 @@ part of tiled; /// When rendering a tile, the order of operation matters. The diagonal flip /// (x/y axis swap) is done first, followed by the horizontal and vertical /// flips. -class Gid extends UnaryExportable { +class Gid extends ExportValue { static const int flippedHorizontallyFlag = 0x80000000; static const int flippedVerticallyFlag = 0x40000000; static const int flippedDiagonallyFlag = 0x20000000; @@ -83,11 +83,16 @@ class Gid extends UnaryExportable { }); } - @override String export() => ((tile & ~flagBits) | (flips.horizontally ? flippedHorizontallyFlag : 0) | (flips.vertically ? flippedVerticallyFlag : 0) | (flips.diagonally ? flippedDiagonallyFlag : 0) | (flips.antiDiagonally ? flippedAntiDiagonallyFlag : 0)) .toString(); + + @override + String get json => export(); + + @override + String get xml => export(); } diff --git a/packages/tiled/lib/src/common/iterable.dart b/packages/tiled/lib/src/common/iterable.dart new file mode 100644 index 0000000..1d6a345 --- /dev/null +++ b/packages/tiled/lib/src/common/iterable.dart @@ -0,0 +1,17 @@ +part of tiled; + +extension Grouping on Iterable { + Map> groupBy(K Function(V value) key) { + final out = >{}; + for (final v in this) { + final k = key(v); + if (!out.containsKey(k)) { + out[k] = [v]; + } else { + out[k]!.add(v); + } + } + + return out; + } +} \ No newline at end of file diff --git a/packages/tiled/lib/src/common/map.dart b/packages/tiled/lib/src/common/map.dart index 87be32b..264c60e 100644 --- a/packages/tiled/lib/src/common/map.dart +++ b/packages/tiled/lib/src/common/map.dart @@ -1,3 +1,5 @@ +part of tiled; + extension Null on Map { Map nonNulls() => {for (final e in entries.where((e) => e.value is V)) e.key : e.value as V}; } \ No newline at end of file diff --git a/packages/tiled/lib/src/common/property.dart b/packages/tiled/lib/src/common/property.dart index b14e03d..58b9cbe 100644 --- a/packages/tiled/lib/src/common/property.dart +++ b/packages/tiled/lib/src/common/property.dart @@ -86,6 +86,14 @@ class Property { ); } } + + ExportValue get exportValue => value.toString().toExport(); + + ExportElement export() => ExportElement('property', { + 'name': name.toExport(), + 'type': type.name.toExport(), + 'value': exportValue, + }, {}); } /// A wrapper for a Tiled property set @@ -164,6 +172,9 @@ class ColorProperty extends Property { required super.value, required this.hexValue, }) : super(type: PropertyType.color); + + @override + ExportValue get exportValue => value.toExport(); } /// [value] is the string text @@ -180,6 +191,10 @@ class FileProperty extends Property { required super.name, required super.value, }) : super(type: PropertyType.file); + + @override + ExportValue get exportValue => + value.isNotEmpty ? value.toExport() : '.'.toExport(); } /// [value] is the integer number diff --git a/packages/tiled/lib/src/common/tiled_image.dart b/packages/tiled/lib/src/common/tiled_image.dart index ed4bdad..ce5b1e6 100644 --- a/packages/tiled/lib/src/common/tiled_image.dart +++ b/packages/tiled/lib/src/common/tiled_image.dart @@ -18,7 +18,7 @@ part of tiled; /// when the image changes) /// * height: The image height in pixels (optional) @immutable -class TiledImage { +class TiledImage implements Exportable { final String? source; final String? format; final int? width; @@ -53,4 +53,19 @@ class TiledImage { @override int get hashCode => source.hashCode; + + @override + ExportElement export(ExportSettings settings) => ExportElement( + 'image', + { + 'width': width?.toExport(), + 'height': height?.toExport(), + 'format': format?.toExport(), + 'source': source?.toExport(), + 'trans': trans?.toExport(), + }.nonNulls(), + { + // missing data, tiled.dart does not support embedded images + }, + ); } diff --git a/packages/tiled/lib/src/data.dart b/packages/tiled/lib/src/data.dart new file mode 100644 index 0000000..870b6e9 --- /dev/null +++ b/packages/tiled/lib/src/data.dart @@ -0,0 +1,72 @@ +part of tiled; + +class TileData extends DelegatingList implements Exportable { + TileData(super.base); + + @override + ExportResolver export(ExportSettings settings) { + String? data; + switch (settings.encoding) { + case null: + break; + case FileEncoding.csv: + data = join(', '); + break; + case FileEncoding.base64: + data = _base64(settings); + break; + } + + return ExportFormatSpecific( + xml: ExportElement('data', { + if (settings.encoding != null) + 'encoding': settings.encoding!.name.toExport(), + if (settings.compression != null) + 'compression': settings.compression!.name.toExport(), + }, { + if (data == null) + 'tiles': ExportList(map( + (gid) => ExportElement( + 'tile', + {'gid': gid.toExport()}, + {}, + ), + )) + else + 'data': data.toExport(), + }), + json: ExportLiteral(this), + ); + } + + String _base64(ExportSettings settings) { + // Compression + List compressed; + switch (settings.compression) { + case Compression.zlib: + compressed = const ZLibEncoder().encode(this); + break; + case Compression.gzip: + compressed = GZipEncoder().encode(this)!; + break; + case Compression.zstd: + throw UnsupportedError('zstd is an unsupported compression'); + case null: + compressed = this; + break; + } + + // Conversion to Uint8List + final uint32 = Uint32List.fromList(compressed); + final dv = ByteData(compressed.length * 4); + + for (var i = 0; i < compressed.length; ++i) { + dv.setInt32(i * 4, uint32[i], Endian.little); + } + + final uint8 = dv.buffer.asUint8List(); + + // encoding + return base64Encode(uint8); + } +} diff --git a/packages/tiled/lib/src/exportable.dart b/packages/tiled/lib/src/exportable.dart deleted file mode 100644 index 73d0309..0000000 --- a/packages/tiled/lib/src/exportable.dart +++ /dev/null @@ -1,75 +0,0 @@ -part of tiled; - -abstract class Exportable { - const Exportable(); - - String xml(); - String json(); -} - -abstract class UnaryExportable extends Exportable { - const UnaryExportable(); - - String export(); - - @override - String json() => export(); - - @override - String xml() => export(); -} - -class PassThroughExportable extends Exportable { - final Object value; - - const PassThroughExportable(this.value); - - @override - String json() => value.toString(); - - @override - String xml() => value.toString(); -} - -extension ExportableString on String { - Exportable toExport() => PassThroughExportable(this); -} - -extension ExportableNum on num { - Exportable toExport() => PassThroughExportable(this); -} - -extension ExportableBool on bool { - Exportable toExport() => PassThroughExportable(this); -} - -class _ExportableColor extends UnaryExportable { - final Color color; - - const _ExportableColor(this.color); - - static String _hex(int value) { - final str = value.toRadixString(16).padLeft(2, '0'); - return str.substring(str.length - 2, str.length - 1); - } - - @override - String export() => '#${_hex(color.alpha)}${_hex(color.red)}${_hex(color.green)}${_hex(color.blue)}'; -} - -extension ExportableColor on Color { - Exportable toExport() => _ExportableColor(this); -} - -class FormatSpecificExportable extends Exportable { - final String Function() xmlF; - final String Function() jsonF; - - const FormatSpecificExportable({required this.xmlF, required this.jsonF}); - - @override - String json() => jsonF(); - - @override - String xml() => xmlF(); -} diff --git a/packages/tiled/lib/src/exporter.dart b/packages/tiled/lib/src/exporter.dart deleted file mode 100644 index bd2c417..0000000 --- a/packages/tiled/lib/src/exporter.dart +++ /dev/null @@ -1,73 +0,0 @@ -part of tiled; - -abstract class Exporter { - T exportValue(Exportable value); - - T exportElement(String name, Map attributes, Map> children); - - E formatSpecificExporting( - E Function(XmlExporter) xml, - E Function(JsonExporter) json, - ); -} - -class XmlExporter extends Exporter { - @override - XmlNode exportValue(Exportable value) => XmlText(value.xml()); - - @override - XmlNode exportElement( - String name, - Map attributes, - Map> children, - ) { - final element = XmlElement( - XmlName(name), - attributes.entries.map( - (e) => XmlAttribute( - XmlName(e.key), - e.value.xml(), - ), - ), - children.values.flattened, - ); - - return element; - } - - @override - E formatSpecificExporting( - E Function(XmlExporter p1) xml, - E Function(JsonExporter p1) json, - ) { - return xml(this); - } -} - -class JsonExporter extends Exporter { - @override - dynamic exportValue(dynamic value) => value; - - @override - Map exportElement( - String name, - Map attributes, - Map> children, - ) => - { - ...attributes, - ...children, - }; - - @override - E formatSpecificExporting( - E Function(XmlExporter p1) xml, - E Function(JsonExporter p1) json, - ) { - return json(this); - } -} - -extension DataExport on List { - -} diff --git a/packages/tiled/lib/src/exporter/export_element.dart b/packages/tiled/lib/src/exporter/export_element.dart new file mode 100644 index 0000000..406ba15 --- /dev/null +++ b/packages/tiled/lib/src/exporter/export_element.dart @@ -0,0 +1,110 @@ +part of tiled; + +abstract class ExportObject {} + +abstract class ExportResolver implements ExportObject { + XmlNode exportXml(); + + dynamic exportJson(); +} + +class ExportElement implements ExportResolver { + final String name; + final Map fields; + final Map children; + final CustomProperties properties; + + ExportElement( + this.name, + this.fields, + this.children, [ + this.properties = CustomProperties.empty, + ]); + + @override + XmlElement exportXml() { + final _children = children.values.expand((e) { + switch (e.runtimeType) { + case ExportList: + return (e as ExportList).map((e) => e.exportXml()); + case ExportResolver: + return [(e as ExportResolver).exportXml()]; + case ExportValue: + return [XmlText((e as ExportValue).xml)]; + default: + throw 'Bad State: ExportChild switch should have been exhaustive'; + } + }); + + return XmlElement( + XmlName(name), + fields.entries.map((e) => XmlAttribute(XmlName(e.key), e.value.xml)), + [ + ..._children, + XmlElement( + XmlName('properties'), + [], + properties.map((e) => e.export().exportXml()), + ), + ], + ); + } + + @override + Map exportJson() => { + ...fields.map( + (key, value) => MapEntry(key, value.json), + ), + ...children.map((key, e) { + switch (e.runtimeType) { + case ExportList: + return MapEntry>( + key, + (e as ExportList).map((e) => e.exportJson()), + ); + case ExportResolver: + return MapEntry( + key, + (e as ExportElement).exportJson(), + ); + default: + throw 'Bad State: ExportChild switch should have been exhaustive'; + } + }), + 'properties': properties.map((e) => e.export().exportJson()), + }; +} + +class ExportDirect implements ExportResolver { + final XmlElement xml; + final dynamic json; + + ExportDirect({required this.xml, required this.json}); + + @override + dynamic exportJson() => json; + + @override + XmlElement exportXml() => xml; +} + +class ExportFormatSpecific implements ExportResolver { + final ExportResolver xml; + final ExportResolver json; + + ExportFormatSpecific({required this.xml, required this.json}); + + @override + dynamic exportJson() => json.exportJson(); + + @override + XmlNode exportXml() => xml.exportXml(); +} + +class ExportList extends DelegatingList + implements ExportObject { + ExportList(Iterable base) : super(base.toList()); + + ExportList.from(Iterable source, ExportSettings settings) + : super(source.map((e) => e.export(settings)).toList()); +} diff --git a/packages/tiled/lib/src/exporter/export_settings.dart b/packages/tiled/lib/src/exporter/export_settings.dart new file mode 100644 index 0000000..325c141 --- /dev/null +++ b/packages/tiled/lib/src/exporter/export_settings.dart @@ -0,0 +1,15 @@ +part of tiled; + +class ExportSettings { + final FileEncoding? encoding; + final Compression? compression; + + ExportSettings({ + required this.encoding, + required this.compression, + }) { + if (compression != null) { + assert(encoding == FileEncoding.base64); + } + } +} diff --git a/packages/tiled/lib/src/exporter/export_value.dart b/packages/tiled/lib/src/exporter/export_value.dart new file mode 100644 index 0000000..47ad8bb --- /dev/null +++ b/packages/tiled/lib/src/exporter/export_value.dart @@ -0,0 +1,93 @@ +part of tiled; + +abstract class ExportValue implements ExportObject, ExportResolver { + const ExportValue(); + + String get xml; + dynamic get json; + + @override + XmlNode exportXml() => XmlText(xml); + + @override + dynamic exportJson() => json; +} + +class ExportLiteral extends ExportValue { + final T value; + + const ExportLiteral(this.value); + + @override + T get json => value; + + @override + String get xml => value.toString(); +} + +extension ExportableString on String { + ExportValue toExport() => ExportLiteral(this); +} + +extension ExportableNum on num { + ExportValue toExport() => ExportLiteral(this); +} + +class _ExportableBool extends ExportValue { + final bool value; + + _ExportableBool(this.value); + + @override + bool get json => value; + + @override + String get xml => (value ? 1 : 0).toString(); +} + +extension ExportableBool on bool { + ExportValue toExport() => _ExportableBool(this); +} + +class _ExportableColor extends ExportValue { + final Color color; + + const _ExportableColor(this.color); + + static String _hex(int value) { + final str = value.toRadixString(16).padLeft(2, '0'); + return str.substring(str.length - 2, str.length - 1); + } + + String get export => + '#${_hex(color.alpha)}${_hex(color.red)}${_hex(color.green)}${_hex(color.blue)}'; + + @override + String get json => export; + + @override + String get xml => export; +} + +extension ExportableColor on Color { + ExportValue toExport() => _ExportableColor(this); +} + +class _ExportablePointList extends ExportValue { + final List points; + + _ExportablePointList(this.points); + + @override + Iterable> get json => points.map((e) => { + 'x': e.x, + 'y': e.y, + }); + + @override + String get xml => points.map((e) => '${e.x},${e.y}').join(' '); +} + +extension ExportablePointList on List { + ExportValue toExport() => _ExportablePointList(this); +} diff --git a/packages/tiled/lib/src/exporter/exportable.dart b/packages/tiled/lib/src/exporter/exportable.dart new file mode 100644 index 0000000..5d2fc1b --- /dev/null +++ b/packages/tiled/lib/src/exporter/exportable.dart @@ -0,0 +1,5 @@ +part of tiled; + +abstract class Exportable { + ExportResolver export(ExportSettings settings); +} diff --git a/packages/tiled/lib/src/exporter/json.dart b/packages/tiled/lib/src/exporter/json.dart new file mode 100644 index 0000000..6175d45 --- /dev/null +++ b/packages/tiled/lib/src/exporter/json.dart @@ -0,0 +1,24 @@ +part of tiled; + +abstract class JsonObject { + dynamic get value; +} + +class JsonList extends DelegatingList implements JsonObject { + JsonList([super.base = const []]); + + @override + List get value => this; +} + +class JsonMap extends DelegatingMap implements JsonObject { + JsonMap([super.base = const {}]); + + @override + Map get value => this; +} + +class JsonValue implements JsonObject { + @override + dynamic get value => this; +} diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 00a83b7..95d2c5a 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -32,7 +32,7 @@ part of tiled; /// Defaults to 1. (since 1.5) /// /// Can contain at most one: , -abstract class Layer { +abstract class Layer extends Exportable { /// Incremental ID - unique across all layers int? id; @@ -112,8 +112,6 @@ abstract class Layer { this.properties = CustomProperties.empty, }); - T export(Exporter exporter); - static Layer parse(Parser parser) { final type = parser.formatSpecificParsing( (json) => json.getLayerType('type'), @@ -146,13 +144,17 @@ abstract class Layer { (json) => null, // data is just a string or list of int on JSON (xml) => xml.getSingleChildOrNull('data'), ); - final compression = parser.getCompressionOrNull('compression') ?? dataNode?.getCompressionOrNull('compression'); - final encoding = - parser.getFileEncodingOrNull('encoding') ?? dataNode?.getFileEncodingOrNull('encoding') ?? FileEncoding.csv; + final compression = parser.getCompressionOrNull('compression') ?? + dataNode?.getCompressionOrNull('compression'); + final encoding = parser.getFileEncodingOrNull('encoding') ?? + dataNode?.getFileEncodingOrNull('encoding') ?? + FileEncoding.csv; Chunk parseChunk(Parser e) => Chunk.parse(e, encoding, compression); - final chunks = - parser.getChildrenAs('chunks', parseChunk) + (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); - final data = dataNode != null ? parseLayerData(dataNode, encoding, compression) : null; + final chunks = parser.getChildrenAs('chunks', parseChunk) + + (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); + final data = dataNode != null + ? parseLayerData(dataNode, encoding, compression) + : null; layer = TileLayer( id: id, name: name, @@ -183,8 +185,10 @@ abstract class Layer { 'draworder', defaults: DrawOrder.topDown, ); - final colorHex = parser.getString('color', defaults: ObjectGroup.defaultColorHex); - final color = parser.getColor('color', defaults: ObjectGroup.defaultColor); + final colorHex = + parser.getString('color', defaults: ObjectGroup.defaultColorHex); + final color = + parser.getColor('color', defaults: ObjectGroup.defaultColor); final objects = parser.getChildrenAs('object', TiledObject.parse); layer = ObjectGroup( id: id, @@ -346,6 +350,9 @@ abstract class Layer { } return uint32; } + + @override + ExportElement export(ExportSettings settings); } class TileLayer extends Layer { @@ -415,7 +422,7 @@ class TileLayer extends Layer { } @override - T export(Exporter exporter, {Compression compression = Compression.zlib, FileEncoding encoding = FileEncoding.base64}) => exporter.exportElement( + ExportElement export(ExportSettings settings) => ExportElement( 'layer', { 'class': class_?.toExport(), @@ -430,9 +437,9 @@ class TileLayer extends Layer { 'compression': (data == null ? compression : null)?.name.toExport(), }.nonNulls(), { - 'chunks': chunks?.map((e) => e.export(exporter, compression: compression, encoding: encoding)), - 'data': da - }.nonNulls(), + if (chunks != null) 'chunks': ExportList.from(chunks!, settings), + if (data != null) 'data': TileData(data!).export(settings), + }, ); } @@ -481,6 +488,31 @@ class ObjectGroup extends Layer { }) : super( type: LayerType.objectGroup, ); + + @override + ExportElement export(ExportSettings settings) => ExportElement( + 'objectgroup', + { + 'id': id?.toExport(), + 'name': name.toExport(), + 'class': class_?.toExport(), + 'type': type.name.toExport(), + 'x': x.toExport(), + 'y': y.toExport(), + 'color': color.toExport(), + 'tintcolor': tintColor?.toExport(), + 'opacity': opacity.toExport(), + 'visible': (visible ? 1 : 0).toExport(), + 'offsetx': offsetX.toExport(), + 'offsety': offsetY.toExport(), + 'parallaxx': parallaxX.toExport(), + 'parallaxy': parallaxY.toExport(), + 'draworder': drawOrder.name.toExport(), + }.nonNulls(), + { + 'objects': ExportList.from(objects, settings), + }, + ); } class ImageLayer extends Layer { @@ -528,6 +560,30 @@ class ImageLayer extends Layer { }) : super( type: LayerType.imageLayer, ); + + @override + ExportElement export(ExportSettings settings) => ExportElement( + 'imagelayer', + { + 'id': id?.toExport(), + 'name': name.toExport(), + 'class': class_?.toExport(), + 'type': type.name.toExport(), + 'x': x.toExport(), + 'y': y.toExport(), + 'tintcolor': tintColor?.toExport(), + 'opacity': opacity.toExport(), + 'visible': (visible ? 1 : 0).toExport(), + 'offsetx': offsetX.toExport(), + 'offsety': offsetY.toExport(), + 'parallaxx': parallaxX.toExport(), + 'parallaxy': parallaxY.toExport(), + 'repeatx': repeatX.toExport(), + 'repeaty': repeatY.toExport(), + }.nonNulls(), + { + 'image': image.export(settings), + }); } class Group extends Layer { @@ -555,4 +611,26 @@ class Group extends Layer { }) : super( type: LayerType.imageLayer, ); + + @override + ExportElement export(ExportSettings settings) => ExportElement( + 'group', + { + 'id': id?.toExport(), + 'name': name.toExport(), + 'class': class_?.toExport(), + 'type': type.name.toExport(), + 'tintcolor': tintColor?.toExport(), + 'opacity': opacity.toExport(), + 'visible': (visible ? 1 : 0).toExport(), + 'offsetx': offsetX.toExport(), + 'offsety': offsetY.toExport(), + 'parallaxx': parallaxX.toExport(), + 'parallaxy': parallaxY.toExport(), + }.nonNulls(), + { + 'layers': ExportList.from(layers, settings), + }, + properties, + ); } diff --git a/packages/tiled/lib/src/objects/text.dart b/packages/tiled/lib/src/objects/text.dart index 5ac76e3..29a912d 100644 --- a/packages/tiled/lib/src/objects/text.dart +++ b/packages/tiled/lib/src/objects/text.dart @@ -37,7 +37,7 @@ part of tiled; /// /// If the text is larger than the object’s bounds, it is clipped to the bounds /// of the object. -class Text { +class Text extends Exportable { String fontFamily; int pixelSize; String color; @@ -84,4 +84,22 @@ class Text { kerning: parser.getBool('kerning', defaults: true), wrap: parser.getBool('wrap', defaults: false), ); + + @override + ExportElement export(ExportSettings settings) => + ExportElement('text', { + 'fontfamily': fontFamily.toExport(), + 'pixelsize': pixelSize.toExport(), + 'wrap': wrap.toExport(), + 'color': color.toExport(), + 'bold': bold.toExport(), + 'italic': italic.toExport(), + 'underline': underline.toExport(), + 'strikeout': strikeout.toExport(), + 'kerning': kerning.toExport(), + 'halign': hAlign.name.toExport(), + 'valign': vAlign.name.toExport(), + }, { + 'text': text.toExport(), + }); } diff --git a/packages/tiled/lib/src/objects/tiled_object.dart b/packages/tiled/lib/src/objects/tiled_object.dart index 8cf4ce8..d22ec35 100644 --- a/packages/tiled/lib/src/objects/tiled_object.dart +++ b/packages/tiled/lib/src/objects/tiled_object.dart @@ -43,7 +43,7 @@ part of tiled; /// /// Can contain at most one: , (since 0.9), /// (since 1.1), , , (since 1.0) -class TiledObject { +class TiledObject extends Exportable { int id; String name; String type; @@ -93,9 +93,13 @@ 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) { @@ -170,4 +174,62 @@ class TiledObject { }, ); } + + @override + ExportResolver export(ExportSettings settings) { + final common = { + 'id': id.toExport(), + 'name': name.toExport(), + 'type': type.toExport(), + 'x': x.toExport(), + 'y': y.toExport(), + 'width': width.toExport(), + 'height': height.toExport(), + 'rotation': rotation.toExport(), + 'gid': gid?.toExport(), + 'visible': visible.toExport(), + // 'template': not supported, not possible to support currently, see #73 + }.nonNulls(); + + return ExportFormatSpecific( + xml: ExportElement( + 'object', + common, + { + if (ellipse) 'ellipse': ExportElement('ellipse', {}, {}), + if (point) 'point': ExportElement('point', {}, {}), + if (polygon.isNotEmpty) + 'polygon': ExportElement( + 'polygon', + { + 'points': polygon.toExport(), + }, + {}, + ), + if (polyline.isNotEmpty) + 'polyline': ExportElement( + 'polyline', + { + 'points': polygon.toExport(), + }, + {}, + properties, + ), + if (text != null) 'text': text!.export(settings), + }, + ), + json: ExportElement( + 'object', + { + ...common, + if (ellipse) 'ellipse': ellipse.toExport(), + if (point) 'point': point.toExport(), + if (polygon.isNotEmpty) 'polygon': polygon.toExport(), + if (polyline.isNotEmpty) 'polyline': polyline.toExport(), + }, + {}, + properties, + ), + ); + } } diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index 50b6cdb..a08a687 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -137,7 +137,9 @@ class TiledMap { .map((e) => e.getAttribute('source')); final tsxProviders = await Future.wait( - tsxSourcePaths.where((key) => key != null).map((key) async => tsxProviderFunction(key!)), + tsxSourcePaths + .where((key) => key != null) + .map((key) async => tsxProviderFunction(key!)), ); return TileMapParser.parseTmx( @@ -214,7 +216,10 @@ class TiledMap { } } imageSet.addAll( - layers.whereType().map((e) => e.image).where((e) => e.source != null), + layers + .whereType() + .map((e) => e.image) + .where((e) => e.source != null), ); return imageSet.toList(); } @@ -227,13 +232,17 @@ class TiledMap { } else if (layer is TileLayer) { const emptyTile = 0; final rows = layer.tileData ?? >[]; - final gids = rows.expand((row) => row.map((gid) => gid.tile)).where((gid) => gid != emptyTile).toSet(); + final gids = rows + .expand((row) => row.map((gid) => gid.tile)) + .where((gid) => gid != emptyTile) + .toSet(); return gids .map(tilesetByTileGId) .toSet() // The different gid can be in the same tileset .expand( - (tileset) => [tileset.image, ...tileset.tiles.map((tile) => tile.image)], + (tileset) => + [tileset.image, ...tileset.tiles.map((tile) => tile.image)], ) .whereNotNull() .toList(); @@ -350,17 +359,35 @@ class TiledMap { ); } - T export(Exporter exporter, {bool embedTilesets = true}) => exporter.exportElement( + ExportElement export(ExportSettings settings) => ExportElement( 'map', { - 'backgroundColor': backgroundColor?.toExport(), - 'compressionlevel': compressionLevel.toExport(), + 'version': '1.10'.toExport(), + 'type': type.name.toExport(), + + 'orientation': orientation?.name.toExport(), + 'renderorder': renderOrder.name.toExport(), + 'compressionLevel': '-1'.toExport(), + + 'width': width.toExport(), 'height': height.toExport(), + 'tilewidth': tileWidth.toExport(), + 'tileheight': tileHeight.toExport(), + 'hexsidelength': hexSideLength?.toExport(), + 'staggeraxis': staggerAxis?.name.toExport(), + 'staggerindex': staggerIndex?.name.toExport(), + // 'parallaxoriginx': , 'parallaxoriginy': , Not supplied by this class + + 'backgroundColor': backgroundColor?.toExport(), + 'nextlayerid': nextLayerId?.toExport(), + 'nextobjectid': nextObjectId?.toExport(), 'infinite': infinite.toExport(), }.nonNulls(), { - 'layers': layers.map((e) => e.export()), + 'layers': ExportList.from(layers, settings), + 'tilesets': ExportList.from(tilesets, settings), }, + properties, ); } diff --git a/packages/tiled/lib/src/tileset/grid.dart b/packages/tiled/lib/src/tileset/grid.dart index 3dc26cf..99378f7 100644 --- a/packages/tiled/lib/src/tileset/grid.dart +++ b/packages/tiled/lib/src/tileset/grid.dart @@ -12,7 +12,7 @@ part of tiled; /// /// This element is only used in case of isometric orientation, and determines /// how tile overlays for terrain and collision information are rendered. -class Grid { +class Grid extends Exportable { int width; int height; GridOrientation orientation; @@ -29,4 +29,15 @@ class Grid { height: parser.getInt('height'), orientation: parser.getGridOrientation('orientation'), ); + + @override + ExportResolver export(ExportSettings settings) => ExportElement( + 'grid', + { + 'orientation': orientation.name.toExport(), + 'width': width.toExport(), + 'height': height.toExport(), + }, + {}, + ); } diff --git a/packages/tiled/lib/src/tileset/tile.dart b/packages/tiled/lib/src/tileset/tile.dart index a10a2e3..3948cc4 100644 --- a/packages/tiled/lib/src/tileset/tile.dart +++ b/packages/tiled/lib/src/tileset/tile.dart @@ -18,7 +18,7 @@ part of tiled; /// /// Can contain at most one: , (since 0.9), , /// . -class Tile { +class Tile implements Exportable { int localId; String? type; double probability; @@ -84,4 +84,50 @@ class Tile { ), properties: parser.getProperties(), ); + + @override + ExportResolver export(ExportSettings settings) { + final fields = { + 'id': localId.toExport(), + 'class': type?.toExport(), + 'probability': probability.toExport(), + 'x': imageRect?.left.toExport(), + 'y': imageRect?.top.toExport(), + 'width': imageRect?.width.toExport(), + 'height': imageRect?.height.toExport(), + }.nonNulls(); + + final children = { + 'image': image!.export(settings), + 'objectgroup': objectGroup?.export(settings) + }.nonNulls(); + + return ExportFormatSpecific( + xml: ExportElement( + 'tile', + fields, + { + ...children, + if (animation.isNotEmpty) + 'animations': ExportElement( + 'animation', + {}, + { + 'frames': ExportList.from(animation, settings), + }, + ), + }, + properties, + ), + json: ExportElement( + 'tile', + fields, + { + ...children, + 'animation': ExportList.from(animation, settings), + }, + properties, + ), + ); + } } diff --git a/packages/tiled/lib/src/tileset/tile_offset.dart b/packages/tiled/lib/src/tileset/tile_offset.dart index 3b6c985..3707e4b 100644 --- a/packages/tiled/lib/src/tileset/tile_offset.dart +++ b/packages/tiled/lib/src/tileset/tile_offset.dart @@ -11,7 +11,7 @@ part of tiled; /// This element is used to specify an offset in pixels, to be applied when /// drawing a tile from the related tileset. /// When not present, no offset is applied. -class TileOffset { +class TileOffset extends Exportable { int x; int y; @@ -25,4 +25,14 @@ class TileOffset { x: parser.getInt('x', defaults: 0), y: parser.getInt('y', defaults: 0), ); + + @override + ExportResolver export(ExportSettings settings) => ExportElement( + 'tileoffset', + { + 'x': x.toExport(), + 'y': y.toExport(), + }, + {}, + ); } diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 49d64f3..9ec841d 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -42,7 +42,7 @@ part of tiled; /// (since 1.5) /// /// Can contain any number: -class Tileset { +class Tileset implements Exportable { int? firstGid; String? source; String? name; @@ -261,4 +261,70 @@ class Tileset { } return tiles; } + + @override + ExportResolver export(ExportSettings settings) => source == null + ? _export(settings, false) + : ExportElement( + 'tileset', + { + 'firstgid': firstGid!.toExport(), + 'source': source!.toExport(), + }.nonNulls(), + {}, + ); + + ExportResolver exportExternal(ExportSettings settings) => + _export(settings, true); + + ExportResolver _export(ExportSettings settings, bool external) { + final fields = { + if (!external) 'firstgid': firstGid!.toExport(), + 'name': name!.toExport(), + 'class': type.name.toExport(), + 'type': type.name.toExport(), + + 'tilewidth': tileWidth!.toExport(), + 'tileheigth': tileHeight!.toExport(), + 'spacing': spacing.toExport(), + 'margin': margin.toExport(), + + 'tilecount': tileCount!.toExport(), + 'columns': columns!.toExport(), + 'objectalignment': objectAlignment.name.toExport(), + // 'tilerendersize': , Not supported by this class + // 'fillmode': , Not supported by this class + }; + + final common = { + if (image != null) + 'image': image!.export(settings) + else + 'tiles': ExportList.from(tiles, settings), + 'tileoffset': tileOffset?.export(settings), + 'grid': grid?.export(settings), + // 'terraintypes': , DEPRECATED + // 'transformations': ExportList.from(transformations, settings), Not supported by this class + }.nonNulls(); + + final wangsets = ExportElement( + 'wangsets', + {}, + {'wangsets': ExportList.from(wangSets, settings)}, + properties, + ); + + return ExportFormatSpecific( + xml: ExportElement( + 'wangsets', + fields, + { + ...common, + 'wangsets': wangsets, + }, + properties, + ), + json: wangsets, + ); + } } diff --git a/packages/tiled/lib/src/tileset/wang/wang_color.dart b/packages/tiled/lib/src/tileset/wang/wang_color.dart index c5661f3..138901e 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_color.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_color.dart @@ -13,7 +13,7 @@ part of tiled; /// others in case of multiple options. (defaults to 0) /// /// Can contain at most one: -class WangColor { +class WangColor implements Exportable { String name; String color; int tile; @@ -37,4 +37,18 @@ class WangColor { probability: parser.getDouble('probability', defaults: 0), properties: parser.getProperties(), ); + + @override + ExportResolver export(ExportSettings settings) => ExportElement( + 'wangcolor', + { + 'name': name.toExport(), + // 'class': , Not supported by this class + 'color': color.toExport(), + 'tile': tile.toExport(), + 'probability': probability.toExport(), + }, + {}, + properties, + ); } diff --git a/packages/tiled/lib/src/tileset/wang/wang_set.dart b/packages/tiled/lib/src/tileset/wang/wang_set.dart index 4a25355..f693c96 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_set.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_set.dart @@ -15,7 +15,7 @@ part of tiled; /// Can contain up to 255: (since Tiled 1.5) /// /// Can contain any number: -class WangSet { +class WangSet extends Exportable { String name; int tile; List cornerColors; @@ -53,4 +53,22 @@ class WangSet { properties: parser.getProperties(), ); } + + @override + ExportResolver export(ExportSettings settings) { + final colors = cornerColors..addAll(edgeColors); + + return ExportElement( + 'wangset', + { + 'name': name.toExport(), + 'tile': tile.toExport(), + }, + { + 'colors': ExportList.from(colors, settings), + 'wangtiles': ExportList.from(wangTiles, settings), + }, + properties, + ); + } } diff --git a/packages/tiled/lib/src/tileset/wang/wang_tile.dart b/packages/tiled/lib/src/tileset/wang/wang_tile.dart index a069d5d..e8c630d 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_tile.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_tile.dart @@ -19,7 +19,7 @@ part of tiled; /// * hflip: Whether the tile is flipped horizontally (removed in Tiled 1.5). /// * vflip: Whether the tile is flipped vertically (removed in Tiled 1.5). /// * dflip: Whether the tile is flipped on its diagonal (removed in Tiled 1.5). -class WangTile { +class WangTile implements Exportable { int tileId; List wangId; bool hFlip; @@ -60,4 +60,31 @@ class WangTile { } return uint32; } + + @override + ExportResolver export(ExportSettings settings) { + final common = { + 'tileid': tileId.toExport(), + }; + + // Flips are deprecated! + return ExportFormatSpecific( + xml: ExportElement( + 'wangtile', + { + ...common, + 'wangid': wangId.join(',').toExport(), + }, + {}, + ), + json: ExportElement( + 'wangtile', + { + ...common, + 'wangid': ExportLiteral(wangId), + }, + {}, + ), + ); + } } diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index 7da69de..784c944 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -8,16 +8,21 @@ import 'dart:typed_data'; import 'package:archive/archive.dart'; import 'package:collection/collection.dart'; import 'package:meta/meta.dart'; -import 'package:tiled/src/common/map.dart'; import 'package:xml/xml.dart'; part 'src/chunk.dart'; -part 'src/exportable.dart'; -part 'src/exporter.dart'; +part 'src/data.dart'; +part 'src/exporter/exportable.dart'; +part 'src/exporter/export_value.dart'; +part 'src/exporter/export_element.dart'; +part 'src/exporter/export_settings.dart'; +part 'src/exporter/json.dart'; part 'src/common/enums.dart'; part 'src/common/flips.dart'; part 'src/common/frame.dart'; part 'src/common/gid.dart'; +part 'src/common/iterable.dart'; +part 'src/common/map.dart'; part 'src/common/point.dart'; part 'src/common/property.dart'; part 'src/common/tiled_image.dart'; From ef1e6ab5d3cfa411ff7c1cd33646af5b2692a6ee Mon Sep 17 00:00:00 2001 From: benni-tec Date: Thu, 2 Nov 2023 16:04:23 +0100 Subject: [PATCH 09/17] added some tests and fixes --- .../tiled/lib/src/common/tiled_image.dart | 2 +- packages/tiled/lib/src/data.dart | 31 +++---- .../lib/src/exporter/export_element.dart | 50 +++++------- .../tiled/lib/src/exporter/export_value.dart | 3 +- .../tiled/lib/src/exporter/exportable.dart | 3 + .../tiled/lib/src/objects/tiled_object.dart | 2 +- packages/tiled/lib/src/tiled_map.dart | 9 ++- packages/tiled/lib/src/tileset/tile.dart | 72 +++++++++-------- packages/tiled/lib/src/tileset/tileset.dart | 31 ++++--- .../lib/src/tileset/wang/wang_color.dart | 2 +- .../tiled/lib/src/tileset/wang/wang_tile.dart | 2 +- packages/tiled/test/exporter/map.dart | 81 +++++++++++++++++++ packages/tiled/test/exporter/properties.dart | 37 +++++++++ packages/tiled/test/exporter/xml.dart | 58 +++++++++++++ 14 files changed, 283 insertions(+), 100 deletions(-) create mode 100644 packages/tiled/test/exporter/map.dart create mode 100644 packages/tiled/test/exporter/properties.dart create mode 100644 packages/tiled/test/exporter/xml.dart diff --git a/packages/tiled/lib/src/common/tiled_image.dart b/packages/tiled/lib/src/common/tiled_image.dart index ce5b1e6..1946192 100644 --- a/packages/tiled/lib/src/common/tiled_image.dart +++ b/packages/tiled/lib/src/common/tiled_image.dart @@ -18,7 +18,7 @@ part of tiled; /// when the image changes) /// * height: The image height in pixels (optional) @immutable -class TiledImage implements Exportable { +class TiledImage with Exportable { final String? source; final String? format; final int? width; diff --git a/packages/tiled/lib/src/data.dart b/packages/tiled/lib/src/data.dart index 870b6e9..0b2e6cd 100644 --- a/packages/tiled/lib/src/data.dart +++ b/packages/tiled/lib/src/data.dart @@ -1,6 +1,6 @@ part of tiled; -class TileData extends DelegatingList implements Exportable { +class TileData extends DelegatingList with Exportable { TileData(super.base); @override @@ -40,33 +40,34 @@ class TileData extends DelegatingList implements Exportable { } String _base64(ExportSettings settings) { + // Conversion to Uint8List + final uint32 = Uint32List.fromList(this); + final dv = ByteData(this.length * 4); + + for (var i = 0; i < this.length; ++i) { + dv.setInt32(i * 4, uint32[i], Endian.little); + } + + final uint8 = dv.buffer.asUint8List(); + // Compression List compressed; + print(settings.compression); switch (settings.compression) { case Compression.zlib: - compressed = const ZLibEncoder().encode(this); + compressed = const ZLibEncoder().encode(uint8); break; case Compression.gzip: - compressed = GZipEncoder().encode(this)!; + compressed = GZipEncoder().encode(uint8)!; break; case Compression.zstd: throw UnsupportedError('zstd is an unsupported compression'); case null: - compressed = this; + compressed = uint8; break; } - // Conversion to Uint8List - final uint32 = Uint32List.fromList(compressed); - final dv = ByteData(compressed.length * 4); - - for (var i = 0; i < compressed.length; ++i) { - dv.setInt32(i * 4, uint32[i], Endian.little); - } - - final uint8 = dv.buffer.asUint8List(); - // encoding - return base64Encode(uint8); + return base64Encode(compressed); } } diff --git a/packages/tiled/lib/src/exporter/export_element.dart b/packages/tiled/lib/src/exporter/export_element.dart index 406ba15..ade0e9b 100644 --- a/packages/tiled/lib/src/exporter/export_element.dart +++ b/packages/tiled/lib/src/exporter/export_element.dart @@ -24,15 +24,12 @@ class ExportElement implements ExportResolver { @override XmlElement exportXml() { final _children = children.values.expand((e) { - switch (e.runtimeType) { - case ExportList: - return (e as ExportList).map((e) => e.exportXml()); - case ExportResolver: - return [(e as ExportResolver).exportXml()]; - case ExportValue: - return [XmlText((e as ExportValue).xml)]; - default: - throw 'Bad State: ExportChild switch should have been exhaustive'; + if (e is ExportList) { + return e.map((e) => e.exportXml()); + } else if (e is ExportResolver) { + return [e.exportXml()]; + } else { + throw 'Bad State: ExportObject switch should have been exhaustive'; } }); @@ -41,11 +38,12 @@ class ExportElement implements ExportResolver { fields.entries.map((e) => XmlAttribute(XmlName(e.key), e.value.xml)), [ ..._children, - XmlElement( - XmlName('properties'), - [], - properties.map((e) => e.export().exportXml()), - ), + if (properties.isNotEmpty) + XmlElement( + XmlName('properties'), + [], + properties.map((e) => e.export().exportXml()).toList(), + ), ], ); } @@ -56,22 +54,18 @@ class ExportElement implements ExportResolver { (key, value) => MapEntry(key, value.json), ), ...children.map((key, e) { - switch (e.runtimeType) { - case ExportList: - return MapEntry>( - key, - (e as ExportList).map((e) => e.exportJson()), - ); - case ExportResolver: - return MapEntry( - key, - (e as ExportElement).exportJson(), - ); - default: - throw 'Bad State: ExportChild switch should have been exhaustive'; + if (e is ExportList) { + return MapEntry>( + key, + e.map((e) => e.exportJson()).toList(), + ); + } else if (e is ExportResolver) { + return MapEntry(key, e.exportJson()); + } else { + throw 'Bad State: ExportChild switch should have been exhaustive'; } }), - 'properties': properties.map((e) => e.export().exportJson()), + 'properties': properties.map((e) => e.export().exportJson()).toList(), }; } diff --git a/packages/tiled/lib/src/exporter/export_value.dart b/packages/tiled/lib/src/exporter/export_value.dart index 47ad8bb..4d681aa 100644 --- a/packages/tiled/lib/src/exporter/export_value.dart +++ b/packages/tiled/lib/src/exporter/export_value.dart @@ -55,8 +55,7 @@ class _ExportableColor extends ExportValue { const _ExportableColor(this.color); static String _hex(int value) { - final str = value.toRadixString(16).padLeft(2, '0'); - return str.substring(str.length - 2, str.length - 1); + return value.toRadixString(16).padLeft(2, '0'); } String get export => diff --git a/packages/tiled/lib/src/exporter/exportable.dart b/packages/tiled/lib/src/exporter/exportable.dart index 5d2fc1b..be1f179 100644 --- a/packages/tiled/lib/src/exporter/exportable.dart +++ b/packages/tiled/lib/src/exporter/exportable.dart @@ -2,4 +2,7 @@ part of tiled; abstract class Exportable { ExportResolver export(ExportSettings settings); + + XmlNode exportXml(ExportSettings settings) => export(settings).exportXml(); + dynamic exportJson(ExportSettings settings) => export(settings).exportJson(); } diff --git a/packages/tiled/lib/src/objects/tiled_object.dart b/packages/tiled/lib/src/objects/tiled_object.dart index d22ec35..ad017f6 100644 --- a/packages/tiled/lib/src/objects/tiled_object.dart +++ b/packages/tiled/lib/src/objects/tiled_object.dart @@ -213,10 +213,10 @@ class TiledObject extends Exportable { 'points': polygon.toExport(), }, {}, - properties, ), if (text != null) 'text': text!.export(settings), }, + properties ), json: ExportElement( 'object', diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index a08a687..dab7784 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -55,7 +55,7 @@ part of tiled; /// /// Can contain any number: , , , , /// (since 1.0), (since 1.3) -class TiledMap { +class TiledMap with Exportable { TileMapType type; String version; String? tiledVersion; @@ -359,6 +359,7 @@ class TiledMap { ); } + @override ExportElement export(ExportSettings settings) => ExportElement( 'map', { @@ -367,7 +368,7 @@ class TiledMap { 'orientation': orientation?.name.toExport(), 'renderorder': renderOrder.name.toExport(), - 'compressionLevel': '-1'.toExport(), + 'compressionlevel': '-1'.toExport(), 'width': width.toExport(), 'height': height.toExport(), @@ -379,14 +380,14 @@ class TiledMap { 'staggerindex': staggerIndex?.name.toExport(), // 'parallaxoriginx': , 'parallaxoriginy': , Not supplied by this class - 'backgroundColor': backgroundColor?.toExport(), + 'backgroundcolor': backgroundColor?.toExport(), 'nextlayerid': nextLayerId?.toExport(), 'nextobjectid': nextObjectId?.toExport(), 'infinite': infinite.toExport(), }.nonNulls(), { - 'layers': ExportList.from(layers, settings), 'tilesets': ExportList.from(tilesets, settings), + 'layers': ExportList.from(layers, settings), }, properties, ); diff --git a/packages/tiled/lib/src/tileset/tile.dart b/packages/tiled/lib/src/tileset/tile.dart index 3948cc4..8c0e663 100644 --- a/packages/tiled/lib/src/tileset/tile.dart +++ b/packages/tiled/lib/src/tileset/tile.dart @@ -18,7 +18,7 @@ part of tiled; /// /// Can contain at most one: , (since 0.9), , /// . -class Tile implements Exportable { +class Tile with Exportable { int localId; String? type; double probability; @@ -50,40 +50,44 @@ class Tile implements Exportable { /// Will be same as [type]. String? get class_ => type; - Tile.parse(Parser parser) - : this( - localId: parser.getInt('id'), + factory Tile.parse(Parser parser) { + final image = parser.getSingleChildOrNullAs('image', TiledImage.parse); + final x = parser.getDoubleOrNull('x'); + final y = parser.getDoubleOrNull('y'); + final width = parser.getDoubleOrNull('width'); + final height = parser.getDoubleOrNull('height'); - /// Tiled 1.9 "type" has been moved to "class" - type: - parser.getStringOrNull('class') ?? parser.getStringOrNull('type'), + final imageRect = [image, x, y, width, height].contains(null) + ? null + : Rectangle(x!, y!, width!, height!); - probability: parser.getDouble('probability', defaults: 0), - terrain: parser - .getStringOrNull('terrain') - ?.split(',') - .map((str) => str.isEmpty ? null : int.parse(str)) - .toList() ?? - [], - image: parser.getSingleChildOrNullAs('image', TiledImage.parse), - imageRect: Rectangle( - parser.getDoubleOrNull('x') ?? 0, - parser.getDoubleOrNull('y') ?? 0, - parser.getDoubleOrNull('width') ?? 0, - parser.getDoubleOrNull('height') ?? 0, - ), - objectGroup: - parser.getSingleChildOrNullAs('objectgroup', Layer.parse), - animation: parser.formatSpecificParsing( - (json) => json.getChildrenAs('animation', Frame.parse), - (xml) => - xml - .getSingleChildOrNull('animation') - ?.getChildrenAs('frame', Frame.parse) ?? - [], - ), - properties: parser.getProperties(), - ); + return Tile( + localId: parser.getInt('id'), + + /// Tiled 1.9 "type" has been moved to "class" + type: parser.getStringOrNull('class') ?? parser.getStringOrNull('type'), + + probability: parser.getDouble('probability', defaults: 0), + terrain: parser + .getStringOrNull('terrain') + ?.split(',') + .map((str) => str.isEmpty ? null : int.parse(str)) + .toList() ?? + [], + image: image, + imageRect: imageRect, + objectGroup: parser.getSingleChildOrNullAs('objectgroup', Layer.parse), + animation: parser.formatSpecificParsing( + (json) => json.getChildrenAs('animation', Frame.parse), + (xml) => + xml + .getSingleChildOrNull('animation') + ?.getChildrenAs('frame', Frame.parse) ?? + [], + ), + properties: parser.getProperties(), + ); + } @override ExportResolver export(ExportSettings settings) { @@ -98,7 +102,7 @@ class Tile implements Exportable { }.nonNulls(); final children = { - 'image': image!.export(settings), + 'image': image?.export(settings), 'objectgroup': objectGroup?.export(settings) }.nonNulls(); diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 9ec841d..5eb5909 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -42,7 +42,7 @@ part of tiled; /// (since 1.5) /// /// Can contain any number: -class Tileset implements Exportable { +class Tileset with Exportable { int? firstGid; String? source; String? name; @@ -284,23 +284,21 @@ class Tileset implements Exportable { 'class': type.name.toExport(), 'type': type.name.toExport(), - 'tilewidth': tileWidth!.toExport(), - 'tileheigth': tileHeight!.toExport(), + 'tilewidth': tileWidth?.toExport(), + 'tileheigth': tileHeight?.toExport(), 'spacing': spacing.toExport(), 'margin': margin.toExport(), - 'tilecount': tileCount!.toExport(), - 'columns': columns!.toExport(), + 'tilecount': tileCount?.toExport(), + 'columns': columns?.toExport(), 'objectalignment': objectAlignment.name.toExport(), // 'tilerendersize': , Not supported by this class // 'fillmode': , Not supported by this class - }; + }.nonNulls(); final common = { - if (image != null) - 'image': image!.export(settings) - else - 'tiles': ExportList.from(tiles, settings), + 'image': image?.export(settings), + 'tiles': ExportList.from(tiles, settings), 'tileoffset': tileOffset?.export(settings), 'grid': grid?.export(settings), // 'terraintypes': , DEPRECATED @@ -316,15 +314,22 @@ class Tileset implements Exportable { return ExportFormatSpecific( xml: ExportElement( - 'wangsets', + 'tileset', fields, { ...common, - 'wangsets': wangsets, + if (wangSets.isNotEmpty) 'wangsets': wangsets, }, properties, ), - json: wangsets, + json: ExportElement( + 'tileset', + fields, + { + ...common, + 'wangsets': ExportList.from(wangSets, settings), + }, + ), ); } } diff --git a/packages/tiled/lib/src/tileset/wang/wang_color.dart b/packages/tiled/lib/src/tileset/wang/wang_color.dart index 138901e..b5cc36e 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_color.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_color.dart @@ -13,7 +13,7 @@ part of tiled; /// others in case of multiple options. (defaults to 0) /// /// Can contain at most one: -class WangColor implements Exportable { +class WangColor with Exportable { String name; String color; int tile; diff --git a/packages/tiled/lib/src/tileset/wang/wang_tile.dart b/packages/tiled/lib/src/tileset/wang/wang_tile.dart index e8c630d..1aecb94 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_tile.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_tile.dart @@ -19,7 +19,7 @@ part of tiled; /// * hflip: Whether the tile is flipped horizontally (removed in Tiled 1.5). /// * vflip: Whether the tile is flipped vertically (removed in Tiled 1.5). /// * dflip: Whether the tile is flipped on its diagonal (removed in Tiled 1.5). -class WangTile implements Exportable { +class WangTile with Exportable { int tileId; List wangId; bool hFlip; diff --git a/packages/tiled/test/exporter/map.dart b/packages/tiled/test/exporter/map.dart new file mode 100644 index 0000000..642bc78 --- /dev/null +++ b/packages/tiled/test/exporter/map.dart @@ -0,0 +1,81 @@ +import 'dart:ui'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:tiled/tiled.dart'; +import 'package:xml/xml.dart'; + +void main() { + final settings = ExportSettings(encoding: null, compression: null); + + late TiledMap export; + setUp(() => export = TiledMap( + width: 576, + height: 432, + tileWidth: 48, + tileHeight: 48, + orientation: MapOrientation.hexagonal, + renderOrder: RenderOrder.leftUp, + hexSideLength: 24, + staggerAxis: StaggerAxis.y, + staggerIndex: StaggerIndex.even, + backgroundColor: const Color(0xaa252627), + nextLayerId: 24, + nextObjectId: 56, + infinite: false, + layers: [ + TileLayer(name: 'test1', width: 48, height: 48), + TileLayer(name: 'test2', width: 48, height: 48), + TileLayer(name: 'test3', width: 48, height: 48), + ], + tilesets: [ + Tileset(firstGid: 1, source: 'xyz.png'), + Tileset(firstGid: 20, source: 'xyz.png'), + ], + )); + + group('Exporter - Map', () { + test( + 'Xml', + () => testSuite(XmlParser(export.exportXml(settings) as XmlElement)), + ); + test( + 'Json', + () => testSuite( + JsonParser(export.exportJson(settings) as Map)), + ); + }); +} + +void testSuite(Parser export) { + void attribute(String name, String expected) => + expect(export.getString(name), equals(expected)); + + attribute('height', '432'); + attribute('width', '576'); + attribute('tilewidth', '48'); + attribute('tileheight', '48'); + attribute('version', '1.10'); + attribute('type', TileMapType.map.name); + attribute('orientation', MapOrientation.hexagonal.name); + attribute('renderorder', RenderOrder.leftUp.name); + attribute('hexsidelength', '24'); + attribute('staggeraxis', StaggerAxis.y.name); + attribute('staggerindex', StaggerIndex.even.name); + attribute('backgroundcolor', '#aa252627'); + attribute('nextlayerid', '24'); + attribute('nextobjectid', '56'); + attribute( + 'infinite', export.formatSpecificParsing((p0) => 'false', (p0) => '0')); + + final layers = export.formatSpecificParsing( + (e) => e.getChildren('layers'), + (e) => e.getChildren('layer'), + ); + expect(layers.length, equals(3)); + + final tilesets = export.formatSpecificParsing( + (e) => e.getChildren('tilesets'), + (e) => e.getChildren('tileset'), + ); + expect(tilesets.length, equals(2)); +} diff --git a/packages/tiled/test/exporter/properties.dart b/packages/tiled/test/exporter/properties.dart new file mode 100644 index 0000000..039ebd0 --- /dev/null +++ b/packages/tiled/test/exporter/properties.dart @@ -0,0 +1,37 @@ +import 'package:collection/collection.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:tiled/tiled.dart'; +import 'package:xml/xml.dart'; + +void main() { + final settings = ExportSettings(encoding: null, compression: null); + + late TiledObject export; + late CustomProperties byName; + setUp(() { + byName = CustomProperties([ + StringProperty(name: 'test_string', value: 'test'), + ].groupFoldBy((e) => e.name, (old, e) => e)); + + export = TiledObject(id: 5, properties: byName); + }); + + void testSuite(Parser export) { + final properties = export.getProperties(); + expect(properties.length, equals(byName.length)); + + for (final property in properties) { + final match = byName.where((e) => e.name == property.name && e.value == property.value); + expect(match.length, equals(1)); + } + } + + group('Exporter - CustomProperties', () { + test('Xml', + () => testSuite(XmlParser(export.exportXml(settings) as XmlElement))); + test( + 'Json', + () => testSuite( + JsonParser(export.exportJson(settings) as Map))); + }); +} diff --git a/packages/tiled/test/exporter/xml.dart b/packages/tiled/test/exporter/xml.dart new file mode 100644 index 0000000..be1dba5 --- /dev/null +++ b/packages/tiled/test/exporter/xml.dart @@ -0,0 +1,58 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:xml/xml.dart'; + +class XmlDeepMatcher extends Matcher { + final XmlElement expected; + + XmlDeepMatcher(this.expected); + XmlDeepMatcher.parse(String xml) : expected = XmlDocument.parse(xml).rootElement..normalize(); + + @override + Description describe(Description description) => description..add(expected.toString()); + + @override + bool matches(dynamic item, Map matchState) { + if (item is! XmlElement) return false; + return _match(item, expected); + } + + bool _match(XmlElement a, XmlElement b) { + return a.localName == b.localName && + _deepIterable( + a.attributes, + b.attributes, + (a, b) => + a.localName == b.localName && + a.attributeType.name == b.attributeType.name && + a.value.trim() == b.value.trim(), + ) && + _deepIterable(_cleanNodes(a.children), _cleanNodes(b.children), (a, b) { + if (a.runtimeType != b.runtimeType) return false; + + if (a is XmlText) { + return a.value.trim() == b.value!.trim(); + } else if (a is XmlElement) { + return _match(a, b as XmlElement); + } else { + return false; + } + }); + } + + bool _deepIterable( + Iterable a, + Iterable b, + bool Function(T a, T b) equals, + ) { + if (a.length != b.length) return false; + return a.every((aa) => b.any((bb) => equals(aa, bb))); + } + + Iterable _cleanNodes(Iterable list) => list.where( + (e) => + e is! XmlCDATA && + e is! XmlComment && + e is! XmlDeclaration && + e is! XmlProcessing, + ); +} From e1c45218fd326366f302f9387416b7100a39c4de Mon Sep 17 00:00:00 2001 From: benni-tec Date: Sat, 4 Nov 2023 18:41:25 +0100 Subject: [PATCH 10/17] removed ExportSettings and changed JsonExport to use JsonObjects (better type safety) --- packages/tiled/lib/src/chunk.dart | 8 ++- packages/tiled/lib/src/common/frame.dart | 2 +- packages/tiled/lib/src/common/gid.dart | 18 +++---- packages/tiled/lib/src/common/property.dart | 2 +- .../tiled/lib/src/common/tiled_image.dart | 2 +- packages/tiled/lib/src/data.dart | 29 +++++----- .../lib/src/exporter/export_element.dart | 30 +++++------ .../lib/src/exporter/export_settings.dart | 15 ------ .../tiled/lib/src/exporter/export_value.dart | 18 +++---- .../tiled/lib/src/exporter/exportable.dart | 6 +-- packages/tiled/lib/src/exporter/json.dart | 8 +-- packages/tiled/lib/src/layer.dart | 53 ++++++++++--------- packages/tiled/lib/src/objects/text.dart | 2 +- .../tiled/lib/src/objects/tiled_object.dart | 4 +- packages/tiled/lib/src/tiled_map.dart | 6 +-- packages/tiled/lib/src/tileset/grid.dart | 2 +- packages/tiled/lib/src/tileset/tile.dart | 10 ++-- .../tiled/lib/src/tileset/tile_offset.dart | 2 +- packages/tiled/lib/src/tileset/tileset.dart | 24 ++++----- .../lib/src/tileset/wang/wang_color.dart | 2 +- .../tiled/lib/src/tileset/wang/wang_set.dart | 6 +-- .../tiled/lib/src/tileset/wang/wang_tile.dart | 4 +- packages/tiled/lib/tiled.dart | 1 - packages/tiled/test/exporter/map.dart | 6 +-- packages/tiled/test/exporter/properties.dart | 6 +-- 25 files changed, 130 insertions(+), 136 deletions(-) delete mode 100644 packages/tiled/lib/src/exporter/export_settings.dart diff --git a/packages/tiled/lib/src/chunk.dart b/packages/tiled/lib/src/chunk.dart index bab4331..b9cbd8a 100644 --- a/packages/tiled/lib/src/chunk.dart +++ b/packages/tiled/lib/src/chunk.dart @@ -61,7 +61,7 @@ class Chunk extends Exportable { } @override - ExportElement export(ExportSettings settings) { + ExportElement export({FileEncoding? encoding, Compression? compression}) { final common = { 'x': x.toExport(), 'y': y.toExport(), @@ -73,7 +73,11 @@ class Chunk extends Exportable { 'chunk', common, { - 'data': TileData(data).export(settings), + 'data': TileDataEncoder( + data: data, + compression: compression, + encoding: encoding, + ).export(), }, ); } diff --git a/packages/tiled/lib/src/common/frame.dart b/packages/tiled/lib/src/common/frame.dart index a543eca..f9ad1b8 100644 --- a/packages/tiled/lib/src/common/frame.dart +++ b/packages/tiled/lib/src/common/frame.dart @@ -24,7 +24,7 @@ class Frame extends Exportable { ); @override - ExportResolver export(ExportSettings settings) => ExportElement('frame', { + ExportResolver export() => ExportElement('frame', { 'tileid': tileId.toExport(), 'duration': duration.toExport(), }, {}); diff --git a/packages/tiled/lib/src/common/gid.dart b/packages/tiled/lib/src/common/gid.dart index 1d32817..04e47e2 100644 --- a/packages/tiled/lib/src/common/gid.dart +++ b/packages/tiled/lib/src/common/gid.dart @@ -32,7 +32,7 @@ part of tiled; /// When rendering a tile, the order of operation matters. The diagonal flip /// (x/y axis swap) is done first, followed by the horizontal and vertical /// flips. -class Gid extends ExportValue { +class Gid extends ExportValue { static const int flippedHorizontallyFlag = 0x80000000; static const int flippedVerticallyFlag = 0x40000000; static const int flippedDiagonallyFlag = 0x20000000; @@ -83,16 +83,16 @@ class Gid extends ExportValue { }); } - String export() => ((tile & ~flagBits) | - (flips.horizontally ? flippedHorizontallyFlag : 0) | - (flips.vertically ? flippedVerticallyFlag : 0) | - (flips.diagonally ? flippedDiagonallyFlag : 0) | - (flips.antiDiagonally ? flippedAntiDiagonallyFlag : 0)) - .toString(); + int export() => + (tile & ~flagBits) | + (flips.horizontally ? flippedHorizontallyFlag : 0) | + (flips.vertically ? flippedVerticallyFlag : 0) | + (flips.diagonally ? flippedDiagonallyFlag : 0) | + (flips.antiDiagonally ? flippedAntiDiagonallyFlag : 0); @override - String get json => export(); + int get json => export(); @override - String get xml => export(); + String get xml => export().toString(); } diff --git a/packages/tiled/lib/src/common/property.dart b/packages/tiled/lib/src/common/property.dart index 58b9cbe..6262241 100644 --- a/packages/tiled/lib/src/common/property.dart +++ b/packages/tiled/lib/src/common/property.dart @@ -12,7 +12,7 @@ part of tiled; /// (default string is “”, default number is 0, default boolean is “false”, /// default color is #00000000, default file is “.” (the current file’s /// parent directory)) -class Property { +class Property with Exportable { String name; PropertyType type; T value; diff --git a/packages/tiled/lib/src/common/tiled_image.dart b/packages/tiled/lib/src/common/tiled_image.dart index 1946192..eef2db2 100644 --- a/packages/tiled/lib/src/common/tiled_image.dart +++ b/packages/tiled/lib/src/common/tiled_image.dart @@ -55,7 +55,7 @@ class TiledImage with Exportable { int get hashCode => source.hashCode; @override - ExportElement export(ExportSettings settings) => ExportElement( + ExportElement export() => ExportElement( 'image', { 'width': width?.toExport(), diff --git a/packages/tiled/lib/src/data.dart b/packages/tiled/lib/src/data.dart index 0b2e6cd..5611238 100644 --- a/packages/tiled/lib/src/data.dart +++ b/packages/tiled/lib/src/data.dart @@ -1,28 +1,33 @@ part of tiled; -class TileData extends DelegatingList with Exportable { - TileData(super.base); +class TileDataEncoder extends DelegatingList with Exportable { + final FileEncoding? encoding; + final Compression? compression; + + TileDataEncoder({ + required List data, + required this.encoding, + required this.compression, + }) : super(data); @override - ExportResolver export(ExportSettings settings) { + ExportResolver export() { String? data; - switch (settings.encoding) { + switch (encoding) { case null: break; case FileEncoding.csv: data = join(', '); break; case FileEncoding.base64: - data = _base64(settings); + data = _base64(); break; } return ExportFormatSpecific( xml: ExportElement('data', { - if (settings.encoding != null) - 'encoding': settings.encoding!.name.toExport(), - if (settings.compression != null) - 'compression': settings.compression!.name.toExport(), + if (encoding != null) 'encoding': encoding!.name.toExport(), + if (compression != null) 'compression': compression!.name.toExport(), }, { if (data == null) 'tiles': ExportList(map( @@ -39,7 +44,7 @@ class TileData extends DelegatingList with Exportable { ); } - String _base64(ExportSettings settings) { + String _base64() { // Conversion to Uint8List final uint32 = Uint32List.fromList(this); final dv = ByteData(this.length * 4); @@ -52,8 +57,8 @@ class TileData extends DelegatingList with Exportable { // Compression List compressed; - print(settings.compression); - switch (settings.compression) { + print(compression); + switch (compression) { case Compression.zlib: compressed = const ZLibEncoder().encode(uint8); break; diff --git a/packages/tiled/lib/src/exporter/export_element.dart b/packages/tiled/lib/src/exporter/export_element.dart index ade0e9b..d09705b 100644 --- a/packages/tiled/lib/src/exporter/export_element.dart +++ b/packages/tiled/lib/src/exporter/export_element.dart @@ -5,7 +5,7 @@ abstract class ExportObject {} abstract class ExportResolver implements ExportObject { XmlNode exportXml(); - dynamic exportJson(); + JsonObject exportJson(); } class ExportElement implements ExportResolver { @@ -49,34 +49,34 @@ class ExportElement implements ExportResolver { } @override - Map exportJson() => { - ...fields.map( - (key, value) => MapEntry(key, value.json), + JsonMap exportJson() => JsonMap({ + ...fields.map( + (key, value) => MapEntry(key, value.exportJson()), ), - ...children.map((key, e) { + ...children.map((key, e) { if (e is ExportList) { - return MapEntry>( + return MapEntry( key, - e.map((e) => e.exportJson()).toList(), + JsonList(e.map((e) => e.exportJson())), ); } else if (e is ExportResolver) { - return MapEntry(key, e.exportJson()); + return MapEntry(key, e.exportJson()); } else { throw 'Bad State: ExportChild switch should have been exhaustive'; } }), - 'properties': properties.map((e) => e.export().exportJson()).toList(), - }; + 'properties': JsonList(properties.map((e) => e.exportJson())), + }); } class ExportDirect implements ExportResolver { final XmlElement xml; - final dynamic json; + final JsonObject json; ExportDirect({required this.xml, required this.json}); @override - dynamic exportJson() => json; + JsonObject exportJson() => json; @override XmlElement exportXml() => xml; @@ -89,7 +89,7 @@ class ExportFormatSpecific implements ExportResolver { ExportFormatSpecific({required this.xml, required this.json}); @override - dynamic exportJson() => json.exportJson(); + JsonObject exportJson() => json.exportJson(); @override XmlNode exportXml() => xml.exportXml(); @@ -99,6 +99,6 @@ class ExportList extends DelegatingList implements ExportObject { ExportList(Iterable base) : super(base.toList()); - ExportList.from(Iterable source, ExportSettings settings) - : super(source.map((e) => e.export(settings)).toList()); + ExportList.from(Iterable source) + : super(source.map((e) => e.export()).toList()); } diff --git a/packages/tiled/lib/src/exporter/export_settings.dart b/packages/tiled/lib/src/exporter/export_settings.dart deleted file mode 100644 index 325c141..0000000 --- a/packages/tiled/lib/src/exporter/export_settings.dart +++ /dev/null @@ -1,15 +0,0 @@ -part of tiled; - -class ExportSettings { - final FileEncoding? encoding; - final Compression? compression; - - ExportSettings({ - required this.encoding, - required this.compression, - }) { - if (compression != null) { - assert(encoding == FileEncoding.base64); - } - } -} diff --git a/packages/tiled/lib/src/exporter/export_value.dart b/packages/tiled/lib/src/exporter/export_value.dart index 4d681aa..7602367 100644 --- a/packages/tiled/lib/src/exporter/export_value.dart +++ b/packages/tiled/lib/src/exporter/export_value.dart @@ -1,19 +1,19 @@ part of tiled; -abstract class ExportValue implements ExportObject, ExportResolver { +abstract class ExportValue implements ExportObject, ExportResolver { const ExportValue(); String get xml; - dynamic get json; + T get json; @override XmlNode exportXml() => XmlText(xml); @override - dynamic exportJson() => json; + JsonValue exportJson() => JsonValue(json); } -class ExportLiteral extends ExportValue { +class ExportLiteral extends ExportValue { final T value; const ExportLiteral(this.value); @@ -33,7 +33,7 @@ extension ExportableNum on num { ExportValue toExport() => ExportLiteral(this); } -class _ExportableBool extends ExportValue { +class _ExportableBool extends ExportValue { final bool value; _ExportableBool(this.value); @@ -49,7 +49,7 @@ extension ExportableBool on bool { ExportValue toExport() => _ExportableBool(this); } -class _ExportableColor extends ExportValue { +class _ExportableColor extends ExportValue { final Color color; const _ExportableColor(this.color); @@ -72,16 +72,16 @@ extension ExportableColor on Color { ExportValue toExport() => _ExportableColor(this); } -class _ExportablePointList extends ExportValue { +class _ExportablePointList extends ExportValue>> { final List points; _ExportablePointList(this.points); @override - Iterable> get json => points.map((e) => { + List> get json => points.map((e) => { 'x': e.x, 'y': e.y, - }); + }).toList(); @override String get xml => points.map((e) => '${e.x},${e.y}').join(' '); diff --git a/packages/tiled/lib/src/exporter/exportable.dart b/packages/tiled/lib/src/exporter/exportable.dart index be1f179..56ebc3d 100644 --- a/packages/tiled/lib/src/exporter/exportable.dart +++ b/packages/tiled/lib/src/exporter/exportable.dart @@ -1,8 +1,8 @@ part of tiled; abstract class Exportable { - ExportResolver export(ExportSettings settings); + ExportResolver export(); - XmlNode exportXml(ExportSettings settings) => export(settings).exportXml(); - dynamic exportJson(ExportSettings settings) => export(settings).exportJson(); + XmlNode exportXml() => export().exportXml(); + JsonObject exportJson() => export().exportJson(); } diff --git a/packages/tiled/lib/src/exporter/json.dart b/packages/tiled/lib/src/exporter/json.dart index 6175d45..ad0e5ba 100644 --- a/packages/tiled/lib/src/exporter/json.dart +++ b/packages/tiled/lib/src/exporter/json.dart @@ -5,7 +5,7 @@ abstract class JsonObject { } class JsonList extends DelegatingList implements JsonObject { - JsonList([super.base = const []]); + JsonList([Iterable? base]) : super(base?.toList() ?? []); @override List get value => this; @@ -18,7 +18,9 @@ class JsonMap extends DelegatingMap implements JsonObject { Map get value => this; } -class JsonValue implements JsonObject { +class JsonValue implements JsonObject { @override - dynamic get value => this; + final T value; + + JsonValue(this.value); } diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 95d2c5a..23bb83b 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -144,17 +144,13 @@ abstract class Layer extends Exportable { (json) => null, // data is just a string or list of int on JSON (xml) => xml.getSingleChildOrNull('data'), ); - final compression = parser.getCompressionOrNull('compression') ?? - dataNode?.getCompressionOrNull('compression'); - final encoding = parser.getFileEncodingOrNull('encoding') ?? - dataNode?.getFileEncodingOrNull('encoding') ?? - FileEncoding.csv; + final compression = parser.getCompressionOrNull('compression') ?? dataNode?.getCompressionOrNull('compression'); + final encoding = + parser.getFileEncodingOrNull('encoding') ?? dataNode?.getFileEncodingOrNull('encoding') ?? FileEncoding.csv; Chunk parseChunk(Parser e) => Chunk.parse(e, encoding, compression); - final chunks = parser.getChildrenAs('chunks', parseChunk) + - (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); - final data = dataNode != null - ? parseLayerData(dataNode, encoding, compression) - : null; + final chunks = + parser.getChildrenAs('chunks', parseChunk) + (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); + final data = dataNode != null ? parseLayerData(dataNode, encoding, compression) : null; layer = TileLayer( id: id, name: name, @@ -185,10 +181,8 @@ abstract class Layer extends Exportable { 'draworder', defaults: DrawOrder.topDown, ); - final colorHex = - parser.getString('color', defaults: ObjectGroup.defaultColorHex); - final color = - parser.getColor('color', defaults: ObjectGroup.defaultColor); + final colorHex = parser.getString('color', defaults: ObjectGroup.defaultColorHex); + final color = parser.getColor('color', defaults: ObjectGroup.defaultColor); final objects = parser.getChildrenAs('object', TiledObject.parse); layer = ObjectGroup( id: id, @@ -352,7 +346,7 @@ abstract class Layer extends Exportable { } @override - ExportElement export(ExportSettings settings); + ExportElement export(); } class TileLayer extends Layer { @@ -422,7 +416,7 @@ class TileLayer extends Layer { } @override - ExportElement export(ExportSettings settings) => ExportElement( + ExportElement export() => ExportElement( 'layer', { 'class': class_?.toExport(), @@ -437,8 +431,17 @@ class TileLayer extends Layer { 'compression': (data == null ? compression : null)?.name.toExport(), }.nonNulls(), { - if (chunks != null) 'chunks': ExportList.from(chunks!, settings), - if (data != null) 'data': TileData(data!).export(settings), + if (chunks != null) + 'chunks': ExportList(chunks!.map((e) => e.export( + encoding: encoding, + compression: compression, + ))), + if (data != null) + 'data': TileDataEncoder( + data: data!, + compression: compression, + encoding: encoding, + ).export(), }, ); } @@ -490,7 +493,7 @@ class ObjectGroup extends Layer { ); @override - ExportElement export(ExportSettings settings) => ExportElement( + ExportElement export() => ExportElement( 'objectgroup', { 'id': id?.toExport(), @@ -510,7 +513,7 @@ class ObjectGroup extends Layer { 'draworder': drawOrder.name.toExport(), }.nonNulls(), { - 'objects': ExportList.from(objects, settings), + 'objects': ExportList.from(objects), }, ); } @@ -562,7 +565,7 @@ class ImageLayer extends Layer { ); @override - ExportElement export(ExportSettings settings) => ExportElement( + ExportElement export() => ExportElement( 'imagelayer', { 'id': id?.toExport(), @@ -582,7 +585,7 @@ class ImageLayer extends Layer { 'repeaty': repeatY.toExport(), }.nonNulls(), { - 'image': image.export(settings), + 'image': image.export(), }); } @@ -613,7 +616,7 @@ class Group extends Layer { ); @override - ExportElement export(ExportSettings settings) => ExportElement( + ExportElement export() => ExportElement( 'group', { 'id': id?.toExport(), @@ -629,8 +632,8 @@ class Group extends Layer { 'parallaxy': parallaxY.toExport(), }.nonNulls(), { - 'layers': ExportList.from(layers, settings), + 'layers': ExportList.from(layers), }, - properties, + properties, ); } diff --git a/packages/tiled/lib/src/objects/text.dart b/packages/tiled/lib/src/objects/text.dart index 29a912d..a7d4de0 100644 --- a/packages/tiled/lib/src/objects/text.dart +++ b/packages/tiled/lib/src/objects/text.dart @@ -86,7 +86,7 @@ class Text extends Exportable { ); @override - ExportElement export(ExportSettings settings) => + ExportElement export() => ExportElement('text', { 'fontfamily': fontFamily.toExport(), 'pixelsize': pixelSize.toExport(), diff --git a/packages/tiled/lib/src/objects/tiled_object.dart b/packages/tiled/lib/src/objects/tiled_object.dart index ad017f6..1504d02 100644 --- a/packages/tiled/lib/src/objects/tiled_object.dart +++ b/packages/tiled/lib/src/objects/tiled_object.dart @@ -176,7 +176,7 @@ class TiledObject extends Exportable { } @override - ExportResolver export(ExportSettings settings) { + ExportResolver export() { final common = { 'id': id.toExport(), 'name': name.toExport(), @@ -214,7 +214,7 @@ class TiledObject extends Exportable { }, {}, ), - if (text != null) 'text': text!.export(settings), + if (text != null) 'text': text!.export(), }, properties ), diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index dab7784..ba0ce32 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -360,7 +360,7 @@ class TiledMap with Exportable { } @override - ExportElement export(ExportSettings settings) => ExportElement( + ExportElement export() => ExportElement( 'map', { 'version': '1.10'.toExport(), @@ -386,8 +386,8 @@ class TiledMap with Exportable { 'infinite': infinite.toExport(), }.nonNulls(), { - 'tilesets': ExportList.from(tilesets, settings), - 'layers': ExportList.from(layers, settings), + 'tilesets': ExportList.from(tilesets), + 'layers': ExportList.from(layers), }, properties, ); diff --git a/packages/tiled/lib/src/tileset/grid.dart b/packages/tiled/lib/src/tileset/grid.dart index 99378f7..5c8be92 100644 --- a/packages/tiled/lib/src/tileset/grid.dart +++ b/packages/tiled/lib/src/tileset/grid.dart @@ -31,7 +31,7 @@ class Grid extends Exportable { ); @override - ExportResolver export(ExportSettings settings) => ExportElement( + ExportResolver export() => ExportElement( 'grid', { 'orientation': orientation.name.toExport(), diff --git a/packages/tiled/lib/src/tileset/tile.dart b/packages/tiled/lib/src/tileset/tile.dart index 8c0e663..7118aca 100644 --- a/packages/tiled/lib/src/tileset/tile.dart +++ b/packages/tiled/lib/src/tileset/tile.dart @@ -90,7 +90,7 @@ class Tile with Exportable { } @override - ExportResolver export(ExportSettings settings) { + ExportResolver export() { final fields = { 'id': localId.toExport(), 'class': type?.toExport(), @@ -102,8 +102,8 @@ class Tile with Exportable { }.nonNulls(); final children = { - 'image': image?.export(settings), - 'objectgroup': objectGroup?.export(settings) + 'image': image?.export(), + 'objectgroup': objectGroup?.export() }.nonNulls(); return ExportFormatSpecific( @@ -117,7 +117,7 @@ class Tile with Exportable { 'animation', {}, { - 'frames': ExportList.from(animation, settings), + 'frames': ExportList.from(animation), }, ), }, @@ -128,7 +128,7 @@ class Tile with Exportable { fields, { ...children, - 'animation': ExportList.from(animation, settings), + 'animation': ExportList.from(animation), }, properties, ), diff --git a/packages/tiled/lib/src/tileset/tile_offset.dart b/packages/tiled/lib/src/tileset/tile_offset.dart index 3707e4b..c7bfa5c 100644 --- a/packages/tiled/lib/src/tileset/tile_offset.dart +++ b/packages/tiled/lib/src/tileset/tile_offset.dart @@ -27,7 +27,7 @@ class TileOffset extends Exportable { ); @override - ExportResolver export(ExportSettings settings) => ExportElement( + ExportResolver export() => ExportElement( 'tileoffset', { 'x': x.toExport(), diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 5eb5909..43d7c46 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -263,8 +263,8 @@ class Tileset with Exportable { } @override - ExportResolver export(ExportSettings settings) => source == null - ? _export(settings, false) + ExportResolver export() => source == null + ? _export(false) : ExportElement( 'tileset', { @@ -274,10 +274,10 @@ class Tileset with Exportable { {}, ); - ExportResolver exportExternal(ExportSettings settings) => - _export(settings, true); + ExportResolver exportExternal() => + _export(true); - ExportResolver _export(ExportSettings settings, bool external) { + ExportResolver _export(bool external) { final fields = { if (!external) 'firstgid': firstGid!.toExport(), 'name': name!.toExport(), @@ -297,18 +297,18 @@ class Tileset with Exportable { }.nonNulls(); final common = { - 'image': image?.export(settings), - 'tiles': ExportList.from(tiles, settings), - 'tileoffset': tileOffset?.export(settings), - 'grid': grid?.export(settings), + 'image': image?.export(), + 'tiles': ExportList.from(tiles), + 'tileoffset': tileOffset?.export(), + 'grid': grid?.export(), // 'terraintypes': , DEPRECATED - // 'transformations': ExportList.from(transformations, settings), Not supported by this class + // 'transformations': ExportList.from(transformations), Not supported by this class }.nonNulls(); final wangsets = ExportElement( 'wangsets', {}, - {'wangsets': ExportList.from(wangSets, settings)}, + {'wangsets': ExportList.from(wangSets)}, properties, ); @@ -327,7 +327,7 @@ class Tileset with Exportable { fields, { ...common, - 'wangsets': ExportList.from(wangSets, settings), + 'wangsets': ExportList.from(wangSets), }, ), ); diff --git a/packages/tiled/lib/src/tileset/wang/wang_color.dart b/packages/tiled/lib/src/tileset/wang/wang_color.dart index b5cc36e..bd5fef7 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_color.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_color.dart @@ -39,7 +39,7 @@ class WangColor with Exportable { ); @override - ExportResolver export(ExportSettings settings) => ExportElement( + ExportResolver export() => ExportElement( 'wangcolor', { 'name': name.toExport(), diff --git a/packages/tiled/lib/src/tileset/wang/wang_set.dart b/packages/tiled/lib/src/tileset/wang/wang_set.dart index f693c96..9bbde4c 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_set.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_set.dart @@ -55,7 +55,7 @@ class WangSet extends Exportable { } @override - ExportResolver export(ExportSettings settings) { + ExportResolver export() { final colors = cornerColors..addAll(edgeColors); return ExportElement( @@ -65,8 +65,8 @@ class WangSet extends Exportable { 'tile': tile.toExport(), }, { - 'colors': ExportList.from(colors, settings), - 'wangtiles': ExportList.from(wangTiles, settings), + 'colors': ExportList.from(colors), + 'wangtiles': ExportList.from(wangTiles), }, properties, ); diff --git a/packages/tiled/lib/src/tileset/wang/wang_tile.dart b/packages/tiled/lib/src/tileset/wang/wang_tile.dart index 1aecb94..b530265 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_tile.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_tile.dart @@ -62,7 +62,7 @@ class WangTile with Exportable { } @override - ExportResolver export(ExportSettings settings) { + ExportResolver export() { final common = { 'tileid': tileId.toExport(), }; @@ -81,7 +81,7 @@ class WangTile with Exportable { 'wangtile', { ...common, - 'wangid': ExportLiteral(wangId), + 'wangid': ExportLiteral>(wangId), }, {}, ), diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index 784c944..5dce153 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -15,7 +15,6 @@ part 'src/data.dart'; part 'src/exporter/exportable.dart'; part 'src/exporter/export_value.dart'; part 'src/exporter/export_element.dart'; -part 'src/exporter/export_settings.dart'; part 'src/exporter/json.dart'; part 'src/common/enums.dart'; part 'src/common/flips.dart'; diff --git a/packages/tiled/test/exporter/map.dart b/packages/tiled/test/exporter/map.dart index 642bc78..ce2170e 100644 --- a/packages/tiled/test/exporter/map.dart +++ b/packages/tiled/test/exporter/map.dart @@ -5,8 +5,6 @@ import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; void main() { - final settings = ExportSettings(encoding: null, compression: null); - late TiledMap export; setUp(() => export = TiledMap( width: 576, @@ -36,12 +34,12 @@ void main() { group('Exporter - Map', () { test( 'Xml', - () => testSuite(XmlParser(export.exportXml(settings) as XmlElement)), + () => testSuite(XmlParser(export.exportXml() as XmlElement)), ); test( 'Json', () => testSuite( - JsonParser(export.exportJson(settings) as Map)), + JsonParser(export.exportJson() as Map)), ); }); } diff --git a/packages/tiled/test/exporter/properties.dart b/packages/tiled/test/exporter/properties.dart index 039ebd0..bf1307a 100644 --- a/packages/tiled/test/exporter/properties.dart +++ b/packages/tiled/test/exporter/properties.dart @@ -4,8 +4,6 @@ import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; void main() { - final settings = ExportSettings(encoding: null, compression: null); - late TiledObject export; late CustomProperties byName; setUp(() { @@ -28,10 +26,10 @@ void main() { group('Exporter - CustomProperties', () { test('Xml', - () => testSuite(XmlParser(export.exportXml(settings) as XmlElement))); + () => testSuite(XmlParser(export.exportXml() as XmlElement))); test( 'Json', () => testSuite( - JsonParser(export.exportJson(settings) as Map))); + JsonParser(export.exportJson() as Map))); }); } From 9174a0ae73daa7679391df6454b94eef7d2eff3e Mon Sep 17 00:00:00 2001 From: benni-tec Date: Mon, 6 Nov 2023 09:12:02 +0100 Subject: [PATCH 11/17] rebase onto #69-dart-sdk --- packages/tiled/lib/src/common/color.dart | 14 ++++++++++- packages/tiled/lib/src/common/property.dart | 2 +- .../tiled/lib/src/exporter/export_value.dart | 23 ------------------- packages/tiled/lib/src/layer.dart | 8 +++---- packages/tiled/lib/src/tiled_map.dart | 2 +- packages/tiled/test/exporter/map.dart | 6 ++--- packages/tiled/test/exporter/properties.dart | 2 +- packages/tiled/test/exporter/xml.dart | 2 +- 8 files changed, 23 insertions(+), 36 deletions(-) diff --git a/packages/tiled/lib/src/common/color.dart b/packages/tiled/lib/src/common/color.dart index 135bf22..cb44af6 100644 --- a/packages/tiled/lib/src/common/color.dart +++ b/packages/tiled/lib/src/common/color.dart @@ -2,7 +2,7 @@ part of tiled; /// Basic data class holding a Color in ARGB format. /// This can be converted to dart:ui's Color using the flame_tiled package -class ColorData { +class ColorData extends ExportValue { static int _sub(int hex, int index) => (hex >> index * 8) & 0x000000ff; final int red; @@ -22,4 +22,16 @@ class ColorData { assert(green >= 0 && green <= 255), assert(blue >= 0 && blue <= 255), assert(alpha >= 0 && alpha <= 255); + + static String _hex(int value) { + return value.toRadixString(16).padLeft(2, '0'); + } + + String get export => '#${_hex(alpha)}${_hex(red)}${_hex(green)}${_hex(blue)}'; + + @override + String get json => export; + + @override + String get xml => export; } diff --git a/packages/tiled/lib/src/common/property.dart b/packages/tiled/lib/src/common/property.dart index 6262241..04ff328 100644 --- a/packages/tiled/lib/src/common/property.dart +++ b/packages/tiled/lib/src/common/property.dart @@ -174,7 +174,7 @@ class ColorProperty extends Property { }) : super(type: PropertyType.color); @override - ExportValue get exportValue => value.toExport(); + ExportValue get exportValue => value; } /// [value] is the string text diff --git a/packages/tiled/lib/src/exporter/export_value.dart b/packages/tiled/lib/src/exporter/export_value.dart index 7602367..e1566fa 100644 --- a/packages/tiled/lib/src/exporter/export_value.dart +++ b/packages/tiled/lib/src/exporter/export_value.dart @@ -49,29 +49,6 @@ extension ExportableBool on bool { ExportValue toExport() => _ExportableBool(this); } -class _ExportableColor extends ExportValue { - final Color color; - - const _ExportableColor(this.color); - - static String _hex(int value) { - return value.toRadixString(16).padLeft(2, '0'); - } - - String get export => - '#${_hex(color.alpha)}${_hex(color.red)}${_hex(color.green)}${_hex(color.blue)}'; - - @override - String get json => export; - - @override - String get xml => export; -} - -extension ExportableColor on Color { - ExportValue toExport() => _ExportableColor(this); -} - class _ExportablePointList extends ExportValue>> { final List points; diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 23bb83b..8574588 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -502,8 +502,8 @@ class ObjectGroup extends Layer { 'type': type.name.toExport(), 'x': x.toExport(), 'y': y.toExport(), - 'color': color.toExport(), - 'tintcolor': tintColor?.toExport(), + 'color': color, + 'tintcolor': tintColor, 'opacity': opacity.toExport(), 'visible': (visible ? 1 : 0).toExport(), 'offsetx': offsetX.toExport(), @@ -574,7 +574,7 @@ class ImageLayer extends Layer { 'type': type.name.toExport(), 'x': x.toExport(), 'y': y.toExport(), - 'tintcolor': tintColor?.toExport(), + 'tintcolor': tintColor, 'opacity': opacity.toExport(), 'visible': (visible ? 1 : 0).toExport(), 'offsetx': offsetX.toExport(), @@ -623,7 +623,7 @@ class Group extends Layer { 'name': name.toExport(), 'class': class_?.toExport(), 'type': type.name.toExport(), - 'tintcolor': tintColor?.toExport(), + 'tintcolor': tintColor, 'opacity': opacity.toExport(), 'visible': (visible ? 1 : 0).toExport(), 'offsetx': offsetX.toExport(), diff --git a/packages/tiled/lib/src/tiled_map.dart b/packages/tiled/lib/src/tiled_map.dart index ba0ce32..9ee666c 100644 --- a/packages/tiled/lib/src/tiled_map.dart +++ b/packages/tiled/lib/src/tiled_map.dart @@ -380,7 +380,7 @@ class TiledMap with Exportable { 'staggerindex': staggerIndex?.name.toExport(), // 'parallaxoriginx': , 'parallaxoriginy': , Not supplied by this class - 'backgroundcolor': backgroundColor?.toExport(), + 'backgroundcolor': backgroundColor, 'nextlayerid': nextLayerId?.toExport(), 'nextobjectid': nextObjectId?.toExport(), 'infinite': infinite.toExport(), diff --git a/packages/tiled/test/exporter/map.dart b/packages/tiled/test/exporter/map.dart index ce2170e..ac0da43 100644 --- a/packages/tiled/test/exporter/map.dart +++ b/packages/tiled/test/exporter/map.dart @@ -1,6 +1,4 @@ -import 'dart:ui'; - -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; @@ -16,7 +14,7 @@ void main() { hexSideLength: 24, staggerAxis: StaggerAxis.y, staggerIndex: StaggerIndex.even, - backgroundColor: const Color(0xaa252627), + backgroundColor: Color.hex(0xaa252627), nextLayerId: 24, nextObjectId: 56, infinite: false, diff --git a/packages/tiled/test/exporter/properties.dart b/packages/tiled/test/exporter/properties.dart index bf1307a..c05c62e 100644 --- a/packages/tiled/test/exporter/properties.dart +++ b/packages/tiled/test/exporter/properties.dart @@ -1,5 +1,5 @@ import 'package:collection/collection.dart'; -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:tiled/tiled.dart'; import 'package:xml/xml.dart'; diff --git a/packages/tiled/test/exporter/xml.dart b/packages/tiled/test/exporter/xml.dart index be1dba5..5a07039 100644 --- a/packages/tiled/test/exporter/xml.dart +++ b/packages/tiled/test/exporter/xml.dart @@ -1,4 +1,4 @@ -import 'package:flutter_test/flutter_test.dart'; +import 'package:test/test.dart'; import 'package:xml/xml.dart'; class XmlDeepMatcher extends Matcher { From a7d451c86c328804d13a89c3e4379b01f4dea12a Mon Sep 17 00:00:00 2001 From: benni-tec Date: Mon, 6 Nov 2023 12:48:24 +0100 Subject: [PATCH 12/17] fixed typo --- packages/tiled/lib/src/tileset/tileset.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 43d7c46..3e3c4bd 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -285,7 +285,7 @@ class Tileset with Exportable { 'type': type.name.toExport(), 'tilewidth': tileWidth?.toExport(), - 'tileheigth': tileHeight?.toExport(), + 'tileheight': tileHeight?.toExport(), 'spacing': spacing.toExport(), 'margin': margin.toExport(), From 657a547517dfaf55c4dcdb3b2ee5256213c3f50e Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 7 Nov 2023 14:44:22 +0100 Subject: [PATCH 13/17] added imageRect passthrough for explicit tiles without an existent imageRect --- packages/tiled/lib/src/tileset/tileset.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 3e3c4bd..a0878d3 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -256,6 +256,8 @@ class Tileset with Exportable { if (tile.localId >= tiles.length) { tiles.add(tile); } else { + final generated = tiles[tile.localId]; + if (tile.imageRect == null) tile.imageRect = generated.imageRect; tiles[tile.localId] = tile; } } From 54f4a0694e421d0bf29e54cde7cf704a80ba6c3d Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 20:53:46 +0100 Subject: [PATCH 14/17] fixed properties missing on layers --- .../lib/src/exporter/export_element.dart | 19 ++++---- packages/tiled/lib/src/layer.dart | 46 ++++++++++--------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/packages/tiled/lib/src/exporter/export_element.dart b/packages/tiled/lib/src/exporter/export_element.dart index d09705b..4876db3 100644 --- a/packages/tiled/lib/src/exporter/export_element.dart +++ b/packages/tiled/lib/src/exporter/export_element.dart @@ -12,13 +12,13 @@ class ExportElement implements ExportResolver { final String name; final Map fields; final Map children; - final CustomProperties properties; + final CustomProperties? properties; ExportElement( this.name, this.fields, this.children, [ - this.properties = CustomProperties.empty, + this.properties, ]); @override @@ -38,11 +38,11 @@ class ExportElement implements ExportResolver { fields.entries.map((e) => XmlAttribute(XmlName(e.key), e.value.xml)), [ ..._children, - if (properties.isNotEmpty) + if (properties != null && properties!.isNotEmpty) XmlElement( XmlName('properties'), [], - properties.map((e) => e.export().exportXml()).toList(), + properties!.map((e) => e.export().exportXml()).toList(), ), ], ); @@ -65,7 +65,10 @@ class ExportElement implements ExportResolver { throw 'Bad State: ExportChild switch should have been exhaustive'; } }), - 'properties': JsonList(properties.map((e) => e.exportJson())), + if (properties != null) + 'properties': JsonList( + properties!.map((e) => e.exportJson()), + ), }); } @@ -95,10 +98,8 @@ class ExportFormatSpecific implements ExportResolver { XmlNode exportXml() => xml.exportXml(); } -class ExportList extends DelegatingList - implements ExportObject { +class ExportList extends DelegatingList implements ExportObject { ExportList(Iterable base) : super(base.toList()); - ExportList.from(Iterable source) - : super(source.map((e) => e.export()).toList()); + ExportList.from(Iterable source) : super(source.map((e) => e.export()).toList()); } diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 8574588..3583366 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -443,6 +443,7 @@ class TileLayer extends Layer { encoding: encoding, ).export(), }, + properties, ); } @@ -515,6 +516,7 @@ class ObjectGroup extends Layer { { 'objects': ExportList.from(objects), }, + properties, ); } @@ -566,27 +568,29 @@ class ImageLayer extends Layer { @override ExportElement export() => ExportElement( - 'imagelayer', - { - 'id': id?.toExport(), - 'name': name.toExport(), - 'class': class_?.toExport(), - 'type': type.name.toExport(), - 'x': x.toExport(), - 'y': y.toExport(), - 'tintcolor': tintColor, - 'opacity': opacity.toExport(), - 'visible': (visible ? 1 : 0).toExport(), - 'offsetx': offsetX.toExport(), - 'offsety': offsetY.toExport(), - 'parallaxx': parallaxX.toExport(), - 'parallaxy': parallaxY.toExport(), - 'repeatx': repeatX.toExport(), - 'repeaty': repeatY.toExport(), - }.nonNulls(), - { - 'image': image.export(), - }); + 'imagelayer', + { + 'id': id?.toExport(), + 'name': name.toExport(), + 'class': class_?.toExport(), + 'type': type.name.toExport(), + 'x': x.toExport(), + 'y': y.toExport(), + 'tintcolor': tintColor, + 'opacity': opacity.toExport(), + 'visible': (visible ? 1 : 0).toExport(), + 'offsetx': offsetX.toExport(), + 'offsety': offsetY.toExport(), + 'parallaxx': parallaxX.toExport(), + 'parallaxy': parallaxY.toExport(), + 'repeatx': repeatX.toExport(), + 'repeaty': repeatY.toExport(), + }.nonNulls(), + { + 'image': image.export(), + }, + properties, + ); } class Group extends Layer { From c0452f8a87a528d995ea7e7f4915a3ac97147ca8 Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 20:57:48 +0100 Subject: [PATCH 15/17] fixed base64 encoding and added tests for ExportTileData --- packages/tiled/lib/src/chunk.dart | 2 +- .../export_tile_data.dart} | 50 ++++++++--------- packages/tiled/lib/src/layer.dart | 2 +- packages/tiled/lib/tiled.dart | 2 +- packages/tiled/test/exporter/tile_data.dart | 54 +++++++++++++++++++ 5 files changed, 82 insertions(+), 28 deletions(-) rename packages/tiled/lib/src/{data.dart => exporter/export_tile_data.dart} (66%) create mode 100644 packages/tiled/test/exporter/tile_data.dart diff --git a/packages/tiled/lib/src/chunk.dart b/packages/tiled/lib/src/chunk.dart index b9cbd8a..c40d7d6 100644 --- a/packages/tiled/lib/src/chunk.dart +++ b/packages/tiled/lib/src/chunk.dart @@ -73,7 +73,7 @@ class Chunk extends Exportable { 'chunk', common, { - 'data': TileDataEncoder( + 'data': ExportTileData( data: data, compression: compression, encoding: encoding, diff --git a/packages/tiled/lib/src/data.dart b/packages/tiled/lib/src/exporter/export_tile_data.dart similarity index 66% rename from packages/tiled/lib/src/data.dart rename to packages/tiled/lib/src/exporter/export_tile_data.dart index 5611238..d40b478 100644 --- a/packages/tiled/lib/src/data.dart +++ b/packages/tiled/lib/src/exporter/export_tile_data.dart @@ -1,26 +1,27 @@ part of tiled; -class TileDataEncoder extends DelegatingList with Exportable { +class ExportTileData with Exportable { final FileEncoding? encoding; final Compression? compression; + final List data; - TileDataEncoder({ - required List data, + ExportTileData({ + required this.data, required this.encoding, required this.compression, - }) : super(data); + }); @override ExportResolver export() { - String? data; + String? encodedData; switch (encoding) { case null: break; case FileEncoding.csv: - data = join(', '); + encodedData = encodeCsv(); break; case FileEncoding.base64: - data = _base64(); + encodedData = encodeBase64(); break; } @@ -29,35 +30,34 @@ class TileDataEncoder extends DelegatingList with Exportable { if (encoding != null) 'encoding': encoding!.name.toExport(), if (compression != null) 'compression': compression!.name.toExport(), }, { - if (data == null) - 'tiles': ExportList(map( - (gid) => ExportElement( - 'tile', - {'gid': gid.toExport()}, - {}, - ), - )) + if (encodedData == null) + 'tiles': exportTiles() else - 'data': data.toExport(), + 'data': encodedData.toExport(), }), json: ExportLiteral(this), ); } - String _base64() { - // Conversion to Uint8List - final uint32 = Uint32List.fromList(this); - final dv = ByteData(this.length * 4); + ExportList exportTiles() => + ExportList(data.map( + (gid) => + ExportElement( + 'tile', + {'gid': gid.toExport()}, + {}, + ), + )); - for (var i = 0; i < this.length; ++i) { - dv.setInt32(i * 4, uint32[i], Endian.little); - } + String encodeCsv() => data.join(', '); - final uint8 = dv.buffer.asUint8List(); + String encodeBase64() { + // Conversion to Uint8List + final uint32 = Uint32List.fromList(data); + final uint8 = uint32.buffer.asUint8List(); // Compression List compressed; - print(compression); switch (compression) { case Compression.zlib: compressed = const ZLibEncoder().encode(uint8); diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 3583366..f320527 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -437,7 +437,7 @@ class TileLayer extends Layer { compression: compression, ))), if (data != null) - 'data': TileDataEncoder( + 'data': ExportTileData( data: data!, compression: compression, encoding: encoding, diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index 5dce153..bc37bfe 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -11,8 +11,8 @@ import 'package:meta/meta.dart'; import 'package:xml/xml.dart'; part 'src/chunk.dart'; -part 'src/data.dart'; part 'src/exporter/exportable.dart'; +part 'src/exporter/export_tile_data.dart'; part 'src/exporter/export_value.dart'; part 'src/exporter/export_element.dart'; part 'src/exporter/json.dart'; diff --git a/packages/tiled/test/exporter/tile_data.dart b/packages/tiled/test/exporter/tile_data.dart new file mode 100644 index 0000000..5e63307 --- /dev/null +++ b/packages/tiled/test/exporter/tile_data.dart @@ -0,0 +1,54 @@ +import 'dart:math'; + +import 'package:test/expect.dart'; +import 'package:test/scaffolding.dart'; +import 'package:tiled/tiled.dart'; + +void main() { + late List testData; + + setUp(() { + testData = List.generate(1000, (index) => Random().nextInt(1 << 32)); + }); + + group("base64", () { + void _test(List testData, Compression? compression) { + final encoder = ExportTileData( + data: testData, + encoding: FileEncoding.base64, + compression: compression, + ); + + final encoded = encoder.encodeBase64(); + final unencoded = Layer.parseLayerData( + JsonParser({"data": encoded}), + FileEncoding.base64, + compression, + ); + + expect(unencoded, orderedEquals(testData)); + } + + + test("base64-uncompressed", () => _test(testData, null)); + test("base64-gzip", () => _test(testData, Compression.gzip)); + test("base64-zlib", () => _test(testData, Compression.zlib)); + }); + + test("csv", () { + final encoder = ExportTileData( + data: testData, + encoding: FileEncoding.csv, + compression: null, + ); + + final encoded = encoder.encodeCsv(); + final unencoded = Layer.parseLayerData( + JsonParser({"data": encoded}), + FileEncoding.csv, + null, + ); + + expect(unencoded, orderedEquals(testData)); + }); +} From 46520809471eaf25ed53f24edf99348efe4376eb Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 21:04:41 +0100 Subject: [PATCH 16/17] formatted --- packages/tiled/lib/src/common/frame.dart | 6 +-- packages/tiled/lib/src/common/gid.dart | 25 +++++++--- packages/tiled/lib/src/common/iterable.dart | 2 +- packages/tiled/lib/src/common/map.dart | 5 +- .../lib/src/exporter/export_element.dart | 6 ++- .../lib/src/exporter/export_tile_data.dart | 14 +++--- .../tiled/lib/src/exporter/export_value.dart | 10 ++-- packages/tiled/lib/src/layer.dart | 22 ++++++--- packages/tiled/lib/src/objects/text.dart | 5 +- .../tiled/lib/src/objects/tiled_object.dart | 49 +++++++++---------- packages/tiled/lib/src/tileset/tileset.dart | 3 +- packages/tiled/test/exporter/map.dart | 5 +- packages/tiled/test/exporter/properties.dart | 10 ++-- packages/tiled/test/exporter/tile_data.dart | 1 - packages/tiled/test/exporter/xml.dart | 6 ++- 15 files changed, 92 insertions(+), 77 deletions(-) diff --git a/packages/tiled/lib/src/common/frame.dart b/packages/tiled/lib/src/common/frame.dart index f9ad1b8..057c5ce 100644 --- a/packages/tiled/lib/src/common/frame.dart +++ b/packages/tiled/lib/src/common/frame.dart @@ -25,7 +25,7 @@ class Frame extends Exportable { @override ExportResolver export() => ExportElement('frame', { - 'tileid': tileId.toExport(), - 'duration': duration.toExport(), - }, {}); + 'tileid': tileId.toExport(), + 'duration': duration.toExport(), + }, {}); } diff --git a/packages/tiled/lib/src/common/gid.dart b/packages/tiled/lib/src/common/gid.dart index 04e47e2..247a288 100644 --- a/packages/tiled/lib/src/common/gid.dart +++ b/packages/tiled/lib/src/common/gid.dart @@ -38,8 +38,10 @@ class Gid extends ExportValue { static const int flippedDiagonallyFlag = 0x20000000; static const int flippedAntiDiagonallyFlag = 0x10000000; - static const int flagBits = - flippedHorizontallyFlag | flippedVerticallyFlag | flippedDiagonallyFlag | flippedAntiDiagonallyFlag; + static const int flagBits = flippedHorizontallyFlag | + flippedVerticallyFlag | + flippedDiagonallyFlag | + flippedAntiDiagonallyFlag; final int tile; final Flips flips; @@ -48,13 +50,20 @@ class Gid extends ExportValue { factory Gid.fromInt(int gid) { // get flips from id - final flippedHorizontally = (gid & flippedHorizontallyFlag) == flippedHorizontallyFlag; - final flippedVertically = (gid & flippedVerticallyFlag) == flippedVerticallyFlag; - final flippedDiagonally = (gid & flippedDiagonallyFlag) == flippedDiagonallyFlag; - final flippedAntiDiagonally = gid & flippedAntiDiagonallyFlag == flippedAntiDiagonallyFlag; + final flippedHorizontally = + (gid & flippedHorizontallyFlag) == flippedHorizontallyFlag; + final flippedVertically = + (gid & flippedVerticallyFlag) == flippedVerticallyFlag; + final flippedDiagonally = + (gid & flippedDiagonallyFlag) == flippedDiagonallyFlag; + final flippedAntiDiagonally = + gid & flippedAntiDiagonallyFlag == flippedAntiDiagonallyFlag; // clear id from flips - final tileId = - gid & ~(flippedHorizontallyFlag | flippedVerticallyFlag | flippedDiagonallyFlag | flippedAntiDiagonallyFlag); + final tileId = gid & + ~(flippedHorizontallyFlag | + flippedVerticallyFlag | + flippedDiagonallyFlag | + flippedAntiDiagonallyFlag); final flip = Flips( flippedHorizontally, flippedVertically, diff --git a/packages/tiled/lib/src/common/iterable.dart b/packages/tiled/lib/src/common/iterable.dart index 1d6a345..443f448 100644 --- a/packages/tiled/lib/src/common/iterable.dart +++ b/packages/tiled/lib/src/common/iterable.dart @@ -14,4 +14,4 @@ extension Grouping on Iterable { return out; } -} \ No newline at end of file +} diff --git a/packages/tiled/lib/src/common/map.dart b/packages/tiled/lib/src/common/map.dart index 264c60e..ca34fba 100644 --- a/packages/tiled/lib/src/common/map.dart +++ b/packages/tiled/lib/src/common/map.dart @@ -1,5 +1,6 @@ part of tiled; extension Null on Map { - Map nonNulls() => {for (final e in entries.where((e) => e.value is V)) e.key : e.value as V}; -} \ No newline at end of file + Map nonNulls() => + {for (final e in entries.where((e) => e.value is V)) e.key: e.value as V}; +} diff --git a/packages/tiled/lib/src/exporter/export_element.dart b/packages/tiled/lib/src/exporter/export_element.dart index 4876db3..02e6ea4 100644 --- a/packages/tiled/lib/src/exporter/export_element.dart +++ b/packages/tiled/lib/src/exporter/export_element.dart @@ -98,8 +98,10 @@ class ExportFormatSpecific implements ExportResolver { XmlNode exportXml() => xml.exportXml(); } -class ExportList extends DelegatingList implements ExportObject { +class ExportList extends DelegatingList + implements ExportObject { ExportList(Iterable base) : super(base.toList()); - ExportList.from(Iterable source) : super(source.map((e) => e.export()).toList()); + ExportList.from(Iterable source) + : super(source.map((e) => e.export()).toList()); } diff --git a/packages/tiled/lib/src/exporter/export_tile_data.dart b/packages/tiled/lib/src/exporter/export_tile_data.dart index d40b478..e6d96cb 100644 --- a/packages/tiled/lib/src/exporter/export_tile_data.dart +++ b/packages/tiled/lib/src/exporter/export_tile_data.dart @@ -39,14 +39,12 @@ class ExportTileData with Exportable { ); } - ExportList exportTiles() => - ExportList(data.map( - (gid) => - ExportElement( - 'tile', - {'gid': gid.toExport()}, - {}, - ), + ExportList exportTiles() => ExportList(data.map( + (gid) => ExportElement( + 'tile', + {'gid': gid.toExport()}, + {}, + ), )); String encodeCsv() => data.join(', '); diff --git a/packages/tiled/lib/src/exporter/export_value.dart b/packages/tiled/lib/src/exporter/export_value.dart index e1566fa..3e262b5 100644 --- a/packages/tiled/lib/src/exporter/export_value.dart +++ b/packages/tiled/lib/src/exporter/export_value.dart @@ -55,10 +55,12 @@ class _ExportablePointList extends ExportValue>> { _ExportablePointList(this.points); @override - List> get json => points.map((e) => { - 'x': e.x, - 'y': e.y, - }).toList(); + List> get json => points + .map((e) => { + 'x': e.x, + 'y': e.y, + }) + .toList(); @override String get xml => points.map((e) => '${e.x},${e.y}').join(' '); diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index f320527..94d6a39 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -144,13 +144,17 @@ abstract class Layer extends Exportable { (json) => null, // data is just a string or list of int on JSON (xml) => xml.getSingleChildOrNull('data'), ); - final compression = parser.getCompressionOrNull('compression') ?? dataNode?.getCompressionOrNull('compression'); - final encoding = - parser.getFileEncodingOrNull('encoding') ?? dataNode?.getFileEncodingOrNull('encoding') ?? FileEncoding.csv; + final compression = parser.getCompressionOrNull('compression') ?? + dataNode?.getCompressionOrNull('compression'); + final encoding = parser.getFileEncodingOrNull('encoding') ?? + dataNode?.getFileEncodingOrNull('encoding') ?? + FileEncoding.csv; Chunk parseChunk(Parser e) => Chunk.parse(e, encoding, compression); - final chunks = - parser.getChildrenAs('chunks', parseChunk) + (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); - final data = dataNode != null ? parseLayerData(dataNode, encoding, compression) : null; + final chunks = parser.getChildrenAs('chunks', parseChunk) + + (dataNode?.getChildrenAs('chunk', parseChunk) ?? []); + final data = dataNode != null + ? parseLayerData(dataNode, encoding, compression) + : null; layer = TileLayer( id: id, name: name, @@ -181,8 +185,10 @@ abstract class Layer extends Exportable { 'draworder', defaults: DrawOrder.topDown, ); - final colorHex = parser.getString('color', defaults: ObjectGroup.defaultColorHex); - final color = parser.getColor('color', defaults: ObjectGroup.defaultColor); + final colorHex = + parser.getString('color', defaults: ObjectGroup.defaultColorHex); + final color = + parser.getColor('color', defaults: ObjectGroup.defaultColor); final objects = parser.getChildrenAs('object', TiledObject.parse); layer = ObjectGroup( id: id, diff --git a/packages/tiled/lib/src/objects/text.dart b/packages/tiled/lib/src/objects/text.dart index a7d4de0..0db68a6 100644 --- a/packages/tiled/lib/src/objects/text.dart +++ b/packages/tiled/lib/src/objects/text.dart @@ -86,8 +86,7 @@ class Text extends Exportable { ); @override - ExportElement export() => - ExportElement('text', { + ExportElement export() => ExportElement('text', { 'fontfamily': fontFamily.toExport(), 'pixelsize': pixelSize.toExport(), 'wrap': wrap.toExport(), @@ -100,6 +99,6 @@ class Text extends Exportable { 'halign': hAlign.name.toExport(), 'valign': vAlign.name.toExport(), }, { - 'text': text.toExport(), + 'text': text.toExport(), }); } diff --git a/packages/tiled/lib/src/objects/tiled_object.dart b/packages/tiled/lib/src/objects/tiled_object.dart index 1504d02..bc3dcbb 100644 --- a/packages/tiled/lib/src/objects/tiled_object.dart +++ b/packages/tiled/lib/src/objects/tiled_object.dart @@ -193,31 +193,30 @@ class TiledObject extends Exportable { return ExportFormatSpecific( xml: ExportElement( - 'object', - common, - { - if (ellipse) 'ellipse': ExportElement('ellipse', {}, {}), - if (point) 'point': ExportElement('point', {}, {}), - if (polygon.isNotEmpty) - 'polygon': ExportElement( - 'polygon', - { - 'points': polygon.toExport(), - }, - {}, - ), - if (polyline.isNotEmpty) - 'polyline': ExportElement( - 'polyline', - { - 'points': polygon.toExport(), - }, - {}, - ), - if (text != null) 'text': text!.export(), - }, - properties - ), + 'object', + common, + { + if (ellipse) 'ellipse': ExportElement('ellipse', {}, {}), + if (point) 'point': ExportElement('point', {}, {}), + if (polygon.isNotEmpty) + 'polygon': ExportElement( + 'polygon', + { + 'points': polygon.toExport(), + }, + {}, + ), + if (polyline.isNotEmpty) + 'polyline': ExportElement( + 'polyline', + { + 'points': polygon.toExport(), + }, + {}, + ), + if (text != null) 'text': text!.export(), + }, + properties), json: ExportElement( 'object', { diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index a0878d3..4ec974b 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -276,8 +276,7 @@ class Tileset with Exportable { {}, ); - ExportResolver exportExternal() => - _export(true); + ExportResolver exportExternal() => _export(true); ExportResolver _export(bool external) { final fields = { diff --git a/packages/tiled/test/exporter/map.dart b/packages/tiled/test/exporter/map.dart index ac0da43..176c424 100644 --- a/packages/tiled/test/exporter/map.dart +++ b/packages/tiled/test/exporter/map.dart @@ -14,7 +14,7 @@ void main() { hexSideLength: 24, staggerAxis: StaggerAxis.y, staggerIndex: StaggerIndex.even, - backgroundColor: Color.hex(0xaa252627), + backgroundColor: ColorData.hex(0xaa252627), nextLayerId: 24, nextObjectId: 56, infinite: false, @@ -36,8 +36,7 @@ void main() { ); test( 'Json', - () => testSuite( - JsonParser(export.exportJson() as Map)), + () => testSuite(JsonParser(export.exportJson() as Map)), ); }); } diff --git a/packages/tiled/test/exporter/properties.dart b/packages/tiled/test/exporter/properties.dart index c05c62e..56c92f7 100644 --- a/packages/tiled/test/exporter/properties.dart +++ b/packages/tiled/test/exporter/properties.dart @@ -19,17 +19,17 @@ void main() { expect(properties.length, equals(byName.length)); for (final property in properties) { - final match = byName.where((e) => e.name == property.name && e.value == property.value); + final match = byName + .where((e) => e.name == property.name && e.value == property.value); expect(match.length, equals(1)); } } group('Exporter - CustomProperties', () { - test('Xml', - () => testSuite(XmlParser(export.exportXml() as XmlElement))); + test('Xml', () => testSuite(XmlParser(export.exportXml() as XmlElement))); test( 'Json', - () => testSuite( - JsonParser(export.exportJson() as Map))); + () => + testSuite(JsonParser(export.exportJson() as Map))); }); } diff --git a/packages/tiled/test/exporter/tile_data.dart b/packages/tiled/test/exporter/tile_data.dart index 5e63307..45202cc 100644 --- a/packages/tiled/test/exporter/tile_data.dart +++ b/packages/tiled/test/exporter/tile_data.dart @@ -29,7 +29,6 @@ void main() { expect(unencoded, orderedEquals(testData)); } - test("base64-uncompressed", () => _test(testData, null)); test("base64-gzip", () => _test(testData, Compression.gzip)); test("base64-zlib", () => _test(testData, Compression.zlib)); diff --git a/packages/tiled/test/exporter/xml.dart b/packages/tiled/test/exporter/xml.dart index 5a07039..4bfeea3 100644 --- a/packages/tiled/test/exporter/xml.dart +++ b/packages/tiled/test/exporter/xml.dart @@ -5,10 +5,12 @@ class XmlDeepMatcher extends Matcher { final XmlElement expected; XmlDeepMatcher(this.expected); - XmlDeepMatcher.parse(String xml) : expected = XmlDocument.parse(xml).rootElement..normalize(); + XmlDeepMatcher.parse(String xml) + : expected = XmlDocument.parse(xml).rootElement..normalize(); @override - Description describe(Description description) => description..add(expected.toString()); + Description describe(Description description) => + description..add(expected.toString()); @override bool matches(dynamic item, Map matchState) { From 3a057e067b7e928edbb3539d0931d46cff97d30f Mon Sep 17 00:00:00 2001 From: benni-tec Date: Tue, 16 Jan 2024 23:03:24 +0100 Subject: [PATCH 17/17] formatted, nicer structure and dartdocs --- packages/tiled/lib/src/chunk.dart | 4 +- packages/tiled/lib/src/common/frame.dart | 14 ++- packages/tiled/lib/src/common/property.dart | 15 ++- .../lib/src/exporter/export_element.dart | 95 +++++++++---------- .../tiled/lib/src/exporter/export_value.dart | 21 +++- .../tiled/lib/src/exporter/exportable.dart | 12 ++- packages/tiled/lib/src/exporter/json.dart | 19 ++-- .../{export_tile_data.dart => tile_data.dart} | 44 +++++---- packages/tiled/lib/src/layer.dart | 16 ++-- packages/tiled/lib/src/objects/text.dart | 2 +- .../tiled/lib/src/objects/tiled_object.dart | 8 +- packages/tiled/lib/src/tileset/grid.dart | 2 +- packages/tiled/lib/src/tileset/tile.dart | 4 +- .../tiled/lib/src/tileset/tile_offset.dart | 2 +- packages/tiled/lib/src/tileset/tileset.dart | 6 +- .../tiled/lib/src/tileset/wang/wang_set.dart | 2 +- packages/tiled/lib/tiled.dart | 2 +- packages/tiled/test/color.dart | 4 +- packages/tiled/test/exporter/map.dart | 50 +++++----- packages/tiled/test/exporter/properties.dart | 8 +- packages/tiled/test/exporter/tile_data.dart | 16 ++-- packages/tiled/test/exporter/xml.dart | 12 ++- packages/tiled/test/tile_test.dart | 12 +-- packages/tiled/test/tileset_test.dart | 4 +- 24 files changed, 213 insertions(+), 161 deletions(-) rename packages/tiled/lib/src/exporter/{export_tile_data.dart => tile_data.dart} (62%) diff --git a/packages/tiled/lib/src/chunk.dart b/packages/tiled/lib/src/chunk.dart index c40d7d6..ffdf192 100644 --- a/packages/tiled/lib/src/chunk.dart +++ b/packages/tiled/lib/src/chunk.dart @@ -17,7 +17,7 @@ part of tiled; /// The data inside is a compressed (encoded) representation of a list /// (that sequentially represents a matrix) of integers representing /// [Gid]s. -class Chunk extends Exportable { +class Chunk with Exportable { List data; int x; @@ -77,7 +77,7 @@ class Chunk extends Exportable { data: data, compression: compression, encoding: encoding, - ).export(), + ), }, ); } diff --git a/packages/tiled/lib/src/common/frame.dart b/packages/tiled/lib/src/common/frame.dart index 057c5ce..c545172 100644 --- a/packages/tiled/lib/src/common/frame.dart +++ b/packages/tiled/lib/src/common/frame.dart @@ -8,7 +8,7 @@ part of tiled; /// * tileid: The local ID of a tile within the parent . /// * duration: How long (in milliseconds) this frame should be displayed /// before advancing to the next frame. -class Frame extends Exportable { +class Frame with Exportable { int tileId; int duration; @@ -24,8 +24,12 @@ class Frame extends Exportable { ); @override - ExportResolver export() => ExportElement('frame', { - 'tileid': tileId.toExport(), - 'duration': duration.toExport(), - }, {}); + ExportResolver export() => ExportElement( + 'frame', + { + 'tileid': tileId.toExport(), + 'duration': duration.toExport(), + }, + {}, + ); } diff --git a/packages/tiled/lib/src/common/property.dart b/packages/tiled/lib/src/common/property.dart index 04ff328..4758f1c 100644 --- a/packages/tiled/lib/src/common/property.dart +++ b/packages/tiled/lib/src/common/property.dart @@ -89,11 +89,16 @@ class Property with Exportable { ExportValue get exportValue => value.toString().toExport(); - ExportElement export() => ExportElement('property', { - 'name': name.toExport(), - 'type': type.name.toExport(), - 'value': exportValue, - }, {}); + @override + ExportElement export() => ExportElement( + 'property', + { + 'name': name.toExport(), + 'type': type.name.toExport(), + 'value': exportValue, + }, + {}, + ); } /// A wrapper for a Tiled property set diff --git a/packages/tiled/lib/src/exporter/export_element.dart b/packages/tiled/lib/src/exporter/export_element.dart index 02e6ea4..255e25e 100644 --- a/packages/tiled/lib/src/exporter/export_element.dart +++ b/packages/tiled/lib/src/exporter/export_element.dart @@ -1,20 +1,25 @@ part of tiled; +/// Base type for all other types. This is necessary to allow for Lists abstract class ExportObject {} +/// Base type for everything that returns a single exported value abstract class ExportResolver implements ExportObject { + /// Creates an XmlNode representing the value XmlNode exportXml(); + /// Creates an JsonObject representing this value JsonObject exportJson(); } +/// Element/object for exporting with default structure class ExportElement implements ExportResolver { final String name; final Map fields; final Map children; final CustomProperties? properties; - ExportElement( + const ExportElement( this.name, this.fields, this.children, [ @@ -22,48 +27,43 @@ class ExportElement implements ExportResolver { ]); @override - XmlElement exportXml() { - final _children = children.values.expand((e) { - if (e is ExportList) { - return e.map((e) => e.exportXml()); - } else if (e is ExportResolver) { - return [e.exportXml()]; - } else { - throw 'Bad State: ExportObject switch should have been exhaustive'; - } - }); - - return XmlElement( - XmlName(name), - fields.entries.map((e) => XmlAttribute(XmlName(e.key), e.value.xml)), - [ - ..._children, - if (properties != null && properties!.isNotEmpty) - XmlElement( - XmlName('properties'), - [], - properties!.map((e) => e.export().exportXml()).toList(), - ), - ], - ); - } + XmlElement exportXml() => XmlElement( + XmlName(name), + fields.entries.map((e) => XmlAttribute(XmlName(e.key), e.value.xml)), + [ + ...children.values.expand((e) { + if (e is ExportList) { + return e.map((e) => e.exportXml()); + } + + if (e is ExportResolver) { + return [e.exportXml()]; + } + + throw 'Bad State: ExportObject switch should have been exhaustive'; + }), + if (properties != null && properties!.isNotEmpty) + XmlElement( + XmlName('properties'), + [], + properties!.map((e) => e.exportXml()).toList(), + ), + ], + ); @override JsonMap exportJson() => JsonMap({ - ...fields.map( - (key, value) => MapEntry(key, value.exportJson()), - ), + ...fields.map((key, value) => MapEntry(key, value.exportJson())), ...children.map((key, e) { if (e is ExportList) { - return MapEntry( - key, - JsonList(e.map((e) => e.exportJson())), - ); - } else if (e is ExportResolver) { + return MapEntry(key, JsonList(e.map((e) => e.exportJson()))); + } + + if (e is ExportResolver) { return MapEntry(key, e.exportJson()); - } else { - throw 'Bad State: ExportChild switch should have been exhaustive'; } + + throw 'Bad State: ExportChild switch should have been exhaustive'; }), if (properties != null) 'properties': JsonList( @@ -72,24 +72,13 @@ class ExportElement implements ExportResolver { }); } -class ExportDirect implements ExportResolver { - final XmlElement xml; - final JsonObject json; - - ExportDirect({required this.xml, required this.json}); - - @override - JsonObject exportJson() => json; - - @override - XmlElement exportXml() => xml; -} - +/// Splits export tree according to the type of export using an ExportResolver +/// for each. class ExportFormatSpecific implements ExportResolver { final ExportResolver xml; final ExportResolver json; - ExportFormatSpecific({required this.xml, required this.json}); + const ExportFormatSpecific({required this.xml, required this.json}); @override JsonObject exportJson() => json.exportJson(); @@ -98,10 +87,14 @@ class ExportFormatSpecific implements ExportResolver { XmlNode exportXml() => xml.exportXml(); } +/// List of ExportResolvers. This is used to get Lists into json, while simply +/// expanding in xml class ExportList extends DelegatingList implements ExportObject { ExportList(Iterable base) : super(base.toList()); ExportList.from(Iterable source) - : super(source.map((e) => e.export()).toList()); + : super( + source.map((e) => e).toList(), + ); } diff --git a/packages/tiled/lib/src/exporter/export_value.dart b/packages/tiled/lib/src/exporter/export_value.dart index 3e262b5..71cab78 100644 --- a/packages/tiled/lib/src/exporter/export_value.dart +++ b/packages/tiled/lib/src/exporter/export_value.dart @@ -1,9 +1,11 @@ part of tiled; -abstract class ExportValue implements ExportObject, ExportResolver { +/// Export tree leafs. Used for exporting values like strings, bools, etc. +abstract class ExportValue implements ExportResolver { const ExportValue(); String get xml; + T get json; @override @@ -13,6 +15,7 @@ abstract class ExportValue implements ExportObject, ExportResolver { JsonValue exportJson() => JsonValue(json); } +/// Literally exports the given value class ExportLiteral extends ExportValue { final T value; @@ -25,14 +28,17 @@ class ExportLiteral extends ExportValue { String get xml => value.toString(); } +/// Conversion to export extension ExportableString on String { ExportValue toExport() => ExportLiteral(this); } +/// Conversion to export extension ExportableNum on num { ExportValue toExport() => ExportLiteral(this); } +/// Encodes bool as 0 and 1 class _ExportableBool extends ExportValue { final bool value; @@ -45,10 +51,12 @@ class _ExportableBool extends ExportValue { String get xml => (value ? 1 : 0).toString(); } +/// Conversion to export extension ExportableBool on bool { ExportValue toExport() => _ExportableBool(this); } +/// Encodes a list of [Point]s as a json array or space seperated xml string class _ExportablePointList extends ExportValue>> { final List points; @@ -56,16 +64,19 @@ class _ExportablePointList extends ExportValue>> { @override List> get json => points - .map((e) => { - 'x': e.x, - 'y': e.y, - }) + .map( + (e) => { + 'x': e.x, + 'y': e.y, + }, + ) .toList(); @override String get xml => points.map((e) => '${e.x},${e.y}').join(' '); } +/// Conversion to export extension ExportablePointList on List { ExportValue toExport() => _ExportablePointList(this); } diff --git a/packages/tiled/lib/src/exporter/exportable.dart b/packages/tiled/lib/src/exporter/exportable.dart index 56ebc3d..2d97fda 100644 --- a/packages/tiled/lib/src/exporter/exportable.dart +++ b/packages/tiled/lib/src/exporter/exportable.dart @@ -1,8 +1,18 @@ part of tiled; -abstract class Exportable { +/// Interface implemented by classes that can be exported. Instead of +/// implementing [ExportResolver]'s methods on every class this mixins allows +/// for these methods to be supplied by a proxy ExportResolver. +/// +/// This is the default mechanism as the xml/json structures are fairly +/// predictable. +abstract class Exportable implements ExportResolver { + /// Returns the proxy usually an [ExportElement] ExportResolver export(); + @override XmlNode exportXml() => export().exportXml(); + + @override JsonObject exportJson() => export().exportJson(); } diff --git a/packages/tiled/lib/src/exporter/json.dart b/packages/tiled/lib/src/exporter/json.dart index ad0e5ba..99d0358 100644 --- a/packages/tiled/lib/src/exporter/json.dart +++ b/packages/tiled/lib/src/exporter/json.dart @@ -1,25 +1,28 @@ part of tiled; -abstract class JsonObject { - dynamic get value; -} +/// Basic object in json structure, either a [JsonElement] or a [JsonValue] +abstract class JsonObject {} + +/// Basic elements, eiter a [JsonList] or a [JsonMap]. +/// Elements can be the root of a json file. +abstract class JsonElement implements JsonObject {} -class JsonList extends DelegatingList implements JsonObject { +/// List in json +class JsonList extends DelegatingList implements JsonElement { JsonList([Iterable? base]) : super(base?.toList() ?? []); - @override List get value => this; } -class JsonMap extends DelegatingMap implements JsonObject { +/// Map in json +class JsonMap extends DelegatingMap implements JsonElement { JsonMap([super.base = const {}]); - @override Map get value => this; } +/// Arbitrary value that is a json type or it will be encoded using [jsonEncode] class JsonValue implements JsonObject { - @override final T value; JsonValue(this.value); diff --git a/packages/tiled/lib/src/exporter/export_tile_data.dart b/packages/tiled/lib/src/exporter/tile_data.dart similarity index 62% rename from packages/tiled/lib/src/exporter/export_tile_data.dart rename to packages/tiled/lib/src/exporter/tile_data.dart index e6d96cb..4975d50 100644 --- a/packages/tiled/lib/src/exporter/export_tile_data.dart +++ b/packages/tiled/lib/src/exporter/tile_data.dart @@ -1,11 +1,12 @@ part of tiled; +/// Export element encoding the tile data class ExportTileData with Exportable { final FileEncoding? encoding; final Compression? compression; final List data; - ExportTileData({ + const ExportTileData({ required this.data, required this.encoding, required this.compression, @@ -26,29 +27,38 @@ class ExportTileData with Exportable { } return ExportFormatSpecific( - xml: ExportElement('data', { - if (encoding != null) 'encoding': encoding!.name.toExport(), - if (compression != null) 'compression': compression!.name.toExport(), - }, { - if (encodedData == null) - 'tiles': exportTiles() - else - 'data': encodedData.toExport(), - }), - json: ExportLiteral(this), + xml: ExportElement( + 'data', + { + if (encoding != null) 'encoding': encoding!.name.toExport(), + if (compression != null) 'compression': compression!.name.toExport(), + }, + { + if (encodedData == null) + 'tiles': exportTiles() + else + 'data': encodedData.toExport(), + }, + ), + json: ExportLiteral(data), ); } - ExportList exportTiles() => ExportList(data.map( - (gid) => ExportElement( - 'tile', - {'gid': gid.toExport()}, - {}, + /// Exports tiles for xml elements + ExportList exportTiles() => ExportList( + data.map( + (gid) => ExportElement( + 'tile', + {'gid': gid.toExport()}, + {}, + ), ), - )); + ); + /// Encodes tiles as csv String encodeCsv() => data.join(', '); + /// Encodes tiles as base64 String encodeBase64() { // Conversion to Uint8List final uint32 = Uint32List.fromList(data); diff --git a/packages/tiled/lib/src/layer.dart b/packages/tiled/lib/src/layer.dart index 94d6a39..ba64d2d 100644 --- a/packages/tiled/lib/src/layer.dart +++ b/packages/tiled/lib/src/layer.dart @@ -32,7 +32,7 @@ part of tiled; /// Defaults to 1. (since 1.5) /// /// Can contain at most one: , -abstract class Layer extends Exportable { +abstract class Layer with Exportable { /// Incremental ID - unique across all layers int? id; @@ -438,23 +438,27 @@ class TileLayer extends Layer { }.nonNulls(), { if (chunks != null) - 'chunks': ExportList(chunks!.map((e) => e.export( + 'chunks': ExportList( + chunks!.map( + (e) => e.export( encoding: encoding, compression: compression, - ))), + ), + ), + ), if (data != null) 'data': ExportTileData( data: data!, compression: compression, encoding: encoding, - ).export(), + ), }, properties, ); } 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). @@ -593,7 +597,7 @@ class ImageLayer extends Layer { 'repeaty': repeatY.toExport(), }.nonNulls(), { - 'image': image.export(), + 'image': image, }, properties, ); diff --git a/packages/tiled/lib/src/objects/text.dart b/packages/tiled/lib/src/objects/text.dart index 0db68a6..4e8599b 100644 --- a/packages/tiled/lib/src/objects/text.dart +++ b/packages/tiled/lib/src/objects/text.dart @@ -37,7 +37,7 @@ part of tiled; /// /// If the text is larger than the object’s bounds, it is clipped to the bounds /// of the object. -class Text extends Exportable { +class Text with Exportable { String fontFamily; int pixelSize; String color; diff --git a/packages/tiled/lib/src/objects/tiled_object.dart b/packages/tiled/lib/src/objects/tiled_object.dart index bc3dcbb..4b18ee0 100644 --- a/packages/tiled/lib/src/objects/tiled_object.dart +++ b/packages/tiled/lib/src/objects/tiled_object.dart @@ -43,7 +43,7 @@ part of tiled; /// /// Can contain at most one: , (since 0.9), /// (since 1.1), , , (since 1.0) -class TiledObject extends Exportable { +class TiledObject with Exportable { int id; String name; String type; @@ -196,8 +196,8 @@ class TiledObject extends Exportable { 'object', common, { - if (ellipse) 'ellipse': ExportElement('ellipse', {}, {}), - if (point) 'point': ExportElement('point', {}, {}), + if (ellipse) 'ellipse': const ExportElement('ellipse', {}, {}), + if (point) 'point': const ExportElement('point', {}, {}), if (polygon.isNotEmpty) 'polygon': ExportElement( 'polygon', @@ -214,7 +214,7 @@ class TiledObject extends Exportable { }, {}, ), - if (text != null) 'text': text!.export(), + if (text != null) 'text': text!, }, properties), json: ExportElement( diff --git a/packages/tiled/lib/src/tileset/grid.dart b/packages/tiled/lib/src/tileset/grid.dart index 5c8be92..8c90812 100644 --- a/packages/tiled/lib/src/tileset/grid.dart +++ b/packages/tiled/lib/src/tileset/grid.dart @@ -12,7 +12,7 @@ part of tiled; /// /// This element is only used in case of isometric orientation, and determines /// how tile overlays for terrain and collision information are rendered. -class Grid extends Exportable { +class Grid with Exportable { int width; int height; GridOrientation orientation; diff --git a/packages/tiled/lib/src/tileset/tile.dart b/packages/tiled/lib/src/tileset/tile.dart index 7118aca..8a04033 100644 --- a/packages/tiled/lib/src/tileset/tile.dart +++ b/packages/tiled/lib/src/tileset/tile.dart @@ -102,8 +102,8 @@ class Tile with Exportable { }.nonNulls(); final children = { - 'image': image?.export(), - 'objectgroup': objectGroup?.export() + 'image': image, + 'objectgroup': objectGroup, }.nonNulls(); return ExportFormatSpecific( diff --git a/packages/tiled/lib/src/tileset/tile_offset.dart b/packages/tiled/lib/src/tileset/tile_offset.dart index c7bfa5c..94c5f19 100644 --- a/packages/tiled/lib/src/tileset/tile_offset.dart +++ b/packages/tiled/lib/src/tileset/tile_offset.dart @@ -11,7 +11,7 @@ part of tiled; /// This element is used to specify an offset in pixels, to be applied when /// drawing a tile from the related tileset. /// When not present, no offset is applied. -class TileOffset extends Exportable { +class TileOffset with Exportable { int x; int y; diff --git a/packages/tiled/lib/src/tileset/tileset.dart b/packages/tiled/lib/src/tileset/tileset.dart index 4ec974b..d62cda0 100644 --- a/packages/tiled/lib/src/tileset/tileset.dart +++ b/packages/tiled/lib/src/tileset/tileset.dart @@ -298,10 +298,10 @@ class Tileset with Exportable { }.nonNulls(); final common = { - 'image': image?.export(), + 'image': image, 'tiles': ExportList.from(tiles), - 'tileoffset': tileOffset?.export(), - 'grid': grid?.export(), + 'tileoffset': tileOffset, + 'grid': grid, // 'terraintypes': , DEPRECATED // 'transformations': ExportList.from(transformations), Not supported by this class }.nonNulls(); diff --git a/packages/tiled/lib/src/tileset/wang/wang_set.dart b/packages/tiled/lib/src/tileset/wang/wang_set.dart index 9bbde4c..5657533 100644 --- a/packages/tiled/lib/src/tileset/wang/wang_set.dart +++ b/packages/tiled/lib/src/tileset/wang/wang_set.dart @@ -15,7 +15,7 @@ part of tiled; /// Can contain up to 255: (since Tiled 1.5) /// /// Can contain any number: -class WangSet extends Exportable { +class WangSet with Exportable { String name; int tile; List cornerColors; diff --git a/packages/tiled/lib/tiled.dart b/packages/tiled/lib/tiled.dart index bc37bfe..eb9dec0 100644 --- a/packages/tiled/lib/tiled.dart +++ b/packages/tiled/lib/tiled.dart @@ -12,7 +12,7 @@ import 'package:xml/xml.dart'; part 'src/chunk.dart'; part 'src/exporter/exportable.dart'; -part 'src/exporter/export_tile_data.dart'; +part 'src/exporter/tile_data.dart'; part 'src/exporter/export_value.dart'; part 'src/exporter/export_element.dart'; part 'src/exporter/json.dart'; diff --git a/packages/tiled/test/color.dart b/packages/tiled/test/color.dart index c39c834..3bd7a38 100644 --- a/packages/tiled/test/color.dart +++ b/packages/tiled/test/color.dart @@ -5,8 +5,8 @@ import 'package:test/scaffolding.dart'; import 'package:tiled/tiled.dart'; void main() { - group("ColorData.hex", () { - test("parse", () { + group('ColorData.hex', () { + test('parse', () { final random = Random(); final red = random.nextInt(256); final green = random.nextInt(256); diff --git a/packages/tiled/test/exporter/map.dart b/packages/tiled/test/exporter/map.dart index 176c424..37d37fa 100644 --- a/packages/tiled/test/exporter/map.dart +++ b/packages/tiled/test/exporter/map.dart @@ -4,30 +4,32 @@ import 'package:xml/xml.dart'; void main() { late TiledMap export; - setUp(() => export = TiledMap( - width: 576, - height: 432, - tileWidth: 48, - tileHeight: 48, - orientation: MapOrientation.hexagonal, - renderOrder: RenderOrder.leftUp, - hexSideLength: 24, - staggerAxis: StaggerAxis.y, - staggerIndex: StaggerIndex.even, - backgroundColor: ColorData.hex(0xaa252627), - nextLayerId: 24, - nextObjectId: 56, - infinite: false, - layers: [ - TileLayer(name: 'test1', width: 48, height: 48), - TileLayer(name: 'test2', width: 48, height: 48), - TileLayer(name: 'test3', width: 48, height: 48), - ], - tilesets: [ - Tileset(firstGid: 1, source: 'xyz.png'), - Tileset(firstGid: 20, source: 'xyz.png'), - ], - )); + setUp( + () => export = TiledMap( + width: 576, + height: 432, + tileWidth: 48, + tileHeight: 48, + orientation: MapOrientation.hexagonal, + renderOrder: RenderOrder.leftUp, + hexSideLength: 24, + staggerAxis: StaggerAxis.y, + staggerIndex: StaggerIndex.even, + backgroundColor: ColorData.hex(0xaa252627), + nextLayerId: 24, + nextObjectId: 56, + infinite: false, + layers: [ + TileLayer(name: 'test1', width: 48, height: 48), + TileLayer(name: 'test2', width: 48, height: 48), + TileLayer(name: 'test3', width: 48, height: 48), + ], + tilesets: [ + Tileset(firstGid: 1, source: 'xyz.png'), + Tileset(firstGid: 20, source: 'xyz.png'), + ], + ), + ); group('Exporter - Map', () { test( diff --git a/packages/tiled/test/exporter/properties.dart b/packages/tiled/test/exporter/properties.dart index 56c92f7..e035809 100644 --- a/packages/tiled/test/exporter/properties.dart +++ b/packages/tiled/test/exporter/properties.dart @@ -7,9 +7,11 @@ void main() { late TiledObject export; late CustomProperties byName; setUp(() { - byName = CustomProperties([ - StringProperty(name: 'test_string', value: 'test'), - ].groupFoldBy((e) => e.name, (old, e) => e)); + byName = CustomProperties( + [ + StringProperty(name: 'test_string', value: 'test'), + ].groupFoldBy((e) => e.name, (old, e) => e), + ); export = TiledObject(id: 5, properties: byName); }); diff --git a/packages/tiled/test/exporter/tile_data.dart b/packages/tiled/test/exporter/tile_data.dart index 45202cc..d1c4887 100644 --- a/packages/tiled/test/exporter/tile_data.dart +++ b/packages/tiled/test/exporter/tile_data.dart @@ -11,8 +11,8 @@ void main() { testData = List.generate(1000, (index) => Random().nextInt(1 << 32)); }); - group("base64", () { - void _test(List testData, Compression? compression) { + group('base64', () { + void encodeDecode(List testData, Compression? compression) { final encoder = ExportTileData( data: testData, encoding: FileEncoding.base64, @@ -21,7 +21,7 @@ void main() { final encoded = encoder.encodeBase64(); final unencoded = Layer.parseLayerData( - JsonParser({"data": encoded}), + JsonParser({'data': encoded}), FileEncoding.base64, compression, ); @@ -29,12 +29,12 @@ void main() { expect(unencoded, orderedEquals(testData)); } - test("base64-uncompressed", () => _test(testData, null)); - test("base64-gzip", () => _test(testData, Compression.gzip)); - test("base64-zlib", () => _test(testData, Compression.zlib)); + test('base64-uncompressed', () => encodeDecode(testData, null)); + test('base64-gzip', () => encodeDecode(testData, Compression.gzip)); + test('base64-zlib', () => encodeDecode(testData, Compression.zlib)); }); - test("csv", () { + test('csv', () { final encoder = ExportTileData( data: testData, encoding: FileEncoding.csv, @@ -43,7 +43,7 @@ void main() { final encoded = encoder.encodeCsv(); final unencoded = Layer.parseLayerData( - JsonParser({"data": encoded}), + JsonParser({'data': encoded}), FileEncoding.csv, null, ); diff --git a/packages/tiled/test/exporter/xml.dart b/packages/tiled/test/exporter/xml.dart index 4bfeea3..6685396 100644 --- a/packages/tiled/test/exporter/xml.dart +++ b/packages/tiled/test/exporter/xml.dart @@ -14,7 +14,9 @@ class XmlDeepMatcher extends Matcher { @override bool matches(dynamic item, Map matchState) { - if (item is! XmlElement) return false; + if (item is! XmlElement) { + return false; + } return _match(item, expected); } @@ -29,7 +31,9 @@ class XmlDeepMatcher extends Matcher { a.value.trim() == b.value.trim(), ) && _deepIterable(_cleanNodes(a.children), _cleanNodes(b.children), (a, b) { - if (a.runtimeType != b.runtimeType) return false; + if (a.runtimeType != b.runtimeType) { + return false; + } if (a is XmlText) { return a.value.trim() == b.value!.trim(); @@ -46,7 +50,9 @@ class XmlDeepMatcher extends Matcher { Iterable b, bool Function(T a, T b) equals, ) { - if (a.length != b.length) return false; + if (a.length != b.length) { + return false; + } return a.every((aa) => b.any((bb) => equals(aa, bb))); } diff --git a/packages/tiled/test/tile_test.dart b/packages/tiled/test/tile_test.dart index c75ae19..c91e049 100644 --- a/packages/tiled/test/tile_test.dart +++ b/packages/tiled/test/tile_test.dart @@ -58,8 +58,8 @@ void main() { final tile1 = tileset1.tiles.firstWhere((t) => t.localId == 0); final tile2 = tileset1.tiles.firstWhere((t) => t.localId == 1); - expect(tile1.imageRect, Rectangle(64, 96, 32, 32)); - expect(tile2.imageRect, Rectangle(0, 0, 20, 20)); + expect(tile1.imageRect, const Rectangle(64, 96, 32, 32)); + expect(tile2.imageRect, const Rectangle(0, 0, 20, 20)); }); test( @@ -70,10 +70,10 @@ void main() { final tile3 = tileset2.tiles.firstWhere((t) => t.localId == 129); final tile4 = tileset2.tiles.firstWhere((t) => t.localId == 11); - expect(tile1.imageRect, Rectangle(112, 48, 16, 16)); - expect(tile2.imageRect, Rectangle(64, 96, 16, 16)); - expect(tile3.imageRect, Rectangle(160, 112, 16, 16)); - expect(tile4.imageRect, Rectangle(176, 0, 16, 16)); + expect(tile1.imageRect, const Rectangle(112, 48, 16, 16)); + expect(tile2.imageRect, const Rectangle(64, 96, 16, 16)); + expect(tile3.imageRect, const Rectangle(160, 112, 16, 16)); + expect(tile4.imageRect, const Rectangle(176, 0, 16, 16)); }, ); }, diff --git a/packages/tiled/test/tileset_test.dart b/packages/tiled/test/tileset_test.dart index d5bed4e..516fd97 100644 --- a/packages/tiled/test/tileset_test.dart +++ b/packages/tiled/test/tileset_test.dart @@ -57,7 +57,9 @@ void main() { test( 'first objectgroup object = ellipsis', () => expect( - ((tileset.tiles.first.objectGroup as ObjectGroup?)!.objects.first) + (tileset.tiles.first.objectGroup as ObjectGroup?)! + .objects + .first .isEllipse, true, ),