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); } }
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; }
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; }
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; }
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"; }
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)); }
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; }
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; }
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); }
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; }