Better mod sprite packing

This commit is contained in:
Anuken
2022-04-19 12:21:54 -04:00
parent a74c5ef943
commit 415402e61b
3 changed files with 61 additions and 6 deletions

View File

@@ -26,6 +26,20 @@ public class MultiPacker implements Disposable{
return null;
}
public void printStats(){
for(PageType type : PageType.all){
var packer = packers[type.ordinal()];
Log.debug("[Atlas] [&ly@&fr]", type);
Log.debug("[Atlas] - " + (packer.getPages().size > 1 ? "&fb&lr" : "&lg") + "@ page@&r", packer.getPages().size, packer.getPages().size > 1 ? "s" : "");
int i = 0;
for(var page : packer.getPages()){
Log.debug("[Atlas] - [@] @x@", i, page.getPixmap().width, page.getPixmap().height);
i ++;
}
}
}
public PixmapPacker getPacker(PageType type){
return packers[type.ordinal()];
}
@@ -78,10 +92,12 @@ public class MultiPacker implements Disposable{
//rubble page - scorch textures for unit deaths & wrecks
//ui page (sprites5.png) - content icons, white icons, fonts and UI elements
public enum PageType{
main(4096),
//main page can be massive.
main(8192),
environment(4096, 2048),
editor(4096, 2048),
rubble,
rubble(4096, 2048),
ui(4096);
public static final PageType[] all = values();

View File

@@ -182,8 +182,15 @@ public class Mods implements Loadable{
boolean linear = Core.settings.getBool("linear", true);
for(Fi file : sprites){
String name = file.nameWithoutExtension();
//TODO !!! document this on the wiki !!!
//do not allow packing standard outline sprites for now, they are no longer necessary and waste space!
if(prefix && name.endsWith("-outline")) continue;
//read and bleed pixmaps in parallel
tasks.add(mainExecutor.submit(() -> {
try{
Pixmap pix = new Pixmap(file.readBytes());
//only bleeds when linear filtering is on at startup
@@ -192,7 +199,7 @@ public class Mods implements Loadable{
}
//this returns a *runnable* which actually packs the resulting pixmap; this has to be done synchronously outside the method
return () -> {
packer.add(getPage(file), (prefix ? mod.name + "-" : "") + file.nameWithoutExtension(), new PixmapRegion(pix));
packer.add(getPage(file), (prefix ? mod.name + "-" : "") + name, new PixmapRegion(pix));
pix.dispose();
};
}catch(Exception e){
@@ -213,11 +220,41 @@ public class Mods implements Loadable{
//get textures packed
if(totalSprites > 0){
class RegionEntry{
String name;
PixmapRegion region;
int[] splits, pads;
RegionEntry(String name, PixmapRegion region, int[] splits, int[] pads){
this.name = name;
this.region = region;
this.splits = splits;
this.pads = pads;
}
}
Seq<RegionEntry>[] entries = new Seq[PageType.all.length];
for(int i = 0; i < PageType.all.length; i++){
entries[i] = new Seq<>();
}
for(AtlasRegion region : Core.atlas.getRegions()){
//TODO PageType completely breaks down with multiple pages.
PageType type = getPage(region);
if(!packer.has(type, region.name)){
packer.add(type, region.name, Core.atlas.getPixmap(region), region.splits, region.pads);
entries[type.ordinal()].add(new RegionEntry(region.name, Core.atlas.getPixmap(region), region.splits, region.pads));
}
}
//sort each page type by size first, for optimal packing
for(int i = 0; i < PageType.all.length; i++){
var rects = entries[i];
var type = PageType.all[i];
//TODO is this in reverse order?
rects.sort(Structs.comparingInt(o -> -Math.max(o.region.width, o.region.height)));
for(var entry : rects){
packer.add(type, entry.name, entry.region, entry.splits, entry.pads);
}
}
@@ -286,6 +323,8 @@ public class Mods implements Loadable{
}
Log.debug("Time to generate icons: @", Time.elapsed());
packer.printStats();
//dispose old atlas data
Core.atlas = packer.flush(filter, new TextureAtlas());

View File

@@ -25,4 +25,4 @@ org.gradle.caching=true
#used for slow jitpack builds; TODO see if this actually works
org.gradle.internal.http.socketTimeout=100000
org.gradle.internal.http.connectionTimeout=100000
archash=705de3b8ee
archash=e4b6af5949