/*******************************************************************************
* Copyright (c) 2015
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*******************************************************************************/
package jsettlers.common.texturegeneration;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Hashtable;
/**
* This program compiles all textures into the needed format for graphics
*
* @author michael
*/
public class TextureCompiler implements Runnable, TextureIndex {
private DataOutputStream textureIndexOut;
private int textureCounter = 0;
private PrintWriter textureConstantsOut;
private int imageIndexCounter;
private final Hashtable<String, Integer> imageIndexes = new Hashtable<String, Integer>();
private final Object imageIndexMutex = new Object();
private final Object textureCounterMutex = new Object();
private File resourceDirectory;
private File genDirectory;
public TextureCompiler() {
this(null, null);
}
public TextureCompiler(File resourceDirectory, File genDirectory) {
this.setResourceDirectory(resourceDirectory);
this.setGenDirectory(genDirectory);
}
public static void main(String[] args) {
if (args.length < 3) {
throw new IllegalArgumentException("Usage: compiler <intput dir> <gen dir>");
}
new TextureCompiler(new File(args[1]), new File(args[2])).run();
}
// For ant
public void execute() throws IOException {
if (genDirectory == null) {
throw new RuntimeException("please use genDirectory=\"...\"");
}
if (resourceDirectory == null) {
throw new RuntimeException("please use resourceDirectory=\"...\"");
}
genDirectory.mkdirs();
openTextureIndex();
File rawDirectory = new File(getResourceDirectory(), "textures_raw");
File outDirectory = new File(getResourceDirectory(), "images");
TextureGenerator gen = new TextureGenerator(this, rawDirectory, outDirectory);
gen.start();
String[] files = rawDirectory.list();
for (String file : files) {
if (file.matches(".*\\.png")) {
String name = file.replaceAll("\\.png", "");
gen.addTexturesByName(Collections.singletonList(name));
}
}
gen.join();
closeTextureIndex();
}
@Override
public void run() {
try {
execute();
} catch (IOException e) {
e.printStackTrace();
}
}
private void openTextureIndex() throws IOException {
File imagesOut = new File(getResourceDirectory(), "images");
textureIndexOut = new DataOutputStream(new FileOutputStream(new File(imagesOut, "texturemap")));
textureIndexOut.write(new byte[] { 'T', 'E', 'X', '1' });
File packageDir = new File(new File(new File(getGenDirectory(), "jsettlers"), "common"), "images");
packageDir.mkdirs();
textureConstantsOut = new PrintWriter(new File(packageDir, "TextureMap.java"));
textureConstantsOut.println("package jsettlers.common.images;");
textureConstantsOut.println("import java.util.Arrays;");
textureConstantsOut.println();
textureConstantsOut.println("// DO NOT EDIT THIS FILE, IT IS GENERATED");
textureConstantsOut.println();
textureConstantsOut.println("public final class TextureMap {");
textureConstantsOut.println(" private TextureMap() {}");
textureConstantsOut.println();
textureConstantsOut.println(" public static int getIndex(String name) {");
textureConstantsOut.println(" int arrindex = Arrays.binarySearch(names, name);");
textureConstantsOut.println(" if (arrindex < 0) {");
textureConstantsOut.println(" throw new IllegalArgumentException(\"Could not find \" + name + \" in image map.\");");
textureConstantsOut.println(" }");
textureConstantsOut.println(" return indexes[arrindex];");
textureConstantsOut.println(" }");
textureConstantsOut.println();
System.out.println("Opened texture index");
}
private void closeTextureIndex() throws IOException {
ArrayList<String> sortedIndexes = new ArrayList<String>(
imageIndexes.keySet());
Collections.sort(sortedIndexes);
textureIndexOut.close();
textureConstantsOut.println(" private static final String[] names = new String[] {");
for (String n : sortedIndexes) {
textureConstantsOut.println(" \"" + n + "\",");
}
textureConstantsOut.println(" };");
textureConstantsOut.println(" private static final int[] indexes = new int[] {");
for (String n : sortedIndexes) {
textureConstantsOut.println(" " + imageIndexes.get(n) + ",");
}
textureConstantsOut.println(" };");
textureConstantsOut.println("}");
textureConstantsOut.close();
System.out.println("Closed texture index");
}
@Override
public void registerTexture(String name, int textureFile, int offsetx, int offsety, int width, int height, boolean hasTorso,
TexturePosition position) throws IOException {
synchronized (imageIndexMutex) {
String safename = name.replaceAll("[^a-zA-Z0-9._]", "_");
imageIndexes.put(safename, imageIndexCounter);
textureIndexOut.writeShort(offsetx);
textureIndexOut.writeShort(offsety);
textureIndexOut.writeShort(width);
textureIndexOut.writeShort(height);
textureIndexOut.writeShort(hasTorso ? textureFile | 0x8000 : textureFile);
textureIndexOut.writeShort(toShort(position.getLeft()));
textureIndexOut.writeShort(toShort(position.getTop()));
textureIndexOut.writeShort(toShort(position.getRight()));
textureIndexOut.writeShort(toShort(position.getBottom()));
System.out.println("Added image " + imageIndexCounter + " to texture " + textureFile + " and added to constant index as " + safename);
imageIndexCounter++;
}
}
private static int toShort(float left) {
return (int) (left * 0x7fff);
}
@Override
public int getNextTextureIndex() {
synchronized (textureCounterMutex) {
return textureCounter++;
}
}
public File getResourceDirectory() {
return resourceDirectory;
}
public void setResourceDirectory(File resourceDirectory) {
this.resourceDirectory = resourceDirectory;
}
public File getGenDirectory() {
return genDirectory;
}
public void setGenDirectory(File genDirectory) {
this.genDirectory = genDirectory;
}
}