Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/flame-engine#71-exporter'
Browse files Browse the repository at this point in the history
  • Loading branch information
benni-tec committed Nov 6, 2023
2 parents 1454252 + 913b6ee commit 27403cb
Show file tree
Hide file tree
Showing 28 changed files with 1,051 additions and 76 deletions.
24 changes: 23 additions & 1 deletion packages/tiled/lib/src/chunk.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<int> data;

int x;
Expand Down Expand Up @@ -59,4 +59,26 @@ class Chunk {

return Chunk(data: data, x: x, y: y, width: width, height: height);
}

@override
ExportElement export({FileEncoding? encoding, Compression? compression}) {
final common = {
'x': x.toExport(),
'y': y.toExport(),
'width': width.toExport(),
'height': height.toExport(),
};

return ExportElement(
'chunk',
common,
{
'data': TileDataEncoder(
data: data,
compression: compression,
encoding: encoding,
).export(),
},
);
}
}
14 changes: 13 additions & 1 deletion packages/tiled/lib/src/common/color.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ int _sub(int hex, int index) {
return value;
}

class Color {
class Color extends ExportValue<String> {
final int red;
final int green;
final int blue;
Expand All @@ -26,4 +26,16 @@ class Color {
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;
}
8 changes: 7 additions & 1 deletion packages/tiled/lib/src/common/frame.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ part of tiled;
/// * tileid: The local ID of a tile within the parent <tileset>.
/// * 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;

Expand All @@ -22,4 +22,10 @@ class Frame {
tileId: parser.getInt('tileid'),
duration: parser.getInt('duration'),
);

@override
ExportResolver export() => ExportElement('frame', {
'tileid': tileId.toExport(),
'duration': duration.toExport(),
}, {});
}
37 changes: 23 additions & 14 deletions packages/tiled/lib/src/common/gid.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,33 +32,29 @@ 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 ExportValue<int> {
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;

const Gid(this.tile, this.flips);

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,
Expand Down Expand Up @@ -86,4 +82,17 @@ class Gid {
});
});
}

int export() =>
(tile & ~flagBits) |
(flips.horizontally ? flippedHorizontallyFlag : 0) |
(flips.vertically ? flippedVerticallyFlag : 0) |
(flips.diagonally ? flippedDiagonallyFlag : 0) |
(flips.antiDiagonally ? flippedAntiDiagonallyFlag : 0);

@override
int get json => export();

@override
String get xml => export().toString();
}
17 changes: 17 additions & 0 deletions packages/tiled/lib/src/common/iterable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
part of tiled;

extension Grouping<V> on Iterable<V> {
Map<K, List<V>> groupBy<K>(K Function(V value) key) {
final out = <K, List<V>>{};
for (final v in this) {
final k = key(v);
if (!out.containsKey(k)) {
out[k] = [v];
} else {
out[k]!.add(v);
}
}

return out;
}
}
5 changes: 5 additions & 0 deletions packages/tiled/lib/src/common/map.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
part of tiled;

extension Null<K, V> on Map<K, V?> {
Map<K, V> nonNulls() => {for (final e in entries.where((e) => e.value is V)) e.key : e.value as V};
}
17 changes: 16 additions & 1 deletion packages/tiled/lib/src/common/property.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<T> {
class Property<T> with Exportable {
String name;
PropertyType type;
T value;
Expand Down Expand Up @@ -86,6 +86,14 @@ class Property<T> {
);
}
}

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
Expand Down Expand Up @@ -164,6 +172,9 @@ class ColorProperty extends Property<Color> {
required super.value,
required this.hexValue,
}) : super(type: PropertyType.color);

@override
ExportValue get exportValue => value;
}

/// [value] is the string text
Expand All @@ -180,6 +191,10 @@ class FileProperty extends Property<String> {
required super.name,
required super.value,
}) : super(type: PropertyType.file);

@override
ExportValue get exportValue =>
value.isNotEmpty ? value.toExport() : '.'.toExport();
}

/// [value] is the integer number
Expand Down
17 changes: 16 additions & 1 deletion packages/tiled/lib/src/common/tiled_image.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ part of tiled;
/// when the image changes)
/// * height: The image height in pixels (optional)
@immutable
class TiledImage {
class TiledImage with Exportable {
final String? source;
final String? format;
final int? width;
Expand Down Expand Up @@ -53,4 +53,19 @@ class TiledImage {

@override
int get hashCode => source.hashCode;

@override
ExportElement export() => 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
},
);
}
78 changes: 78 additions & 0 deletions packages/tiled/lib/src/data.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
part of tiled;

class TileDataEncoder extends DelegatingList<int> with Exportable {
final FileEncoding? encoding;
final Compression? compression;

TileDataEncoder({
required List<int> data,
required this.encoding,
required this.compression,
}) : super(data);

@override
ExportResolver export() {
String? data;
switch (encoding) {
case null:
break;
case FileEncoding.csv:
data = join(', ');
break;
case FileEncoding.base64:
data = _base64();
break;
}

return ExportFormatSpecific(
xml: ExportElement('data', {
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()},
{},
),
))
else
'data': data.toExport(),
}),
json: ExportLiteral(this),
);
}

String _base64() {
// 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<int> compressed;
print(compression);
switch (compression) {
case Compression.zlib:
compressed = const ZLibEncoder().encode(uint8);
break;
case Compression.gzip:
compressed = GZipEncoder().encode(uint8)!;
break;
case Compression.zstd:
throw UnsupportedError('zstd is an unsupported compression');
case null:
compressed = uint8;
break;
}

// encoding
return base64Encode(compressed);
}
}
Loading

0 comments on commit 27403cb

Please sign in to comment.