map<uint, terrainFactory> setFactories(Poco::XML::Node* node) { using namespace Poco; map<uint, terrainFactory> factories; XML::NodeIterator childIterator(node, XML::NodeFilter::SHOW_ELEMENT); XML::Node* tileNode = childIterator.nextNode(); while (tileNode) { if (tileNode->nodeName() == "tile") { ScopedNamedNodeMap tileAttributes(tileNode->attributes()); stringstream id(tileAttributes->getNamedItem("id")->getNodeValue()); uint tileId = 0; id >>tileId; auto propertiesNode = tileNode->firstChild()->nextSibling(); auto propertyNode = propertiesNode->firstChild()->nextSibling(); if (propertyNode->hasAttributes()) { ScopedNamedNodeMap attributes(propertyNode->attributes()); setFactory(factories, tileId, attributes->getNamedItem("value")->nodeValue()); } else { throw FileFormatException("TMX file malformed: tile>>properties should have a child, but does not."); } } tileNode = childIterator.nextNode(); }
GameMap::UniquePtr TiledMapParser::parse() { using namespace Poco; loadMapImages(fileInfo); ifstream in(Constants::MapPath + fileInfo.getTmxFileName()); if (!in.good()) { throw FileLoadException("Unable to load the Tiled tmx file: " + Constants::MapPath + fileInfo.getTmxFileName()); } XML::InputSource src(in); XML::DOMParser parser; AutoPtr<XML::Document> doc = parser.parse(&src); MapProperties properties; std::map<uint, terrainFactory> terrainFactories; GameMap::NavGraphList navGraph; XML::NodeIterator iterator(doc, XML::NodeFilter::SHOW_ELEMENT); XML::Node* node = iterator.nextNode(); while (node) { if (node->nodeName() == "map") { if (!node->hasAttributes()) throw FileFormatException("The Tiled map file is formatted incorrectly: there are no map attributes."); // Load the properties. properties = processMapProperties(node); ScopedNodeList childNodes = node->childNodes(); for (int i = 0; i < childNodes->length(); ++i) { auto childNode = childNodes->item(i); if (childNode->nodeName() == "tileset") { terrainFactories = setFactories(childNode); } else if (childNode->nodeName() == "layer") { processTerrain(navGraph, terrainFactories, childNode, properties); } } } else { // Postconditions: Assert<FileFormatException>(properties.rows != 0, "Properties not loaded from Tiled map file."); Assert<FileFormatException>(!navGraph.empty(), "NavGraph not loaded from Tiled map file."); // Everything has been processed, so no need to continue iteration. break; } node = iterator.nextNode(); } GameMap::UniquePtr gameMap = make_unique<GameMap>(properties.rows, properties.columns, properties.tileHeight, properties.tileWidth, move(navGraph)); return move(gameMap); }