1 package micropolisj.build_tool;
3 import micropolisj.engine.TileSpec;
5 import java.awt.image.BufferedImage;
7 import java.nio.charset.Charset;
9 import javax.imageio.*;
10 import javax.swing.ImageIcon;
14 static HashMap<String,String> tileData =
new HashMap<String,String>();
15 static HashMap<String,SourceImage> loadedImages =
new HashMap<String,SourceImage>();
17 static final Charset UTF8 = Charset.forName(
"UTF-8");
18 static int SKIP_TILES = 0;
19 static int NTILES = 1005;
20 static int TILE_SIZE = 16;
22 public static void main(String [] args)
25 if (args.length != 2) {
26 throw new Exception(
"Wrong number of arguments");
29 if (System.getProperty(
"tile_size") != null) {
30 TILE_SIZE = Integer.parseInt(System.getProperty(
"tile_size"));
32 if (System.getProperty(
"skip_tiles") != null) {
33 SKIP_TILES = Integer.parseInt(System.getProperty(
"skip_tiles"));
35 if (System.getProperty(
"tile_count") != null) {
36 NTILES = Integer.parseInt(System.getProperty(
"tile_count"));
39 File recipeFile =
new File(args[0]);
40 File outputFile =
new File(args[1]);
42 Properties recipe =
new Properties();
44 new InputStreamReader(
45 new FileInputStream(recipeFile),
50 BufferedImage buf =
new BufferedImage(TILE_SIZE,TILE_SIZE*NTILES,BufferedImage.TYPE_INT_RGB);
51 Graphics2D gr = buf.createGraphics();
53 for (
int i = 0; i < NTILES; i++) {
54 int tileNumber = SKIP_TILES + i;
55 String rawSpec = recipe.getProperty(Integer.toString(tileNumber));
56 if (rawSpec == null) {
61 FrameSpec ref = parseFrameSpec(tileSpec);
67 drawTo(ref, gr, 0, TILE_SIZE*i);
70 System.out.println(
"Generating tiles array: "+outputFile);
71 ImageIO.write(buf,
"png", outputFile);
74 static void drawTo(FrameSpec ref, Graphics2D gr,
int destX,
int destY)
77 if (ref.background != null) {
78 drawTo(ref.background, gr, destX, destY);
81 if (!loadedImages.containsKey(ref.fileName)) {
82 loadedImages.put(ref.fileName,
83 loadImage(ref.fileName));
86 SourceImage sourceImg = loadedImages.get(ref.fileName);
91 destX+TILE_SIZE, destY+TILE_SIZE,
92 ref.offsetX * sourceImg.basisSize / 16,
93 ref.offsetY * sourceImg.basisSize / 16,
94 (ref.offsetX + (ref.width != 0 ? ref.width : 16)) * sourceImg.basisSize / 16,
95 (ref.offsetY + (ref.height != 0 ? ref.height : 16)) * sourceImg.basisSize / 16,
99 static class SourceImage
104 SourceImage(Image image,
int basisSize) {
106 this.basisSize = basisSize;
110 static class FrameSpec
112 FrameSpec background;
120 static FrameSpec parseFrameSpec(TileSpec spec)
122 FrameSpec result = null;
124 for (String layerStr : spec.getImages()) {
126 FrameSpec rv =
new FrameSpec();
127 rv.background = result;
130 String [] parts = layerStr.split(
"@", 2);
131 rv.fileName = parts[0];
133 if (parts.length >= 2) {
134 String offsetInfo = parts[1];
135 parts = offsetInfo.split(
",");
136 if (parts.length >= 1) {
137 rv.offsetX = Integer.parseInt(parts[0]);
139 if (parts.length >= 2) {
140 rv.offsetY = Integer.parseInt(parts[1]);
142 if (parts.length >= 3) {
143 rv.width = Integer.parseInt(parts[2]);
145 if (parts.length >= 4) {
146 rv.height = Integer.parseInt(parts[3]);
155 static File findInkscape()
157 String exeName =
"inkscape";
158 if (System.getProperty(
"os.name").startsWith(
"Windows")) {
162 File [] pathsToTry = {
163 new File(
"/usr/bin"),
164 new File(
"c:\\Program Files\\Inkscape"),
165 new File(
"c:\\Program Files (x86)\\Inkscape")
167 for (File p : pathsToTry) {
168 File f =
new File(p, exeName);
173 throw new Error(
"INKSCAPE not installed (or not found)");
176 static File stagingDir =
new File(
"generated");
177 static File renderSvg(String fileName, File svgFile)
180 File pngFile =
new File(stagingDir, fileName+
"_"+TILE_SIZE+
"x"+TILE_SIZE+
".png");
181 if (pngFile.exists() &&
182 pngFile.lastModified() > svgFile.lastModified())
188 File inkscapeBin = findInkscape();
190 System.out.println(
"Generating raster image: "+pngFile);
191 if (pngFile.exists()) {
195 pngFile.getParentFile().mkdirs();
198 String [] cmdline = {
199 inkscapeBin.toString(),
200 "--export-dpi="+(TILE_SIZE*90.0/16.0),
201 "--export-png="+pngFile.toString(),
204 Process p = Runtime.getRuntime().exec(cmdline);
207 exit_value = p.waitFor();
209 catch (InterruptedException e) {
210 throw new RuntimeException(e);
213 if (exit_value != 0) {
214 throw new RuntimeException(
"Helper exit status: "+exit_value);
217 if (!pngFile.exists()) {
218 throw new RuntimeException(
"File not found: "+pngFile);
224 static SourceImage loadImage(String fileName)
227 File svgFile, pngFile = null;
229 svgFile =
new File(fileName+
"_"+TILE_SIZE+
"x"+TILE_SIZE+
".svg");
231 if (svgFile.exists()) {
232 pngFile = renderSvg(fileName, svgFile);
235 svgFile =
new File(fileName+
".svg");
236 if (svgFile.exists()) {
237 pngFile = renderSvg(fileName, svgFile);
241 if (pngFile != null && pngFile.exists()) {
242 ImageIcon ii =
new ImageIcon(pngFile.toString());
243 return new SourceImage(
248 pngFile =
new File(fileName+
"_"+TILE_SIZE+
"x"+TILE_SIZE+
".png");
249 if (pngFile.exists()) {
250 ImageIcon ii =
new ImageIcon(pngFile.toString());
251 return new SourceImage(
256 pngFile =
new File(fileName+
".png");
257 if (pngFile.exists()) {
258 ImageIcon ii =
new ImageIcon(pngFile.toString());
259 return new SourceImage(
264 throw new IOException(
"File not found: "+fileName+
".{svg,png}");