summary refs log tree commit diff stats
path: root/tools/mapedit/src/world.cpp
diff options
context:
space:
mode:
authorKelly Rauchenberger <fefferburbia@gmail.com>2015-03-16 16:53:05 -0400
committerKelly Rauchenberger <fefferburbia@gmail.com>2015-03-16 16:53:05 -0400
commit0d30e9b57229905f78e7bd60fe5d3cde72851f28 (patch)
tree4ca2abff9fb1933685f570e97a8b9e88a976c95f /tools/mapedit/src/world.cpp
parent36536297aac5c07e3d5fb96abed74570fc7615e9 (diff)
downloadtherapy-0d30e9b57229905f78e7bd60fe5d3cde72851f28.tar.gz
therapy-0d30e9b57229905f78e7bd60fe5d3cde72851f28.tar.bz2
therapy-0d30e9b57229905f78e7bd60fe5d3cde72851f28.zip
Rewrote map editor so a single file contains all maps
Maps are viewed in a tree control on the left. They can be dragged and dropped. Maps are bolded when they are dirty. Saving saves expansion status and order of maps in tree.
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}