summary refs log tree commit diff stats
path: root/tools/mapedit/src/world.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tools/mapedit/src/world.cpp')
-rw-r--r--tools/mapedit/src/world.cpp369
1 files changed, 369 insertions, 0 deletions
diff --git a/tools/mapedit/src/world.cpp b/tools/mapedit/src/world.cpp new file mode 100644 index 0000000..4c42593 --- /dev/null +++ b/tools/mapedit/src/world.cpp
@@ -0,0 +1,369 @@
1#include "world.h"
2#include <libxml/parser.h>
3#include <libxml/xmlwriter.h>
4#include "frame.h"
5#include <sstream>
6
7World::World()
8{
9 newMap();
10
11 rootChildren.push_back(0);
12}
13
14World::World(std::string filename)
15{
16 this->filename = filename;
17
18 xmlDocPtr doc = xmlParseFile(filename.c_str());
19 if (doc == nullptr)
20 {
21 throw MapLoadException(filename);
22 }
23
24 xmlNodePtr top = xmlDocGetRootElement(doc);
25 if (top == nullptr)
26 {
27 throw MapLoadException(filename);
28 }
29
30 if (xmlStrcmp(top->name, (const xmlChar*) "world"))
31 {
32 throw MapLoadException(filename);
33 }
34
35 for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next)
36 {
37 if (!xmlStrcmp(node->name, (const xmlChar*) "nextmapid"))
38 {
39 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
40 if (key != 0)
41 {
42 nextMapID = atoi((char*) key);
43 }
44 xmlFree(key);
45 } else if (!xmlStrcmp(node->name, (const xmlChar*) "lastmap"))
46 {
47 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
48 if (key != 0)
49 {
50 lastmap = atoi((char*) key);
51 }
52 xmlFree(key);
53 } else if (!xmlStrcmp(node->name, (const xmlChar*) "root"))
54 {
55 xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1);
56 if (key != 0)
57 {
58 rootChildren.push_back(atoi((char*) key));
59 }
60 xmlFree(key);
61 } else if (!xmlStrcmp(node->name, (const xmlChar*) "map"))
62 {
63 xmlChar* idKey = xmlGetProp(node, (xmlChar*) "id");
64 if (idKey == 0) throw MapLoadException(filename);
65 int id = atoi((char*) idKey);
66 xmlFree(idKey);
67
68 auto map = std::make_shared<Map>(id, this);
69
70 for (xmlNodePtr mapNode = node->xmlChildrenNode; mapNode != NULL; mapNode = mapNode->next)
71 {
72 if (!xmlStrcmp(mapNode->name, (const xmlChar*) "name"))
73 {
74 xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1);
75 if (key != 0)
76 {
77 map->setTitle((char*) key, false);
78 }
79
80 xmlFree(key);
81 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "environment"))
82 {
83 xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1);
84 int* mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int));
85 mapdata[0] = atoi(strtok((char*) key, ",\n"));
86 for (int i=1; i<(MAP_WIDTH*MAP_HEIGHT); i++)
87 {
88 mapdata[i] = atoi(strtok(NULL, ",\n"));
89 }
90 map->setMapdata(mapdata, false);
91 xmlFree(key);
92 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "leftmap"))
93 {
94 xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1);
95 if (key != 0)
96 {
97 map->setLeftmap(atoi((char*) key), false);
98 }
99 xmlFree(key);
100 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "rightmap"))
101 {
102 xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1);
103 if (key != 0)
104 {
105 map->setRightmap(atoi((char*) key));
106 }
107 xmlFree(key);
108 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "entities"))
109 {
110 for (xmlNodePtr entityNode = mapNode->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next)
111 {
112 if (!xmlStrcmp(entityNode->name, (const xmlChar*) "entity"))
113 {
114 auto data = std::make_shared<MapObjectEntry>();
115
116 for (xmlNodePtr entityDataNode = entityNode->xmlChildrenNode; entityDataNode != NULL; entityDataNode = entityDataNode->next)
117 {
118 if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-type"))
119 {
120 xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1);
121 data->object = MapObject::getAllObjects().at((char*) key).get();
122 xmlFree(key);
123 } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position"))
124 {
125 xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1);
126 sscanf((char*) key, "%lf,%lf", &data->position.first, &data->position.second);
127 xmlFree(key);
128 }
129 }
130
131 map->addObject(data, false);
132 }
133 }
134 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "child"))
135 {
136 xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1);
137 if (key != 0)
138 {
139 map->addChild(atoi((char*) key));
140 }
141 xmlFree(key);
142 } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "expanded"))
143 {
144 xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1);
145 if ((key != 0) && ((char) key[0] == '1'))
146 {
147 map->setExpanded(true);
148 }
149 }
150 }
151
152 maps[map->getID()] = map;
153 }
154 }
155
156 xmlFreeDoc(doc);
157}
158
159std::shared_ptr<Map> World::newMap()
160{
161 auto nm = std::make_shared<Map>(nextMapID++, this);
162 maps[nm->getID()] = nm;
163 return nm;
164}
165
166std::shared_ptr<Map> World::getMap(int id) const
167{
168 return maps.at(id);
169}
170
171void World::setDirty(bool dirty)
172{
173 this->dirty = dirty;
174 parent->MapDirtyDidChange(dirty);
175}
176
177bool World::getDirty() const
178{
179 return dirty;
180}
181
182std::string World::getFilename() const
183{
184 return filename;
185}
186
187void World::setParent(MapeditFrame* parent)
188{
189 this->parent = parent;
190}
191
192Map* World::getLastMap() const
193{
194 return getMap(lastmap).get();
195}
196
197#define MY_ENCODING "ISO-8859-1"
198
199void World::save(std::string name, wxTreeCtrl* mapTree)
200{
201 int rc;
202
203 xmlTextWriterPtr writer = xmlNewTextWriterFilename(name.c_str(), 0);
204 if (writer == NULL) throw MapWriteException(name);
205
206 rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL);
207 if (rc < 0) throw MapWriteException(name);
208
209 // <world>
210 rc = xmlTextWriterStartElement(writer, (xmlChar*) "world");
211 if (rc < 0) throw MapWriteException(name);
212
213 // <nextmapid/>
214 std::ostringstream nextMap_out;
215 nextMap_out << nextMapID;
216 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "nextmapid", (xmlChar*) nextMap_out.str().c_str());
217 if (rc < 0) throw MapWriteException(name);
218
219 // <lastmap/>
220 std::ostringstream lastMap_out;
221 lastMap_out << lastmap;
222 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "lastmap", (xmlChar*) lastMap_out.str().c_str());
223 if (rc < 0) throw MapWriteException(name);
224
225 // ASSUMPTION: There will always be at least one child of the invisible root element. i.e. you cannot delete to zero maps.
226 wxTreeItemId root = mapTree->GetRootItem();
227 wxTreeItemIdValue cookie1;
228 for (wxTreeItemId it = mapTree->GetFirstChild(root, cookie1); it.IsOk(); it = mapTree->GetNextChild(root, cookie1))
229 {
230 // <root>
231 MapPtrCtr* ctl = (MapPtrCtr*) mapTree->GetItemData(it);
232 std::ostringstream rootid_out;
233 rootid_out << ctl->map->getID();
234 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "root", (xmlChar*) rootid_out.str().c_str());
235 if (rc < 0) throw MapWriteException(name);
236 }
237
238 for (auto mapPair : maps)
239 {
240 Map& map = *mapPair.second;
241
242 // <map>
243 rc = xmlTextWriterStartElement(writer, (xmlChar*) "map");
244 if (rc < 0) throw MapWriteException(name);
245
246 // id=
247 std::ostringstream id_out;
248 id_out << map.getID();
249 rc = xmlTextWriterWriteAttribute(writer, (xmlChar*) "id", (xmlChar*) id_out.str().c_str());
250 if (rc < 0) throw MapWriteException(name);
251
252 // <name/>
253 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "name", (xmlChar*) map.getTitle().c_str());
254 if (rc < 0) throw MapWriteException(name);
255
256 // <environment/>
257 std::ostringstream mapdata_out;
258 for (int y=0; y<MAP_HEIGHT; y++)
259 {
260 for (int x=0; x<MAP_WIDTH; x++)
261 {
262 mapdata_out << map.getTileAt(x,y) << ",";
263 }
264
265 mapdata_out << std::endl;
266 }
267
268 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "environment", (xmlChar*) mapdata_out.str().c_str());
269 if (rc < 0) throw MapWriteException(name);
270
271 // <leftmap/>
272 std::ostringstream leftmap_out;
273 if (map.getLeftmap())
274 {
275 leftmap_out << map.getLeftmap()->getID();
276 }
277 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "leftmap", (xmlChar*) leftmap_out.str().c_str());
278 if (rc < 0) throw MapWriteException(name);
279
280 // <rightmap/>
281 std::ostringstream rightmap_out;
282 if (map.getRightmap())
283 {
284 rightmap_out << map.getRightmap()->getID();
285 }
286 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "rightmap", (xmlChar*) rightmap_out.str().c_str());
287 if (rc < 0) throw MapWriteException(name);
288
289 // <entities>
290 rc = xmlTextWriterStartElement(writer, (xmlChar*) "entities");
291 if (rc < 0) throw MapWriteException(name);
292
293 for (auto object : map.getObjects())
294 {
295 // <entity>
296 rc = xmlTextWriterStartElement(writer, (xmlChar*) "entity");
297 if (rc < 0) throw MapWriteException(name);
298
299 // <entity-type/>
300 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-type", (xmlChar*) object->object->getType().c_str());
301 if (rc < 0) throw MapWriteException(name);
302
303 // <entity-position/>
304 std::ostringstream entpos_out;
305 entpos_out << object->position.first << "," << object->position.second;
306 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-position", (xmlChar*) entpos_out.str().c_str());
307 if (rc < 0) throw MapWriteException(name);
308
309 // </entity>
310 rc = xmlTextWriterEndElement(writer);
311 if (rc < 0) throw MapWriteException(name);
312 }
313
314 // </entities>
315 rc = xmlTextWriterEndElement(writer);
316 if (rc < 0) throw MapWriteException(name);
317
318 wxTreeItemId node = map.getTreeItemId();
319 if (mapTree->ItemHasChildren(node))
320 {
321 wxTreeItemIdValue cookie2;
322 for (wxTreeItemId it = mapTree->GetFirstChild(node, cookie2); it.IsOk(); it = mapTree->GetNextChild(node, cookie2))
323 {
324 // <child/>
325 MapPtrCtr* ctl = (MapPtrCtr*) mapTree->GetItemData(it);
326 std::ostringstream childid_out;
327 childid_out << ctl->map->getID();
328 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "child", (xmlChar*) childid_out.str().c_str());
329 if (rc < 0) throw MapWriteException(name);
330 }
331
332 if (mapTree->IsExpanded(node))
333 {
334 // <expanded/>
335 rc = xmlTextWriterWriteElement(writer, (xmlChar*) "expanded", (xmlChar*) "1");
336 if (rc < 0) throw MapWriteException(name);
337 }
338 }
339
340 // </map>
341 rc = xmlTextWriterEndElement(writer);
342 if (rc < 0) throw MapWriteException(name);
343 }
344
345 // </world>
346 rc = xmlTextWriterEndDocument(writer);
347 if (rc < 0) throw MapWriteException(name);
348
349 xmlFreeTextWriter(writer);
350
351 setDirty(false);
352}
353
354std::list<std::shared_ptr<Map>> World::getRootMaps() const
355{
356 std::list<std::shared_ptr<Map>> ret;
357
358 for (auto id : rootChildren)
359 {
360 ret.push_back(getMap(id));
361 }
362
363 return ret;
364}
365
366const std::map<int, std::shared_ptr<Map>> World::getMaps() const
367{
368 return maps;
369}