Model::EntityDefinition* DefParser::nextDefinition() { Token token = m_tokenizer.nextToken(); while (token.type() != Eof && token.type() != ODefinition) token = m_tokenizer.nextToken(); if (token.type() == Eof) return NULL; expect(ODefinition, token); StringList baseClasses; ClassInfo classInfo; token = m_tokenizer.nextToken(); expect(Word, token); classInfo.name = token.data(); token = m_tokenizer.peekToken(); expect(OParenthesis | Newline, token); if (token.type() == OParenthesis) { classInfo.setColor(parseColor()); token = m_tokenizer.peekToken(); expect(OParenthesis | Question, token); if (token.type() == OParenthesis) { classInfo.setSize(parseBounds()); } else { m_tokenizer.nextToken(); } token = m_tokenizer.peekToken(); if (token.type() == Word) { Model::FlagsPropertyDefinition::Ptr spawnflags = parseFlags(); classInfo.properties[spawnflags->name()] = spawnflags; } } expect(Newline, token = m_tokenizer.nextToken()); parseProperties(classInfo.properties, classInfo.models, baseClasses); classInfo.setDescription(parseDescription()); expect(CDefinition, token = m_tokenizer.nextToken()); Model::EntityDefinition* definition = NULL; if (classInfo.hasColor) { ClassInfo::resolveBaseClasses(m_baseClasses, baseClasses, classInfo); if (classInfo.hasSize) { // point definition definition = new Model::PointEntityDefinition(classInfo.name, classInfo.color, classInfo.size, classInfo.description, classInfo.propertyList(), classInfo.models); } else { definition = new Model::BrushEntityDefinition(classInfo.name, classInfo.color, classInfo.description, classInfo.propertyList()); } } else { // base definition m_baseClasses[classInfo.name] = classInfo; definition = nextDefinition(); } return definition; }
void ClassInfo::resolveBaseClasses(const Map& baseClasses, const StringList& classnames, ClassInfo& classInfo) { StringList::const_reverse_iterator classnameIt, classnameEnd; for (classnameIt = classnames.rbegin(), classnameEnd = classnames.rend(); classnameIt != classnameEnd; ++classnameIt) { const String& classname = *classnameIt; ClassInfo::Map::const_iterator baseClassIt = baseClasses.find(classname); if (baseClassIt != baseClasses.end()) { const ClassInfo& baseClass = baseClassIt->second; if (!classInfo.hasDescription && baseClass.hasDescription) classInfo.setDescription(baseClass.description); if (!classInfo.hasColor && baseClass.hasColor) classInfo.setColor(baseClass.color); if (!classInfo.hasSize && baseClass.hasSize) classInfo.setSize(baseClass.size); Model::PropertyDefinition::Map::const_iterator propertyIt, propertyEnd; for (propertyIt = baseClass.properties.begin(), propertyEnd = baseClass.properties.end(); propertyIt != propertyEnd; ++propertyIt) { const Model::PropertyDefinition::Ptr baseclassProperty = propertyIt->second; Model::PropertyDefinition::Map::iterator classPropertyIt = classInfo.properties.find(baseclassProperty->name()); if (classPropertyIt != classInfo.properties.end()) { // the class already has a definition for this property, attempt merging them mergeProperties(baseclassProperty.get(), classPropertyIt->second.get()); } else { // the class doesn't have a definition for this property, add the base class property classInfo.properties[baseclassProperty->name()] = baseclassProperty; } } Model::ModelDefinition::List::const_iterator modelIt, modelEnd; for (modelIt = baseClass.models.begin(), modelEnd = baseClass.models.end(); modelIt != modelEnd; ++modelIt) { const Model::ModelDefinition::Ptr model = *modelIt; classInfo.models.push_back(model); } } } }