OSDN Git Service

(no commit message)
authordfraska <dfraska@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Thu, 14 Apr 2011 03:53:20 +0000 (03:53 +0000)
committerdfraska <dfraska@6c4fd544-2939-11df-bb46-9574ba5d0bfa>
Thu, 14 Apr 2011 03:53:20 +0000 (03:53 +0000)
extensions/tiled-preprocessor/src/com/badlogic/gdx/tiledmappacker/TileSetLayout.java
extensions/tiled-preprocessor/src/com/badlogic/gdx/tiledmappacker/TiledMapPacker.java

index 8daeaba..526e6d7 100644 (file)
@@ -29,14 +29,13 @@ import com.badlogic.gdx.utils.IntMap;
  * Contains extra information that can only be calculated after a Tiled Map's tile set images are loaded.\r
  * @author David Fraska\r
  * */\r
-public class TileSetLayout {\r
+public class TileSetLayout extends TileSet {\r
 \r
        public final BufferedImage image;\r
        private final IntMap<Vector2> imageTilePositions;\r
        private int numRows;\r
        private int numCols;\r
        public final int numTiles;\r
-       public final TileSet tileSet;\r
 \r
        /**\r
         * Constructs a Tile Set layout. The tile set image contained in the baseDir should be the original tile set images before\r
@@ -44,8 +43,9 @@ public class TileSetLayout {
         * @param tileSet the tile set to process\r
         * @param baseDir the directory in which the tile set image is stored\r
         * */\r
-       TileSetLayout (TileSet tileSet, FileHandle baseDir) throws IOException {\r
-               this.tileSet = tileSet;\r
+       protected TileSetLayout (TileSet tileSet, FileHandle baseDir) throws IOException {\r
+               super(tileSet);\r
+\r
                image = ImageIO.read(baseDir.child(tileSet.imageName).read());\r
 \r
                imageTilePositions = new IntMap<Vector2>();\r
@@ -55,14 +55,14 @@ public class TileSetLayout {
                numRows = 0;\r
                numCols = 0;\r
                for (y = tileSet.margin; y < image.getHeight() - tileSet.margin; y += tileSet.tileHeight + tileSet.spacing) {\r
-                       for (x = tileSet.margin; x < image.getWidth() - tileSet.margin; x += tileSet.tileWidth + tileSet.spacing){\r
-                               if(y == tileSet.margin) numCols++;\r
+                       for (x = tileSet.margin; x < image.getWidth() - tileSet.margin; x += tileSet.tileWidth + tileSet.spacing) {\r
+                               if (y == tileSet.margin) numCols++;\r
                                imageTilePositions.put(tile, new Vector2(x, y));\r
                                tile++;\r
                        }\r
                        numRows++;\r
                }\r
-               \r
+\r
                numTiles = numRows * numCols;\r
        }\r
 \r
@@ -76,6 +76,6 @@ public class TileSetLayout {
 \r
        /** Returns the location of the tile in {@link TileSetLayout#image} */\r
        public Vector2 getLocation (int tile) {\r
-               return imageTilePositions.get(tile - tileSet.firstgid);\r
+               return imageTilePositions.get(tile - firstgid);\r
        }\r
 }\r
index 10c2fb8..d8499bb 100644 (file)
@@ -18,6 +18,7 @@ package com.badlogic.gdx.tiledmappacker;
 import java.awt.Graphics;\r
 import java.awt.image.BufferedImage;\r
 import java.io.File;\r
+import java.io.FilenameFilter;\r
 import java.io.IOException;\r
 import java.util.ArrayList;\r
 \r
@@ -42,6 +43,8 @@ import com.badlogic.gdx.ApplicationListener;
 import com.badlogic.gdx.Gdx;\r
 import com.badlogic.gdx.backends.jogl.JoglApplication;\r
 import com.badlogic.gdx.files.FileHandle;\r
+import com.badlogic.gdx.graphics.g2d.tiled.TileAtlas;\r
+import com.badlogic.gdx.graphics.g2d.tiled.TileMapRenderer;\r
 import com.badlogic.gdx.graphics.g2d.tiled.TileSet;\r
 import com.badlogic.gdx.graphics.g2d.tiled.TiledLayer;\r
 import com.badlogic.gdx.graphics.g2d.tiled.TiledLoader;\r
@@ -52,7 +55,7 @@ import com.badlogic.gdx.math.Vector2;
 import com.badlogic.gdx.utils.GdxRuntimeException;\r
 \r
 /**\r
- * Packs a Tiled Map, adding some properties to improve the speed of the {@link TiledMapRenderer}. Also runs the texture packer on\r
+ * Packs a Tiled Map, adding some properties to improve the speed of the {@link TileMapRenderer}. Also runs the texture packer on\r
  * the tiles for use with a {@link TileAtlas}\r
  * @author David Fraska\r
  */\r
@@ -60,93 +63,105 @@ public class TiledMapPacker {
 \r
        private TexturePacker packer;\r
        private TiledMap map;\r
-       private int tileCount = 0;\r
 \r
        private File outputDir;\r
-       private FileHandle tmxFileHandle;\r
-       private FileHandle imageDirHandle;\r
+       private ArrayList<String> processedTileSets = new ArrayList<String>();\r
 \r
        private ArrayList<Integer> blendedTiles = new ArrayList<Integer>();\r
 \r
+       static private class TmxFilter implements FilenameFilter {\r
+\r
+               public TmxFilter () {\r
+               }\r
+\r
+               @Override public boolean accept (File dir, String name) {\r
+                       if (name.endsWith(".tmx")) return true;\r
+\r
+                       return false;\r
+               }\r
+\r
+       }\r
+\r
        /**\r
-        * Packs a Tiled Map, adding some properties to improve the speed of the {@link TiledMapRenderer}. Also runs the texture packer\r
-        * on the tiles for use with a {@link TileAtlas}\r
-        * @param tmxFile the map's tmx file\r
-        * @param imageDir the directory containing tile set images\r
+        * Typically, you should run the {@link TiledMapPacker#main(String[])} method instead of this method.\r
+        * Packs a directory of Tiled Maps, adding properties to improve the speed of the {@link TileMapRenderer}. Also runs the\r
+        * texture packer on the tile sets for use with a {@link TileAtlas}\r
+        * @param inputDir the directory containing tile set images and tmx files\r
         * @param outputDir the directory to output a fully processed map to\r
         * @param settings the settings used in the TexturePacker\r
         * */\r
-       public void processMap (File tmxFile, File imageDir, File outputDir, Settings settings) throws IOException {\r
+       public void processMap (File inputDir, File outputDir, Settings settings) throws IOException {\r
                this.outputDir = outputDir;\r
 \r
-               tmxFileHandle = Gdx.files.absolute(tmxFile.getAbsolutePath());\r
-               imageDirHandle = Gdx.files.absolute(imageDir.getAbsolutePath());\r
+               FileHandle inputDirHandle = Gdx.files.absolute(inputDir.getAbsolutePath());\r
+               File[] files = inputDir.listFiles(new TmxFilter());\r
 \r
-               new File(outputDir, tmxFileHandle.name()).delete();\r
-               if (outputDir.exists()) {\r
-                       String prefix = tmxFileHandle.nameWithoutExtension();\r
-                       for (File file : outputDir.listFiles())\r
-                               if (file.getName().startsWith(prefix)) file.delete();\r
-               }\r
+               for (File file : files) {\r
+                       map = TiledLoader.createMap(Gdx.files.absolute(file.getAbsolutePath()));\r
 \r
-               map = TiledLoader.createMap(tmxFileHandle);\r
+                       for (TileSet set : map.tileSets) {\r
+                               if (!processedTileSets.contains(set.imageName)) {\r
+                                       processedTileSets.add(set.imageName);\r
+                                       packTileSet(set, inputDirHandle, settings);\r
+                               }\r
+                       }\r
 \r
-               packMap(map, settings);\r
+                       writeUpdatedTMX(map.tmxFile);\r
+               }\r
        }\r
 \r
-       private void packMap (TiledMap map, Settings settings) throws IOException {\r
-               packer = new TexturePacker(settings);\r
-\r
+       private void packTileSet (TileSet set, FileHandle inputDirHandle, Settings settings) throws IOException {\r
                BufferedImage tile;\r
                Vector2 tileLocation;\r
                TileSetLayout packerTileSet;\r
                Graphics g;\r
 \r
-               ArrayList<Integer> tilesOnMap = new ArrayList<Integer>();\r
-\r
-               // Loop through all tiles on map\r
-               for (TiledLayer layer : map.layers) {\r
-                       for (int row = 0; row < layer.height; row++) {\r
-                               for (int col = 0; col < layer.width; col++) {\r
-                                       if (layer.tile[row][col] != 0) {\r
-                                               tileCount++;\r
-                                               if (!tilesOnMap.contains(layer.tile[row][col])) {\r
-                                                       tilesOnMap.add(layer.tile[row][col]);\r
-                                               }\r
-                                       }\r
-                               }\r
-                       }\r
-               }\r
+               packer = new TexturePacker(settings);\r
+\r
+               TileSetLayout layout = new TileSetLayout(set, inputDirHandle);\r
 \r
-               for (int i = 0; i < tilesOnMap.size(); i++) {\r
-                       //FIXME: this is kind of brute force. We don't know when a tileSet is going to change, so we just assume\r
-                       //it changes every tile. Should probably keep track of how many tiles are in the tileSet and use that.\r
-                       packerTileSet = getTileSetLayout(tilesOnMap.get(i)); \r
-                       tileLocation = packerTileSet.getLocation(tilesOnMap.get(i));\r
-                       tile = new BufferedImage(packerTileSet.tileSet.tileWidth, packerTileSet.tileSet.tileHeight,\r
-                               BufferedImage.TYPE_4BYTE_ABGR);\r
+               for (int gid = layout.firstgid, i = 0; i < layout.numTiles; gid++, i++) {\r
+                       tileLocation = layout.getLocation(gid);\r
+                       tile = new BufferedImage(layout.tileWidth, layout.tileHeight, BufferedImage.TYPE_4BYTE_ABGR);\r
 \r
                        g = tile.createGraphics();\r
-                       g.drawImage(packerTileSet.image, 0, 0, packerTileSet.tileSet.tileWidth, packerTileSet.tileSet.tileHeight,\r
-                               (int)tileLocation.x, (int)tileLocation.y, (int)tileLocation.x + packerTileSet.tileSet.tileWidth, (int)tileLocation.y\r
-                                       + packerTileSet.tileSet.tileHeight, null);\r
+                       g.drawImage(layout.image, 0, 0, layout.tileWidth, layout.tileHeight, (int)tileLocation.x, (int)tileLocation.y,\r
+                               (int)tileLocation.x + layout.tileWidth, (int)tileLocation.y + layout.tileHeight, null);\r
 \r
-                       if (isBlended(tile)) setBlended(tilesOnMap.get(i));\r
+                       if (isBlended(tile)) setBlended(gid);\r
 \r
-                       packer.addImage(tile, map.tmxFile.nameWithoutExtension() + "_" + tilesOnMap.get(i));\r
+                       packer.addImage(tile, removeExtension(set.imageName) + "_" + i);\r
                }\r
 \r
-               packer.process(outputDir, new File(outputDir, map.tmxFile.nameWithoutExtension() + " packfile"),\r
-                       tmxFileHandle.nameWithoutExtension());\r
-               writeUpdatedTMX();\r
+               packer\r
+                       .process(outputDir, new File(outputDir, removeExtension(set.imageName) + " packfile"), removeExtension(set.imageName));\r
+       }\r
+\r
+       private static String removeExtension (String s) {\r
+\r
+               String separator = System.getProperty("file.separator");\r
+               String filename;\r
+\r
+               // Remove the path up to the filename.\r
+               int lastSeparatorIndex = s.lastIndexOf(separator);\r
+               if (lastSeparatorIndex == -1) {\r
+                       filename = s;\r
+               } else {\r
+                       filename = s.substring(lastSeparatorIndex + 1);\r
+               }\r
+\r
+               // Remove the extension.\r
+               int extensionIndex = filename.lastIndexOf(".");\r
+               if (extensionIndex == -1) return filename;\r
+\r
+               return filename.substring(0, extensionIndex);\r
        }\r
 \r
        private void setBlended (int tileNum) {\r
                blendedTiles.add(tileNum);\r
-               // System.out.println("TileNum " + tileNum + " is blended");\r
        }\r
 \r
-       private void writeUpdatedTMX () throws IOException {\r
+       private void writeUpdatedTMX (FileHandle tmxFileHandle) throws IOException {\r
                Document doc;\r
                DocumentBuilder docBuilder;\r
                DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();\r
@@ -154,16 +169,15 @@ public class TiledMapPacker {
                try {\r
                        docBuilder = docFactory.newDocumentBuilder();\r
                        doc = docBuilder.parse(tmxFileHandle.read());\r
-                       \r
+\r
                        Node map = doc.getFirstChild();\r
-                       while(map.getNodeType() != Node.ELEMENT_NODE || map.getNodeName() != "map"){\r
-                               if((map = map.getNextSibling()) == null){\r
+                       while (map.getNodeType() != Node.ELEMENT_NODE || map.getNodeName() != "map") {\r
+                               if ((map = map.getNextSibling()) == null) {\r
                                        throw new GdxRuntimeException("Couldn't find map node!");\r
                                }\r
                        }\r
-                       \r
+\r
                        setProperty(doc, map, "blended tiles", toCSV(blendedTiles));\r
-                       setProperty(doc, map, "tile count", String.valueOf(tileCount));\r
 \r
                        TransformerFactory transformerFactory = TransformerFactory.newInstance();\r
                        Transformer transformer = transformerFactory.newTransformer();\r
@@ -196,7 +210,7 @@ public class TiledMapPacker {
                        valueNode.setNodeValue(value);\r
                }\r
        }\r
-       \r
+\r
        private static String toCSV (ArrayList<Integer> values) {\r
                String temp = "";\r
                for (int i = 0; i < values.size() - 1; i++) {\r
@@ -216,7 +230,7 @@ public class TiledMapPacker {
                }\r
 \r
                Node newNode = parent.getOwnerDocument().createElement(child);\r
-               \r
+\r
                if (childNodes.item(0) != null)\r
                        return parent.insertBefore(newNode, childNodes.item(0));\r
                else\r
@@ -262,12 +276,12 @@ public class TiledMapPacker {
                return false;\r
        }\r
 \r
-       private TileSetLayout getTileSetLayout (int tileNum) throws IOException {\r
+       private TileSetLayout getTileSetLayout (int tileNum, FileHandle inputDirHandle) throws IOException {\r
                int firstgid = 0;\r
                int lastgid;\r
 \r
                for (TileSet set : map.tileSets) {\r
-                       TileSetLayout layout = new TileSetLayout(set, imageDirHandle);\r
+                       TileSetLayout layout = new TileSetLayout(set, inputDirHandle);\r
                        firstgid = set.firstgid;\r
                        lastgid = firstgid + layout.numTiles - 1;\r
                        if (tileNum >= firstgid && tileNum <= lastgid) {\r
@@ -278,12 +292,19 @@ public class TiledMapPacker {
                return null;\r
        }\r
 \r
+       /**\r
+        * Processes a \r
+        * @param args args[0]: the input directory containing tmx files and tile set images.\r
+        *                              args[1]: The output directory, should be empty before running.\r
+        */\r
        public static void main (String[] args) {\r
-               File tmxFile, baseDir, outputDir;\r
+               File tmxFile, inputDir, outputDir;\r
 \r
                Settings settings = new Settings();\r
                settings.padding = 2;\r
                settings.duplicatePadding = true;\r
+               settings.incremental = true;\r
+               settings.alias = true;\r
 \r
                // Create a new JoglApplication so that Gdx stuff works properly\r
                new JoglApplication(new ApplicationListener() {\r
@@ -308,24 +329,20 @@ public class TiledMapPacker {
 \r
                TiledMapPacker packer = new TiledMapPacker();\r
 \r
-               if (args.length != 3) {\r
-                       System.out.println("Usage: TMXFILE BASEDIR OUTPUTDIR");\r
-                       return;\r
+               if (args.length != 2) {\r
+                       System.out.println("Usage: INPUTDIR OUTPUTDIR");\r
+                       System.exit(0);\r
                }\r
 \r
-               tmxFile = new File(args[0]);\r
-               baseDir = new File(args[1]);\r
-               outputDir = new File(args[2]);\r
+               inputDir = new File(args[0]);\r
+               outputDir = new File(args[1]);\r
 \r
-               if (!baseDir.exists()) {\r
-                       throw new RuntimeException("Base directory does not exist");\r
-               }\r
-               if (!tmxFile.exists()) {\r
-                       throw new RuntimeException("TMX file does not exist");\r
+               if (!inputDir.exists()) {\r
+                       throw new RuntimeException("Input directory does not exist");\r
                }\r
 \r
                try {\r
-                       packer.processMap(tmxFile, baseDir, outputDir, settings);\r
+                       packer.processMap(inputDir, outputDir, settings);\r
                } catch (IOException e) {\r
                        throw new RuntimeException("Error processing map: " + e.getMessage());\r
                }\r