/*******************************************************************************
* Copyright 2011 See AUTHORS file.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
******************************************************************************/
package com.badlogic.gdx.tools.imagepacker;
import com.badlogic.gdx.tools.FileProcessor;
import com.badlogic.gdx.tools.imagepacker.TexturePacker2.Settings;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.Json;
import com.badlogic.gdx.utils.JsonReader;
import com.badlogic.gdx.utils.ObjectMap;
import com.badlogic.gdx.utils.SerializationException;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.regex.Pattern;
/** @author Nathan Sweet */
public class TexturePackerFileProcessor extends FileProcessor {
private final Settings defaultSettings;
private ObjectMap<File, Settings> dirToSettings = new ObjectMap();
private Json json = new Json();
private String packFileName;
private File root;
ArrayList<File> ignoreDirs = new ArrayList();
public TexturePackerFileProcessor () {
this(new Settings(), "pack.atlas");
}
public TexturePackerFileProcessor (Settings defaultSettings, String packFileName) {
this.defaultSettings = defaultSettings;
if (packFileName.indexOf('.') == -1) packFileName += ".atlas";
this.packFileName = packFileName;
setFlattenOutput(true);
addInputSuffix(".png", ".jpg");
}
public ArrayList<Entry> process (File inputFile, File outputRoot) throws Exception {
root = inputFile;
// Collect pack.json setting files.
final ArrayList<File> settingsFiles = new ArrayList();
FileProcessor settingsProcessor = new FileProcessor() {
protected void processFile (Entry inputFile) throws Exception {
settingsFiles.add(inputFile.inputFile);
}
};
settingsProcessor.addInputRegex("pack\\.json");
settingsProcessor.process(inputFile, null);
// Sort parent first.
Collections.sort(settingsFiles, new Comparator<File>() {
public int compare (File file1, File file2) {
return file1.toString().length() - file2.toString().length();
}
});
for (File settingsFile : settingsFiles) {
// Find first parent with settings, or use defaults.
Settings settings = null;
File parent = settingsFile.getParentFile();
while (true) {
if (parent.equals(root)) break;
parent = parent.getParentFile();
settings = dirToSettings.get(parent);
if (settings != null) {
settings = new Settings(settings);
break;
}
}
if (settings == null) settings = new Settings(defaultSettings);
// Merge settings from current directory.
try {
json.readFields(settings, new JsonReader().parse(new FileReader(settingsFile)));
} catch (SerializationException ex) {
throw new GdxRuntimeException("Error reading settings file: " + settingsFile, ex);
}
dirToSettings.put(settingsFile.getParentFile(), settings);
}
// Do actual processing.
return super.process(inputFile, outputRoot);
}
public ArrayList<Entry> process (File[] files, File outputRoot) throws Exception {
// Delete pack file and images.
if (outputRoot.exists()) {
new File(outputRoot, packFileName).delete();
FileProcessor deleteProcessor = new FileProcessor() {
protected void processFile (Entry inputFile) throws Exception {
inputFile.inputFile.delete();
}
};
deleteProcessor.setRecursive(false);
String prefix = packFileName;
int dotIndex = prefix.lastIndexOf('.');
if (dotIndex != -1) prefix = prefix.substring(0, dotIndex);
deleteProcessor.addInputRegex(Pattern.quote(prefix) + "\\d*\\.(png|jpg)");
deleteProcessor.process(outputRoot, null);
}
return super.process(files, outputRoot);
}
protected void processDir (Entry inputDir, ArrayList<Entry> files) throws Exception {
if (ignoreDirs.contains(inputDir.inputFile)) return;
// Find first parent with settings, or use defaults.
Settings settings = null;
File parent = inputDir.inputFile;
while (true) {
settings = dirToSettings.get(parent);
if (settings != null) break;
if (parent.equals(root)) break;
parent = parent.getParentFile();
}
if (settings == null) settings = defaultSettings;
if (settings.combineSubdirectories) {
// Collect all files under subdirectories and ignore subdirectories so they won't be packed twice.
files = new FileProcessor(this) {
protected void processDir (Entry entryDir, ArrayList<Entry> files) {
ignoreDirs.add(entryDir.inputFile);
}
protected void processFile (Entry entry) {
addProcessedFile(entry);
}
}.process(inputDir.inputFile, null);
}
if (files.isEmpty()) return;
// Pack.
System.out.println(inputDir.inputFile.getName());
TexturePacker2 packer = new TexturePacker2(root, settings);
for (Entry file : files)
packer.addImage(file.inputFile);
packer.pack(inputDir.outputDir, packFileName);
}
}