2013-06-26 22:11:38 +00:00
|
|
|
package micropolisj.build_tool;
|
|
|
|
|
2013-07-17 20:11:47 +00:00
|
|
|
import micropolisj.engine.TileSpec;
|
2013-06-25 17:39:24 +00:00
|
|
|
import java.awt.*;
|
|
|
|
import java.awt.image.BufferedImage;
|
|
|
|
import java.io.*;
|
2013-06-29 17:55:11 +00:00
|
|
|
import java.nio.charset.Charset;
|
2013-06-25 17:39:24 +00:00
|
|
|
import java.util.*;
|
|
|
|
import javax.imageio.*;
|
|
|
|
import javax.swing.ImageIcon;
|
|
|
|
|
|
|
|
public class MakeTiles
|
|
|
|
{
|
|
|
|
static HashMap<String,String> tileData = new HashMap<String,String>();
|
2013-07-17 20:30:39 +00:00
|
|
|
static HashMap<String,SourceImage> loadedImages = new HashMap<String,SourceImage>();
|
2013-06-25 17:39:24 +00:00
|
|
|
|
2013-06-29 17:55:11 +00:00
|
|
|
static final Charset UTF8 = Charset.forName("UTF-8");
|
2013-06-25 17:39:24 +00:00
|
|
|
static final int NTILES = 960;
|
2013-07-17 20:30:36 +00:00
|
|
|
static int TILE_SIZE = 16;
|
2013-06-25 17:39:24 +00:00
|
|
|
|
|
|
|
public static void main(String [] args)
|
|
|
|
throws Exception
|
|
|
|
{
|
2013-07-17 20:30:36 +00:00
|
|
|
if (args.length != 2) {
|
|
|
|
throw new Exception("Wrong number of arguments");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (System.getProperty("tile_size") != null) {
|
|
|
|
TILE_SIZE = Integer.parseInt(System.getProperty("tile_size"));
|
|
|
|
}
|
|
|
|
|
2013-06-25 17:39:24 +00:00
|
|
|
File recipeFile = new File(args[0]);
|
|
|
|
File outputFile = new File(args[1]);
|
|
|
|
|
2013-06-29 17:55:11 +00:00
|
|
|
Properties recipe = new Properties();
|
|
|
|
recipe.load(
|
|
|
|
new InputStreamReader(
|
|
|
|
new FileInputStream(recipeFile),
|
|
|
|
UTF8
|
|
|
|
));
|
2013-06-25 17:39:24 +00:00
|
|
|
|
|
|
|
// actually assemble the image
|
|
|
|
BufferedImage buf = new BufferedImage(TILE_SIZE,TILE_SIZE*NTILES,BufferedImage.TYPE_INT_RGB);
|
|
|
|
Graphics2D gr = buf.createGraphics();
|
|
|
|
|
|
|
|
for (int i = 0; i < NTILES; i++) {
|
2013-07-17 19:58:02 +00:00
|
|
|
String rawSpec = recipe.getProperty(Integer.toString(i));
|
|
|
|
assert rawSpec != null;
|
2013-06-25 17:39:24 +00:00
|
|
|
|
2013-07-17 20:11:54 +00:00
|
|
|
TileSpec tileSpec = TileSpec.parse(i, rawSpec);
|
2013-07-17 20:30:39 +00:00
|
|
|
FrameSpec ref = parseFrameSpec(tileSpec);
|
2013-06-26 13:12:52 +00:00
|
|
|
drawTo(ref, gr, 0, TILE_SIZE*i);
|
2013-06-25 17:39:24 +00:00
|
|
|
}
|
|
|
|
|
2013-07-20 21:29:25 +00:00
|
|
|
System.out.println("Generating tiles array: "+outputFile);
|
2013-06-25 17:39:24 +00:00
|
|
|
ImageIO.write(buf, "png", outputFile);
|
|
|
|
}
|
|
|
|
|
2013-07-17 20:30:39 +00:00
|
|
|
static void drawTo(FrameSpec ref, Graphics2D gr, int destX, int destY)
|
2013-06-26 13:12:52 +00:00
|
|
|
throws IOException
|
2013-06-25 17:39:24 +00:00
|
|
|
{
|
2013-06-26 13:12:52 +00:00
|
|
|
if (ref.background != null) {
|
|
|
|
drawTo(ref.background, gr, destX, destY);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!loadedImages.containsKey(ref.fileName)) {
|
|
|
|
loadedImages.put(ref.fileName,
|
|
|
|
loadImage(ref.fileName));
|
|
|
|
}
|
|
|
|
|
2013-07-17 20:30:39 +00:00
|
|
|
SourceImage sourceImg = loadedImages.get(ref.fileName);
|
2013-06-26 13:12:52 +00:00
|
|
|
|
|
|
|
gr.drawImage(
|
2013-07-17 20:30:39 +00:00
|
|
|
sourceImg.image,
|
2013-06-26 13:12:52 +00:00
|
|
|
destX, destY,
|
|
|
|
destX+TILE_SIZE, destY+TILE_SIZE,
|
2013-07-17 20:30:39 +00:00
|
|
|
ref.offsetX * sourceImg.basisSize / 16,
|
|
|
|
ref.offsetY * sourceImg.basisSize / 16,
|
|
|
|
(ref.offsetX + (ref.width != 0 ? ref.width : 16)) * sourceImg.basisSize / 16,
|
|
|
|
(ref.offsetY + (ref.height != 0 ? ref.height : 16)) * sourceImg.basisSize / 16,
|
2013-06-26 13:12:52 +00:00
|
|
|
null);
|
|
|
|
}
|
|
|
|
|
2013-07-17 20:30:39 +00:00
|
|
|
static class SourceImage
|
2013-06-26 13:12:52 +00:00
|
|
|
{
|
2013-07-17 20:30:39 +00:00
|
|
|
Image image;
|
|
|
|
int basisSize;
|
|
|
|
|
|
|
|
SourceImage(Image image, int basisSize) {
|
|
|
|
this.image = image;
|
|
|
|
this.basisSize = basisSize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static class FrameSpec
|
|
|
|
{
|
|
|
|
FrameSpec background;
|
2013-06-25 17:39:24 +00:00
|
|
|
String fileName;
|
|
|
|
int offsetX;
|
|
|
|
int offsetY;
|
|
|
|
int width;
|
|
|
|
int height;
|
|
|
|
}
|
|
|
|
|
2013-07-17 20:30:39 +00:00
|
|
|
static FrameSpec parseFrameSpec(TileSpec spec)
|
2013-06-25 17:39:24 +00:00
|
|
|
{
|
2013-07-17 20:30:39 +00:00
|
|
|
FrameSpec result = null;
|
2013-06-26 13:12:52 +00:00
|
|
|
|
2013-07-17 19:58:14 +00:00
|
|
|
for (String layerStr : spec.getImages()) {
|
2013-06-25 17:39:24 +00:00
|
|
|
|
2013-07-17 20:30:39 +00:00
|
|
|
FrameSpec rv = new FrameSpec();
|
2013-06-26 13:12:52 +00:00
|
|
|
rv.background = result;
|
|
|
|
result = rv;
|
|
|
|
|
|
|
|
String [] parts = layerStr.split("@", 2);
|
2013-06-25 17:39:24 +00:00
|
|
|
rv.fileName = parts[0];
|
|
|
|
|
2013-06-25 17:40:11 +00:00
|
|
|
if (parts.length >= 2) {
|
2013-06-26 13:12:52 +00:00
|
|
|
String offsetInfo = parts[1];
|
|
|
|
parts = offsetInfo.split(",");
|
|
|
|
if (parts.length >= 1) {
|
|
|
|
rv.offsetX = Integer.parseInt(parts[0]);
|
|
|
|
}
|
|
|
|
if (parts.length >= 2) {
|
|
|
|
rv.offsetY = Integer.parseInt(parts[1]);
|
|
|
|
}
|
|
|
|
if (parts.length >= 3) {
|
|
|
|
rv.width = Integer.parseInt(parts[2]);
|
|
|
|
}
|
|
|
|
if (parts.length >= 4) {
|
|
|
|
rv.height = Integer.parseInt(parts[3]);
|
|
|
|
}
|
2013-06-25 17:40:11 +00:00
|
|
|
}//endif something given after '@' in image specifier
|
|
|
|
|
2013-06-26 13:12:52 +00:00
|
|
|
}//end foreach layer in image specification
|
|
|
|
|
|
|
|
return result;
|
2013-06-25 17:39:24 +00:00
|
|
|
}
|
|
|
|
|
2013-07-20 21:29:25 +00:00
|
|
|
static File findInkscape()
|
|
|
|
{
|
|
|
|
String exeName = "inkscape";
|
|
|
|
if (System.getProperty("os.name").startsWith("Windows")) {
|
|
|
|
exeName += ".exe";
|
|
|
|
}
|
|
|
|
|
|
|
|
File [] pathsToTry = {
|
|
|
|
new File("/usr/bin"),
|
|
|
|
new File("c:\\Program Files\\Inkscape"),
|
|
|
|
new File("c:\\Program Files (x86)\\Inkscape")
|
|
|
|
};
|
|
|
|
for (File p : pathsToTry) {
|
|
|
|
File f = new File(p, exeName);
|
|
|
|
if (f.exists()) {
|
|
|
|
return f;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
throw new Error("INKSCAPE not installed (or not found)");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void renderSvg(File svgFile, File pngFile)
|
|
|
|
throws IOException
|
|
|
|
{
|
|
|
|
if (pngFile.exists() &&
|
|
|
|
pngFile.lastModified() > svgFile.lastModified())
|
|
|
|
{
|
|
|
|
// looks like the PNG file is already up-to-date
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
File inkscapeBin = findInkscape();
|
|
|
|
|
|
|
|
System.out.println("Generating raster image: "+pngFile);
|
|
|
|
if (pngFile.exists()) {
|
|
|
|
pngFile.delete();
|
|
|
|
}
|
|
|
|
|
|
|
|
String [] cmdline = {
|
|
|
|
inkscapeBin.toString(),
|
|
|
|
"--export-width="+TILE_SIZE,
|
|
|
|
"--export-height="+TILE_SIZE,
|
|
|
|
"--export-png="+pngFile.toString(),
|
|
|
|
svgFile.toString()
|
|
|
|
};
|
|
|
|
Process p = Runtime.getRuntime().exec(cmdline);
|
|
|
|
int exit_value;
|
|
|
|
try {
|
|
|
|
exit_value = p.waitFor();
|
|
|
|
}
|
|
|
|
catch (InterruptedException e) {
|
|
|
|
throw new RuntimeException(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (exit_value != 0) {
|
|
|
|
throw new RuntimeException("Helper exit status: "+exit_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!pngFile.exists()) {
|
|
|
|
throw new RuntimeException("File not found: "+pngFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-07-17 20:30:39 +00:00
|
|
|
static SourceImage loadImage(String fileName)
|
2013-06-25 17:39:24 +00:00
|
|
|
throws IOException
|
|
|
|
{
|
2013-07-20 21:29:25 +00:00
|
|
|
File svgFile, pngFile;
|
|
|
|
|
|
|
|
svgFile = new File(fileName+"_"+TILE_SIZE+"x"+TILE_SIZE+".svg");
|
|
|
|
pngFile = new File(fileName+"_"+TILE_SIZE+"x"+TILE_SIZE+".png");
|
|
|
|
|
|
|
|
if (svgFile.exists()) {
|
|
|
|
renderSvg(svgFile, pngFile);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
svgFile = new File(fileName+".svg");
|
|
|
|
if (svgFile.exists()) {
|
|
|
|
renderSvg(svgFile, pngFile);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pngFile.exists()) {
|
|
|
|
ImageIcon ii = new ImageIcon(pngFile.toString());
|
2013-07-17 20:30:39 +00:00
|
|
|
return new SourceImage(
|
|
|
|
ii.getImage(),
|
|
|
|
TILE_SIZE);
|
|
|
|
}
|
|
|
|
|
2013-07-20 21:29:25 +00:00
|
|
|
pngFile = new File(fileName+".png");
|
|
|
|
if (pngFile.exists()) {
|
|
|
|
ImageIcon ii = new ImageIcon(pngFile.toString());
|
2013-07-17 20:30:39 +00:00
|
|
|
return new SourceImage(
|
|
|
|
ii.getImage(),
|
|
|
|
16);
|
|
|
|
}
|
|
|
|
|
2013-07-20 21:29:25 +00:00
|
|
|
throw new IOException("File not found: "+fileName+".{svg,png}");
|
2013-06-25 17:39:24 +00:00
|
|
|
}
|
|
|
|
}
|