mirror of
https://github.com/flame-engine/flame.git
synced 2025-11-03 04:18:25 +08:00
feat: Adding configurable padding to Tiled atlas packing (#2868)
Adds new configurations to Flame Tiled's atlas packing. Spacing which can be used to tilesets are not too close to each other in the atlas, something that can cause texture leaking causing weird rendering issues.
This commit is contained in:
@ -216,6 +216,8 @@ class RenderableTiledMap {
|
||||
bool Function(Tileset)? tsxPackingFilter,
|
||||
bool useAtlas = true,
|
||||
Paint Function(double opacity)? layerPaintFactory,
|
||||
double atlasPackingSpacingX = 0,
|
||||
double atlasPackingSpacingY = 0,
|
||||
}) async {
|
||||
final contents =
|
||||
await (bundle ?? Flame.bundle).loadString('$prefix$fileName');
|
||||
@ -232,6 +234,8 @@ class RenderableTiledMap {
|
||||
tsxPackingFilter: tsxPackingFilter,
|
||||
useAtlas: useAtlas,
|
||||
layerPaintFactory: layerPaintFactory ?? _defaultLayerPaintFactory,
|
||||
atlasPackingSpacingX: atlasPackingSpacingX,
|
||||
atlasPackingSpacingY: atlasPackingSpacingY,
|
||||
);
|
||||
}
|
||||
|
||||
@ -253,6 +257,8 @@ class RenderableTiledMap {
|
||||
bool Function(Tileset)? tsxPackingFilter,
|
||||
bool useAtlas = true,
|
||||
Paint Function(double opacity)? layerPaintFactory,
|
||||
double atlasPackingSpacingX = 0,
|
||||
double atlasPackingSpacingY = 0,
|
||||
}) async {
|
||||
final map = await TiledMap.fromString(
|
||||
contents,
|
||||
@ -270,6 +276,8 @@ class RenderableTiledMap {
|
||||
tsxPackingFilter: tsxPackingFilter,
|
||||
useAtlas: useAtlas,
|
||||
layerPaintFactory: layerPaintFactory ?? _defaultLayerPaintFactory,
|
||||
atlasPackingSpacingX: atlasPackingSpacingX,
|
||||
atlasPackingSpacingY: atlasPackingSpacingY,
|
||||
);
|
||||
}
|
||||
|
||||
@ -288,6 +296,8 @@ class RenderableTiledMap {
|
||||
bool Function(Tileset)? tsxPackingFilter,
|
||||
bool useAtlas = true,
|
||||
Paint Function(double opacity)? layerPaintFactory,
|
||||
double atlasPackingSpacingX = 0,
|
||||
double atlasPackingSpacingY = 0,
|
||||
}) async {
|
||||
// We're not going to load animation frames that are never referenced; but
|
||||
// we do supply the common cache for all layers in this map, and maintain
|
||||
@ -312,6 +322,8 @@ class RenderableTiledMap {
|
||||
images: images,
|
||||
tsxPackingFilter: tsxPackingFilter,
|
||||
useAtlas: useAtlas,
|
||||
spacingX: atlasPackingSpacingX,
|
||||
spacingY: atlasPackingSpacingY,
|
||||
),
|
||||
ignoreFlip: ignoreFlip,
|
||||
images: images,
|
||||
|
||||
@ -111,6 +111,8 @@ class TiledAtlas {
|
||||
Images? images,
|
||||
bool Function(Tileset)? tsxPackingFilter,
|
||||
bool useAtlas = true,
|
||||
double spacingX = 0,
|
||||
double spacingY = 0,
|
||||
}) async {
|
||||
final tilesetImageList = _onlyTileImages(
|
||||
map,
|
||||
@ -209,12 +211,17 @@ class TiledAtlas {
|
||||
final tileImageSource = entry.$1;
|
||||
|
||||
final image = await imagesInstance.load(tileImageSource);
|
||||
final rect = bin.pack(image.width.toDouble(), image.height.toDouble());
|
||||
final rect = bin.pack(
|
||||
image.width.toDouble() + spacingX,
|
||||
image.height.toDouble() + spacingY,
|
||||
);
|
||||
|
||||
pictureRect = pictureRect.expandToInclude(rect);
|
||||
|
||||
final offset =
|
||||
offsetMap[tiledImage.source!] = Offset(rect.left, rect.top);
|
||||
final offset = offsetMap[tiledImage.source!] = Offset(
|
||||
rect.left - spacingX,
|
||||
rect.top - spacingY,
|
||||
);
|
||||
|
||||
canvas.drawImage(image, offset, emptyPaint);
|
||||
}
|
||||
|
||||
@ -117,6 +117,8 @@ class TiledComponent<T extends FlameGame> extends PositionComponent
|
||||
bool Function(Tileset)? tsxPackingFilter,
|
||||
bool useAtlas = true,
|
||||
Paint Function(double opacity)? layerPaintFactory,
|
||||
double atlasPackingSpacingX = 0,
|
||||
double atlasPackingSpacingY = 0,
|
||||
}) async {
|
||||
return TiledComponent(
|
||||
await RenderableTiledMap.fromFile(
|
||||
@ -131,6 +133,8 @@ class TiledComponent<T extends FlameGame> extends PositionComponent
|
||||
tsxPackingFilter: tsxPackingFilter,
|
||||
useAtlas: useAtlas,
|
||||
layerPaintFactory: layerPaintFactory,
|
||||
atlasPackingSpacingX: atlasPackingSpacingX,
|
||||
atlasPackingSpacingY: atlasPackingSpacingY,
|
||||
),
|
||||
priority: priority,
|
||||
);
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 49 KiB |
BIN
packages/flame_tiled/test/goldens/larger_atlas_with_spacing.png
Normal file
BIN
packages/flame_tiled/test/goldens/larger_atlas_with_spacing.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
@ -134,6 +134,32 @@ void main() {
|
||||
);
|
||||
});
|
||||
|
||||
test(
|
||||
'packs complex maps with multiple images using a custom spacing',
|
||||
() async {
|
||||
final component = await TiledComponent.load(
|
||||
'isometric_plain.tmx',
|
||||
Vector2(128, 74),
|
||||
bundle: bundle,
|
||||
images: Images(bundle: bundle),
|
||||
atlasPackingSpacingX: 2,
|
||||
atlasPackingSpacingY: 2,
|
||||
);
|
||||
|
||||
final atlas = TiledAtlas.atlasMap.values.first;
|
||||
expect(
|
||||
await imageToPng(atlas.atlas!),
|
||||
matchesGoldenFile('goldens/larger_atlas_with_spacing.png'),
|
||||
);
|
||||
expect(
|
||||
renderMapToPng(component),
|
||||
matchesGoldenFile(
|
||||
'goldens/larger_atlas_component_with_spacing.png',
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
test('can ignore tilesets in the packing', () async {
|
||||
await TiledComponent.load(
|
||||
'isometric_plain.tmx',
|
||||
|
||||
Reference in New Issue
Block a user