Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve TextureAtlas parsing, store name/value pairs per region #6316

Merged
merged 27 commits into from Dec 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
c13809c
Changed TextureAtlas parsing to store unrecognized values as name/val…
NathanSweet Dec 16, 2020
bab610d
Default original size to packed size. Comment field map sizes.
NathanSweet Dec 17, 2020
1de4028
Javadoc typo.
NathanSweet Dec 17, 2020
377a7aa
Spaces before commas.
NathanSweet Dec 17, 2020
21a8407
Added bounds/offsets entries to reduce the number of entries needed p…
NathanSweet Dec 17, 2020
a294741
Use equalsIgnoreCase when comparing entry values.
NathanSweet Dec 17, 2020
2bc0a3f
Check the index first, which is cheaper.
NathanSweet Dec 18, 2020
5cfe622
Skip sorting regions when there are no indexes.
NathanSweet Dec 18, 2020
5cfa7cc
Added CHANGES entry for #6316.
NathanSweet Dec 18, 2020
466947e
Merge branch 'master' into master-NathanSweet
NathanSweet Dec 18, 2020
b852c83
Added a pretty print texture packer setting, enabled by default.
NathanSweet Dec 18, 2020
e51b738
Added a legacy output setting.
NathanSweet Dec 18, 2020
e7f9d13
Mentioned the legacyOutput setting in CHANGES.
NathanSweet Dec 18, 2020
e2d25c9
Filter used by issue_pack wasn't GWT-compatible.
tommyettinger Dec 19, 2020
32fee82
Fixed mipmaps not being created when the min filter needs them (fixes…
NathanSweet Dec 18, 2020
cd2f2d6
Default legacyOutput to true.
NathanSweet Dec 18, 2020
eb57019
Added optional header entries.
NathanSweet Dec 19, 2020
abd8eb3
Set default for Page#format field.
NathanSweet Dec 19, 2020
17ac61e
Ignore values after the 4th.
NathanSweet Dec 19, 2020
0519e76
Ignore non-int values for unknown region entries.
NathanSweet Dec 19, 2020
1c9b09c
Revert change to issue_pack, since the issue was fixed.
tommyettinger Dec 19, 2020
37fafc1
CHANGES entry for AtlasRegion breaking change.
NathanSweet Dec 19, 2020
9c54859
CHANGES for Region too.
NathanSweet Dec 19, 2020
ccd9f42
BSpline#calculate, throw if degree is not 3, javadoc.
NathanSweet Dec 19, 2020
6f1dd1a
Clean up. Set the texture on the page rather than using a map.
NathanSweet Dec 20, 2020
ca465cc
Move TextureAtlasData member class to end of TextureAtlas.
NathanSweet Dec 20, 2020
96886af
Bunch of clean up.
NathanSweet Dec 20, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES
@@ -1,5 +1,6 @@
[1.9.13]
- [BREAKING CHANGE] Fixed keycode representations for ESCAPE, END, INSERT and F1 to F12. These keys are working on Android now, but if you hardcoded or saved the values you might need to migrate.
- [BREAKING CHANGE] TextureAtlas.AtlasRegion and Region splits and pads fields have been removed and moved to name/value pairs, use #findValue("split") and #findValue("pad") instead.
- GWT: Key codes set with Gdx.input.setCatchKey prevent default browser behaviour
- Added Scaling.contain mode: Scales the source to fit the target while keeping the same aspect ratio, but the source is not scaled at all if smaller in both directions.
- API Addition: Added hasContents() to Clipboard interface, to reduce clipboard notifications on iOS 14
Expand All @@ -8,6 +9,8 @@
Following changes might be done depending on platform: Keys.STAR to Keys.NUMPAD_MULTIPLY, Keys.SLASH to Keys.NUMPAD_DIVIDE, Keys.NUM to Keys.NUM_LOCK, Keys.COMMA to Keys.NUMPAD_COMMA, Keys.PERIOD to Keys.NUMPAD_DOT, Keys.COMMA to Keys.NUMPAD_COMMA, Keys.ENTER to Keys.NUMPAD_ENTER, Keys.PLUS to Keys.NUMPAD_ADD, Keys.MINUS to Keys.NUMPAD_SUBTRACT
- Added a QuadFloatTree class.
- Desktop: Cubemap Seamless feature is now enabled by default when supported, can be changed via backend specific methods, see supportsCubeMapSeamless and enableCubeMapSeamless in both LwjglGraphics and Lwjgl3Graphics.
- API Addition: TextureAtlas reads arbitrary name/value pairs for each region. See #6316.
- TexturePacker writes using a new format when legacyOutput is false (default is true). TextureAtlas can read both old and new formats. See #6316.

[1.9.12]
- [BREAKING CHANGE] iOS: Changed how Retina/hdpi handled on iOS. See #3709.
Expand Down
Expand Up @@ -44,6 +44,7 @@
import com.badlogic.gdx.utils.FloatArray;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.Null;

import java.awt.Color;
import java.awt.Graphics2D;
Expand Down Expand Up @@ -402,31 +403,117 @@ private void writePackFile (File outputDir, String scaledPackFileName, Array<Pag
}
}

