package com.badlogic.gdx.graphics.g2d; import com.badlogic.gdx.files.FileHandle; import com.badlogic.gdx.function.Iterables; import com.badlogic.gdx.graphics.Pixmap; import com.badlogic.gdx.utils.*; /** * Loads images from texture atlas, just like {@link TextureAtlas}, but stores them in pixmaps instead of textures * to avoid creation of texture resources. * <p> * Internally uses {@link com.badlogic.gdx.graphics.g2d.TextureAtlas.TextureAtlasData} to avoid code duplication. */ public class PixmapAtlas implements Disposable { private final ObjectSet<Pixmap> pixmaps = new ObjectSet<>(4); private final Array<AtlasPage> pages = new Array<>(); private final Array<AtlasRegion> regions = new Array<>(); public PixmapAtlas(FileHandle packFile) { this(packFile, packFile.parent(), false); } public PixmapAtlas(FileHandle packFile, PixmapReader reader) { load(new TextureAtlas.TextureAtlasData(packFile, packFile.parent(), false), reader); } public PixmapAtlas(FileHandle packFile, FileHandle imagesDir, boolean flip) { load(new TextureAtlas.TextureAtlasData(packFile, imagesDir, flip), DEFAULT_READER); } public PixmapAtlas(TextureAtlas.TextureAtlasData data) { load(data, DEFAULT_READER); } private PixmapAtlas() { } private void load(TextureAtlas.TextureAtlasData data, PixmapReader reader) { ObjectMap<TextureAtlas.TextureAtlasData.Page, AtlasPage> pageToPixmap = new ObjectMap<>(); for (int pageIndex = 0; pageIndex < data.pages.size; pageIndex++) { TextureAtlas.TextureAtlasData.Page page = data.pages.get(pageIndex); Pixmap pixmap = reader.read(page.textureFile, (int) page.width, (int) page.height); pixmaps.add(pixmap); AtlasPage atlasPage = new AtlasPage(pageIndex, page.textureFile, pixmap); pages.add(atlasPage); pageToPixmap.put(page, atlasPage); } for (TextureAtlas.TextureAtlasData.Region region : data.regions) { int width = region.width; int height = region.height; AtlasPage atlasPage = pageToPixmap.get(region.page); AtlasRegion atlasRegion = new AtlasRegion( atlasPage.pixmap, region.left, region.top, region.rotate ? height : width, region.rotate ? width : height); atlasRegion.page = atlasPage; atlasRegion.index = region.index; atlasRegion.name = region.name; atlasRegion.rotate = region.rotate; regions.add(atlasRegion); } } @Override public void dispose() { Iterables.forEach(pixmaps, Pixmap::dispose); pixmaps.clear(); pages.clear(); regions.clear(); } public ObjectSet<Pixmap> getPixmaps() { return pixmaps; } public Iterable<AtlasPage> getPages() { return pages; } public AtlasRegion findRegion(String name) { for (AtlasRegion region : regions) { if (region.name.equals(name)) { return region; } } return null; } public FileHandle getFolder() { return pages.get(0).fileHandle.parent(); } public static PixmapAtlas createFromPixmap(FileHandle pixmapFile, String regionName) { Pixmap pixmap = new Pixmap(pixmapFile); PixmapAtlas atlas = new PixmapAtlas(); // add single pixmap atlas.pixmaps.add(pixmap); // add one page AtlasPage atlasPage = new AtlasPage(0, pixmapFile, pixmap); atlas.pages.add(atlasPage); // add one region int width = pixmap.getWidth(); int height = pixmap.getHeight(); AtlasRegion atlasRegion = new AtlasRegion(pixmap, 0, 0, width, height); atlasRegion.page = atlasPage; atlasRegion.index = 0; atlasRegion.name = regionName; atlasRegion.rotate = false; atlas.regions.add(atlasRegion); return atlas; } public static class AtlasRegion extends PixmapRegion { public AtlasPage page; // todo: "copy" required fields from TextureAtlas$AtlasRegion int index; String name; boolean rotate; AtlasRegion(Pixmap pixmap, int x, int y, int width, int height) { super(pixmap, x, y, width, height); } } public static class AtlasPage { public final int pageIndex; public final FileHandle fileHandle; public final Pixmap pixmap; AtlasPage(int pageIndex, FileHandle fileHandle, Pixmap pixmap) { this.pageIndex = pageIndex; this.fileHandle = fileHandle; this.pixmap = pixmap; } } @FunctionalInterface public interface PixmapReader { Pixmap read(FileHandle file, int width, int height); } private static PixmapReader DEFAULT_READER = (file, width, height) -> new Pixmap(file); }