From 0d30e9b57229905f78e7bd60fe5d3cde72851f28 Mon Sep 17 00:00:00 2001 From: Kelly Rauchenberger Date: Mon, 16 Mar 2015 16:53:05 -0400 Subject: 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. --- tools/mapedit/src/world.cpp | 369 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 369 insertions(+) create mode 100644 tools/mapedit/src/world.cpp (limited to 'tools/mapedit/src/world.cpp') 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 @@ +#include "world.h" +#include +#include +#include "frame.h" +#include + +World::World() +{ + newMap(); + + rootChildren.push_back(0); +} + +World::World(std::string filename) +{ + this->filename = filename; + + xmlDocPtr doc = xmlParseFile(filename.c_str()); + if (doc == nullptr) + { + throw MapLoadException(filename); + } + + xmlNodePtr top = xmlDocGetRootElement(doc); + if (top == nullptr) + { + throw MapLoadException(filename); + } + + if (xmlStrcmp(top->name, (const xmlChar*) "world")) + { + throw MapLoadException(filename); + } + + for (xmlNodePtr node = top->xmlChildrenNode; node != NULL; node = node->next) + { + if (!xmlStrcmp(node->name, (const xmlChar*) "nextmapid")) + { + xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (key != 0) + { + nextMapID = atoi((char*) key); + } + xmlFree(key); + } else if (!xmlStrcmp(node->name, (const xmlChar*) "lastmap")) + { + xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (key != 0) + { + lastmap = atoi((char*) key); + } + xmlFree(key); + } else if (!xmlStrcmp(node->name, (const xmlChar*) "root")) + { + xmlChar* key = xmlNodeListGetString(doc, node->xmlChildrenNode, 1); + if (key != 0) + { + rootChildren.push_back(atoi((char*) key)); + } + xmlFree(key); + } else if (!xmlStrcmp(node->name, (const xmlChar*) "map")) + { + xmlChar* idKey = xmlGetProp(node, (xmlChar*) "id"); + if (idKey == 0) throw MapLoadException(filename); + int id = atoi((char*) idKey); + xmlFree(idKey); + + auto map = std::make_shared(id, this); + + for (xmlNodePtr mapNode = node->xmlChildrenNode; mapNode != NULL; mapNode = mapNode->next) + { + if (!xmlStrcmp(mapNode->name, (const xmlChar*) "name")) + { + xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); + if (key != 0) + { + map->setTitle((char*) key, false); + } + + xmlFree(key); + } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "environment")) + { + xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); + int* mapdata = (int*) malloc(MAP_WIDTH*MAP_HEIGHT*sizeof(int)); + mapdata[0] = atoi(strtok((char*) key, ",\n")); + for (int i=1; i<(MAP_WIDTH*MAP_HEIGHT); i++) + { + mapdata[i] = atoi(strtok(NULL, ",\n")); + } + map->setMapdata(mapdata, false); + xmlFree(key); + } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "leftmap")) + { + xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); + if (key != 0) + { + map->setLeftmap(atoi((char*) key), false); + } + xmlFree(key); + } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "rightmap")) + { + xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); + if (key != 0) + { + map->setRightmap(atoi((char*) key)); + } + xmlFree(key); + } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "entities")) + { + for (xmlNodePtr entityNode = mapNode->xmlChildrenNode; entityNode != NULL; entityNode = entityNode->next) + { + if (!xmlStrcmp(entityNode->name, (const xmlChar*) "entity")) + { + auto data = std::make_shared(); + + for (xmlNodePtr entityDataNode = entityNode->xmlChildrenNode; entityDataNode != NULL; entityDataNode = entityDataNode->next) + { + if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-type")) + { + xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); + data->object = MapObject::getAllObjects().at((char*) key).get(); + xmlFree(key); + } else if (!xmlStrcmp(entityDataNode->name, (const xmlChar*) "entity-position")) + { + xmlChar* key = xmlNodeListGetString(doc, entityDataNode->xmlChildrenNode, 1); + sscanf((char*) key, "%lf,%lf", &data->position.first, &data->position.second); + xmlFree(key); + } + } + + map->addObject(data, false); + } + } + } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "child")) + { + xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); + if (key != 0) + { + map->addChild(atoi((char*) key)); + } + xmlFree(key); + } else if (!xmlStrcmp(mapNode->name, (const xmlChar*) "expanded")) + { + xmlChar* key = xmlNodeListGetString(doc, mapNode->xmlChildrenNode, 1); + if ((key != 0) && ((char) key[0] == '1')) + { + map->setExpanded(true); + } + } + } + + maps[map->getID()] = map; + } + } + + xmlFreeDoc(doc); +} + +std::shared_ptr World::newMap() +{ + auto nm = std::make_shared(nextMapID++, this); + maps[nm->getID()] = nm; + return nm; +} + +std::shared_ptr World::getMap(int id) const +{ + return maps.at(id); +} + +void World::setDirty(bool dirty) +{ + this->dirty = dirty; + parent->MapDirtyDidChange(dirty); +} + +bool World::getDirty() const +{ + return dirty; +} + +std::string World::getFilename() const +{ + return filename; +} + +void World::setParent(MapeditFrame* parent) +{ + this->parent = parent; +} + +Map* World::getLastMap() const +{ + return getMap(lastmap).get(); +} + +#define MY_ENCODING "ISO-8859-1" + +void World::save(std::string name, wxTreeCtrl* mapTree) +{ + int rc; + + xmlTextWriterPtr writer = xmlNewTextWriterFilename(name.c_str(), 0); + if (writer == NULL) throw MapWriteException(name); + + rc = xmlTextWriterStartDocument(writer, NULL, MY_ENCODING, NULL); + if (rc < 0) throw MapWriteException(name); + + // + rc = xmlTextWriterStartElement(writer, (xmlChar*) "world"); + if (rc < 0) throw MapWriteException(name); + + // + std::ostringstream nextMap_out; + nextMap_out << nextMapID; + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "nextmapid", (xmlChar*) nextMap_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + + // + std::ostringstream lastMap_out; + lastMap_out << lastmap; + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "lastmap", (xmlChar*) lastMap_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + + // ASSUMPTION: There will always be at least one child of the invisible root element. i.e. you cannot delete to zero maps. + wxTreeItemId root = mapTree->GetRootItem(); + wxTreeItemIdValue cookie1; + for (wxTreeItemId it = mapTree->GetFirstChild(root, cookie1); it.IsOk(); it = mapTree->GetNextChild(root, cookie1)) + { + // + MapPtrCtr* ctl = (MapPtrCtr*) mapTree->GetItemData(it); + std::ostringstream rootid_out; + rootid_out << ctl->map->getID(); + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "root", (xmlChar*) rootid_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + } + + for (auto mapPair : maps) + { + Map& map = *mapPair.second; + + // + rc = xmlTextWriterStartElement(writer, (xmlChar*) "map"); + if (rc < 0) throw MapWriteException(name); + + // id= + std::ostringstream id_out; + id_out << map.getID(); + rc = xmlTextWriterWriteAttribute(writer, (xmlChar*) "id", (xmlChar*) id_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + + // + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "name", (xmlChar*) map.getTitle().c_str()); + if (rc < 0) throw MapWriteException(name); + + // + std::ostringstream mapdata_out; + for (int y=0; y + std::ostringstream leftmap_out; + if (map.getLeftmap()) + { + leftmap_out << map.getLeftmap()->getID(); + } + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "leftmap", (xmlChar*) leftmap_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + + // + std::ostringstream rightmap_out; + if (map.getRightmap()) + { + rightmap_out << map.getRightmap()->getID(); + } + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "rightmap", (xmlChar*) rightmap_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + + // + rc = xmlTextWriterStartElement(writer, (xmlChar*) "entities"); + if (rc < 0) throw MapWriteException(name); + + for (auto object : map.getObjects()) + { + // + rc = xmlTextWriterStartElement(writer, (xmlChar*) "entity"); + if (rc < 0) throw MapWriteException(name); + + // + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-type", (xmlChar*) object->object->getType().c_str()); + if (rc < 0) throw MapWriteException(name); + + // + std::ostringstream entpos_out; + entpos_out << object->position.first << "," << object->position.second; + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "entity-position", (xmlChar*) entpos_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + + // + rc = xmlTextWriterEndElement(writer); + if (rc < 0) throw MapWriteException(name); + } + + // + rc = xmlTextWriterEndElement(writer); + if (rc < 0) throw MapWriteException(name); + + wxTreeItemId node = map.getTreeItemId(); + if (mapTree->ItemHasChildren(node)) + { + wxTreeItemIdValue cookie2; + for (wxTreeItemId it = mapTree->GetFirstChild(node, cookie2); it.IsOk(); it = mapTree->GetNextChild(node, cookie2)) + { + // + MapPtrCtr* ctl = (MapPtrCtr*) mapTree->GetItemData(it); + std::ostringstream childid_out; + childid_out << ctl->map->getID(); + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "child", (xmlChar*) childid_out.str().c_str()); + if (rc < 0) throw MapWriteException(name); + } + + if (mapTree->IsExpanded(node)) + { + // + rc = xmlTextWriterWriteElement(writer, (xmlChar*) "expanded", (xmlChar*) "1"); + if (rc < 0) throw MapWriteException(name); + } + } + + // + rc = xmlTextWriterEndElement(writer); + if (rc < 0) throw MapWriteException(name); + } + + // + rc = xmlTextWriterEndDocument(writer); + if (rc < 0) throw MapWriteException(name); + + xmlFreeTextWriter(writer); + + setDirty(false); +} + +std::list> World::getRootMaps() const +{ + std::list> ret; + + for (auto id : rootChildren) + { + ret.push_back(getMap(id)); + } + + return ret; +} + +const std::map> World::getMaps() const +{ + return maps; +} -- cgit 1.4.1