Browse code

initial import

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