2 Copyright (C) 2001-2006, William Joseph.
5 This file is part of GtkRadiant.
7 GtkRadiant is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 GtkRadiant is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GtkRadiant; if not, write to the Free Software
19 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 // parses xml tree format into internal objects
34 #include "eclasslib.h"
36 #include "xml/xmlparser.h"
38 #include "generic/reference.h"
39 #include "generic/object.h"
42 #define PARSE_ERROR "XML PARSE ERROR"
45 inline XMLImporter* Node_getXMLImporter(scene::Node& node)
47 return NodeTypeCast<XMLImporter>::cast(node);
51 scene::Node& createPrimitive(const char* name)
53 if(string_equal(name, "brush"))
55 return GlobalBrushCreator().createBrush();
57 else if(string_equal(name, "patch"))
59 return GlobalPatchCreator().createPatch();
62 ASSERT_MESSAGE(0, PARSE_ERROR << ": primitive type not supported: \"" << name << "\"\n");
63 scene::Node* node = 0;
67 class TreeXMLImporter : public XMLImporter
70 virtual TreeXMLImporter& child() = 0;
73 class SubPrimitiveImporter : public TreeXMLImporter
75 XMLImporter* m_importer;
77 SubPrimitiveImporter(XMLImporter* importer) : m_importer(importer)
80 void pushElement(const XMLElement& element)
82 m_importer->pushElement(element);
84 void popElement(const char* name)
86 m_importer->popElement(name);
88 std::size_t write(const char* buffer, std::size_t length)
90 return m_importer->write(buffer, length);
92 SubPrimitiveImporter& child()
98 class PrimitiveImporter : public TreeXMLImporter
100 scene::Node& m_parent;
101 XMLImporter* m_importer;
102 char m_child[sizeof(SubPrimitiveImporter)];
104 SubPrimitiveImporter& subprimitive()
106 return *reinterpret_cast<SubPrimitiveImporter*>(m_child);
109 PrimitiveImporter(scene::Node& parent) : m_parent(parent), m_importer(0)
112 void pushElement(const XMLElement& element)
114 if(string_equal(element.name(), "epair"))
116 ASSERT_MESSAGE(string_equal(element.name(), "epair"), PARSE_ERROR);
117 Node_getEntity(m_parent)->setKeyValue(element.attribute("key"), element.attribute("value"));
121 NodeSmartReference node(createPrimitive(element.name()));
123 m_importer = Node_getXMLImporter(node);
125 constructor(subprimitive(), m_importer);
127 m_importer->pushElement(element);
129 Node_getTraversable(m_parent)->insert(node);
132 void popElement(const char* name)
134 if(string_equal(name, "epair"))
139 m_importer->popElement(name);
141 destructor(subprimitive());
145 std::size_t write(const char* buffer, std::size_t length)
147 return m_importer->write(buffer, length);
149 TreeXMLImporter& child()
151 return subprimitive();
155 class EntityImporter : public TreeXMLImporter
157 scene::Node& m_parent;
158 char m_node[sizeof(NodeSmartReference)];
159 char m_child[sizeof(PrimitiveImporter)];
160 EntityCreator& m_entityTable;
162 NodeSmartReference& node()
164 return *reinterpret_cast<NodeSmartReference*>(m_node);
166 PrimitiveImporter& primitive()
168 return *reinterpret_cast<PrimitiveImporter*>(m_child);
172 EntityImporter(scene::Node& parent, EntityCreator& entityTable) : m_parent(parent), m_entityTable(entityTable)
175 void pushElement(const XMLElement& element)
177 ASSERT_MESSAGE(string_equal(element.name(), "entity"), PARSE_ERROR);
178 constructor(node(), NodeSmartReference(m_entityTable.createEntity(GlobalEntityClassManager().findOrInsert("", true))));
179 constructor(primitive(), makeReference(node().get()));
181 void popElement(const char* name)
183 ASSERT_MESSAGE(string_equal(name, "entity"), PARSE_ERROR);
184 NodeSmartReference entity(m_entityTable.createEntity(GlobalEntityClassManager().findOrInsert(Node_getEntity(node())->getKeyValue("classname"), node_is_group(node()))));
187 EntityCopyingVisitor visitor(*Node_getEntity(entity));
188 Node_getEntity(node())->forEachKeyValue(visitor);
191 if(Node_getTraversable(entity) != 0 && !Node_getEntity(entity)->getEntityClass().fixedsize)
193 parentBrushes(node(), entity);
196 Node_getTraversable(m_parent)->insert(entity);
198 destructor(primitive());
201 std::size_t write(const char* buffer, std::size_t length)
205 TreeXMLImporter& child()
211 class MapDoom3Importer : public TreeXMLImporter
214 char m_child[sizeof(EntityImporter)];
215 EntityCreator& m_entityTable;
217 EntityImporter& getEntity()
219 return *reinterpret_cast<EntityImporter*>(m_child);
222 MapDoom3Importer(scene::Node& root, EntityCreator& entityTable) : m_root(root), m_entityTable(entityTable)
225 void pushElement(const XMLElement& element)
227 ASSERT_MESSAGE(string_equal(element.name(), "mapdoom3"), PARSE_ERROR);
228 constructor(getEntity(), makeReference(m_root), makeReference(m_entityTable));
230 void popElement(const char* name)
232 ASSERT_MESSAGE(string_equal(name, "mapdoom3"), PARSE_ERROR);
233 destructor(getEntity());
235 std::size_t write(const char* data, std::size_t length)
239 TreeXMLImporter& child()
245 class TreeXMLImporterStack : public XMLImporter
247 std::vector< Reference<TreeXMLImporter> > m_importers;
249 TreeXMLImporterStack(TreeXMLImporter& importer)
251 m_importers.push_back(makeReference(importer));
253 void pushElement(const XMLElement& element)
255 m_importers.back().get().pushElement(element);
256 m_importers.push_back(makeReference(m_importers.back().get().child()));
258 void popElement(const char* name)
260 m_importers.pop_back();
261 m_importers.back().get().popElement(name);
263 std::size_t write(const char* buffer, std::size_t length)
265 return (*(m_importers.end() - 2)).get().write(buffer, length);
270 void Map_Read(scene::Node& root, TextInputStream& in, EntityCreator& entityTable)
272 XMLStreamParser parser(in);
274 MapDoom3Importer importer(root, entityTable);
275 TreeXMLImporterStack stack(importer);
276 parser.exportXML(stack);