bool ReparentBrushesCommand::performDo() {
            m_oldParents.clear();

            Model::EntityList entities;
            if (!m_newParent.worldspawn())
                entities.push_back(&m_newParent);
            
            Model::BrushList::const_iterator it, end;
            for (it = m_brushes.begin(), end = m_brushes.end(); it != end; ++it) {
                Model::Brush* brush = *it;
                Model::Entity* oldParent = brush->entity();
                if (oldParent != NULL) {
                    m_oldParents[brush] = oldParent;
                    if (!oldParent->worldspawn() &&
                        std::find(entities.begin(), entities.end(), oldParent) == entities.end())
                        entities.push_back(oldParent);
                }
            }
            
            document().entitiesWillChange(entities);
            for (it = m_brushes.begin(), end = m_brushes.end(); it != end; ++it) {
                Model::Brush& brush = **it;
                Model::Entity& oldParent = *brush.entity();
                oldParent.removeBrush(brush);
                m_newParent.addBrush(brush);
            }
            document().entitiesDidChange(entities);
            
            return true;
        }
 bool SetBrushFaceAttributesTool::performCopy(const InputState& inputState, const bool applyToBrush) {
     if (!applies(inputState))
         return false;
     
     MapDocumentSPtr document = lock(m_document);
     
     const Model::BrushFaceList& selectedFaces = document->selectedBrushFaces();
     if (selectedFaces.size() != 1)
         return false;
     
     const Model::Hit& hit = inputState.pickResult().query().pickable().type(Model::Brush::BrushHit).occluded().first();
     if (!hit.isMatch())
         return false;
     
     Model::BrushFace* source = selectedFaces.front();
     Model::BrushFace* targetFace = Model::hitToFace(hit);
     Model::Brush* targetBrush = targetFace->brush();
     const Model::BrushFaceList targetList = applyToBrush ? targetBrush->faces() : Model::BrushFaceList(1, targetFace);
     
     const Transaction transaction(document);
     document->deselectAll();
     document->select(targetList);
     if (copyAttributes(inputState))
         document->setFaceAttributes(source->attribs());
     else
         document->setTexture(source->texture());
     document->deselectAll();
     document->select(source);
     return true;
 }
 BrushSnapshot::BrushSnapshot(const Model::Brush& brush) {
     m_uniqueId = brush.uniqueId();
     const Model::FaceList& brushFaces = brush.faces();
     for (unsigned int i = 0; i < brushFaces.size(); i++) {
         Model::Face* snapshot = new Model::Face(*brushFaces[i]);
         m_faces.push_back(snapshot);
     }
 }
예제 #4
0
 void Entity::addBrushes(const BrushList& brushes) {
     for (unsigned int i = 0; i < brushes.size(); i++) {
         Model::Brush* brush = brushes[i];
         brush->setEntity(this);
         m_brushes.push_back(brush);
     }
     invalidateGeometry();
 }
 bool SplitEdgesCommand::canDo() const {
     Model::EdgeList::const_iterator eIt, eEnd;
     for (eIt = m_edges.begin(), eEnd = m_edges.end(); eIt != eEnd; ++eIt) {
         Model::Edge* edge = *eIt;
         Model::Brush* brush = edge->left->face->brush();
         if (!brush->canSplitEdge(edge, m_delta))
             return false;
     }
     return true;
 }
예제 #6
0
 bool MoveFacesCommand::canDo() const {
     Model::BrushFacesMap::const_iterator it, end;
     for (it = m_brushFaces.begin(), end = m_brushFaces.end(); it != end; ++it) {
         Model::Brush* brush = it->first;
         const Model::FaceInfoList& faces = it->second;
         if (!brush->canMoveFaces(faces, m_delta))
             return false;
     }
     return true;
 }
 bool MoveVerticesCommand::canDo() const {
     BrushVerticesMap::const_iterator it, end;
     for (it = m_brushVertices.begin(), end = m_brushVertices.end(); it != end; ++it) {
         Model::Brush* brush = it->first;
         const Vec3f::List& vertices = it->second;
         if (!brush->canMoveVertices(vertices, m_delta))
             return false;
     }
     return true;
 }