Writer writer = new OutputStreamWriter(new FileOutputStream(packFile, true), "UTF-8");
for (Page page : pages) {
writer.write("\n" + page.imageName + "\n");
writer.write("size: " + page.imageWidth + "," + page.imageHeight + "\n");
writer.write("format: " + settings.format + "\n");
writer.write("filter: " + settings.filterMin + "," + settings.filterMag + "\n");
writer.write("repeat: " + getRepeatValue() + "\n");
String tab = "", colon = ":", comma = ",";
if (settings.prettyPrint) {
tab = "\t";
colon = ": ";
comma = ", ";
}

boolean appending = packFile.exists();
OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(packFile, true), "UTF-8");
for (int i = 0, n = pages.size; i < n; i++) {
Page page = pages.get(i);

if (settings.legacyOutput)
writePageLegacy(writer, page);
else {
if (i != 0 || appending) writer.write("\n");
writePage(writer, appending, page);
}

page.outputRects.sort();
for (Rect rect : page.outputRects) {
writeRect(writer, page, rect, rect.name);
if (settings.legacyOutput)
writeRectLegacy(writer, page, rect, rect.name);
else
writeRect(writer, page, rect, rect.name);
Array<Alias> aliases = new Array(rect.aliases.toArray());
aliases.sort();
for (Alias alias : aliases) {
Rect aliasRect = new Rect();
aliasRect.set(rect);
alias.apply(aliasRect);
writeRect(writer, page, aliasRect, alias.name);
if (settings.legacyOutput)
writeRectLegacy(writer, page, aliasRect, alias.name);
else
writeRect(writer, page, aliasRect, alias.name);
}
}
}
writer.close();
}

private void writePage (OutputStreamWriter writer, boolean appending, Page page) throws IOException {
String tab = "", colon = ":", comma = ",";
if (settings.prettyPrint) {
tab = "\t";
colon = ": ";
comma = ", ";
}

writer.write(page.imageName + "\n");
writer.write(tab + "size" + colon + page.imageWidth + comma + page.imageHeight + "\n");

if (settings.format != Format.RGBA8888) writer.write(tab + "format" + colon + settings.format + "\n");

if (settings.filterMin != TextureFilter.Nearest || settings.filterMag != TextureFilter.Nearest)
writer.write(tab + "filter" + colon + settings.filterMin + comma + settings.filterMag + "\n");

String repeatValue = getRepeatValue();
if (repeatValue != null) writer.write(tab + "repeat" + colon + repeatValue + "\n");

if (settings.premultiplyAlpha) writer.write(tab + "pma" + colon + "true\n");
}

private void writeRect (Writer writer, Page page, Rect rect, String name) throws IOException {
String tab = "", colon = ":", comma = ",";
if (settings.prettyPrint) {
tab = "\t";
colon = ": ";
comma = ", ";
}

writer.write(Rect.getAtlasName(name, settings.flattenPaths) + "\n");
if (rect.index != -1) writer.write(tab + "index" + colon + rect.index + "\n");

writer.write(tab + "bounds" + colon //
+ (page.x + rect.x) + comma + (page.y + page.height - rect.y - (rect.height - settings.paddingY)) + comma //
+ rect.regionWidth + comma + rect.regionHeight + "\n");

int offsetY = rect.originalHeight - rect.regionHeight - rect.offsetY;
if (rect.offsetX != 0 || offsetY != 0 //
|| rect.originalWidth != rect.regionWidth || rect.originalHeight != rect.regionHeight) {
writer.write(tab + "offsets" + colon //
+ rect.offsetX + comma + offsetY + comma //
+ rect.originalWidth + comma + rect.originalHeight + "\n");
}

if (rect.rotated) writer.write(tab + "rotate" + colon + rect.rotated + "\n");

if (rect.splits != null) {
writer.write(tab + "split" + colon //
+ rect.splits[0] + comma + rect.splits[1] + comma //
+ rect.splits[2] + comma + rect.splits[3] + "\n");
}

if (rect.pads != null) {
if (rect.splits == null) writer.write(tab + "split" + colon + "0" + comma + "0" + comma + "0" + comma + "0\n");
writer.write(
tab + "pad" + colon + rect.pads[0] + comma + rect.pads[1] + comma + rect.pads[2] + comma + rect.pads[3] + "\n");
}
}

private void writePageLegacy (OutputStreamWriter writer, Page page) throws IOException {
writer.write("\n" + page.imageName + "\n");
writer.write("size: " + page.imageWidth + ", " + page.imageHeight + "\n");
writer.write("format: " + settings.format + "\n");
writer.write("filter: " + settings.filterMin + ", " + settings.filterMag + "\n");
String repeatValue = getRepeatValue();
writer.write("repeat: " + (repeatValue == null ? "none" : repeatValue) + "\n");
}

