/* Copyright (C) 2001-2006, William Joseph. All Rights Reserved. This file is part of GtkRadiant. GtkRadiant is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. GtkRadiant is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GtkRadiant; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include "parse.h" #include #include "ientity.h" #include "ibrush.h" #include "ipatch.h" #include "ieclass.h" #include "iscriplib.h" #include "scenelib.h" #include "string/string.h" #include "stringio.h" #include "eclasslib.h" inline MapImporter* Node_getMapImporter(scene::Node& node) { return NodeTypeCast::cast(node); } typedef std::list< std::pair > KeyValues; NodeSmartReference g_nullNode(NewNullNode()); NodeSmartReference Entity_create(EntityCreator& entityTable, EntityClass* entityClass, const KeyValues& keyValues) { scene::Node& entity(entityTable.createEntity(entityClass)); for(KeyValues::const_iterator i = keyValues.begin(); i != keyValues.end(); ++i) { Node_getEntity(entity)->setKeyValue((*i).first.c_str(), (*i).second.c_str()); } return NodeSmartReference(entity); } NodeSmartReference Entity_parseTokens(Tokeniser& tokeniser, EntityCreator& entityTable, const PrimitiveParser& parser, int index) { NodeSmartReference entity(g_nullNode); KeyValues keyValues; const char* classname = ""; int count_primitives = 0; while(1) { tokeniser.nextLine(); const char* token = tokeniser.getToken(); if(token == 0) { Tokeniser_unexpectedError(tokeniser, token, "#entity-token"); return g_nullNode; } if (!strcmp(token, "}")) // end entity { if(entity == g_nullNode) { // entity does not have brushes entity = Entity_create(entityTable, GlobalEntityClassManager().findOrInsert(classname, false), keyValues); } return entity; } else if(!strcmp(token, "{")) // begin primitive { if(entity == g_nullNode) { // entity has brushes entity = Entity_create(entityTable, GlobalEntityClassManager().findOrInsert(classname, true), keyValues); } tokeniser.nextLine(); NodeSmartReference primitive(parser.parsePrimitive(tokeniser)); if(primitive == g_nullNode || !Node_getMapImporter(primitive)->importTokens(tokeniser)) { globalErrorStream() << "brush " << count_primitives << ": parse error\n"; return g_nullNode; } scene::Traversable* traversable = Node_getTraversable(entity); if(Node_getEntity(entity)->isContainer() && traversable != 0) { traversable->insert(primitive); } else { globalErrorStream() << "entity " << index << ": type " << classname << ": discarding brush " << count_primitives << "\n"; } ++count_primitives; } else // epair { CopiedString key(token); token = tokeniser.getToken(); if(token == 0) { Tokeniser_unexpectedError(tokeniser, token, "#epair-value"); return g_nullNode; } keyValues.push_back(KeyValues::value_type(key, token)); if(string_equal(key.c_str(), "classname")) { classname = keyValues.back().second.c_str(); } } } // unreachable code return g_nullNode; } void Map_Read(scene::Node& root, Tokeniser& tokeniser, EntityCreator& entityTable, const PrimitiveParser& parser) { int count_entities = 0; for(;;) { tokeniser.nextLine(); if (!tokeniser.getToken()) // { or 0 break; NodeSmartReference entity(Entity_parseTokens(tokeniser, entityTable, parser, count_entities)); if(entity == g_nullNode) { globalErrorStream() << "entity " << count_entities << ": parse error\n"; return; } Node_getTraversable(root)->insert(entity); ++count_entities; } }