|
1 #include <stdexcept> |
|
2 #include "abstracteditmode.h" |
|
3 #include "selectmode.h" |
|
4 #include "drawmode.h" |
|
5 #include "circlemode.h" |
|
6 #include "magicwandmode.h" |
|
7 #include "../mainWindow.h" |
|
8 |
|
9 AbstractEditMode::AbstractEditMode (GLRenderer* renderer) : |
|
10 _renderer (renderer) {} |
|
11 |
|
12 AbstractEditMode* AbstractEditMode::createByType (GLRenderer* renderer, EditModeType type) |
|
13 { |
|
14 switch (type) |
|
15 { |
|
16 case EditModeType::Select: return new SelectMode (renderer); |
|
17 case EditModeType::Draw: return new DrawMode (renderer); |
|
18 case EditModeType::Circle: return new CircleMode (renderer); |
|
19 case EditModeType::MagicWand: return new MagicWandMode (renderer); |
|
20 } |
|
21 |
|
22 throw std::logic_error ("bad type given to AbstractEditMode::createByType"); |
|
23 } |
|
24 |
|
25 GLRenderer* AbstractEditMode::renderer() const |
|
26 { |
|
27 return _renderer; |
|
28 } |
|
29 |
|
30 AbstractDrawMode::AbstractDrawMode (GLRenderer* renderer) : |
|
31 AbstractEditMode (renderer), |
|
32 _polybrush (QBrush (QColor (64, 192, 0, 128))) |
|
33 { |
|
34 // Disable the context menu - we need the right mouse button |
|
35 // for removing vertices. |
|
36 renderer->setContextMenuPolicy (Qt::NoContextMenu); |
|
37 |
|
38 // Use the crosshair cursor when drawing. |
|
39 renderer->setCursor (Qt::CrossCursor); |
|
40 |
|
41 // Clear the selection when beginning to draw. |
|
42 getCurrentDocument()->clearSelection(); |
|
43 |
|
44 g_win->updateSelection(); |
|
45 m_drawedVerts.clear(); |
|
46 } |
|
47 |
|
48 AbstractSelectMode::AbstractSelectMode (GLRenderer* renderer) : |
|
49 AbstractEditMode (renderer) |
|
50 { |
|
51 renderer->unsetCursor(); |
|
52 renderer->setContextMenuPolicy (Qt::DefaultContextMenu); |
|
53 } |
|
54 |
|
55 // ============================================================================= |
|
56 // |
|
57 void AbstractDrawMode::addDrawnVertex (Vertex const& pos) |
|
58 { |
|
59 if (preAddVertex (pos)) |
|
60 return; |
|
61 |
|
62 m_drawedVerts << pos; |
|
63 } |
|
64 |
|
65 virtual void AbstractDrawMode::mouseReleased (MouseEventData const& data) |
|
66 { |
|
67 if (data.releasedButtons & Qt::MidButton) |
|
68 { |
|
69 // Find the closest vertex to our cursor |
|
70 double minimumDistance = 1024.0; |
|
71 const Vertex* closest = null; |
|
72 Vertex cursorPosition = renderer()->coordconv2_3 (data.ev->pos(), false); |
|
73 QPoint cursorPosition2D (data.ev->pos()); |
|
74 const Axis relZ = renderer()->getRelativeZ(); |
|
75 QList<Vertex> vertices; |
|
76 |
|
77 for (auto it = renderer()->document()->vertices().begin(); it != renderer()->document()->vertices().end(); ++it) |
|
78 vertices << it.key(); |
|
79 |
|
80 // Sort the vertices in order of distance to camera |
|
81 std::sort (vertices.begin(), vertices.end(), [&](const Vertex& a, const Vertex& b) -> bool |
|
82 { |
|
83 if (renderer()->getFixedCamera (renderer()->camera()).negatedDepth) |
|
84 return a[relZ] > b[relZ]; |
|
85 |
|
86 return a[relZ] < b[relZ]; |
|
87 }); |
|
88 |
|
89 for (const Vertex& vrt : vertices) |
|
90 { |
|
91 // If the vertex in 2d space is very close to the cursor then we use |
|
92 // it regardless of depth. |
|
93 QPoint vect2d = renderer()->coordconv3_2 (vrt) - cursorPosition2D; |
|
94 const double distance2DSquared = std::pow (vect2d.x(), 2) + std::pow (vect2d.y(), 2); |
|
95 if (distance2DSquared < 16.0 * 16.0) |
|
96 { |
|
97 closest = &vrt; |
|
98 break; |
|
99 } |
|
100 |
|
101 // Check if too far away from the cursor. |
|
102 if (distance2DSquared > 64.0 * 64.0) |
|
103 continue; |
|
104 |
|
105 // Not very close to the cursor. Compare using true distance, |
|
106 // including depth. |
|
107 const double distanceSquared = (vrt - cursorPosition).lengthSquared(); |
|
108 |
|
109 if (distanceSquared < minimumDistance) |
|
110 { |
|
111 minimumDistance = distanceSquared; |
|
112 closest = &vrt; |
|
113 } |
|
114 } |
|
115 |
|
116 if (closest != null) |
|
117 addDrawnVertex (*closest); |
|
118 |
|
119 return true; |
|
120 } |
|
121 |
|
122 return false; |
|
123 } |