replaced preview layers in favor of overpainting callback

Sun, 25 Jul 2021 16:26:38 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Sun, 25 Jul 2021 16:26:38 +0300
changeset 109
40a1cf2f38f5
parent 108
94c92c923713
child 110
d922431eacf7

replaced preview layers in favor of overpainting callback

src/document.cpp file | annotate | diff | comparison | revisions
src/document.h file | annotate | diff | comparison | revisions
src/geometry.h file | annotate | diff | comparison | revisions
src/mainwindow.cpp file | annotate | diff | comparison | revisions
src/tools/basetool.h file | annotate | diff | comparison | revisions
src/tools/drawtool.cpp file | annotate | diff | comparison | revisions
src/tools/drawtool.h file | annotate | diff | comparison | revisions
src/ui/canvas.cpp file | annotate | diff | comparison | revisions
src/ui/canvas.h file | annotate | diff | comparison | revisions
--- 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<ldraw::id_t>& newSelection)
 {
 	if (newSelection.size() == 1)
--- 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();
--- 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)
 	{
--- 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()
--- 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 {}
 };
 
--- 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 <QMessageBox>
 #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");
+}
--- 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<glm::vec3> polygon;
+	std::vector<glm::vec3> previewPolygon;
+	glm::vec3 previewPoint;
 };
--- 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<QPointF> 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<glm::vec3> &points)
+{
+	QVector<QPointF> 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<unsigned int>(name)];
-}
-
-Canvas::PreviewLayer& Canvas::modifyPreviewLayer(PreviewLayerName name)
-{
-	return previewLayers[static_cast<unsigned int>(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;
+}
--- 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 <QPainter>
 #include <QBrush>
 #include <QPen>
 #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<Point> points;
-		QVector<Polygon> polygons;
-	};
-	static constexpr int NUM_PREVIEW_LAYERS = 1;
-
+	using OverpaintCallback = std::function<void(Canvas*, QPainter*)>;
 	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<glm::vec3>& points);
 public slots:
 	void handleSelectionChange(const QSet<ldraw::id_t>& selectedIds, const QSet<ldraw::id_t>& deselectedIds);
 protected:
@@ -67,7 +47,7 @@
 	geom::Plane gridPlane;
 	int totalMouseMove = 0;
 	QSet<ldraw::id_t> selection;
-	PreviewLayer previewLayers[NUM_PREVIEW_LAYERS];
+	OverpaintCallback overpaintCallback = nullptr;
 };
 
 struct Canvas::MouseClickInfo

mercurial