| 1 /* |
|
| 2 * LDForge: LDraw parts authoring CAD |
|
| 3 * Copyright (C) 2013, 2014 Santeri Piippo |
|
| 4 * |
|
| 5 * This program is free software: you can redistribute it and/or modify |
|
| 6 * it under the terms of the GNU General Public License as published by |
|
| 7 * the Free Software Foundation, either version 3 of the License, or |
|
| 8 * (at your option) any later version. |
|
| 9 * |
|
| 10 * This program is distributed in the hope that it will be useful, |
|
| 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
| 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
| 13 * GNU General Public License for more details. |
|
| 14 * |
|
| 15 * You should have received a copy of the GNU General Public License |
|
| 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
| 17 */ |
|
| 18 |
|
| 19 #include <QPainter> |
|
| 20 #include <QMouseEvent> |
|
| 21 #include "drawmode.h" |
|
| 22 #include "../ldObject.h" |
|
| 23 #include "../glRenderer.h" |
|
| 24 |
|
| 25 CFGENTRY (Bool, drawLineLengths, true) |
|
| 26 CFGENTRY (Bool, drawAngles, false) |
|
| 27 |
|
| 28 DrawMode::DrawMode (GLRenderer* renderer) : |
|
| 29 Super (renderer), |
|
| 30 _rectdraw (false) {} |
|
| 31 |
|
| 32 EditModeType DrawMode::type() const |
|
| 33 { |
|
| 34 return EditModeType::Draw; |
|
| 35 } |
|
| 36 |
|
| 37 void DrawMode::render (QPainter& painter) const |
|
| 38 { |
|
| 39 QPoint poly[4]; |
|
| 40 Vertex poly3d[4]; |
|
| 41 int numverts = 4; |
|
| 42 QFontMetrics metrics = QFontMetrics (QFont()); |
|
| 43 |
|
| 44 // Calculate polygon data |
|
| 45 if (not _rectdraw) |
|
| 46 { |
|
| 47 numverts = _drawedVerts.size() + 1; |
|
| 48 int i = 0; |
|
| 49 |
|
| 50 for (Vertex const& vert : _drawedVerts) |
|
| 51 poly3d[i++] = vert; |
|
| 52 |
|
| 53 // Draw the cursor vertex as the last one in the list. |
|
| 54 if (numverts <= 4) |
|
| 55 poly3d[i] = renderer()->position3D(); |
|
| 56 else |
|
| 57 numverts = 4; |
|
| 58 } |
|
| 59 else |
|
| 60 { |
|
| 61 // Get vertex information from m_rectverts |
|
| 62 if (_drawedVerts.size() > 0) |
|
| 63 for (int i = 0; i < numverts; ++i) |
|
| 64 poly3d[i] = _rectverts[i]; |
|
| 65 else |
|
| 66 poly3d[0] = renderer()->position3D(); |
|
| 67 } |
|
| 68 |
|
| 69 // Convert to 2D |
|
| 70 for (int i = 0; i < numverts; ++i) |
|
| 71 poly[i] = renderer()->coordconv3_2 (poly3d[i]); |
|
| 72 |
|
| 73 if (numverts > 0) |
|
| 74 { |
|
| 75 // Draw the polygon-to-be |
|
| 76 painter.setBrush (_polybrush); |
|
| 77 painter.drawPolygon (poly, numverts); |
|
| 78 |
|
| 79 // Draw vertex blips |
|
| 80 for (int i = 0; i < numverts; ++i) |
|
| 81 { |
|
| 82 QPoint& blip = poly[i]; |
|
| 83 painter.setPen (renderer()->linePen()); |
|
| 84 renderer()->drawBlip (painter, blip); |
|
| 85 |
|
| 86 // Draw their coordinates |
|
| 87 painter.setPen (renderer()->textPen()); |
|
| 88 painter.drawText (blip.x(), blip.y() - 8, poly3d[i].toString (true)); |
|
| 89 } |
|
| 90 |
|
| 91 // Draw line lenghts and angle info if appropriate |
|
| 92 if (numverts >= 2) |
|
| 93 { |
|
| 94 int numlines = (_drawedVerts.size() == 1) ? 1 : _drawedVerts.size() + 1; |
|
| 95 painter.setPen (renderer()->textPen()); |
|
| 96 |
|
| 97 for (int i = 0; i < numlines; ++i) |
|
| 98 { |
|
| 99 const int j = (i + 1 < numverts) ? i + 1 : 0; |
|
| 100 const int h = (i - 1 >= 0) ? i - 1 : numverts - 1; |
|
| 101 |
|
| 102 if (cfg::drawLineLengths) |
|
| 103 { |
|
| 104 const QString label = QString::number ((poly3d[j] - poly3d[i]).length()); |
|
| 105 QPoint origin = QLineF (poly[i], poly[j]).pointAt (0.5).toPoint(); |
|
| 106 painter.drawText (origin, label); |
|
| 107 } |
|
| 108 |
|
| 109 if (cfg::drawAngles) |
|
| 110 { |
|
| 111 QLineF l0 (poly[h], poly[i]), |
|
| 112 l1 (poly[i], poly[j]); |
|
| 113 |
|
| 114 double angle = 180 - l0.angleTo (l1); |
|
| 115 |
|
| 116 if (angle < 0) |
|
| 117 angle = 180 - l1.angleTo (l0); |
|
| 118 |
|
| 119 QString label = QString::number (angle) + QString::fromUtf8 (QByteArray ("\302\260")); |
|
| 120 QPoint pos = poly[i]; |
|
| 121 pos.setY (pos.y() + metrics.height()); |
|
| 122 |
|
| 123 painter.drawText (pos, label); |
|
| 124 } |
|
| 125 } |
|
| 126 } |
|
| 127 } |
|
| 128 } |
|
| 129 |
|
| 130 bool DrawMode::preAddVertex (Vertex const& pos) |
|
| 131 { |
|
| 132 // If we picked an already-existing vertex, stop drawing |
|
| 133 for (Vertex& vert : _drawedVerts) |
|
| 134 { |
|
| 135 if (vert == pos) |
|
| 136 { |
|
| 137 endDraw(); |
|
| 138 return true; |
|
| 139 } |
|
| 140 } |
|
| 141 |
|
| 142 return false; |
|
| 143 } |
|
| 144 |
|
| 145 bool DrawMode::mouseReleased (MouseEventData const& data) |
|
| 146 { |
|
| 147 if (Super::mouseReleased (data)) |
|
| 148 return true; |
|
| 149 |
|
| 150 if (data.releasedButtons & Qt::LeftButton) |
|
| 151 { |
|
| 152 if (_rectdraw) |
|
| 153 { |
|
| 154 if (_drawedVerts.size() == 2) |
|
| 155 { |
|
| 156 endDraw(); |
|
| 157 return true; |
|
| 158 } |
|
| 159 } |
|
| 160 else |
|
| 161 { |
|
| 162 // If we have 4 verts, stop drawing. |
|
| 163 if (_drawedVerts.size() >= 4) |
|
| 164 { |
|
| 165 endDraw(); |
|
| 166 return true; |
|
| 167 } |
|
| 168 |
|
| 169 if (_drawedVerts.isEmpty()) |
|
| 170 { |
|
| 171 _rectdraw = (data.ev->modifiers() & Qt::ShiftModifier); |
|
| 172 updateRectVerts(); |
|
| 173 } |
|
| 174 } |
|
| 175 |
|
| 176 addDrawnVertex (renderer()->position3D()); |
|
| 177 return true; |
|
| 178 } |
|
| 179 |
|
| 180 return false; |
|
| 181 } |
|
| 182 |
|
| 183 // |
|
| 184 // Update rect vertices when the mouse moves since the 3d position likely has changed |
|
| 185 // |
|
| 186 bool DrawMode::mouseMoved (QMouseEvent*) |
|
| 187 { |
|
| 188 updateRectVerts(); |
|
| 189 return false; |
|
| 190 } |
|
| 191 |
|
| 192 void DrawMode::updateRectVerts() |
|
| 193 { |
|
| 194 if (not _rectdraw) |
|
| 195 return; |
|
| 196 |
|
| 197 if (_drawedVerts.isEmpty()) |
|
| 198 { |
|
| 199 for (int i = 0; i < 4; ++i) |
|
| 200 _rectverts[i] = renderer()->position3D(); |
|
| 201 |
|
| 202 return; |
|
| 203 } |
|
| 204 |
|
| 205 Vertex v0 = _drawedVerts[0], |
|
| 206 v1 = (_drawedVerts.size() >= 2) ? _drawedVerts[1] : renderer()->position3D(); |
|
| 207 |
|
| 208 const Axis localx = renderer()->getCameraAxis (false), |
|
| 209 localy = renderer()->getCameraAxis (true), |
|
| 210 localz = (Axis) (3 - localx - localy); |
|
| 211 |
|
| 212 for (int i = 0; i < 4; ++i) |
|
| 213 _rectverts[i].setCoordinate (localz, renderer()->getDepthValue()); |
|
| 214 |
|
| 215 _rectverts[0].setCoordinate (localx, v0[localx]); |
|
| 216 _rectverts[0].setCoordinate (localy, v0[localy]); |
|
| 217 _rectverts[1].setCoordinate (localx, v1[localx]); |
|
| 218 _rectverts[1].setCoordinate (localy, v0[localy]); |
|
| 219 _rectverts[2].setCoordinate (localx, v1[localx]); |
|
| 220 _rectverts[2].setCoordinate (localy, v1[localy]); |
|
| 221 _rectverts[3].setCoordinate (localx, v0[localx]); |
|
| 222 _rectverts[3].setCoordinate (localy, v1[localy]); |
|
| 223 } |
|
| 224 |
|
| 225 void DrawMode::endDraw() |
|
| 226 { |
|
| 227 // Clean the selection and create the object |
|
| 228 QList<Vertex>& verts = _drawedVerts; |
|
| 229 LDObjectList objs; |
|
| 230 |
|
| 231 if (_rectdraw) |
|
| 232 { |
|
| 233 LDQuadPtr quad (spawn<LDQuad>()); |
|
| 234 |
|
| 235 updateRectVerts(); |
|
| 236 |
|
| 237 for (int i = 0; i < quad->numVertices(); ++i) |
|
| 238 quad->setVertex (i, _rectverts[i]); |
|
| 239 |
|
| 240 quad->setColor (maincolor()); |
|
| 241 objs << quad; |
|
| 242 } |
|
| 243 else |
|
| 244 { |
|
| 245 switch (verts.size()) |
|
| 246 { |
|
| 247 case 1: |
|
| 248 { |
|
| 249 // 1 vertex - add a vertex object |
|
| 250 LDVertexPtr obj = spawn<LDVertex>(); |
|
| 251 obj->pos = verts[0]; |
|
| 252 obj->setColor (maincolor()); |
|
| 253 objs << obj; |
|
| 254 break; |
|
| 255 } |
|
| 256 |
|
| 257 case 2: |
|
| 258 { |
|
| 259 // 2 verts - make a line |
|
| 260 LDLinePtr obj = spawn<LDLine> (verts[0], verts[1]); |
|
| 261 obj->setColor (edgecolor()); |
|
| 262 objs << obj; |
|
| 263 break; |
|
| 264 } |
|
| 265 |
|
| 266 case 3: |
|
| 267 case 4: |
|
| 268 { |
|
| 269 LDObjectPtr obj = (verts.size() == 3) ? |
|
| 270 static_cast<LDObjectPtr> (spawn<LDTriangle>()) : |
|
| 271 static_cast<LDObjectPtr> (spawn<LDQuad>()); |
|
| 272 |
|
| 273 obj->setColor (maincolor()); |
|
| 274 |
|
| 275 for (int i = 0; i < verts.size(); ++i) |
|
| 276 obj->setVertex (i, verts[i]); |
|
| 277 |
|
| 278 objs << obj; |
|
| 279 break; |
|
| 280 } |
|
| 281 } |
|
| 282 } |
|
| 283 |
|
| 284 finishDraw (objs); |
|
| 285 _rectdraw = false; |
|
| 286 } |
|