예제 #1
0
 Model::Entity* MapParser::parseEntity(const BBox& worldBounds, Utility::ProgressIndicator* indicator) {
     Token token = m_tokenizer.nextToken();
     if (token.type() == TokenType::Eof)
         return NULL;
     
     expect(TokenType::OBrace | TokenType::CBrace, token);
     if (token.type() == TokenType::CBrace)
         return NULL;
     
     Model::Entity* entity = new Model::Entity(worldBounds);
     size_t firstLine = token.line();
     
     while ((token = m_tokenizer.nextToken()).type() != TokenType::Eof) {
         switch (token.type()) {
             case TokenType::String: {
                 String key = token.data();
                 expect(TokenType::String, token = m_tokenizer.nextToken());
                 String value = token.data();
                 entity->setProperty(key, value);
                 break;
             }
             case TokenType::OBrace: {
                 m_tokenizer.pushToken(token);
                 bool moreBrushes = true;
                 while (moreBrushes) {
                     Model::Brush* brush = parseBrush(worldBounds, indicator);
                     if (brush != NULL)
                         entity->addBrush(*brush);
                     expect(TokenType::OBrace | TokenType::CBrace, token = m_tokenizer.nextToken());
                     moreBrushes = (token.type() == TokenType::OBrace);
                     m_tokenizer.pushToken(token);
                 }
                 break;
             }
             case TokenType::CBrace: {
                 if (indicator != NULL)
                     indicator->update(static_cast<int>(token.position()));
                 entity->setFilePosition(firstLine, token.line() - firstLine);
                 return entity;
             }
             default:
                 delete entity;
                 throw MapParserException(token, TokenType::String | TokenType::OBrace | TokenType::CBrace);
         }
     }
     
     return entity;
 }
예제 #2
0
 Model::Brush* MapParser::parseBrush(const BBox& worldBounds, Utility::ProgressIndicator* indicator) {
     Token token = m_tokenizer.nextToken();
     if (token.type() == TokenType::Eof)
         return NULL;
     
     expect(TokenType::OBrace | TokenType::CBrace, token);
     if (token.type() == TokenType::CBrace)
         return NULL;
     
     Model::Brush* brush = new Model::Brush(worldBounds);
     brush->setFilePosition(token.line());
     
     while ((token = m_tokenizer.nextToken()).type() != TokenType::Eof) {
         switch (token.type()) {
             case TokenType::OParenthesis: {
                 m_tokenizer.pushToken(token);
                 Model::Face* face = parseFace(worldBounds);
                 if (face != NULL && brush != NULL) {
                     if (!brush->addFace(face)) {
                         m_console.warn("Skipping malformed brush at line %i", brush->filePosition());
                         delete brush;
                         brush = NULL;
                     }
                 } else {
                     delete face;
                 }
                 break;
             }
             case TokenType::CBrace:
                 if (indicator != NULL) indicator->update(static_cast<int>(token.position()));
                 if (brush != NULL && !brush->closed()) {
                     m_console.warn("Non-closed brush at line %i", brush->filePosition());
                     // delete brush;
                     // brush = NULL;
                 }
                 return brush;
             default:
                 delete brush;
                 throw MapParserException(token, TokenType::OParenthesis | TokenType::CParenthesis);
         }
     }
     
     return NULL;
 }
예제 #3
0
        Model::Brush* MapParser::parseBrush(const BBox& worldBounds, Utility::ProgressIndicator* indicator) {
            Token token = m_tokenizer.nextToken();
            if (token.type() == TokenType::Eof)
                return NULL;
            
            expect(TokenType::OBrace | TokenType::CBrace, token);
            if (token.type() == TokenType::CBrace)
                return NULL;
            
            const size_t firstLine = token.line();
            Model::FaceList faces;
            
            while ((token = m_tokenizer.nextToken()).type() != TokenType::Eof) {
                switch (token.type()) {
                    case TokenType::OParenthesis: {
                        m_tokenizer.pushToken(token);
                        Model::Face* face = parseFace(worldBounds);
                        if (face != NULL)
                            faces.push_back(face);
                        break;
                    }
                    case TokenType::CBrace: {
                        if (indicator != NULL) indicator->update(static_cast<int>(token.position()));
                        
                        Model::Brush* brush = new Model::Brush(worldBounds);

                        // sort the faces by the weight of their plane normals like QBSP does
                        Model::FaceList sortedFaces = faces;
                        std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Plane::WeightOrder(true)));
                        std::sort(sortedFaces.begin(), sortedFaces.end(), Model::Face::WeightOrder(Plane::WeightOrder(false)));
                        
                        Model::FaceList::iterator faceIt = sortedFaces.begin();
                        Model::FaceList::iterator faceEnd = sortedFaces.end();
                        while (faceIt != faceEnd) {
                            Model::Face* face = *faceIt++;
                            if (!brush->addFace(face)) {
                                m_console.warn("Skipping malformed brush at line %i", firstLine);
                                delete brush;
                                brush = NULL;
                                break;
                            }
                        }
                        
                        // if something went wrong, we must delete all faces that have not been added to the brush yet
                        if (faceIt != faceEnd)
                            Utility::deleteAll(sortedFaces, faceIt);
                        
                        if (brush != NULL) {
                            brush->setFilePosition(firstLine, token.line() - firstLine);
                            if (!brush->closed())
                                m_console.warn("Non-closed brush at line %i", firstLine);
                        }
                        return brush;
                    }
                    default: {
                        Utility::deleteAll(faces);
                        throw MapParserException(token, TokenType::OParenthesis | TokenType::CParenthesis);
                    }
                }
            }
            
            return NULL;
        }