예제 #8
0
 size_t MapWriter::writeBrush(Model::Brush& brush, const size_t lineNumber, FILE* stream) {
     size_t lineCount = 0;
     std::fprintf(stream, "{\n"); lineCount++;
     const Model::FaceList& faces = brush.faces();
     Model::FaceList::const_iterator faceIt, faceEnd;
     for (faceIt = faces.begin(), faceEnd = faces.end(); faceIt != faceEnd; ++faceIt) {
         lineCount += writeFace(**faceIt, lineNumber + lineCount, stream);
     }
     std::fprintf(stream, "}\n"); lineCount++;
     brush.setFilePosition(lineNumber, lineCount);
     return lineCount;
 }
예제 #9
0
 void MapWriter::writeBrush(const Model::Brush& brush, std::ostream& stream) {
     stream << "{\n";
     const Model::FaceList& faces = brush.faces();
     Model::FaceList::const_iterator faceIt, faceEnd;
     for (faceIt = faces.begin(), faceEnd = faces.end(); faceIt != faceEnd; ++faceIt)
         writeFace(**faceIt, stream);
     stream << "}\n";
 }
예제 #10
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;
 }
        bool SplitEdgesCommand::performDo() {
            if (!canDo())
                return false;
            
            m_vertices.clear();
            makeSnapshots(m_brushes);
            document().brushesWillChange(m_brushes);

            Model::EdgeList::const_iterator eIt, eEnd;
            for (eIt = m_edges.begin(), eEnd = m_edges.end(); eIt != eEnd; ++eIt) {
                Model::Edge* edge = *eIt;
                Model::Brush* brush = edge->left->face->brush();
                Vec3f newVertexPosition = brush->splitEdge(edge, m_delta);
                m_vertices.insert(newVertexPosition);
            }

            document().brushesDidChange(m_brushes);
            return true;
        }
 SnapBrushVerticesCommand::Ptr SnapBrushVerticesCommand::snap(const Model::BrushList& brushes, const size_t snapTo) {
     Model::BrushVerticesMap brushVertices;
     Vec3::List vertexPositions;
     
     Model::BrushList::const_iterator bIt, bEnd;
     Model::Brush::VertexList::const_iterator vIt, vEnd;
     
     for (bIt = brushes.begin(), bEnd = brushes.end(); bIt != bEnd; ++bIt) {
         Model::Brush* brush = *bIt;
         const Model::Brush::VertexList vertices = brush->vertices();
         for (vIt = vertices.begin(), vEnd = vertices.end(); vIt != vEnd; ++vIt) {
             const Model::BrushVertex* vertex = *vIt;
             brushVertices[brush].push_back(vertex->position());
             vertexPositions.push_back(vertex->position());
         }
     }
     
     return Ptr(new SnapBrushVerticesCommand(brushes, brushVertices, vertexPositions, snapTo));
 }
