Browse code

initial import

devnewton authored on 19/02/2013 19:26:43
Showing 16 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,31 @@
1
+/*
2
+ * Copyright (c) 2013 devnewton <devnewton@bci.im>
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are
7
+ * met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright
10
+ *   notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ *   notice, this list of conditions and the following disclaimer in the
14
+ *   documentation and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of 'devnewton <devnewton@bci.im>' nor the names of
17
+ *   its contributors may be used to endorse or promote products derived
18
+ *   from this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
0 32
\ No newline at end of file
1 33
new file mode 100644
... ...
@@ -0,0 +1,20 @@
1
+Redistribution and use in source and binary forms, with or without
2
+modification, are permitted provided that the following conditions are met:
3
+
4
+   1. Redistributions of source code must retain the above copyright notice,
5
+      this list of conditions and the following disclaimer.
6
+
7
+   2. Redistributions in binary form must reproduce the above copyright
8
+      notice, this list of conditions and the following disclaimer in the
9
+      documentation and/or other materials provided with the distribution.
10
+
11
+THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
12
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
13
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
14
+EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
15
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
16
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
17
+OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
18
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
19
+OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
20
+ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0 21
new file mode 100644
... ...
@@ -0,0 +1,42 @@
1
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
2
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
3
+    <modelVersion>4.0.0</modelVersion>
4
+
5
+    <groupId>im.bci</groupId>
6
+    <artifactId>tiledmerge</artifactId>
7
+    <version>1.0-SNAPSHOT</version>
8
+    <packaging>jar</packaging>
9
+
10
+    <name>tiledmerge</name>
11
+    <url>http://maven.apache.org</url>
12
+
13
+    <properties>
14
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
15
+    </properties>
16
+
17
+    <dependencies>
18
+        <dependency>
19
+            <groupId>args4j</groupId>
20
+            <artifactId>args4j</artifactId>
21
+            <version>2.0.16</version>
22
+        </dependency>
23
+        <dependency>
24
+            <groupId>im.bci</groupId>
25
+            <artifactId>libtiled</artifactId>
26
+            <version>1.0</version>
27
+        </dependency>
28
+        <dependency>
29
+            <groupId>commons-io</groupId>
30
+            <artifactId>commons-io</artifactId>
31
+            <version>1.3.2</version>
32
+        </dependency>
33
+    </dependencies>
34
+  
35
+    <repositories>
36
+        <repository>
37
+            <id>project.local</id>
38
+            <name>project</name>
39
+            <url>file:${project.basedir}/repo</url>
40
+        </repository>
41
+    </repositories>
42
+</project>
0 43
new file mode 100644
1 44
Binary files /dev/null and b/repo/im/bci/libtiled/1.0/libtiled-1.0.jar differ
2 45
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+22ebfe527493a22657e7ada52ceffcb6
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+c6ddac96bb91da50ca5c4788f449f1553495faff
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,8 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
3
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
4
+  <modelVersion>4.0.0</modelVersion>
5
+  <groupId>im.bci</groupId>
6
+  <artifactId>libtiled</artifactId>
7
+  <version>1.0</version>
8
+</project>
0 9
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+a541283d444ab58d2891481ac7a9992d
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+1b8acde59d3f29b079867790262473f406d031c2
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,12 @@
1
+<?xml version="1.0" encoding="UTF-8"?>
2
+<metadata>
3
+  <groupId>im.bci</groupId>
4
+  <artifactId>libtiled</artifactId>
5
+  <versioning>
6
+    <release>1.0</release>
7
+    <versions>
8
+      <version>1.0</version>
9
+    </versions>
10
+    <lastUpdated>20130219190837</lastUpdated>
11
+  </versioning>
12
+</metadata>
0 13
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+b5ae32bf62cbf520593969632540b217
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1 @@
1
+2731c06bb329c43db031bfb0926c7b8b5b79d509
0 2
\ No newline at end of file
1 3
new file mode 100644
... ...
@@ -0,0 +1,91 @@
1
+/*
2
+ * Copyright (c) 2013 devnewton <devnewton@bci.im>
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are
7
+ * met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright
10
+ *   notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ *   notice, this list of conditions and the following disclaimer in the
14
+ *   documentation and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of 'devnewton <devnewton@bci.im>' nor the names of
17
+ *   its contributors may be used to endorse or promote products derived
18
+ *   from this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+package im.bci.tiledmerge;
33
+
34
+import java.io.File;
35
+import java.io.IOException;
36
+import java.util.Iterator;
37
+import java.util.List;
38
+import org.apache.commons.io.FileUtils;
39
+import org.kohsuke.args4j.Argument;
40
+import org.kohsuke.args4j.CmdLineException;
41
+import org.kohsuke.args4j.CmdLineParser;
42
+import org.kohsuke.args4j.Option;
43
+import tiled.core.TileSet;
44
+
45
+public class App {
46
+
47
+    @Option(name = "-o", usage = "output directory (default to current directory)")
48
+    private File outputDir = new File(".").getAbsoluteFile();
49
+    
50
+    @Option(name = "-t", usage = "merged tileset filename")
51
+    private String mergedTilesetName = "merged.tsx";
52
+    
53
+    @Option(name = "-p", usage = "merged map filename prefix")
54
+    private String mergedMapFilenamePrefix = "merged_";
55
+    
56
+    @Argument(required = true, multiValued = true, usage = "input tmx files or directories containing tmx (default to current directory)")
57
+    private List<File> inputs;
58
+
59
+    public static void main(String[] args) throws IOException {
60
+        App app = new App();
61
+        CmdLineParser parser = new CmdLineParser(app);
62
+        try {
63
+            parser.parseArgument(args);
64
+        } catch (CmdLineException e) {
65
+            System.err.println(e.getMessage());
66
+            System.err.println("tiledmerge [args] input1.tmx input2.tmx /dir/with/tmx/files/ ...");
67
+            parser.printUsage(System.err);
68
+            return;
69
+        }
70
+        app.merge();
71
+    }
72
+
73
+    private void merge() throws IOException {
74
+        TiledMerger merger = new TiledMerger();
75
+        for (File input : inputs) {
76
+            if (input.isFile()) {
77
+                merger.addTmx(input);
78
+            } else if (input.isDirectory()) {
79
+                Iterator it = FileUtils.iterateFiles(input, new String[]{"tmx"}, true);
80
+                while (it.hasNext()) {
81
+                    File file = (File) it.next();
82
+                    if(!file.getName().startsWith(mergedMapFilenamePrefix)) {
83
+                        merger.addTmx(file);   
84
+                    }
85
+                }
86
+            }
87
+        }
88
+        TileSet mergedTileset = merger.saveMergedTileset(outputDir, mergedTilesetName);
89
+        merger.saveMergedMaps(mergedTileset, mergedMapFilenamePrefix);
90
+    }
91
+}
0 92
new file mode 100644
... ...
@@ -0,0 +1,120 @@
1
+/*
2
+ * Copyright (c) 2013 devnewton <devnewton@bci.im>
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are
7
+ * met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright
10
+ *   notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ *   notice, this list of conditions and the following disclaimer in the
14
+ *   documentation and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of 'devnewton <devnewton@bci.im>' nor the names of
17
+ *   its contributors may be used to endorse or promote products derived
18
+ *   from this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+package im.bci.tiledmerge;
33
+
34
+import java.awt.Image;
35
+import java.awt.image.BufferedImage;
36
+import java.awt.image.PixelGrabber;
37
+import java.io.File;
38
+import java.io.IOException;
39
+import java.util.ArrayList;
40
+import java.util.Arrays;
41
+import java.util.List;
42
+import java.util.Properties;
43
+import java.util.logging.Level;
44
+import java.util.logging.Logger;
45
+import javax.imageio.ImageIO;
46
+import tiled.core.Tile;
47
+import tiled.core.TileSet;
48
+
49
+/**
50
+ *
51
+ * @author devnewton
52
+ */
53
+public class MergeableTile {
54
+
55
+    private List<OriginalTilesInfos> originalTiles = new ArrayList<OriginalTilesInfos>();
56
+    private final BufferedImage image;
57
+    private final Properties properties;
58
+    private final int width;
59
+    private final int height;
60
+    private Tile mergedTile;
61
+
62
+    MergeableTile(Tile tile, File file) {
63
+        originalTiles.add(new OriginalTilesInfos(tile, file));
64
+        this.image = tile.getImage();
65
+        this.properties = tile.getProperties();
66
+        this.width = tile.getWidth();
67
+        this.height = tile.getHeight();
68
+    }
69
+
70
+    boolean mergeWith(MergeableTile other) {
71
+        if (canMergeWith(other)) {
72
+            originalTiles.addAll(other.originalTiles);
73
+            return true;
74
+        } else {
75
+            return false;
76
+        }
77
+    }
78
+
79
+    private boolean canMergeWith(MergeableTile other) {
80
+        return properties.equals(other.properties) && width == other.width && height == other.height && areImagesPixelEquals(image, other.image);
81
+    }
82
+
83
+    private boolean areImagesPixelEquals(Image a, Image b) {
84
+        try {
85
+            return Arrays.equals(convertToPixels(a), convertToPixels(b));
86
+        } catch (InterruptedException ex) {
87
+            Logger.getLogger(MergeableTile.class.getName()).log(Level.SEVERE, null, ex);
88
+            return false;
89
+        }
90
+    }
91
+
92
+    public static int[] convertToPixels(Image img) throws InterruptedException {
93
+
94
+        int width = img.getWidth(null);
95
+        int height = img.getHeight(null);
96
+        int[] pixel = new int[width * height];
97
+        PixelGrabber pg = new PixelGrabber(img, 0, 0, width, height, pixel, 0, width);
98
+        pg.grabPixels();
99
+        return pixel;
100
+
101
+    }
102
+
103
+    void createMergedTile(TileSet tileset, String tileImagePrefix) throws IOException {
104
+        mergedTile = new Tile(tileset);
105
+        mergedTile.setProperties(properties);
106
+        mergedTile.setImage(image);
107
+        tileset.addNewTile(mergedTile);
108
+        mergedTile.setTilebmpFile(new File(tileImagePrefix + "_" + mergedTile.getId() + ".png"));
109
+        ImageIO.write((BufferedImage)mergedTile.getImage(), "png", mergedTile.getTilebmpFile());
110
+    }
111
+
112
+    Tile getMerged(Tile originalTile) {
113
+        for(OriginalTilesInfos infos : originalTiles) {
114
+            if(infos.getTile() == originalTile) {
115
+                return mergedTile;
116
+            }
117
+        }
118
+        return null;
119
+    }
120
+}
0 121
new file mode 100644
... ...
@@ -0,0 +1,53 @@
1
+/*
2
+ * Copyright (c) 2013 devnewton <devnewton@bci.im>
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are
7
+ * met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright
10
+ *   notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ *   notice, this list of conditions and the following disclaimer in the
14
+ *   documentation and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of 'devnewton <devnewton@bci.im>' nor the names of
17
+ *   its contributors may be used to endorse or promote products derived
18
+ *   from this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+package im.bci.tiledmerge;
33
+
34
+import java.io.File;
35
+import tiled.core.Tile;
36
+
37
+/**
38
+ *
39
+ * @author bob
40
+ */
41
+public class OriginalTilesInfos {
42
+    private Tile tile;
43
+    private File map;
44
+
45
+    public OriginalTilesInfos(Tile tile, File map) {
46
+        this.tile = tile;
47
+        this.map = map;
48
+    }
49
+
50
+    public Tile getTile() {
51
+        return tile;
52
+    }    
53
+}
0 54
new file mode 100644
... ...
@@ -0,0 +1,181 @@
1
+/*
2
+ * Copyright (c) 2013 devnewton <devnewton@bci.im>
3
+ * All rights reserved.
4
+ *
5
+ * Redistribution and use in source and binary forms, with or without
6
+ * modification, are permitted provided that the following conditions are
7
+ * met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright
10
+ *   notice, this list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright
13
+ *   notice, this list of conditions and the following disclaimer in the
14
+ *   documentation and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of 'devnewton <devnewton@bci.im>' nor the names of
17
+ *   its contributors may be used to endorse or promote products derived
18
+ *   from this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+package im.bci.tiledmerge;
33
+
34
+import java.io.File;
35
+import java.io.FileInputStream;
36
+import java.io.IOException;
37
+import java.util.ArrayList;
38
+import java.util.HashMap;
39
+import java.util.List;
40
+import java.util.Map;
41
+import java.util.Map.Entry;
42
+import java.util.Properties;
43
+import java.util.logging.Level;
44
+import java.util.logging.Logger;
45
+import tiled.core.MapLayer;
46
+import tiled.core.Tile;
47
+import tiled.core.TileLayer;
48
+import tiled.core.TileSet;
49
+import tiled.io.TMXMapReader;
50
+import tiled.io.TMXMapWriter;
51
+
52
+/**
53
+ *
54
+ * @author devnewton
55
+ */
56
+public class TiledMerger {
57
+
58
+    private Map<File, tiled.core.Map> maps = new HashMap<File, tiled.core.Map>();
59
+    private List<MergeableTile> tiles = new ArrayList<MergeableTile>();
60
+
61
+    void addTmx(File file) {
62
+        System.out.println("Merge " + file);
63
+        try {
64
+            TMXMapReader reader = new TMXMapReader();
65
+            FileInputStream is = new FileInputStream(file);
66
+            try {
67
+                tiled.core.Map map = reader.readMap(is);
68
+                maps.put(file, map);
69
+
70
+                for (TileSet tileset : map.getTileSets()) {
71
+                    for (Tile tile : tileset) {
72
+                        MergeableTile mergeable = new MergeableTile(tile, file);
73
+                        mergeOrAddToTile(mergeable);
74
+                    }
75
+                }
76
+            } finally {
77
+                is.close();
78
+            }
79
+        } catch (Exception ex) {
80
+            Logger.getLogger(TiledMerger.class.getName()).log(Level.SEVERE, null, ex);
81
+        }
82
+    }
83
+
84
+    void merge() {
85
+        throw new UnsupportedOperationException("Not yet implemented");
86
+    }
87
+
88
+    private void mergeOrAddToTile(MergeableTile newTile) {
89
+        for (MergeableTile existingTile : tiles) {
90
+            if (existingTile.mergeWith(newTile)) {
91
+                return;
92
+            }
93
+        }
94
+        tiles.add(newTile);
95
+    }
96
+
97
+    TileSet saveMergedTileset(File outputDir, String mergedTilesetName) throws IOException {
98
+        File mergeTilesetFile = new File(outputDir.getCanonicalPath() + File.separator + mergedTilesetName);
99
+        TileSet mergedTileset = buildMergedTileset(mergeTilesetFile.getCanonicalPath().replace(".tsx", ""));
100
+        TMXMapWriter writer = new TMXMapWriter();
101
+        try {
102
+            System.out.println("Write merged tileset " + mergeTilesetFile);
103
+            mergedTileset.setSource(mergeTilesetFile.getCanonicalPath());
104
+            writer.writeTileset(mergedTileset, mergeTilesetFile.getCanonicalPath());
105
+        } catch (Exception ex) {
106
+            Logger.getLogger(TiledMerger.class.getName()).log(Level.SEVERE, null, ex);
107
+        }
108
+        return mergedTileset;
109
+    }
110
+
111
+    private TileSet buildMergedTileset(String tileImagePrefix) throws IOException {
112
+        TileSet tileset = new TileSet();
113
+        for (MergeableTile mergeableTile : tiles) {
114
+            mergeableTile.createMergedTile(tileset, tileImagePrefix);
115
+        }
116
+        return tileset;
117
+    }
118
+
119
+    void saveMergedMaps(TileSet mergedTileset, String mergedMapFilenamePrefix) {
120
+        for (Entry<File, tiled.core.Map> entry : maps.entrySet()) {
121
+            saveMergedMap(entry.getKey(), buildMergedMap(entry.getValue(), mergedTileset), mergedMapFilenamePrefix);
122
+        }
123
+    }
124
+
125
+    private void saveMergedMap(File file, tiled.core.Map map, String prefix) {
126
+        File mergedOuputFile = new File(file.getParent() + File.separator + prefix + file.getName());
127
+        TMXMapWriter writer = new TMXMapWriter();
128
+        try {
129
+            writer.writeMap(map, mergedOuputFile.getCanonicalPath());
130
+        } catch (Exception ex) {
131
+            Logger.getLogger(TiledMerger.class.getName()).log(Level.SEVERE, null, ex);
132
+        }
133
+
134
+    }
135
+
136
+    private tiled.core.Map buildMergedMap(tiled.core.Map originalMap, TileSet mergedTileset) {
137
+        tiled.core.Map mergedMap = new tiled.core.Map(originalMap.getWidth(), originalMap.getHeight());
138
+        mergedMap.setProperties((Properties) originalMap.getProperties().clone());
139
+        mergedMap.setTileWidth(originalMap.getTileWidth());
140
+        mergedMap.setTileHeight(originalMap.getTileHeight());
141
+        mergedMap.addTileset(mergedTileset);
142
+        for (MapLayer layer : originalMap.getLayers()) {
143
+            if (layer instanceof TileLayer) {
144
+                mergedMap.addLayer(buildMergedLayer(mergedMap, originalMap, (TileLayer) layer, mergedTileset));
145
+            } else {
146
+                try {
147
+                    mergedMap.addLayer((MapLayer) layer.clone());
148
+                } catch (CloneNotSupportedException ex) {
149
+                    Logger.getLogger(TiledMerger.class.getName()).log(Level.SEVERE, null, ex);
150
+                }
151
+            }
152
+        }
153
+        return mergedMap;
154
+    }
155
+
156
+    private TileLayer buildMergedLayer(tiled.core.Map mergedMap, tiled.core.Map originalMap, TileLayer originalLayer, TileSet mergedTileset) {
157
+        TileLayer layer = new TileLayer(mergedMap, originalLayer.getWidth(), originalLayer.getHeight());
158
+        layer.setProperties((Properties) originalLayer.getProperties().clone());
159
+        layer.setName(originalLayer.getName());
160
+        for (int y = 0; y < layer.getWidth(); ++y) {
161
+            for (int x = 0; x < layer.getHeight(); ++x) {
162
+                layer.setTileAt(x, y, findMergedTile(originalLayer.getTileAt(x, y)));
163
+            }
164
+        }
165
+        return layer;
166
+    }
167
+
168
+    private Tile findMergedTile(Tile originalTile) {
169
+        if (null == originalTile) {
170
+            return null;
171
+        }
172
+        for (MergeableTile mergableTile : tiles) {
173
+            Tile mergedTile = mergableTile.getMerged(originalTile);
174
+            if (null != mergedTile) {
175
+                return mergedTile;
176
+            }
177
+        }
178
+        System.out.println("Cannot find merged tile for gid=" + originalTile.getGid());
179
+        return null;
180
+    }
181
+}