diff options
Diffstat (limited to 'tools/mapedit/src/map.cpp')
-rw-r--r-- | tools/mapedit/src/map.cpp | 289 |
1 files changed, 113 insertions, 176 deletions
diff --git a/tools/mapedit/src/map.cpp b/tools/mapedit/src/map.cpp index f9c07fc..32541e6 100644 --- a/tools/mapedit/src/map.cpp +++ b/tools/mapedit/src/map.cpp | |||
@@ -1,106 +1,27 @@ | |||
1 | #include "map.h" | 1 | #include "map.h" |
2 | #include <libxml/parser.h> | ||
3 | #include <libxml/xmlwriter.h> | ||
4 | #include <sstream> | ||
5 | #include "frame.h" | 2 | #include "frame.h" |
6 | 3 | ||
7 | Map::Map() | 4 | Map::Map(int id, World* world) : id(id), world(world) |
8 | { | 5 | { |
9 | mapdata = (int*) calloc(MAP_WIDTH * MAP_HEIGHT, sizeof(int)); | 6 | mapdata = (int*) calloc(MAP_WIDTH * MAP_HEIGHT, sizeof(int)); |
10 | } | 7 | } |
11 | 8 | ||
12 | Map::Map(std::string filename) | ||
13 | { | ||
14 | xmlDocPtr doc = xmlParseFile(filename.c_str()); | ||
15 | if (doc == nullptr) | ||
16 | { | ||
17 | throw MapLoadException(filename); | ||
18 | } | ||
19 | |||
20 | xmlNodePtr top = xmlDocGetRootElement(doc); | ||
21 | if (top == nullptr) | ||
22 | { | ||
23 | throw MapLoadException(filename); | ||
24 | } | ||
25 | |||
26 | if (xmlStrcmp(top->name, (const xmlChar*) "map-def")) | ||
27 | { | ||
28 | throw MapLoadException(filename); | ||
29 | } | ||
30 | |||
31 | for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) | ||
32 | { | ||
33 | if (!xmlStrcmp(node->name, (const xmlChar*) "name")) | ||
34 | { | ||
35 | xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); | ||
36 | title = (char*) key; | ||
37 | xmlFree(key); | ||
38 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "environment")) | ||
39 | { | ||
40 | xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); | ||
41 | mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int)); | ||
42 | mapdata[0] = atoi(strtok((char*) key, ",\n")); | ||
43 | for (int i=1; i<(MAP_WIDTH*MAP_HEIGHT); i++) | ||
44 | { | ||
45 | mapdata[i] = atoi(strtok(NULL, ",\n")); | ||
46 | } | ||
47 | xmlFree(key); | ||
48 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "leftmap")) | ||
49 | { | ||
50 | xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); | ||
51 | leftmap = (char*) key; | ||
52 | xmlFree(key); | ||
53 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "rightmap")) | ||
54 | { | ||
55 | xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); | ||
56 | rightmap = (char*) key; | ||
57 | xmlFree(key); | ||
58 | } else if (!xmlStrcmp(node->name, (const xmlChar*) "entities")) | ||
59 | { | ||
60 | for (xmlNodePtr entityNode = node->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next) | ||
61 | { | ||
62 | if (!xmlStrcmp(entityNode->name, (const xmlChar*) "entity")) | ||
63 | { | ||
64 | auto data = std::make_shared<MapObjectEntry>(); | ||
65 | |||
66 | for (xmlNodePtr entityDataNode = entityNode->xmlChildrenNode; entityDataNode != NULL; entityDataNode = entityDataNode->next) | ||
67 | { | ||
68 | if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-type")) | ||
69 | { | ||
70 | xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); | ||
71 | data->object = MapObject::getAllObjects().at((char*) key).get(); | ||
72 | xmlFree(key); | ||
73 | } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position")) | ||
74 | { | ||
75 | xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); | ||
76 | sscanf((char*) key, "%lf,%lf", &data->position.first, &data->position.second); | ||
77 | xmlFree(key); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | objects.push_back(data); | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | |||
87 | xmlFreeDoc(doc); | ||
88 | } | ||
89 | |||
90 | Map::Map(const Map& map) | 9 | Map::Map(const Map& map) |
91 | { | 10 | { |
92 | mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int)); | 11 | mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int)); |
93 | memcpy(mapdata, map.mapdata, MAP_WIDTH*MAP_HEIGHT*sizeof(int)); | 12 | memcpy(mapdata, map.mapdata, MAP_WIDTH*MAP_HEIGHT*sizeof(int)); |
94 | 13 | ||
14 | id = map.id; | ||
95 | title = map.title; | 15 | title = map.title; |
96 | leftmap = map.leftmap; | 16 | leftmap = map.leftmap; |
97 | rightmap = map.rightmap; | 17 | rightmap = map.rightmap; |
98 | dirty = map.dirty; | ||
99 | objects = map.objects; | 18 | objects = map.objects; |
100 | frame = map.frame; | 19 | world = map.world; |
20 | treeItemId = map.treeItemId; | ||
21 | children = map.children; | ||
101 | } | 22 | } |
102 | 23 | ||
103 | Map::Map(Map&& map) : Map() | 24 | Map::Map(Map&& map) : Map(-1, map.world) |
104 | { | 25 | { |
105 | swap(*this, map); | 26 | swap(*this, map); |
106 | } | 27 | } |
@@ -123,141 +44,157 @@ void swap(Map& first, Map& second) | |||
123 | std::swap(first.title, second.title); | 44 | std::swap(first.title, second.title); |
124 | std::swap(first.leftmap, second.leftmap); | 45 | std::swap(first.leftmap, second.leftmap); |
125 | std::swap(first.rightmap, second.rightmap); | 46 | std::swap(first.rightmap, second.rightmap); |
126 | std::swap(first.dirty, second.dirty); | ||
127 | std::swap(first.objects, second.objects); | 47 | std::swap(first.objects, second.objects); |
128 | std::swap(first.frame, second.frame); | 48 | std::swap(first.id, second.id); |
49 | std::swap(first.world, second.world); | ||
50 | std::swap(first.treeItemId, second.treeItemId); | ||
51 | std::swap(first.children, second.children); | ||
129 | } | 52 | } |
130 | 53 | ||
131 | #define MY_ENCODING "ISO-8859-1" | 54 | int Map::getID() const |
55 | { | ||
56 | return id; | ||
57 | } | ||
132 | 58 | ||
133 | void Map::save(std::string name) | 59 | std::string Map::getTitle() const |
134 | { | 60 | { |
135 | if (!dirty) return; | 61 | return title; |
136 | 62 | } | |
137 | int rc; | ||
138 | |||
139 | xmlTextWriterPtr writer = xmlNewTextWriterFilename(name.c_str(), 0); | ||
140 | if (writer == NULL) throw MapWriteException(name); | ||
141 | 63 | ||
142 | rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); | 64 | int Map::getTileAt(int x, int y) const |
143 | if (rc < 0) throw MapWriteException(name); | 65 | { |
144 | 66 | return mapdata[x+y*MAP_WIDTH]; | |
145 | rc = xmlTextWriterStartElement(writer, (xmlChar*) "map-def"); | 67 | } |
146 | if (rc < 0) throw MapWriteException(name); | 68 | |
147 | 69 | const std::list<std::shared_ptr<MapObjectEntry>>& Map::getObjects() const | |
148 | rc = xmlTextWriterWriteElement(writer, (xmlChar*) "name", (xmlChar*) title.c_str()); | 70 | { |
149 | if (rc < 0) throw MapWriteException(name); | 71 | return objects; |
150 | 72 | } | |
151 | std::ostringstream mapdata_out; | 73 | |
152 | for (int y=0; y<MAP_HEIGHT; y++) | 74 | std::shared_ptr<Map> Map::getLeftmap() const |
75 | { | ||
76 | if (leftmap == -1) | ||
153 | { | 77 | { |
154 | for (int x=0; x<MAP_WIDTH; x++) | 78 | return std::shared_ptr<Map>(); |
155 | { | 79 | } else { |
156 | mapdata_out << mapdata[x+y*MAP_WIDTH] << ","; | 80 | return world->getMap(leftmap); |
157 | } | ||
158 | |||
159 | mapdata_out << std::endl; | ||
160 | } | 81 | } |
161 | 82 | } | |
162 | rc = xmlTextWriterWriteElement(writer, (xmlChar*) "environment", (xmlChar*) mapdata_out.str().c_str()); | ||
163 | if (rc < 0) throw MapWriteException(name); | ||
164 | |||
165 | rc = xmlTextWriterWriteElement(writer, (xmlChar*) "leftmap", (xmlChar*) leftmap.c_str()); | ||
166 | if (rc < 0) throw MapWriteException(name); | ||
167 | 83 | ||
168 | rc = xmlTextWriterWriteElement(writer, (xmlChar*) "rightmap", (xmlChar*) rightmap.c_str()); | 84 | std::shared_ptr<Map> Map::getRightmap() const |
169 | if (rc < 0) throw MapWriteException(name); | 85 | { |
170 | 86 | if (rightmap == -1) | |
171 | rc = xmlTextWriterStartElement(writer, (xmlChar*) "entities"); | ||
172 | if (rc < 0) throw MapWriteException(name); | ||
173 | |||
174 | for (auto object : objects) | ||
175 | { | 87 | { |
176 | rc = xmlTextWriterStartElement(writer, (xmlChar*) "entity"); | 88 | return std::shared_ptr<Map>(); |
177 | if (rc < 0) throw MapWriteException(name); | 89 | } else { |
178 | 90 | return world->getMap(rightmap); | |
179 | rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-type", (xmlChar*) object->object->getType().c_str()); | ||
180 | if (rc < 0) throw MapWriteException(name); | ||
181 | |||
182 | std::ostringstream entpos_out; | ||
183 | entpos_out << object->position.first << "," << object->position.second; | ||
184 | |||
185 | rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-position", (xmlChar*) entpos_out.str().c_str()); | ||
186 | if (rc < 0) throw MapWriteException(name); | ||
187 | |||
188 | rc = xmlTextWriterEndElement(writer); | ||
189 | if (rc < 0) throw MapWriteException(name); | ||
190 | } | 91 | } |
191 | |||
192 | rc = xmlTextWriterEndElement(writer); | ||
193 | if (rc < 0) throw MapWriteException(name); | ||
194 | |||
195 | rc = xmlTextWriterEndElement(writer); | ||
196 | if (rc < 0) throw MapWriteException(name); | ||
197 | |||
198 | rc = xmlTextWriterEndDocument(writer); | ||
199 | if (rc < 0) throw MapWriteException(name); | ||
200 | |||
201 | xmlFreeTextWriter(writer); | ||
202 | |||
203 | setDirty(false); | ||
204 | } | 92 | } |
205 | 93 | ||
206 | bool Map::hasUnsavedChanges() const | 94 | wxTreeItemId Map::getTreeItemId() const |
207 | { | 95 | { |
208 | return dirty; | 96 | return treeItemId; |
209 | } | 97 | } |
210 | 98 | ||
211 | void Map::setTileAt(int x, int y, int tile) | 99 | std::list<std::shared_ptr<Map>> Map::getChildren() const |
212 | { | 100 | { |
213 | setDirty(true); | 101 | std::list<std::shared_ptr<Map>> ret; |
214 | mapdata[x+y*MAP_WIDTH] = tile; | 102 | |
103 | for (auto id : children) | ||
104 | { | ||
105 | ret.push_back(world->getMap(id)); | ||
106 | } | ||
107 | |||
108 | return ret; | ||
215 | } | 109 | } |
216 | 110 | ||
217 | int Map::getTileAt(int x, int y) const | 111 | bool Map::getExpanded() const |
218 | { | 112 | { |
219 | return mapdata[x+y*MAP_WIDTH]; | 113 | return expanded; |
220 | } | 114 | } |
221 | 115 | ||
222 | std::string Map::getTitle() const | 116 | void Map::setTitle(std::string title, bool dirty) |
223 | { | 117 | { |
224 | return title; | 118 | this->title = title; |
119 | |||
120 | if (dirty) | ||
121 | { | ||
122 | world->setDirty(true); | ||
123 | } | ||
225 | } | 124 | } |
226 | 125 | ||
227 | void Map::setTitle(std::string title) | 126 | void Map::setTileAt(int x, int y, int tile, bool dirty) |
228 | { | 127 | { |
229 | setDirty(true); | 128 | mapdata[x+y*MAP_WIDTH] = tile; |
230 | this->title = title; | 129 | |
130 | if (dirty) | ||
131 | { | ||
132 | world->setDirty(true); | ||
133 | } | ||
231 | } | 134 | } |
232 | 135 | ||
233 | const std::list<std::shared_ptr<MapObjectEntry>>& Map::getObjects() const | 136 | void Map::setMapdata(int* mapdata, bool dirty) |
234 | { | 137 | { |
235 | return objects; | 138 | free(this->mapdata); |
139 | this->mapdata = mapdata; | ||
140 | |||
141 | if (dirty) | ||
142 | { | ||
143 | world->setDirty(true); | ||
144 | } | ||
236 | } | 145 | } |
237 | 146 | ||
238 | void Map::addObject(std::shared_ptr<MapObjectEntry>& obj) | 147 | void Map::addObject(std::shared_ptr<MapObjectEntry>& obj, bool dirty) |
239 | { | 148 | { |
240 | setDirty(true); | ||
241 | objects.push_back(obj); | 149 | objects.push_back(obj); |
150 | |||
151 | if (dirty) | ||
152 | { | ||
153 | world->setDirty(true); | ||
154 | } | ||
242 | } | 155 | } |
243 | 156 | ||
244 | void Map::removeObject(std::shared_ptr<MapObjectEntry>& obj) | 157 | void Map::removeObject(std::shared_ptr<MapObjectEntry>& obj, bool dirty) |
245 | { | 158 | { |
246 | setDirty(true); | ||
247 | objects.remove(obj); | 159 | objects.remove(obj); |
160 | |||
161 | if (dirty) | ||
162 | { | ||
163 | world->setDirty(true); | ||
164 | } | ||
248 | } | 165 | } |
249 | 166 | ||
250 | bool Map::getDirty() const | 167 | void Map::setLeftmap(int id, bool dirty) |
251 | { | 168 | { |
252 | return dirty; | 169 | leftmap = id; |
170 | |||
171 | if (dirty) | ||
172 | { | ||
173 | world->setDirty(true); | ||
174 | } | ||
253 | } | 175 | } |
254 | 176 | ||
255 | void Map::setDirty(bool dirty) | 177 | void Map::setRightmap(int id, bool dirty) |
256 | { | 178 | { |
257 | this->dirty = dirty; | 179 | rightmap = id; |
258 | 180 | ||
259 | if (frame != nullptr) | 181 | if (dirty) |
260 | { | 182 | { |
261 | frame->MapDirtyDidChange(dirty); | 183 | world->setDirty(true); |
262 | } | 184 | } |
263 | } | 185 | } |
186 | |||
187 | void Map::setTreeItemId(wxTreeItemId id) | ||
188 | { | ||
189 | this->treeItemId = id; | ||
190 | } | ||
191 | |||
192 | void Map::addChild(int id) | ||
193 | { | ||
194 | children.push_back(id); | ||
195 | } | ||
196 | |||
197 | void Map::setExpanded(bool exp) | ||
198 | { | ||
199 | expanded = exp; | ||
200 | } | ||