Wed, 25 May 2022 13:49:45 +0300
add missing file
#include <QMessageBox> #include <document.h> #include "linetypes/edge.h" #include "linetypes/triangle.h" #include "linetypes/quadrilateral.h" #include "drawtool.h" #include "modeleditor.h" static const QBrush pointBrush = {Qt::white}; static const QPen polygonPen = {QBrush{Qt::black}, 2.0, Qt::DashLine}; static const QPen badPolygonPen = {QBrush{Qt::red}, 2.0, Qt::DashLine}; static const QPen pointPen = {QBrush{Qt::black}, 2.0}; static const QBrush greenPolygonBrush = {QColor{64, 255, 128, 192}}; static const QBrush redPolygonBrush = {QColor{255, 96, 96, 192}}; AbstractDrawTool::AbstractDrawTool(Document *document) : BaseTool{document} { } DrawTool::DrawTool(Document* document) : AbstractDrawTool{document} { } QString DrawTool::name() const { static const QString result = tr("Draw"); return result; } QString DrawTool::toolTip() const { static const QString result = tr("Draw new elements into the model."); return result; } bool AbstractDrawTool::mouseClick(Canvas* canvas, QMouseEvent* event) { if (event->button() == Qt::LeftButton) { this->addCurrentPoint(canvas); return true; } else if (event->button() == Qt::RightButton) { this->removeLastPoint(); return true; } else { return false; } } bool AbstractDrawTool::mouseMove(Document* document, Canvas* canvas, QMouseEvent *event) { static_cast<void>(document); static_cast<void>(event); const auto& worldPosition = canvas->getWorldPosition(); if (worldPosition.has_value()) { this->previewPoint = worldPosition.value(); this->updatePreviewPolygon(); } return false; } bool AbstractDrawTool::keyReleased(Document*, Canvas* canvas, QKeyEvent* event) { if (event->key() == Qt::Key_Escape) { this->polygon.clear(); this->updatePreviewPolygon(); canvas->update(); return true; } else { return false; } } void AbstractDrawTool::addCurrentPoint(Canvas* canvas) { const auto& worldPosition = canvas->getWorldPosition(); if (worldPosition.has_value()) { const glm::vec3& pos = worldPosition.value(); if (this->isCloseToExistingPoints(pos)) { this->closeShape(); } else { this->addPoint(pos); } } } void AbstractDrawTool::updatePreviewPolygon() { this->previewPolygon = this->polygon; this->previewPolygon.resize(this->polygon.size() + 1); this->previewPolygon.back() = this->previewPoint; if (this->previewPolygon.size() > 2) { this->isconcave = not geom::isConvex(this->previewPolygon); } } void AbstractDrawTool::reset() { this->polygon.clear(); } void AbstractDrawTool::overpaint(Canvas* canvas, QPainter* painter) const { painter->setPen(this->isconcave ? ::badPolygonPen : ::polygonPen); if (this->previewPolygon.size() > 2 and not this->isconcave) { if (canvas->worldPolygonWinding(this->previewPolygon) == Winding::Clockwise) { painter->setBrush(::greenPolygonBrush); } else { painter->setBrush(::redPolygonBrush); } canvas->drawWorldPolygon(painter, this->previewPolygon); } else { canvas->drawWorldPolyline(painter, this->previewPolygon); } painter->setBrush(::pointBrush); painter->setPen(::pointPen); for (const glm::vec3& point : this->polygon) { canvas->drawWorldPoint(painter, point); } canvas->drawWorldPoint(painter, this->previewPoint); } void AbstractDrawTool::addPoint(const glm::vec3 &pos) { this->polygon.push_back(pos); this->updatePreviewPolygon(); } void AbstractDrawTool::removeLastPoint() { if (this->polygon.size() > 0) { this->polygon.erase(this->polygon.end() - 1); this->updatePreviewPolygon(); } } void AbstractDrawTool::clearPoints() { this->polygon.clear(); this->updatePreviewPolygon(); } bool AbstractDrawTool::isCloseToExistingPoints(const glm::vec3 &pos) const { const auto isCloseToPos = [&](const glm::vec3& x) { return geom::isclose(x, pos); }; return any(this->polygon, isCloseToPos); } QString DrawTool::iconName() const { return ":/icons/pencil-outline.png"; } void DrawTool::addPoint(const glm::vec3 &pos) { AbstractDrawTool::addPoint(pos); if (this->polygon.size() == 4) { this->closeShape(); } } template<std::size_t N, typename T> std::array<T, N> vectorToArray(const std::vector<T>& x) { std::array<T, N> result; for (std::size_t i = 0; i < x.size() and i < N; i += 1) { result[i] = x[i]; } return result; } void DrawTool::closeShape() { if (this->polygon.size() >= 2 and this->polygon.size() <= 4) { std::unique_ptr<ModelEditor> modelEditor = this->document->editModel(); switch (this->polygon.size()) { case 2: modelEditor->append<ldraw::Edge>(vectorToArray<2>(this->polygon), ldraw::EDGE_COLOR); break; case 3: modelEditor->append<ldraw::Triangle>(vectorToArray<3>(this->polygon), ldraw::MAIN_COLOR); break; case 4: modelEditor->append<ldraw::Quadrilateral>(vectorToArray<4>(this->polygon), ldraw::MAIN_COLOR); break; } } this->clearPoints(); }