# HG changeset patch # User Teemu Piippo # Date 1627219598 -10800 # Node ID 40a1cf2f38f54c2222237a755b72ba0a2750795c # Parent 94c92c923713f2ab7b3efbfe8305f9506f45cb85 replaced preview layers in favor of overpainting callback diff -r 94c92c923713 -r 40a1cf2f38f5 src/document.cpp --- a/src/document.cpp Sun Jul 25 13:49:37 2021 +0300 +++ b/src/document.cpp Sun Jul 25 16:26:38 2021 +0300 @@ -95,6 +95,11 @@ this->renderer->setRenderPreferences(newPreferences); } +void Document::setCanvasOverpaintCallback(Canvas::OverpaintCallback fn) +{ + this->renderer->setOverpaintCallback(fn); +} + void Document::selectionChanged(const QSet& newSelection) { if (newSelection.size() == 1) diff -r 94c92c923713 -r 40a1cf2f38f5 src/document.h --- a/src/document.h Sun Jul 25 13:49:37 2021 +0300 +++ b/src/document.h Sun Jul 25 16:26:38 2021 +0300 @@ -42,6 +42,7 @@ QByteArray saveSplitterState() const; void restoreSplitterState(const QByteArray& state); void setRenderPreferences(const gl::RenderPreferences& newPreferences); + void setCanvasOverpaintCallback(Canvas::OverpaintCallback fn); signals: void newStatusText(const QString& newStatusText); void splitterChanged(); diff -r 94c92c923713 -r 40a1cf2f38f5 src/geometry.h --- a/src/geometry.h Sun Jul 25 13:49:37 2021 +0300 +++ b/src/geometry.h Sun Jul 25 16:26:38 2021 +0300 @@ -117,9 +117,9 @@ }; /** - * @param center - * @param radius - * @returns a QRectF that encloses the specified circle + * @brief Inscribes a circle + * @param circle + * @return a QRectF that inscribes the specified circle */ inline constexpr QRectF inscribe(const CircleF& circle) { diff -r 94c92c923713 -r 40a1cf2f38f5 src/mainwindow.cpp --- a/src/mainwindow.cpp Sun Jul 25 13:49:37 2021 +0300 +++ b/src/mainwindow.cpp Sun Jul 25 16:26:38 2021 +0300 @@ -214,6 +214,13 @@ connect(document, &Document::splitterChanged, this, &MainWindow::handleDocumentSplitterChange); connect(document, &Document::mouseClick, this, &MainWindow::canvasMouseReleased); connect(document, &Document::mouseMove, this, &MainWindow::canvasMouseMoved); + document->setCanvasOverpaintCallback([&](Canvas* canvas, QPainter* painter) + { + if (this->selectedTool != nullptr) + { + this->selectedTool->overpaint(canvas, painter); + } + }); } void MainWindow::runSettingsEditor() diff -r 94c92c923713 -r 40a1cf2f38f5 src/tools/basetool.h --- a/src/tools/basetool.h Sun Jul 25 13:49:37 2021 +0300 +++ b/src/tools/basetool.h Sun Jul 25 16:26:38 2021 +0300 @@ -18,5 +18,6 @@ virtual bool mouseMove(const Canvas::MouseMoveInfo&) { return false; } virtual bool keyReleased(QKeyEvent*) { return false; } virtual void reset() {} + virtual void overpaint(Canvas*, QPainter*) const {} }; diff -r 94c92c923713 -r 40a1cf2f38f5 src/tools/drawtool.cpp --- a/src/tools/drawtool.cpp Sun Jul 25 13:49:37 2021 +0300 +++ b/src/tools/drawtool.cpp Sun Jul 25 16:26:38 2021 +0300 @@ -1,9 +1,10 @@ #include #include "drawtool.h" -static const QBrush brush = {Qt::white}; -static const QPen pen = {Qt::black}; -static const QBrush polygonBrush = {QColor{64, 255, 128}}; +static const QBrush pointBrush = {Qt::white}; +static const QPen polygonPen = {QBrush{Qt::black}, 2.0, Qt::DashLine}; +static const QPen pointPen = {QBrush{Qt::black}, 2.0}; +static const QBrush polygonBrush = {QColor{64, 255, 128, 192}}; DrawTool::DrawTool(QObject* parent) : BaseTool{parent} {} @@ -28,47 +29,58 @@ const auto isCloseToPos = [&](const glm::vec3& x){return geom::isclose(x, pos);}; if (any(this->polygon, isCloseToPos)) { - QMessageBox::information(nullptr, "test", "close the polygon"); + this->closeShape(); } else { this->polygon.push_back(pos); - auto& previewLayer = info.invoker->modifyPreviewLayer(Canvas::DrawToolPreview); - previewLayer.points.resize(this->polygon.size()); - previewLayer.points.back() = {pos, brush, pen}; - previewLayer.polygons.clear(); - previewLayer.polygons.push_back({geom::NPolygon{this->polygon}, polygonBrush, pen}); if (this->polygon.size() == 4) { - QMessageBox::information(nullptr, "test", "close the polygon"); + this->closeShape(); } } } + this->previewPolygon = this->polygon; return true; } bool DrawTool::mouseMove(const Canvas::MouseMoveInfo& info) { - if (this->polygon.size() < 4 and info.worldPosition.has_value()) + if (info.worldPosition.has_value()) { - auto& previewLayer = info.invoker->modifyPreviewLayer(Canvas::DrawToolPreview); - previewLayer.points.resize(this->polygon.size() + 1); - previewLayer.points.back() = {info.worldPosition.value(), brush, pen}; - if (previewLayer.polygons.size() > 0) + this->previewPoint = info.worldPosition.value(); + if (this->polygon.size() < 4) { - auto& polygon = previewLayer.polygons.back(); - polygon.geometry.points.resize(this->polygon.size() + 1); - polygon.geometry.points.back() = info.worldPosition.value(); + this->previewPolygon.resize(this->polygon.size() + 1); + this->previewPolygon.back() = this->previewPoint; } - return true; } - else - { - return false; - } + return false; } void DrawTool::reset() { this->polygon.clear(); } + +void DrawTool::overpaint(Canvas* canvas, QPainter* painter) const +{ + painter->setBrush(::polygonBrush); + painter->setPen(::polygonPen); + canvas->drawWorldPolygon(painter, this->previewPolygon); + painter->setBrush(::pointBrush); + painter->setPen(::pointPen); + for (const glm::vec3& point : this->polygon) + { + canvas->drawWorldPoint(painter, point); + } + if (this->polygon.size() < 4) + { + canvas->drawWorldPoint(painter, this->previewPoint); + } +} + +void DrawTool::closeShape() +{ + QMessageBox::information(nullptr, "test", "close the polygon"); +} diff -r 94c92c923713 -r 40a1cf2f38f5 src/tools/drawtool.h --- a/src/tools/drawtool.h Sun Jul 25 13:49:37 2021 +0300 +++ b/src/tools/drawtool.h Sun Jul 25 16:26:38 2021 +0300 @@ -13,6 +13,10 @@ bool mouseClick(const Canvas::MouseClickInfo& info) override; bool mouseMove(const Canvas::MouseMoveInfo&) override; void reset() override; + void overpaint(Canvas*, QPainter*) const override; private: + void closeShape(); std::vector polygon; + std::vector previewPolygon; + glm::vec3 previewPoint; }; diff -r 94c92c923713 -r 40a1cf2f38f5 src/ui/canvas.cpp --- a/src/ui/canvas.cpp Sun Jul 25 13:49:37 2021 +0300 +++ b/src/ui/canvas.cpp Sun Jul 25 16:26:38 2021 +0300 @@ -175,6 +175,7 @@ } { QPainter painter{this}; + painter.setRenderHint(QPainter::Antialiasing); QFont font; //font.setStyle(QFont::StyleItalic); painter.setFont(font); @@ -227,35 +228,31 @@ renderText(axis.text, *intersection); } } - for (const PreviewLayer& previewLayer : this->previewLayers) + if (this->overpaintCallback != nullptr) { - for (const PreviewLayer::Polygon& polygon3d : previewLayer.polygons) - { - painter.setBrush(polygon3d.brush); - painter.setPen(polygon3d.pen); - QVector points2d; - points2d.reserve(polygon3d.geometry.points.size()); - for (const glm::vec3& point : polygon3d.geometry.points) - { - points2d.push_back(this->modelToScreenCoordinates(point)); - } - painter.drawPolygon(QPolygonF{points2d}); - } - for (const PreviewLayer::Point& point : previewLayer.points) - { - const geom::CircleF circle = { - this->modelToScreenCoordinates(point.location), - 5.0, - }; - painter.setBrush(point.brush); - painter.setPen(point.pen); - painter.drawEllipse(geom::inscribe(circle)); - } + this->overpaintCallback(this, &painter); } } } } +void Canvas::drawWorldPolygon(QPainter* painter, const std::vector &points) +{ + QVector points2d; + points2d.reserve(points.size()); + for (const glm::vec3& point : points) + { + points2d.push_back(this->modelToScreenCoordinates(point)); + } + painter->drawPolygon(QPolygonF{points2d}); +} + +void Canvas::drawWorldPoint(QPainter* painter, const glm::vec3& worldPoint) const +{ + const QPointF center = this->modelToScreenCoordinates(worldPoint); + painter->drawEllipse(geom::inscribe(geom::CircleF{center, 5})); +} + void Canvas::updateGridMatrix() { const geom::Triangle triangle { @@ -292,16 +289,6 @@ return std::abs(dot) < threshold; } -const Canvas::PreviewLayer& Canvas::getPreviewLayer(PreviewLayerName name) const -{ - return previewLayers[static_cast(name)]; -} - -Canvas::PreviewLayer& Canvas::modifyPreviewLayer(PreviewLayerName name) -{ - return previewLayers[static_cast(name)]; -} - void Canvas::clearSelection() { this->selection.clear(); @@ -317,3 +304,8 @@ emit selectionChanged(this->selection); this->update(); } + +void Canvas::setOverpaintCallback(Canvas::OverpaintCallback fn) +{ + this->overpaintCallback = fn; +} diff -r 94c92c923713 -r 40a1cf2f38f5 src/ui/canvas.h --- a/src/ui/canvas.h Sun Jul 25 13:49:37 2021 +0300 +++ b/src/ui/canvas.h Sun Jul 25 16:26:38 2021 +0300 @@ -1,4 +1,5 @@ #pragma once +#include #include #include #include "gl/partrenderer.h" @@ -11,38 +12,17 @@ public: struct MouseClickInfo; struct MouseMoveInfo; - enum PreviewLayerName : std::int8_t - { - DrawToolPreview - }; - struct PreviewLayer - { - struct Point - { - glm::vec3 location; - QBrush brush = {}; - QPen pen = {}; - }; - struct Polygon - { - geom::NPolygon geometry; - QBrush brush = {}; - QPen pen = {}; - }; - QVector points; - QVector polygons; - }; - static constexpr int NUM_PREVIEW_LAYERS = 1; - + using OverpaintCallback = std::function; Canvas( Model* model, DocumentManager* documents, const ldraw::ColorTable& colorTable, QWidget* parent = nullptr); - const PreviewLayer& getPreviewLayer(PreviewLayerName name) const; - PreviewLayer& modifyPreviewLayer(PreviewLayerName name); void clearSelection(); void addToSelection(ldraw::id_t id); + void setOverpaintCallback(OverpaintCallback fn); + void drawWorldPoint(QPainter* painter, const glm::vec3& worldPoint) const; + void drawWorldPolygon(QPainter* painter, const std::vector& points); public slots: void handleSelectionChange(const QSet& selectedIds, const QSet& deselectedIds); protected: @@ -67,7 +47,7 @@ geom::Plane gridPlane; int totalMouseMove = 0; QSet selection; - PreviewLayer previewLayers[NUM_PREVIEW_LAYERS]; + OverpaintCallback overpaintCallback = nullptr; }; struct Canvas::MouseClickInfo