summaryrefslogtreecommitdiff
path: root/tools/tmxcopy/map.hpp
blob: 3be932abb28b17342a2cf72f5872bedbc8621f3b (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
/*
 *  TMXCopy
 *  Copyright (C) 2007  Philipp Sehmisch
 *  Copyright (C) 2009  Steve Cotton
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <string>
#include <vector>
#include <set>
#include <map>
#include <libxml/parser.h>

struct ConfigurationOptions
{
    /* When copying map layers, how to match source layer to
     * destination layer.
     *
     * True: Pair the first layer to the first layer, the second
     * to the second, etc.
     *
     * False: Pair up layers with matching names.
     */
    bool copyLayersByOrdinal;

    /* Create extra layers in the target as necessary. */
    bool createMissingLayers;
};

struct Tileset
{
    std::string imagefile;
    int firstgid;
    std::string name;
    int tilewidth;
    int tileheight;

    bool operator== (Tileset const& a)
    {
        return (imagefile == a.imagefile &&
                tilewidth == a.tilewidth &&
                tileheight == a.tileheight
                );
    }

    Tileset()
    {
    }

    Tileset(const Tileset& src) :
        imagefile(src.imagefile), firstgid(src.firstgid),
        name(src.name),
        tilewidth(src.tilewidth), tileheight(src.tileheight)
    {
    }

};

/**
 * A tile in a layer of a map.
 *
 * With the exception of the emptyTile and empty() function,
 * interpreting what this tile represents depends on the map it
 * belongs to (specifically the ordering of that map's tilesets).
 */
struct Tile
{
    int tileset; // number of tileset
    size_t index; // index in said tileset

    bool empty()
    {
        return (tileset == -1);
    }

    /* This is to allow std::map<Tile,Tile> */
    bool operator< (const Tile& b) const
    {
        return ((tileset < b.tileset) ||
            ((tileset == b.tileset) && (index < b.index)));
    }

    bool operator!= (const Tile& b) const
    {
        return ((tileset != b.tileset) || (index != b.index));
    }
};

typedef std::vector<Tile> LayerTiles;

/* This represents an empty tile in the layer.
 * Note that {0,0} would be the first tile in the first tileset.
 */
const Tile emptyTile = {-1, 0};

class Layer
{
    public:
        /* name - the name of the layer, as shown in Tiled
         * tileCount - total number of tiles (width*height)
         */
        Layer(std::string name, LayerTiles::size_type tileCount)
            : mTiles(tileCount, emptyTile),
            mName (name)
        {
        }

        std::string getName() { return mName; }
        Tile& at(LayerTiles::size_type c) { return mTiles.at(c); }
        Tile& getTile(int x, int y, int mapWidth) { return mTiles.at(x + y*mapWidth); }

    private:
        LayerTiles mTiles;
        std::string mName;
};

class Map
{
    public:
        Map(std::string filename);
        ~Map();

        /**
         * Copies an area from srcMap, replacing its current contents.
         */
        bool overwrite(Map* srcMap,
                    int srcX, int srcY, int srcWidth, int srcHeight,
                    int destX, int destY,
                    const ConfigurationOptions& config);

        /**
         * Fills an area of this map with random parts of the template.
         * Currently, each layer of the template is treated as an object that
         * should be copied in its entirity.
         */
        bool randomFill(Map* templateMap, const std::string& destLayerName,
                    int destX, int destY, int destWidth, int destHeight,
                    const ConfigurationOptions& config);

        /**
         * Translates a layer - using the template, generates collision from visible layers (for example).
         * TODO - avoid confusion with the geometry term "translate"
         */
        bool translateAllLayers(Map* templateMap, const std::string& destLayerName,
                    const ConfigurationOptions& config);

        int save(std::string filename);

        int getNumberOfLayers() { return mLayers.size(); }

        Layer* getLayer(size_t num) { return mLayers.at(num); }
        Layer* getLayer(std::string name);

        std::vector<Tileset*>* getTilesets() { return &mTilesets; }

        int getWidth() { return mWidth; }
        int getHeight() { return mHeight; }

    private:
        std::map<int, int> addAndTranslateTilesets(const Map* srcMap);

        std::vector<Layer*> mLayers;

        int mWidth;
        int mHeight;
        int mMaxGid;

        std::vector<Tileset*> mTilesets;

        xmlDocPtr mXmlDoc;
};