private void writeRectLegacy (Writer writer, Page page, Rect rect, String name) throws IOException {
writer.write(Rect.getAtlasName(name, settings.flattenPaths) + "\n");
writer.write(" rotate: " + rect.rotated + "\n");
writer
Expand All @@ -446,11 +533,11 @@ private void writeRect (Writer writer, Page page, Rect rect, String name) throws
writer.write(" index: " + rect.index + "\n");
}

private String getRepeatValue () {
private @Null String getRepeatValue () {
if (settings.wrapX == TextureWrap.Repeat && settings.wrapY == TextureWrap.Repeat) return "xy";
if (settings.wrapX == TextureWrap.Repeat && settings.wrapY == TextureWrap.ClampToEdge) return "x";
if (settings.wrapX == TextureWrap.ClampToEdge && settings.wrapY == TextureWrap.Repeat) return "y";
return "none";
return null;
}

private int getBufferedImageType (Format format) {
Expand Down Expand Up @@ -843,6 +930,8 @@ static public class Settings {
public String[] scaleSuffix = {""};
public Resampling[] scaleResampling = {Resampling.bicubic};
public String atlasExtension = ".atlas";
public boolean prettyPrint = true;
public boolean legacyOutput = true;

public Settings () {
}
Expand Down Expand Up @@ -894,6 +983,8 @@ public void set (Settings settings) {
scaleSuffix = Arrays.copyOf(settings.scaleSuffix, settings.scaleSuffix.length);
scaleResampling = Arrays.copyOf(settings.scaleResampling, settings.scaleResampling.length);
atlasExtension = settings.atlasExtension;
prettyPrint = settings.prettyPrint;
legacyOutput = settings.legacyOutput;
}

public String getScaledPackFileName (String packFileName, int scaleIndex) {
Expand Down
Expand Up @@ -100,7 +100,7 @@ public void splitAtlas (TextureAtlasData atlas, String outputDir) {
String extension = null;

// check if the region is a ninepatch or a normal image and delegate accordingly
if (region.splits == null) {
if (region.findValue("split") == null) {
splitImage = extractImage(img, region, outputDirFile, 0);
if (region.width != region.originalWidth || region.height != region.originalHeight) {
BufferedImage originalImg = new BufferedImage(region.originalWidth, region.originalHeight, img.getType());
Expand Down Expand Up @@ -181,17 +181,19 @@ private BufferedImage extractNinePatch (BufferedImage page, Region region, File
g2.setColor(Color.BLACK);

// Draw the four lines to save the ninepatch's padding and splits
int startX = region.splits[0] + NINEPATCH_PADDING;
int endX = region.width - region.splits[1] + NINEPATCH_PADDING - 1;
int startY = region.splits[2] + NINEPATCH_PADDING;
int endY = region.height - region.splits[3] + NINEPATCH_PADDING - 1;
int[] splits = region.findValue("split");
int startX = splits[0] + NINEPATCH_PADDING;
int endX = region.width - splits[1] + NINEPATCH_PADDING - 1;
int startY = splits[2] + NINEPATCH_PADDING;
int endY = region.height - splits[3] + NINEPATCH_PADDING - 1;
if (endX >= startX) g2.drawLine(startX, 0, endX, 0);
if (endY >= startY) g2.drawLine(0, startY, 0, endY);
if (region.pads != null) {
int padStartX = region.pads[0] + NINEPATCH_PADDING;
int padEndX = region.width - region.pads[1] + NINEPATCH_PADDING - 1;
int padStartY = region.pads[2] + NINEPATCH_PADDING;
int padEndY = region.height - region.pads[3] + NINEPATCH_PADDING - 1;
int[] pads = region.findValue("pad");
if (pads != null) {
int padStartX = pads[0] + NINEPATCH_PADDING;
int padEndX = region.width - pads[1] + NINEPATCH_PADDING - 1;
int padStartY = pads[2] + NINEPATCH_PADDING;
int padEndY = region.height - pads[3] + NINEPATCH_PADDING - 1;
g2.drawLine(padStartX, splitImage.getHeight() - 1, padEndX, splitImage.getHeight() - 1);
g2.drawLine(splitImage.getWidth() - 1, padStartY, splitImage.getWidth() - 1, padEndY);
}
Expand Down
4 changes: 2 additions & 2 deletions gdx/src/com/badlogic/gdx/graphics/g2d/PixmapPacker.java
Expand Up @@ -365,8 +365,8 @@ public synchronized void updateTextureAtlas (TextureAtlas atlas, TextureFilter m
TextureAtlas.AtlasRegion region = new TextureAtlas.AtlasRegion(page.texture, (int)rect.x, (int)rect.y, (int)rect.width, (int)rect.height);

if (rect.splits != null) {
region.splits = rect.splits;
region.pads = rect.pads;
region.names = new String[] {"split", "pad"};
region.values = new int[][] {rect.splits, rect.pads};
}

int imageIndex = -1;
Expand Down