5 Canvas::Canvas( |
5 Canvas::Canvas( |
6 Model* model, |
6 Model* model, |
7 DocumentManager* documents, |
7 DocumentManager* documents, |
8 const ldraw::ColorTable& colorTable, |
8 const ldraw::ColorTable& colorTable, |
9 QWidget* parent) : |
9 QWidget* parent) : |
10 PartRenderer{model, documents, colorTable, parent} |
10 PartRenderer{model, documents, colorTable, parent}, |
|
11 gridProgram{this} |
11 { |
12 { |
12 this->setMouseTracking(true); |
13 this->setMouseTracking(true); |
13 } |
14 } |
14 |
15 |
15 void Canvas::handleSelectionChange(const QSet<ldraw::Id>& selectedIds, const QSet<ldraw::Id>& deselectedIds) |
16 void Canvas::handleSelectionChange(const QSet<ldraw::Id>& selectedIds, const QSet<ldraw::Id>& deselectedIds) |
19 this->selection.unite(selectedIds); |
20 this->selection.unite(selectedIds); |
20 this->compiler->setSelectedObjects(this->selection); |
21 this->compiler->setSelectedObjects(this->selection); |
21 this->update(); |
22 this->update(); |
22 } |
23 } |
23 |
24 |
|
25 QString vectorToString(const glm::vec3& vec) |
|
26 { |
|
27 return "(%1, %2, %3)"_q |
|
28 .arg(toDouble(vec.x)) |
|
29 .arg(toDouble(vec.y)) |
|
30 .arg(toDouble(vec.z)); |
|
31 } |
|
32 |
24 void Canvas::mouseMoveEvent(QMouseEvent* event) |
33 void Canvas::mouseMoveEvent(QMouseEvent* event) |
25 { |
34 { |
26 const ldraw::Id id = this->pick(event->pos()); |
35 const ldraw::Id id = this->pick(event->pos()); |
27 this->highlighted = id; |
36 this->highlighted = id; |
28 this->totalMouseMove += (event->pos() - this->lastMousePosition).manhattanLength(); |
37 this->totalMouseMove += (event->pos() - this->lastMousePosition).manhattanLength(); |
29 this->lastMousePosition = event->pos(); |
38 this->worldPosition = this->screenToModelCoordinates(event->pos(), geom::XY); |
30 this->worldPosition = this->screenToModelCoordinates(this->lastMousePosition, geom::XY); |
|
31 if (this->worldPosition.has_value()) |
39 if (this->worldPosition.has_value()) |
32 { |
40 { |
33 this->worldPosition = glm::round(*this->worldPosition); |
41 this->worldPosition = glm::round(*this->worldPosition); |
34 } |
42 } |
35 if (this->worldPosition.has_value()) |
43 if (this->worldPosition.has_value()) |
36 { |
44 { |
37 this->newStatusText("Position: (%1, %2, %3)"_q |
45 this->newStatusText("Position: (%1, %2, %3)"_q |
38 .arg(this->worldPosition->x) |
46 .arg(toDouble(this->worldPosition->x)) |
39 .arg(this->worldPosition->y) |
47 .arg(toDouble(this->worldPosition->y)) |
40 .arg(this->worldPosition->z)); |
48 .arg(toDouble(this->worldPosition->z))); |
41 } |
49 } |
42 else |
50 else |
43 { |
51 { |
44 this->newStatusText("Position: <none>"_q); |
52 this->newStatusText("Position: <none>"_q); |
45 } |
53 } |
70 this->update(); |
78 this->update(); |
71 } |
79 } |
72 PartRenderer::mouseReleaseEvent(event); |
80 PartRenderer::mouseReleaseEvent(event); |
73 } |
81 } |
74 |
82 |
|
83 void Canvas::initializeGL() |
|
84 { |
|
85 // We first create the grid program and connect everything and only then call the part renderer's initialization |
|
86 // functions so that when initialization sets up, the signals also set up the matrices on our side. |
|
87 this->gridProgram.emplace(this); |
|
88 this->gridProgram->initialize(); |
|
89 connect(this, &PartRenderer::projectionMatrixChanged, [&]() |
|
90 { |
|
91 this->gridProgram->setProjectionMatrix(this->projectionMatrix); |
|
92 }); |
|
93 connect(this, &PartRenderer::modelMatrixChanged, [&]() |
|
94 { |
|
95 this->gridProgram->setModelMatrix(this->modelMatrix); |
|
96 }); |
|
97 connect(this, &PartRenderer::viewMatrixChanged, [&]() |
|
98 { |
|
99 this->gridProgram->setViewMatrix(this->viewMatrix); |
|
100 }); |
|
101 connect(this, &PartRenderer::renderPreferencesChanged, [&]() |
|
102 { |
|
103 if (this->gridProgram.has_value()) |
|
104 { |
|
105 const bool isDark = luma(this->renderPreferences.backgroundColor) < 0.25; |
|
106 this->gridProgram->setGridColor(isDark ? Qt::white : Qt::black); |
|
107 } |
|
108 }); |
|
109 PartRenderer::initializeGL(); |
|
110 } |
|
111 |
75 void Canvas::paintGL() |
112 void Canvas::paintGL() |
76 { |
113 { |
77 PartRenderer::paintGL(); |
114 PartRenderer::paintGL(); |
|
115 glEnable(GL_BLEND); |
|
116 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
|
117 this->gridProgram->draw(); |
|
118 glDisable(GL_BLEND); |
78 if (this->worldPosition.has_value()) |
119 if (this->worldPosition.has_value()) |
79 { |
120 { |
80 QPainter painter{this}; |
121 QPainter painter{this}; |
81 painter.setRenderHint(QPainter::Antialiasing); |
122 painter.setRenderHint(QPainter::Antialiasing); |
82 painter.setPen(Qt::black); |
123 painter.setPen(Qt::black); |
83 painter.setBrush(Qt::green); |
124 painter.setBrush(Qt::green); |
84 painter.drawEllipse(this->modelToScreenCoordinates(*this->worldPosition), 10, 10); |
125 const QPointF pos = this->modelToScreenCoordinates(*this->worldPosition); |
|
126 painter.drawEllipse(pos, 5, 5); |
|
127 painter.setPen(Qt::white); |
|
128 painter.drawText(pos + QPointF{5, 5}, vectorToString(*this->worldPosition)); |
85 } |
129 } |
86 } |
130 } |