예제 #13
0
        bool SplitEdgesCommand::performDo() {
            if (!canDo())
                return false;
            
            m_vertices.clear();
            makeSnapshots(m_brushes);
            document().brushesWillChange(m_brushes);

            BrushEdgeMap::const_iterator it, end;
            for (it = m_brushEdges.begin(), end = m_brushEdges.end(); it != end; ++it) {
                Model::Brush* brush = it->first;
                const Model::EdgeInfo& edgeInfo = it->second;
                Vec3f newVertexPosition = brush->splitEdge(edgeInfo, m_delta);
                m_vertices.insert(newVertexPosition);
            }

            document().brushesDidChange(m_brushes);
            return true;
        }
        bool MoveEdgesCommand::performDo() {
            if (!canDo())
                return false;
            
            m_edges.clear();
            makeSnapshots(m_brushes);
            document().brushesWillChange(m_brushes);
            
            BrushEdgesMap::const_iterator it, end;
            for (it = m_brushEdges.begin(), end = m_brushEdges.end(); it != end; ++it) {
                Model::Brush* brush = it->first;
                const Model::EdgeList& edges = it->second;
                const Model::EdgeList newEdges = brush->moveEdges(edges, m_delta);
                m_edges.insert(m_edges.end(), newEdges.begin(), newEdges.end());
            }

            document().brushesDidChange(m_brushes);
            return true;
        }
        bool MoveVerticesCommand::performDo() {
            if (!canDo())
                return false;
            
            m_vertices.clear();
            makeSnapshots(m_brushes);
            document().brushesWillChange(m_brushes);

            BrushVerticesMap::const_iterator it, end;
            for (it = m_brushVertices.begin(), end = m_brushVertices.end(); it != end; ++it) {
                Model::Brush* brush = it->first;
                const Vec3f::List& oldVertexPositions = it->second;
                Vec3f::List newVertexPositions = brush->moveVertices(oldVertexPositions, m_delta);
                m_vertices.insert(newVertexPositions.begin(), newVertexPositions.end());
            }
            
            document().brushesDidChange(m_brushes);
            return true;
        }
예제 #16
0
        bool MoveFacesCommand::performDo() {
            if (!canDo())
                return false;

            m_handleManager.remove(m_brushes);
            makeSnapshots(m_brushes);
            document().brushesWillChange(m_brushes);
            m_facesAfter.clear();

            Model::BrushFacesMap::const_iterator it, end;
            for (it = m_brushFaces.begin(), end = m_brushFaces.end(); it != end; ++it) {
                Model::Brush* brush = it->first;
                const Model::FaceInfoList& faceInfos = it->second;
                const Model::FaceInfoList newFaces = brush->moveFaces(faceInfos, m_delta);
                m_facesAfter.insert(m_facesAfter.end(), newFaces.begin(), newFaces.end());
            }

            document().brushesDidChange(m_brushes);
            m_handleManager.add(m_brushes);
            m_handleManager.selectFaceHandles(m_facesAfter);

            return true;
        }
예제 #17
0
 bool ResizeBrushesTool::splitBrushes(const Vec3& delta) {
     MapDocumentSPtr document = lock(m_document);
     const BBox3& worldBounds = document->worldBounds();
     const bool lockTextures = document->textureLock();
     
     Model::BrushFaceList::const_iterator fIt, fEnd;
     
     // first ensure that the drag can be applied at all
     for (fIt = m_dragFaces.begin(), fEnd = m_dragFaces.end(); fIt != fEnd; ++fIt) {
         const Model::BrushFace* face = *fIt;
         if (!Math::pos(face->boundary().normal.dot(delta)))
             return false;
     }
     
     Model::ParentChildrenMap newNodes;
     Model::BrushFaceList newDragFaces;
     for (fIt = m_dragFaces.begin(), m_dragFaces.end(); fIt != fEnd; ++fIt) {
         Model::BrushFace* dragFace = *fIt;
         Model::Brush* brush = dragFace->brush();
         
         Model::Brush* newBrush = brush->clone(worldBounds);
         Model::BrushFace* newDragFace = findMatchingFace(newBrush, dragFace);
         Model::BrushFace* clipFace = newDragFace->clone();
         clipFace->invert();
         
         newBrush->moveBoundary(worldBounds, newDragFace, delta, lockTextures);
         const bool clipResult = newBrush->clip(worldBounds, clipFace);
         assert(clipResult);
         unused(clipResult);
         
         newNodes[brush->parent()].push_back(newBrush);
         newDragFaces.push_back(newDragFace);
     }
     
     document->deselectAll();
     const Model::NodeList addedNodes = document->addNodes(newNodes);
     document->select(addedNodes);
     m_dragFaces = newDragFaces;
     
     return true;
 }
 void BrushSnapshot::restore(Model::Brush& brush) {
     brush.replaceFaces(m_faces);
 }
예제 #19
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;
        }