| 66 cfg (Bool, gl_axes, false); |
67 cfg (Bool, gl_axes, false); |
| 67 cfg (Bool, gl_wireframe, false); |
68 cfg (Bool, gl_wireframe, false); |
| 68 cfg (Bool, gl_logostuds, false); |
69 cfg (Bool, gl_logostuds, false); |
| 69 |
70 |
| 70 // argh |
71 // argh |
| 71 const char* g_CameraNames[7] = { |
72 const char* g_CameraNames[7] = |
| 72 QT_TRANSLATE_NOOP ("GLRenderer", "Top"), |
73 { QT_TRANSLATE_NOOP ("GLRenderer", "Top"), |
| 73 QT_TRANSLATE_NOOP ("GLRenderer", "Front"), |
74 QT_TRANSLATE_NOOP ("GLRenderer", "Front"), |
| 74 QT_TRANSLATE_NOOP ("GLRenderer", "Left"), |
75 QT_TRANSLATE_NOOP ("GLRenderer", "Left"), |
| 75 QT_TRANSLATE_NOOP ("GLRenderer", "Bottom"), |
76 QT_TRANSLATE_NOOP ("GLRenderer", "Bottom"), |
| 76 QT_TRANSLATE_NOOP ("GLRenderer", "Back"), |
77 QT_TRANSLATE_NOOP ("GLRenderer", "Back"), |
| 77 QT_TRANSLATE_NOOP ("GLRenderer", "Right"), |
78 QT_TRANSLATE_NOOP ("GLRenderer", "Right"), |
| 78 QT_TRANSLATE_NOOP ("GLRenderer", "Free") |
79 QT_TRANSLATE_NOOP ("GLRenderer", "Free") |
| 79 }; |
80 }; |
| 80 |
81 |
| 81 const GL::Camera g_Cameras[7] = { |
82 const GL::Camera g_Cameras[7] = |
| 82 GL::Top, |
83 { GL::Top, |
| 83 GL::Front, |
84 GL::Front, |
| 84 GL::Left, |
85 GL::Left, |
| 85 GL::Bottom, |
86 GL::Bottom, |
| 86 GL::Back, |
87 GL::Back, |
| 87 GL::Right, |
88 GL::Right, |
| 88 GL::Free |
89 GL::Free |
| 89 }; |
90 }; |
| 90 |
91 |
| 91 const struct GLAxis { |
92 const struct GLAxis |
| 92 const QColor col; |
93 { const QColor col; |
| 93 const vertex vert; |
94 const vertex vert; |
| 94 } g_GLAxes[3] = { |
95 } g_GLAxes[3] = |
| 95 { QColor (255, 0, 0), vertex (10000, 0, 0) }, |
96 { { QColor (255, 0, 0), vertex (10000, 0, 0) }, |
| 96 { QColor (80, 192, 0), vertex (0, 10000, 0) }, |
97 { QColor (80, 192, 0), vertex (0, 10000, 0) }, |
| 97 { QColor (0, 160, 192), vertex (0, 0, 10000) }, |
98 { QColor (0, 160, 192), vertex (0, 0, 10000) }, |
| 98 }; |
99 }; |
| 99 |
100 |
| 100 static bool g_glInvert = false; |
101 static bool g_glInvert = false; |
| 101 static List<short> g_warnedColors; |
102 static List<short> g_warnedColors; |
| 102 |
103 |
| 103 // ============================================================================= |
104 // ============================================================================= |
| 104 // ----------------------------------------------------------------------------- |
105 // ----------------------------------------------------------------------------- |
| 105 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) { |
106 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) |
| 106 m_picking = m_rangepick = false; |
107 { m_picking = m_rangepick = false; |
| 107 m_camera = (GL::Camera) gl_camera.value; |
108 m_camera = (GL::Camera) gl_camera.value; |
| 108 m_drawToolTip = false; |
109 m_drawToolTip = false; |
| 109 m_editMode = Select; |
110 m_editMode = Select; |
| 110 m_rectdraw = false; |
111 m_rectdraw = false; |
| 111 m_panning = false; |
112 m_panning = false; |
| 112 setFile (null); |
113 setFile (null); |
| 113 setDrawOnly (false); |
114 setDrawOnly (false); |
| 114 resetAngles(); |
115 resetAngles(); |
| 115 setMessageLog (null); |
116 setMessageLog (null); |
| 116 |
117 |
| 117 m_toolTipTimer = new QTimer (this); |
118 m_toolTipTimer = new QTimer (this); |
| 118 m_toolTipTimer->setSingleShot (true); |
119 m_toolTipTimer->setSingleShot (true); |
| 119 connect (m_toolTipTimer, SIGNAL (timeout()), this, SLOT (slot_toolTipTimer())); |
120 connect (m_toolTipTimer, SIGNAL (timeout()), this, SLOT (slot_toolTipTimer())); |
| 120 |
121 |
| 121 m_thickBorderPen = QPen (QColor (0, 0, 0, 208), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); |
122 m_thickBorderPen = QPen (QColor (0, 0, 0, 208), 2, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin); |
| 122 m_thinBorderPen = m_thickBorderPen; |
123 m_thinBorderPen = m_thickBorderPen; |
| 123 m_thinBorderPen.setWidth (1); |
124 m_thinBorderPen.setWidth (1); |
| 124 |
125 |
| 125 // Init camera icons |
126 // Init camera icons |
| 126 for (const GL::Camera cam : g_Cameras) { |
127 for (const GL::Camera cam : g_Cameras) |
| 127 str iconname = fmt ("camera-%1", tr (g_CameraNames[cam]).toLower()); |
128 { str iconname = fmt ("camera-%1", tr (g_CameraNames[cam]).toLower()); |
| 128 |
129 |
| 129 CameraIcon* info = &m_cameraIcons[cam]; |
130 CameraIcon* info = &m_cameraIcons[cam]; |
| 130 info->img = new QPixmap (getIcon (iconname)); |
131 info->img = new QPixmap (getIcon (iconname)); |
| 131 info->cam = cam; |
132 info->cam = cam; |
| 132 } |
133 } |
| 133 |
134 |
| 134 for (int i = 0; i < 6; ++i) { |
135 for (int i = 0; i < 6; ++i) |
| 135 m_overlays[i].img = null; |
136 { m_overlays[i].img = null; |
| 136 m_depthValues[i] = 0.0f; |
137 m_depthValues[i] = 0.0f; |
| 137 } |
138 } |
| 138 |
139 |
| 139 calcCameraIcons(); |
140 calcCameraIcons(); |
| 140 } |
141 } |
| 141 |
142 |
| 142 // ============================================================================= |
143 // ============================================================================= |
| 143 // ----------------------------------------------------------------------------- |
144 // ----------------------------------------------------------------------------- |
| 144 GLRenderer::~GLRenderer() { |
145 GLRenderer::~GLRenderer() |
| 145 for (int i = 0; i < 6; ++i) |
146 { for (int i = 0; i < 6; ++i) |
| 146 delete m_overlays[i].img; |
147 delete m_overlays[i].img; |
| 147 |
148 |
| 148 for (CameraIcon& info : m_cameraIcons) |
149 for (CameraIcon & info : m_cameraIcons) |
| 149 delete info.img; |
150 delete info.img; |
| 150 } |
151 } |
| 151 |
152 |
| 152 // ============================================================================= |
153 // ============================================================================= |
| 153 // ----------------------------------------------------------------------------- |
154 // ----------------------------------------------------------------------------- |
| 154 void GLRenderer::calcCameraIcons() { |
155 void GLRenderer::calcCameraIcons() |
| 155 ushort i = 0; |
156 { ushort i = 0; |
| 156 |
157 |
| 157 for (CameraIcon& info : m_cameraIcons) { |
158 for (CameraIcon & info : m_cameraIcons) |
| 158 const long x1 = (m_width - (info.cam != Free ? 48 : 16)) + ((i % 3) * 16) - 1, |
159 { const long x1 = (m_width - (info.cam != Free ? 48 : 16)) + ( (i % 3) * 16) - 1, |
| 159 y1 = ((i / 3) * 16) + 1; |
160 y1 = ( (i / 3) * 16) + 1; |
| 160 |
161 |
| 161 info.srcRect = QRect (0, 0, 16, 16); |
162 info.srcRect = QRect (0, 0, 16, 16); |
| 162 info.destRect = QRect (x1, y1, 16, 16); |
163 info.destRect = QRect (x1, y1, 16, 16); |
| 163 info.selRect = QRect (info.destRect.x(), info.destRect.y(), |
164 info.selRect = QRect (info.destRect.x(), info.destRect.y(), |
| 164 info.destRect.width() + 1, info.destRect.height() + 1); |
165 info.destRect.width() + 1, info.destRect.height() + 1); |
| 165 ++i; |
166 ++i; |
| 166 } |
167 } |
| 167 } |
168 } |
| 168 |
169 |
| 169 // ============================================================================= |
170 // ============================================================================= |
| 170 // ----------------------------------------------------------------------------- |
171 // ----------------------------------------------------------------------------- |
| 171 void GLRenderer::initGLData() { |
172 void GLRenderer::initGLData() |
| 172 glEnable (GL_BLEND); |
173 { glEnable (GL_BLEND); |
| 173 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
174 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); |
| 174 glEnable (GL_POLYGON_OFFSET_FILL); |
175 glEnable (GL_POLYGON_OFFSET_FILL); |
| 175 glPolygonOffset (1.0f, 1.0f); |
176 glPolygonOffset (1.0f, 1.0f); |
| 176 |
177 |
| 177 glEnable (GL_DEPTH_TEST); |
178 glEnable (GL_DEPTH_TEST); |
| 178 glShadeModel (GL_SMOOTH); |
179 glShadeModel (GL_SMOOTH); |
| 179 glEnable (GL_MULTISAMPLE); |
180 glEnable (GL_MULTISAMPLE); |
| 180 |
181 |
| 181 glEnable (GL_LINE_SMOOTH); |
182 glEnable (GL_LINE_SMOOTH); |
| 182 glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); |
183 glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); |
| 183 } |
184 } |
| 184 |
185 |
| 185 // ============================================================================= |
186 // ============================================================================= |
| 186 // ----------------------------------------------------------------------------- |
187 // ----------------------------------------------------------------------------- |
| 187 void GLRenderer::resetAngles() { |
188 void GLRenderer::resetAngles() |
| 188 m_rotX = 30.0f; |
189 { m_rotX = 30.0f; |
| 189 m_rotY = 325.f; |
190 m_rotY = 325.f; |
| 190 m_panX = m_panY = m_rotZ = 0.0f; |
191 m_panX = m_panY = m_rotZ = 0.0f; |
| 191 zoomToFit(); |
192 zoomToFit(); |
| 192 } |
193 } |
| 193 |
194 |
| 194 // ============================================================================= |
195 // ============================================================================= |
| 195 // ----------------------------------------------------------------------------- |
196 // ----------------------------------------------------------------------------- |
| 196 void GLRenderer::initializeGL() { |
197 void GLRenderer::initializeGL() |
| 197 setBackground(); |
198 { setBackground(); |
| 198 |
199 |
| 199 glLineWidth (gl_linethickness); |
200 glLineWidth (gl_linethickness); |
| 200 |
201 |
| 201 setAutoFillBackground (false); |
202 setAutoFillBackground (false); |
| 202 setMouseTracking (true); |
203 setMouseTracking (true); |
| 203 setFocusPolicy (Qt::WheelFocus); |
204 setFocusPolicy (Qt::WheelFocus); |
| 204 compileAllObjects(); |
205 compileAllObjects(); |
| 205 } |
206 } |
| 206 |
207 |
| 207 // ============================================================================= |
208 // ============================================================================= |
| 208 // ----------------------------------------------------------------------------- |
209 // ----------------------------------------------------------------------------- |
| 209 QColor GLRenderer::getMainColor() { |
210 QColor GLRenderer::getMainColor() |
| 210 QColor col (gl_maincolor); |
211 { QColor col (gl_maincolor); |
| 211 |
212 |
| 212 if (!col.isValid()) |
213 if (!col.isValid()) |
| 213 return QColor (0, 0, 0); |
214 return QColor (0, 0, 0); |
| 214 |
215 |
| 215 col.setAlpha (gl_maincolor_alpha * 255.f); |
216 col.setAlpha (gl_maincolor_alpha * 255.f); |
| 216 return col; |
217 return col; |
| 217 } |
218 } |
| 218 |
219 |
| 219 // ============================================================================= |
220 // ============================================================================= |
| 220 // ----------------------------------------------------------------------------- |
221 // ----------------------------------------------------------------------------- |
| 221 void GLRenderer::setBackground() { |
222 void GLRenderer::setBackground() |
| 222 QColor col (gl_bgcolor); |
223 { QColor col (gl_bgcolor); |
| 223 |
224 |
| 224 if (!col.isValid()) |
225 if (!col.isValid()) |
| 225 return; |
226 return; |
| 226 |
227 |
| 227 col.setAlpha (255); |
228 col.setAlpha (255); |
| 228 |
229 |
| 229 m_darkbg = luma (col) < 80; |
230 m_darkbg = luma (col) < 80; |
| 230 m_bgcolor = col; |
231 m_bgcolor = col; |
| 231 qglClearColor (col); |
232 qglClearColor (col); |
| 232 } |
233 } |
| 233 |
234 |
| 234 // ============================================================================= |
235 // ============================================================================= |
| 235 // ----------------------------------------------------------------------------- |
236 // ----------------------------------------------------------------------------- |
| 236 void GLRenderer::setObjectColor (LDObject* obj, const ListType list) { |
237 void GLRenderer::setObjectColor (LDObject* obj, const ListType list) |
| 237 QColor qcol; |
238 { QColor qcol; |
| 238 |
239 |
| 239 if (!obj->isColored()) |
240 if (!obj->isColored()) |
| 240 return; |
241 return; |
| 241 |
242 |
| 242 if (list == GL::PickList) { |
243 if (list == GL::PickList) |
| 243 // Make the color by the object's ID if we're picking, so we can make the |
244 { // Make the color by the object's ID if we're picking, so we can make the |
| 244 // ID again from the color we get from the picking results. Be sure to use |
245 // ID again from the color we get from the picking results. Be sure to use |
| 245 // the top level parent's index since we want a subfile's children point |
246 // the top level parent's index since we want a subfile's children point |
| 246 // to the subfile itself. |
247 // to the subfile itself. |
| 247 long i = obj->topLevelParent()->id(); |
248 long i = obj->topLevelParent()->id(); |
| 248 |
249 |
| 249 // Calculate a color based from this index. This method caters for |
250 // Calculate a color based from this index. This method caters for |
| 250 // 16777216 objects. I don't think that'll be exceeded anytime soon. :) |
251 // 16777216 objects. I don't think that'll be exceeded anytime soon. :) |
| 251 // ATM biggest is 53588.dat with 12600 lines. |
252 // ATM biggest is 53588.dat with 12600 lines. |
| 252 double r = (i / (256 * 256)) % 256, |
253 double r = (i / (256 * 256)) % 256, |
| 253 g = (i / 256) % 256, |
254 g = (i / 256) % 256, |
| 254 b = i % 256; |
255 b = i % 256; |
| 255 |
256 |
| 256 qglColor (QColor (r, g, b)); |
257 qglColor (QColor (r, g, b)); |
| 257 return; |
258 return; |
| 258 } |
259 } |
| 259 |
260 |
| 260 if ((list == BFCFrontList || list == BFCBackList) && |
261 if ( (list == BFCFrontList || list == BFCBackList) && |
| 261 obj->getType() != LDObject::Line && |
262 obj->getType() != LDObject::Line && |
| 262 obj->getType() != LDObject::CndLine) { |
263 obj->getType() != LDObject::CndLine) |
| 263 |
264 { |
| |
265 |
| 264 if (list == GL::BFCFrontList) |
266 if (list == GL::BFCFrontList) |
| 265 qcol = QColor (40, 192, 0); |
267 qcol = QColor (40, 192, 0); |
| 266 else |
268 else |
| 267 qcol = QColor (224, 0, 0); |
269 qcol = QColor (224, 0, 0); |
| 268 } else { |
270 } |
| 269 if (obj->color() == maincolor) |
271 else |
| |
272 { if (obj->color() == maincolor) |
| 270 qcol = getMainColor(); |
273 qcol = getMainColor(); |
| 271 else { |
274 else |
| 272 LDColor* col = getColor (obj->color()); |
275 { LDColor* col = getColor (obj->color()); |
| 273 |
276 |
| 274 if (col) |
277 if (col) |
| 275 qcol = col->faceColor; |
278 qcol = col->faceColor; |
| 276 } |
279 } |
| 277 |
280 |
| 278 if (obj->color() == edgecolor) { |
281 if (obj->color() == edgecolor) |
| 279 qcol = luma (m_bgcolor) < 40 ? QColor (64, 64, 64) : Qt::black; |
282 { qcol = luma (m_bgcolor) < 40 ? QColor (64, 64, 64) : Qt::black; |
| 280 LDColor* col; |
283 LDColor* col; |
| 281 |
284 |
| 282 if (!gl_blackedges && obj->parent() && (col = getColor (obj->parent()->color()))) |
285 if (!gl_blackedges && obj->parent() && (col = getColor (obj->parent()->color()))) |
| 283 qcol = col->edgeColor; |
286 qcol = col->edgeColor; |
| 284 } |
287 } |
| 285 |
288 |
| 286 if (qcol.isValid() == false) { |
289 if (qcol.isValid() == false) |
| 287 // The color was unknown. Use main color to make the object at least |
290 { // The color was unknown. Use main color to make the object at least |
| 288 // not appear pitch-black. |
291 // not appear pitch-black. |
| 289 if (obj->color() != edgecolor) |
292 if (obj->color() != edgecolor) |
| 290 qcol = getMainColor(); |
293 qcol = getMainColor(); |
| 291 |
294 |
| 292 // Warn about the unknown colors, but only once. |
295 // Warn about the unknown colors, but only once. |
| 293 for (short i : g_warnedColors) |
296 for (short i : g_warnedColors) |
| 294 if (obj->color() == i) |
297 if (obj->color() == i) |
| 295 return; |
298 return; |
| 296 |
299 |
| 297 printf ("%s: Unknown color %d!\n", __func__, obj->color()); |
300 printf ("%s: Unknown color %d!\n", __func__, obj->color()); |
| 298 g_warnedColors << obj->color(); |
301 g_warnedColors << obj->color(); |
| 299 return; |
302 return; |
| 300 } |
303 } |
| 301 } |
304 } |
| 302 |
305 |
| 303 long r = qcol.red(), |
306 long r = qcol.red(), |
| 304 g = qcol.green(), |
307 g = qcol.green(), |
| 305 b = qcol.blue(), |
308 b = qcol.blue(), |
| 306 a = qcol.alpha(); |
309 a = qcol.alpha(); |
| 307 |
310 |
| 308 if (obj->topLevelParent()->selected()) { |
311 if (obj->topLevelParent()->selected()) |
| 309 // Brighten it up for the select list. |
312 { // Brighten it up for the select list. |
| 310 const uchar add = 51; |
313 const uchar add = 51; |
| 311 |
314 |
| 312 r = min (r + add, 255l); |
315 r = min (r + add, 255l); |
| 313 g = min (g + add, 255l); |
316 g = min (g + add, 255l); |
| 314 b = min (b + add, 255l); |
317 b = min (b + add, 255l); |
| 315 } |
318 } |
| 316 |
319 |
| 317 glColor4f ( |
320 glColor4f ( |
| 318 ((double) r) / 255.0f, |
321 ( (double) r) / 255.0f, |
| 319 ((double) g) / 255.0f, |
322 ( (double) g) / 255.0f, |
| 320 ((double) b) / 255.0f, |
323 ( (double) b) / 255.0f, |
| 321 ((double) a) / 255.0f); |
324 ( (double) a) / 255.0f); |
| 322 } |
325 } |
| 323 |
326 |
| 324 // ============================================================================= |
327 // ============================================================================= |
| 325 // ----------------------------------------------------------------------------- |
328 // ----------------------------------------------------------------------------- |
| 326 void GLRenderer::refresh() { |
329 void GLRenderer::refresh() |
| 327 update(); |
330 { update(); |
| 328 swapBuffers(); |
331 swapBuffers(); |
| 329 } |
332 } |
| 330 |
333 |
| 331 // ============================================================================= |
334 // ============================================================================= |
| 332 // ----------------------------------------------------------------------------- |
335 // ----------------------------------------------------------------------------- |
| 333 void GLRenderer::hardRefresh() { |
336 void GLRenderer::hardRefresh() |
| 334 compileAllObjects(); |
337 { compileAllObjects(); |
| 335 refresh(); |
338 refresh(); |
| 336 |
339 |
| 337 glLineWidth (gl_linethickness); |
340 glLineWidth (gl_linethickness); |
| 338 } |
341 } |
| 339 |
342 |
| 340 // ============================================================================= |
343 // ============================================================================= |
| 341 // ----------------------------------------------------------------------------- |
344 // ----------------------------------------------------------------------------- |
| 342 void GLRenderer::resizeGL (int w, int h) { |
345 void GLRenderer::resizeGL (int w, int h) |
| 343 m_width = w; |
346 { m_width = w; |
| 344 m_height = h; |
347 m_height = h; |
| 345 |
348 |
| 346 calcCameraIcons(); |
349 calcCameraIcons(); |
| 347 |
350 |
| 348 glViewport (0, 0, w, h); |
351 glViewport (0, 0, w, h); |
| 349 glMatrixMode (GL_PROJECTION); |
352 glMatrixMode (GL_PROJECTION); |
| 350 glLoadIdentity(); |
353 glLoadIdentity(); |
| 351 gluPerspective (45.0f, (double) w / (double) h, 1.0f, 10000.0f); |
354 gluPerspective (45.0f, (double) w / (double) h, 1.0f, 10000.0f); |
| 352 glMatrixMode (GL_MODELVIEW); |
355 glMatrixMode (GL_MODELVIEW); |
| 353 } |
356 } |
| 354 |
357 |
| 355 // ============================================================================= |
358 // ============================================================================= |
| 356 // ----------------------------------------------------------------------------- |
359 // ----------------------------------------------------------------------------- |
| 357 void GLRenderer::drawGLScene() { |
360 void GLRenderer::drawGLScene() |
| 358 if (file() == null) |
361 { if (file() == null) |
| 359 return; |
362 return; |
| 360 |
363 |
| 361 if (gl_wireframe && !picking()) |
364 if (gl_wireframe && !picking()) |
| 362 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); |
365 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE); |
| 363 |
366 |
| 364 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
367 glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| 365 glEnable (GL_DEPTH_TEST); |
368 glEnable (GL_DEPTH_TEST); |
| 366 |
369 |
| 367 if (m_camera != Free) { |
370 if (m_camera != Free) |
| 368 glMatrixMode (GL_PROJECTION); |
371 { glMatrixMode (GL_PROJECTION); |
| 369 glPushMatrix(); |
372 glPushMatrix(); |
| 370 |
373 |
| 371 glLoadIdentity(); |
374 glLoadIdentity(); |
| 372 glOrtho (-m_virtWidth, m_virtWidth, -m_virtHeight, m_virtHeight, -100.0f, 100.0f); |
375 glOrtho (-m_virtWidth, m_virtWidth, -m_virtHeight, m_virtHeight, -100.0f, 100.0f); |
| 373 glTranslatef (m_panX, m_panY, 0.0f); |
376 glTranslatef (m_panX, m_panY, 0.0f); |
| 374 |
377 |
| 375 if (m_camera != Front && m_camera != Back) { |
378 if (m_camera != Front && m_camera != Back) |
| 376 glRotatef (90.0f, g_staticCameras[m_camera].glrotate[0], |
379 { glRotatef (90.0f, g_staticCameras[m_camera].glrotate[0], |
| 377 g_staticCameras[m_camera].glrotate[1], |
380 g_staticCameras[m_camera].glrotate[1], |
| 378 g_staticCameras[m_camera].glrotate[2]); |
381 g_staticCameras[m_camera].glrotate[2]); |
| 379 } |
382 } |
| 380 |
383 |
| 381 // Back camera needs to be handled differently |
384 // Back camera needs to be handled differently |
| 382 if (m_camera == GLRenderer::Back) { |
385 if (m_camera == GLRenderer::Back) |
| 383 glRotatef (180.0f, 1.0f, 0.0f, 0.0f); |
386 { glRotatef (180.0f, 1.0f, 0.0f, 0.0f); |
| 384 glRotatef (180.0f, 0.0f, 0.0f, 1.0f); |
387 glRotatef (180.0f, 0.0f, 0.0f, 1.0f); |
| 385 } |
388 } |
| 386 } else { |
389 } |
| 387 glMatrixMode (GL_MODELVIEW); |
390 else |
| |
391 { glMatrixMode (GL_MODELVIEW); |
| 388 glPushMatrix(); |
392 glPushMatrix(); |
| 389 glLoadIdentity(); |
393 glLoadIdentity(); |
| 390 |
394 |
| 391 glTranslatef (0.0f, 0.0f, -2.0f); |
395 glTranslatef (0.0f, 0.0f, -2.0f); |
| 392 glTranslatef (m_panX, m_panY, -zoom()); |
396 glTranslatef (m_panX, m_panY, -zoom()); |
| 393 glRotatef (m_rotX, 1.0f, 0.0f, 0.0f); |
397 glRotatef (m_rotX, 1.0f, 0.0f, 0.0f); |
| 394 glRotatef (m_rotY, 0.0f, 1.0f, 0.0f); |
398 glRotatef (m_rotY, 0.0f, 1.0f, 0.0f); |
| 395 glRotatef (m_rotZ, 0.0f, 0.0f, 1.0f); |
399 glRotatef (m_rotZ, 0.0f, 0.0f, 1.0f); |
| 396 } |
400 } |
| 397 |
401 |
| 398 const GL::ListType list = (!drawOnly() && m_picking) ? PickList : NormalList; |
402 const GL::ListType list = (!drawOnly() && m_picking) ? PickList : NormalList; |
| 399 |
403 |
| 400 if (gl_colorbfc && !m_picking && !drawOnly()) { |
404 if (gl_colorbfc && !m_picking && !drawOnly()) |
| 401 glEnable (GL_CULL_FACE); |
405 { glEnable (GL_CULL_FACE); |
| 402 |
406 |
| 403 for (LDObject* obj : file()->objects()) { |
407 for (LDObject * obj : file()->objects()) |
| 404 if (obj->hidden()) |
408 { if (obj->hidden()) |
| 405 continue; |
409 continue; |
| 406 |
410 |
| 407 glCullFace (GL_BACK); |
411 glCullFace (GL_BACK); |
| 408 glCallList (obj->glLists[BFCFrontList]); |
412 glCallList (obj->glLists[BFCFrontList]); |
| 409 |
413 |
| 410 glCullFace (GL_FRONT); |
414 glCullFace (GL_FRONT); |
| 411 glCallList (obj->glLists[BFCBackList]); |
415 glCallList (obj->glLists[BFCBackList]); |
| 412 } |
416 } |
| 413 |
417 |
| 414 glDisable (GL_CULL_FACE); |
418 glDisable (GL_CULL_FACE); |
| 415 } else { |
419 } |
| 416 for (LDObject* obj : file()->objects()) { |
420 else |
| 417 if (obj->hidden()) |
421 { for (LDObject * obj : file()->objects()) |
| |
422 { if (obj->hidden()) |
| 418 continue; |
423 continue; |
| 419 |
424 |
| 420 glCallList (obj->glLists[list]); |
425 glCallList (obj->glLists[list]); |
| 421 } |
426 } |
| 422 } |
427 } |
| 423 |
428 |
| 424 if (gl_axes && !m_picking && !drawOnly()) |
429 if (gl_axes && !m_picking && !drawOnly()) |
| 425 glCallList (m_axeslist); |
430 glCallList (m_axeslist); |
| 426 |
431 |
| 427 glPopMatrix(); |
432 glPopMatrix(); |
| 428 glMatrixMode (GL_MODELVIEW); |
433 glMatrixMode (GL_MODELVIEW); |
| 429 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); |
434 glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); |
| 430 } |
435 } |
| 431 |
436 |
| 432 // ============================================================================= |
437 // ============================================================================= |
| 433 // ----------------------------------------------------------------------------- |
438 // ----------------------------------------------------------------------------- |
| 434 // This converts a 2D point on the screen to a 3D point in the model. If 'snap' |
439 // This converts a 2D point on the screen to a 3D point in the model. If 'snap' |
| 435 // is true, the 3D point will snap to the current grid. |
440 // is true, the 3D point will snap to the current grid. |
| 436 // ----------------------------------------------------------------------------- |
441 // ----------------------------------------------------------------------------- |
| 437 vertex GLRenderer::coordconv2_3 (const QPoint& pos2d, bool snap) const { |
442 vertex GLRenderer::coordconv2_3 (const QPoint& pos2d, bool snap) const |
| 438 assert (camera() != Free); |
443 { assert (camera() != Free); |
| 439 |
444 |
| 440 vertex pos3d; |
445 vertex pos3d; |
| 441 const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
446 const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
| 442 const Axis axisX = cam->axisX; |
447 const Axis axisX = cam->axisX; |
| 443 const Axis axisY = cam->axisY; |
448 const Axis axisY = cam->axisY; |
| 444 const short negXFac = cam->negX ? -1 : 1, |
449 const short negXFac = cam->negX ? -1 : 1, |
| 445 negYFac = cam->negY ? -1 : 1; |
450 negYFac = cam->negY ? -1 : 1; |
| 446 |
451 |
| 447 // Calculate cx and cy - these are the LDraw unit coords the cursor is at. |
452 // Calculate cx and cy - these are the LDraw unit coords the cursor is at. |
| 448 double cx = (-m_virtWidth + ((2 * pos2d.x() * m_virtWidth) / m_width) - m_panX); |
453 double cx = (-m_virtWidth + ( (2 * pos2d.x() * m_virtWidth) / m_width) - m_panX); |
| 449 double cy = (m_virtHeight - ((2 * pos2d.y() * m_virtHeight) / m_height) - m_panY); |
454 double cy = (m_virtHeight - ( (2 * pos2d.y() * m_virtHeight) / m_height) - m_panY); |
| 450 |
455 |
| 451 if (snap) { |
456 if (snap) |
| 452 cx = Grid::snap (cx, (Grid::Config) axisX); |
457 { cx = Grid::snap (cx, (Grid::Config) axisX); |
| 453 cy = Grid::snap (cy, (Grid::Config) axisY); |
458 cy = Grid::snap (cy, (Grid::Config) axisY); |
| 454 } |
459 } |
| 455 |
460 |
| 456 cx *= negXFac; |
461 cx *= negXFac; |
| 457 cy *= negYFac; |
462 cy *= negYFac; |
| 458 |
463 |
| 459 str tmp; |
464 str tmp; |
| 460 // Create the vertex from the coordinates |
465 // Create the vertex from the coordinates |
| 461 pos3d[axisX] = tmp.sprintf ("%.3f", cx).toDouble(); |
466 pos3d[axisX] = tmp.sprintf ("%.3f", cx).toDouble(); |
| 462 pos3d[axisY] = tmp.sprintf ("%.3f", cy).toDouble(); |
467 pos3d[axisY] = tmp.sprintf ("%.3f", cy).toDouble(); |
| 463 pos3d[3 - axisX - axisY] = depthValue(); |
468 pos3d[3 - axisX - axisY] = depthValue(); |
| 467 // ============================================================================= |
472 // ============================================================================= |
| 468 // ----------------------------------------------------------------------------- |
473 // ----------------------------------------------------------------------------- |
| 469 // Inverse operation for the above - convert a 3D position to a 2D screen |
474 // Inverse operation for the above - convert a 3D position to a 2D screen |
| 470 // position |
475 // position |
| 471 // ----------------------------------------------------------------------------- |
476 // ----------------------------------------------------------------------------- |
| 472 QPoint GLRenderer::coordconv3_2 (const vertex& pos3d) const { |
477 QPoint GLRenderer::coordconv3_2 (const vertex& pos3d) const |
| 473 GLfloat m[16]; |
478 { GLfloat m[16]; |
| 474 const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
479 const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
| 475 const Axis axisX = cam->axisX; |
480 const Axis axisX = cam->axisX; |
| 476 const Axis axisY = cam->axisY; |
481 const Axis axisY = cam->axisY; |
| 477 const short negXFac = cam->negX ? -1 : 1, |
482 const short negXFac = cam->negX ? -1 : 1, |
| 478 negYFac = cam->negY ? -1 : 1; |
483 negYFac = cam->negY ? -1 : 1; |
| 479 |
484 |
| 480 glGetFloatv (GL_MODELVIEW_MATRIX, m); |
485 glGetFloatv (GL_MODELVIEW_MATRIX, m); |
| 481 |
486 |
| 482 const double x = pos3d.x(); |
487 const double x = pos3d.x(); |
| 483 const double y = pos3d.y(); |
488 const double y = pos3d.y(); |
| 484 const double z = pos3d.z(); |
489 const double z = pos3d.z(); |
| 485 |
490 |
| 486 vertex transformed; |
491 vertex transformed; |
| 487 transformed[X] = (m[0] * x) + (m[1] * y) + (m[2] * z) + m[3]; |
492 transformed[X] = (m[0] * x) + (m[1] * y) + (m[2] * z) + m[3]; |
| 488 transformed[Y] = (m[4] * x) + (m[5] * y) + (m[6] * z) + m[7]; |
493 transformed[Y] = (m[4] * x) + (m[5] * y) + (m[6] * z) + m[7]; |
| 489 transformed[Z] = (m[8] * x) + (m[9] * y) + (m[10] * z) + m[11]; |
494 transformed[Z] = (m[8] * x) + (m[9] * y) + (m[10] * z) + m[11]; |
| 490 |
495 |
| 491 double rx = (((transformed[axisX] * negXFac) + m_virtWidth + m_panX) * m_width) / (2 * m_virtWidth); |
496 double rx = ( ( (transformed[axisX] * negXFac) + m_virtWidth + m_panX) * m_width) / (2 * m_virtWidth); |
| 492 double ry = (((transformed[axisY] * negYFac) - m_virtHeight + m_panY) * m_height) / (2 * m_virtHeight); |
497 double ry = ( ( (transformed[axisY] * negYFac) - m_virtHeight + m_panY) * m_height) / (2 * m_virtHeight); |
| 493 |
498 |
| 494 return QPoint (rx, -ry); |
499 return QPoint (rx, -ry); |
| 495 } |
500 } |
| 496 |
501 |
| 497 // ============================================================================= |
502 // ============================================================================= |
| 498 // ----------------------------------------------------------------------------- |
503 // ----------------------------------------------------------------------------- |
| 499 void GLRenderer::paintEvent (QPaintEvent* ev) { |
504 void GLRenderer::paintEvent (QPaintEvent* ev) |
| 500 Q_UNUSED (ev) |
505 { Q_UNUSED (ev) |
| 501 |
506 |
| 502 makeCurrent(); |
507 makeCurrent(); |
| 503 m_virtWidth = zoom(); |
508 m_virtWidth = zoom(); |
| 504 m_virtHeight = (m_height * m_virtWidth) / m_width; |
509 m_virtHeight = (m_height * m_virtWidth) / m_width; |
| 505 |
510 |
| 506 initGLData(); |
511 initGLData(); |
| 507 drawGLScene(); |
512 drawGLScene(); |
| 508 |
513 |
| 509 QPainter paint (this); |
514 QPainter paint (this); |
| 510 QFontMetrics metrics = QFontMetrics (QFont()); |
515 QFontMetrics metrics = QFontMetrics (QFont()); |
| 511 paint.setRenderHint (QPainter::HighQualityAntialiasing); |
516 paint.setRenderHint (QPainter::HighQualityAntialiasing); |
| 512 |
517 |
| 513 // If we wish to only draw the brick, stop here |
518 // If we wish to only draw the brick, stop here |
| 514 if (drawOnly()) |
519 if (drawOnly()) |
| 515 return; |
520 return; |
| 516 |
521 |
| 517 if (m_camera != Free && !picking()) { |
522 if (m_camera != Free && !picking()) |
| 518 // Paint the overlay image if we have one |
523 { // Paint the overlay image if we have one |
| 519 const overlayMeta& overlay = m_overlays[m_camera]; |
524 const overlayMeta& overlay = m_overlays[m_camera]; |
| 520 if (overlay.img != null) { |
525 |
| 521 QPoint v0 = coordconv3_2 (m_overlays[m_camera].v0), |
526 if (overlay.img != null) |
| 522 v1 = coordconv3_2 (m_overlays[m_camera].v1); |
527 { QPoint v0 = coordconv3_2 (m_overlays[m_camera].v0), |
| 523 |
528 v1 = coordconv3_2 (m_overlays[m_camera].v1); |
| |
529 |
| 524 QRect targRect (v0.x(), v0.y(), abs (v1.x() - v0.x()), abs (v1.y() - v0.y())), |
530 QRect targRect (v0.x(), v0.y(), abs (v1.x() - v0.x()), abs (v1.y() - v0.y())), |
| 525 srcRect (0, 0, overlay.img->width(), overlay.img->height()); |
531 srcRect (0, 0, overlay.img->width(), overlay.img->height()); |
| 526 paint.drawImage (targRect, *overlay.img, srcRect); |
532 paint.drawImage (targRect, *overlay.img, srcRect); |
| 527 } |
533 } |
| 528 |
534 |
| 529 // Paint the coordinates onto the screen. |
535 // Paint the coordinates onto the screen. |
| 530 str text = fmt (tr ("X: %1, Y: %2, Z: %3"), m_hoverpos[X], m_hoverpos[Y], m_hoverpos[Z]); |
536 str text = fmt (tr ("X: %1, Y: %2, Z: %3"), m_hoverpos[X], m_hoverpos[Y], m_hoverpos[Z]); |
| 531 |
537 |
| 532 QFontMetrics metrics = QFontMetrics (font()); |
538 QFontMetrics metrics = QFontMetrics (font()); |
| 533 QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text); |
539 QRect textSize = metrics.boundingRect (0, 0, m_width, m_height, Qt::AlignCenter, text); |
| 534 |
540 |
| 535 paint.setPen (getTextPen()); |
541 paint.setPen (getTextPen()); |
| 536 paint.drawText (m_width - textSize.width(), m_height - 16, textSize.width(), |
542 paint.drawText (m_width - textSize.width(), m_height - 16, textSize.width(), |
| 537 textSize.height(), Qt::AlignCenter, text); |
543 textSize.height(), Qt::AlignCenter, text); |
| 538 |
544 |
| 539 // If we're drawing, draw the vertices onto the screen. |
545 // If we're drawing, draw the vertices onto the screen. |
| 540 if (editMode() == Draw) { |
546 if (editMode() == Draw) |
| 541 int numverts = 4; |
547 { int numverts = 4; |
| 542 |
548 |
| 543 if (!m_rectdraw) |
549 if (!m_rectdraw) |
| 544 numverts = m_drawedVerts.size() + 1; |
550 numverts = m_drawedVerts.size() + 1; |
| 545 |
551 |
| 546 if (numverts > 0) { |
552 if (numverts > 0) |
| 547 QPoint poly[4]; |
553 { QPoint poly[4]; |
| 548 vertex polyverts[4]; |
554 vertex polyverts[4]; |
| 549 |
555 |
| 550 if (!m_rectdraw) { |
556 if (!m_rectdraw) |
| 551 uchar i = 0; |
557 { uchar i = 0; |
| 552 for (vertex& vert : m_drawedVerts) { |
558 |
| 553 poly[i] = coordconv3_2 (vert); |
559 for (vertex & vert : m_drawedVerts) |
| |
560 { poly[i] = coordconv3_2 (vert); |
| 554 polyverts[i] = vert; |
561 polyverts[i] = vert; |
| 555 ++i; |
562 ++i; |
| 556 } |
563 } |
| 557 |
564 |
| 558 // Draw the cursor vertex as the last one in the list. |
565 // Draw the cursor vertex as the last one in the list. |
| 559 if (numverts <= 4) { |
566 if (numverts <= 4) |
| 560 poly[i] = coordconv3_2 (m_hoverpos); |
567 { poly[i] = coordconv3_2 (m_hoverpos); |
| 561 polyverts[i] = m_hoverpos; |
568 polyverts[i] = m_hoverpos; |
| 562 } else { |
|
| 563 numverts = 4; |
|
| 564 } |
569 } |
| 565 } else { |
570 else |
| 566 if (m_drawedVerts.size() > 0) { |
571 { numverts = 4; |
| 567 // Get vertex information from m_rectverts |
572 } |
| 568 for (int i = 0; i < numverts; ++i) { |
573 } |
| 569 polyverts[i] = m_rectverts[i]; |
574 else |
| |
575 { if (m_drawedVerts.size() > 0) |
| |
576 { // Get vertex information from m_rectverts |
| |
577 for (int i = 0; i < numverts; ++i) |
| |
578 { polyverts[i] = m_rectverts[i]; |
| 570 poly[i] = coordconv3_2 (polyverts[i]); |
579 poly[i] = coordconv3_2 (polyverts[i]); |
| 571 } |
580 } |
| 572 } else { |
581 } |
| 573 poly[0] = coordconv3_2 (m_hoverpos); |
582 else |
| |
583 { poly[0] = coordconv3_2 (m_hoverpos); |
| 574 polyverts[0] = m_hoverpos; |
584 polyverts[0] = m_hoverpos; |
| 575 } |
585 } |
| 576 } |
586 } |
| 577 |
587 |
| 578 // Draw the polygon-to-be |
588 // Draw the polygon-to-be |
| 579 QPen pen = m_thinBorderPen; |
589 QPen pen = m_thinBorderPen; |
| 580 pen.setWidth (2); |
590 pen.setWidth (2); |
| 581 pen.setColor (luma (m_bgcolor) < 40 ? Qt::white : Qt::black); |
591 pen.setColor (luma (m_bgcolor) < 40 ? Qt::white : Qt::black); |
| 582 paint.setPen (pen); |
592 paint.setPen (pen); |
| 583 paint.setBrush (QColor (64, 192, 0, 128)); |
593 paint.setBrush (QColor (64, 192, 0, 128)); |
| 584 paint.drawPolygon (poly, numverts); |
594 paint.drawPolygon (poly, numverts); |
| 585 |
595 |
| 586 // Draw vertex blips |
596 // Draw vertex blips |
| 587 for (int i = 0; i < numverts; ++i) { |
597 for (int i = 0; i < numverts; ++i) |
| 588 QPoint& blip = poly[i]; |
598 { QPoint& blip = poly[i]; |
| 589 drawBlip (paint, blip); |
599 drawBlip (paint, blip); |
| 590 |
600 |
| 591 // Draw their coordinates |
601 // Draw their coordinates |
| 592 paint.drawText (blip.x(), blip.y() - 8, polyverts[i].stringRep (true)); |
602 paint.drawText (blip.x(), blip.y() - 8, polyverts[i].stringRep (true)); |
| 593 } |
603 } |
| 594 } |
604 } |
| 595 } |
605 } |
| |
606 |
| 596 elif (editMode() == CircleMode) |
607 elif (editMode() == CircleMode) |
| 597 { // If we have not specified the center point of the circle yet, preview it on the screen. |
608 { // If we have not specified the center point of the circle yet, preview it on the screen. |
| 598 if (m_drawedVerts.size() == 0) |
609 if (m_drawedVerts.size() == 0) |
| 599 drawBlip (paint, coordconv3_2 (m_hoverpos)); |
610 drawBlip (paint, coordconv3_2 (m_hoverpos)); |
| 600 else |
611 else |
| 710 paint.drawEllipse (pos.x() - blipsize / 2, pos.y() - blipsize / 2, blipsize, blipsize); |
721 paint.drawEllipse (pos.x() - blipsize / 2, pos.y() - blipsize / 2, blipsize, blipsize); |
| 711 } |
722 } |
| 712 |
723 |
| 713 // ============================================================================= |
724 // ============================================================================= |
| 714 // ----------------------------------------------------------------------------- |
725 // ----------------------------------------------------------------------------- |
| 715 QColor GLRenderer::getTextPen () const { |
726 QColor GLRenderer::getTextPen () const |
| 716 return m_darkbg ? Qt::white : Qt::black; |
727 { return m_darkbg ? Qt::white : Qt::black; |
| 717 } |
728 } |
| 718 |
729 |
| 719 // ============================================================================= |
730 // ============================================================================= |
| 720 // ----------------------------------------------------------------------------- |
731 // ----------------------------------------------------------------------------- |
| 721 void GLRenderer::compileAllObjects() { |
732 void GLRenderer::compileAllObjects() |
| 722 if (!file()) |
733 { if (!file()) |
| 723 return; |
734 return; |
| 724 |
735 |
| 725 // Compiling all is a big job, use a busy cursor |
736 // Compiling all is a big job, use a busy cursor |
| 726 setCursor (Qt::BusyCursor); |
737 setCursor (Qt::BusyCursor); |
| 727 |
738 |
| 728 m_knownVerts.clear(); |
739 m_knownVerts.clear(); |
| 729 |
740 |
| 730 for (LDObject* obj : file()->objects()) |
741 for (LDObject * obj : file()->objects()) |
| 731 compileObject (obj); |
742 compileObject (obj); |
| 732 |
743 |
| 733 // Compile axes |
744 // Compile axes |
| 734 glDeleteLists (m_axeslist, 1); |
745 glDeleteLists (m_axeslist, 1); |
| 735 m_axeslist = glGenLists (1); |
746 m_axeslist = glGenLists (1); |
| 736 glNewList (m_axeslist, GL_COMPILE); |
747 glNewList (m_axeslist, GL_COMPILE); |
| 737 glBegin (GL_LINES); |
748 glBegin (GL_LINES); |
| 738 |
749 |
| 739 for (const GLAxis& ax : g_GLAxes) { |
750 for (const GLAxis & ax : g_GLAxes) |
| 740 qglColor (ax.col); |
751 { qglColor (ax.col); |
| 741 compileVertex (ax.vert); |
752 compileVertex (ax.vert); |
| 742 compileVertex (-ax.vert); |
753 compileVertex (-ax.vert); |
| 743 } |
754 } |
| 744 |
755 |
| 745 glEnd(); |
756 glEnd(); |
| 746 glEndList(); |
757 glEndList(); |
| 747 |
758 |
| 748 setCursor (Qt::ArrowCursor); |
759 setCursor (Qt::ArrowCursor); |
| 749 } |
760 } |
| 750 |
761 |
| 751 // ============================================================================= |
762 // ============================================================================= |
| 752 // ----------------------------------------------------------------------------- |
763 // ----------------------------------------------------------------------------- |
| 753 void GLRenderer::compileSubObject (LDObject* obj, const GLenum gltype) { |
764 void GLRenderer::compileSubObject (LDObject* obj, const GLenum gltype) |
| 754 glBegin (gltype); |
765 { glBegin (gltype); |
| 755 |
766 |
| 756 const short numverts = (obj->getType() != LDObject::CndLine) ? obj->vertices() : 2; |
767 const short numverts = (obj->getType() != LDObject::CndLine) ? obj->vertices() : 2; |
| 757 |
768 |
| 758 if (g_glInvert == false) |
769 if (g_glInvert == false) |
| 759 for (short i = 0; i < numverts; ++i) |
770 for (short i = 0; i < numverts; ++i) |
| 760 compileVertex (obj->m_coords[i]); |
771 compileVertex (obj->m_coords[i]); |
| 761 else |
772 else |
| 762 for (short i = numverts - 1; i >= 0; --i) |
773 for (short i = numverts - 1; i >= 0; --i) |
| 763 compileVertex (obj->m_coords[i]); |
774 compileVertex (obj->m_coords[i]); |
| 764 |
775 |
| 765 glEnd(); |
776 glEnd(); |
| 766 } |
777 } |
| 767 |
778 |
| 768 // ============================================================================= |
779 // ============================================================================= |
| 769 // ----------------------------------------------------------------------------- |
780 // ----------------------------------------------------------------------------- |
| 770 void GLRenderer::compileList (LDObject* obj, const GLRenderer::ListType list) { |
781 void GLRenderer::compileList (LDObject* obj, const GLRenderer::ListType list) |
| 771 setObjectColor (obj, list); |
782 { setObjectColor (obj, list); |
| 772 |
783 |
| 773 switch (obj->getType()) { |
784 switch (obj->getType()) |
| 774 case LDObject::Line: |
785 { case LDObject::Line: |
| 775 compileSubObject (obj, GL_LINES); |
786 compileSubObject (obj, GL_LINES); |
| 776 break; |
787 break; |
| 777 |
788 |
| 778 case LDObject::CndLine: |
789 case LDObject::CndLine: |
| 779 // Draw conditional lines with a dash pattern - however, use a full |
790 |
| 780 // line when drawing a pick list to make selecting them easier. |
791 // Draw conditional lines with a dash pattern - however, use a full |
| 781 if (list != GL::PickList) { |
792 // line when drawing a pick list to make selecting them easier. |
| 782 glLineStipple (1, 0x6666); |
793 if (list != GL::PickList) |
| 783 glEnable (GL_LINE_STIPPLE); |
794 { glLineStipple (1, 0x6666); |
| 784 } |
795 glEnable (GL_LINE_STIPPLE); |
| 785 |
796 } |
| 786 compileSubObject (obj, GL_LINES); |
797 |
| 787 |
798 compileSubObject (obj, GL_LINES); |
| 788 glDisable (GL_LINE_STIPPLE); |
799 |
| 789 break; |
800 glDisable (GL_LINE_STIPPLE); |
| 790 |
801 break; |
| 791 case LDObject::Triangle: |
802 |
| 792 compileSubObject (obj, GL_TRIANGLES); |
803 case LDObject::Triangle: |
| 793 break; |
804 compileSubObject (obj, GL_TRIANGLES); |
| 794 |
805 break; |
| 795 case LDObject::Quad: |
806 |
| 796 compileSubObject (obj, GL_QUADS); |
807 case LDObject::Quad: |
| 797 break; |
808 compileSubObject (obj, GL_QUADS); |
| 798 |
809 break; |
| 799 case LDObject::Subfile: { |
810 |
| 800 LDSubfile* ref = static_cast<LDSubfile*> (obj); |
811 case LDObject::Subfile: |
| |
812 { LDSubfile* ref = static_cast<LDSubfile*> (obj); |
| 801 List<LDObject*> objs; |
813 List<LDObject*> objs; |
| 802 |
814 |
| 803 objs = ref->inlineContents ( |
815 objs = ref->inlineContents ( |
| 804 LDSubfile::DeepInline | |
816 LDSubfile::DeepInline | |
| 805 LDSubfile::CacheInline | |
817 LDSubfile::CacheInline | |
| 806 LDSubfile::RendererInline); |
818 LDSubfile::RendererInline); |
| 807 bool oldinvert = g_glInvert; |
819 bool oldinvert = g_glInvert; |
| 808 |
820 |
| 809 if (ref->transform().determinant() < 0) |
821 if (ref->transform().determinant() < 0) |
| 810 g_glInvert = !g_glInvert; |
822 g_glInvert = !g_glInvert; |
| 811 |
823 |
| 812 LDObject* prev = ref->prev(); |
824 LDObject* prev = ref->prev(); |
| |
825 |
| 813 if (prev && prev->getType() == LDObject::BFC && static_cast<LDBFC*> (prev)->type == LDBFC::InvertNext) |
826 if (prev && prev->getType() == LDObject::BFC && static_cast<LDBFC*> (prev)->type == LDBFC::InvertNext) |
| 814 g_glInvert = !g_glInvert; |
827 g_glInvert = !g_glInvert; |
| 815 |
828 |
| 816 for (LDObject* obj : objs) { |
829 for (LDObject * obj : objs) |
| 817 compileList (obj, list); |
830 { compileList (obj, list); |
| 818 delete obj; |
831 delete obj; |
| 819 } |
832 } |
| 820 |
833 |
| 821 g_glInvert = oldinvert; |
834 g_glInvert = oldinvert; |
| 822 } |
835 } |
| 823 break; |
836 break; |
| 824 |
837 |
| 825 default: |
838 default: |
| 826 break; |
839 break; |
| 827 } |
840 } |
| 828 } |
841 } |
| 829 |
842 |
| 830 // ============================================================================= |
843 // ============================================================================= |
| 831 // ----------------------------------------------------------------------------- |
844 // ----------------------------------------------------------------------------- |
| 832 void GLRenderer::compileVertex (const vertex& vrt) { |
845 void GLRenderer::compileVertex (const vertex& vrt) |
| 833 glVertex3d (vrt[X], -vrt[Y], -vrt[Z]); |
846 { glVertex3d (vrt[X], -vrt[Y], -vrt[Z]); |
| 834 } |
847 } |
| 835 |
848 |
| 836 // ============================================================================= |
849 // ============================================================================= |
| 837 // ----------------------------------------------------------------------------- |
850 // ----------------------------------------------------------------------------- |
| 838 void GLRenderer::clampAngle (double& angle) const { |
851 void GLRenderer::clampAngle (double& angle) const |
| 839 while (angle < 0) |
852 { while (angle < 0) |
| 840 angle += 360.0; |
853 angle += 360.0; |
| |
854 |
| 841 while (angle > 360.0) |
855 while (angle > 360.0) |
| 842 angle -= 360.0; |
856 angle -= 360.0; |
| 843 } |
857 } |
| 844 |
858 |
| 845 // ============================================================================= |
859 // ============================================================================= |
| 846 // ----------------------------------------------------------------------------- |
860 // ----------------------------------------------------------------------------- |
| 847 void GLRenderer::addDrawnVertex (vertex pos) { |
861 void GLRenderer::addDrawnVertex (vertex pos) |
| 848 // If we picked an already-existing vertex, stop drawing |
862 { // If we picked an already-existing vertex, stop drawing |
| 849 for (vertex& vert : m_drawedVerts) { |
863 for (vertex & vert : m_drawedVerts) |
| 850 if (vert == pos) { |
864 { if (vert == pos) |
| 851 endDraw (true); |
865 { endDraw (true); |
| 852 return; |
866 return; |
| 853 } |
867 } |
| 854 } |
868 } |
| 855 |
869 |
| 856 m_drawedVerts << pos; |
870 m_drawedVerts << pos; |
| 857 } |
871 } |
| 858 |
872 |
| 859 // ============================================================================= |
873 // ============================================================================= |
| 860 // ----------------------------------------------------------------------------- |
874 // ----------------------------------------------------------------------------- |
| 861 void GLRenderer::mouseReleaseEvent (QMouseEvent* ev) { |
875 void GLRenderer::mouseReleaseEvent (QMouseEvent* ev) |
| 862 const bool wasLeft = (m_lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton), |
876 { const bool wasLeft = (m_lastButtons & Qt::LeftButton) && ! (ev->buttons() & Qt::LeftButton), |
| 863 wasRight = (m_lastButtons & Qt::RightButton) && !(ev->buttons() & Qt::RightButton), |
877 wasRight = (m_lastButtons & Qt::RightButton) && ! (ev->buttons() & Qt::RightButton), |
| 864 wasMid = (m_lastButtons & Qt::MidButton) && !(ev->buttons() & Qt::MidButton); |
878 wasMid = (m_lastButtons & Qt::MidButton) && ! (ev->buttons() & Qt::MidButton); |
| 865 |
879 |
| 866 if (m_panning) |
880 if (m_panning) |
| 867 m_panning = false; |
881 m_panning = false; |
| 868 |
882 |
| 869 if (wasLeft) { |
883 if (wasLeft) |
| 870 // Check if we selected a camera icon |
884 { // Check if we selected a camera icon |
| 871 if (!m_rangepick) { |
885 if (!m_rangepick) |
| 872 for (CameraIcon& info : m_cameraIcons) { |
886 { for (CameraIcon & info : m_cameraIcons) |
| 873 if (info.destRect.contains (ev->pos())) { |
887 { if (info.destRect.contains (ev->pos())) |
| 874 setCamera (info.cam); |
888 { setCamera (info.cam); |
| 875 goto end; |
889 goto end; |
| 876 } |
890 } |
| 877 } |
891 } |
| 878 } |
892 } |
| 879 |
893 |
| 880 switch (editMode()) { |
894 switch (editMode()) |
| 881 case Draw: |
895 { case Draw: |
| 882 if (m_rectdraw) { |
896 |
| 883 if (m_drawedVerts.size() == 2) { |
897 if (m_rectdraw) |
| 884 endDraw (true); |
898 { if (m_drawedVerts.size() == 2) |
| |
899 { endDraw (true); |
| |
900 return; |
| |
901 } |
| |
902 } |
| |
903 else |
| |
904 { // If we have 4 verts, stop drawing. |
| |
905 if (m_drawedVerts.size() >= 4) |
| |
906 { endDraw (true); |
| |
907 return; |
| |
908 } |
| |
909 |
| |
910 if (m_drawedVerts.size() == 0 && ev->modifiers() & Qt::ShiftModifier) |
| |
911 { m_rectdraw = true; |
| |
912 updateRectVerts(); |
| |
913 } |
| |
914 } |
| |
915 |
| |
916 addDrawnVertex (m_hoverpos); |
| |
917 break; |
| |
918 |
| |
919 case CircleMode: |
| |
920 |
| |
921 if (m_drawedVerts.size() == 2) |
| |
922 { endDraw (true); |
| 885 return; |
923 return; |
| 886 } |
924 } |
| 887 } else { |
925 |
| 888 // If we have 4 verts, stop drawing. |
926 addDrawnVertex (m_hoverpos); |
| 889 if (m_drawedVerts.size() >= 4) { |
927 break; |
| 890 endDraw (true); |
928 |
| 891 return; |
929 case Select: |
| |
930 |
| |
931 if (!drawOnly()) |
| |
932 { if (m_totalmove < 10) |
| |
933 m_rangepick = false; |
| |
934 |
| |
935 if (!m_rangepick) |
| |
936 m_addpick = (m_keymods & Qt::ControlModifier); |
| |
937 |
| |
938 if (m_totalmove < 10 || m_rangepick) |
| |
939 pick (ev->x(), ev->y()); |
| 892 } |
940 } |
| 893 |
941 |
| 894 if (m_drawedVerts.size() == 0 && ev->modifiers() & Qt::ShiftModifier) { |
942 break; |
| 895 m_rectdraw = true; |
943 } |
| 896 updateRectVerts(); |
944 |
| 897 } |
|
| 898 } |
|
| 899 |
|
| 900 addDrawnVertex (m_hoverpos); |
|
| 901 break; |
|
| 902 |
|
| 903 case CircleMode: |
|
| 904 if (m_drawedVerts.size() == 2) |
|
| 905 { endDraw (true); |
|
| 906 return; |
|
| 907 } |
|
| 908 |
|
| 909 addDrawnVertex (m_hoverpos); |
|
| 910 break; |
|
| 911 |
|
| 912 case Select: |
|
| 913 if (!drawOnly()) { |
|
| 914 if (m_totalmove < 10) |
|
| 915 m_rangepick = false; |
|
| 916 |
|
| 917 if (!m_rangepick) |
|
| 918 m_addpick = (m_keymods & Qt::ControlModifier); |
|
| 919 |
|
| 920 if (m_totalmove < 10 || m_rangepick) |
|
| 921 pick (ev->x(), ev->y()); |
|
| 922 } |
|
| 923 |
|
| 924 break; |
|
| 925 } |
|
| 926 |
|
| 927 m_rangepick = false; |
945 m_rangepick = false; |
| 928 } |
946 } |
| 929 |
947 |
| 930 if (wasMid && editMode() == Draw && m_drawedVerts.size() < 4 && m_totalmove < 10) { |
948 if (wasMid && editMode() != Select && m_drawedVerts.size() < 4 && m_totalmove < 10) |
| 931 // Find the closest vertex to our cursor |
949 { // Find the closest vertex to our cursor |
| 932 double mindist = 1024.0f; |
950 double mindist = 1024.0f; |
| 933 vertex closest; |
951 vertex closest; |
| 934 bool valid = false; |
952 bool valid = false; |
| 935 |
953 |
| 936 QPoint curspos = coordconv3_2 (m_hoverpos); |
954 QPoint curspos = coordconv3_2 (m_hoverpos); |
| 937 |
955 |
| 938 for (const vertex& pos3d: m_knownVerts) { |
956 for (const vertex & pos3d: m_knownVerts) |
| 939 QPoint pos2d = coordconv3_2 (pos3d); |
957 { QPoint pos2d = coordconv3_2 (pos3d); |
| 940 |
958 |
| 941 // Measure squared distance |
959 // Measure squared distance |
| 942 const double dx = abs (pos2d.x() - curspos.x()), |
960 const double dx = abs (pos2d.x() - curspos.x()), |
| 943 dy = abs (pos2d.y() - curspos.y()), |
961 dy = abs (pos2d.y() - curspos.y()), |
| 944 distsq = (dx * dx) + (dy * dy); |
962 distsq = (dx * dx) + (dy * dy); |
| 945 |
963 |
| 946 if (distsq >= 1024.0f) // 32.0f ** 2 |
964 if (distsq >= 1024.0f) // 32.0f ** 2 |
| 947 continue; // too far away |
965 continue; // too far away |
| 948 |
966 |
| 949 if (distsq < mindist) { |
967 if (distsq < mindist) |
| 950 mindist = distsq; |
968 { mindist = distsq; |
| 951 closest = pos3d; |
969 closest = pos3d; |
| 952 valid = true; |
970 valid = true; |
| 953 |
971 |
| 954 // If it's only 4 pixels away, I think we found our vertex now. |
972 // If it's only 4 pixels away, I think we found our vertex now. |
| 955 if (distsq <= 16.0f) // 4.0f ** 2 |
973 if (distsq <= 16.0f) // 4.0f ** 2 |
| 956 break; |
974 break; |
| 957 } |
975 } |
| 958 } |
976 } |
| 959 |
977 |
| 960 if (valid) |
978 if (valid) |
| 961 addDrawnVertex (closest); |
979 addDrawnVertex (closest); |
| 962 } |
980 } |
| 963 |
981 |
| 964 if (wasRight && m_drawedVerts.size() > 0) { |
982 if (wasRight && m_drawedVerts.size() > 0) |
| 965 // Remove the last vertex |
983 { // Remove the last vertex |
| 966 m_drawedVerts.erase (m_drawedVerts.size() - 1); |
984 m_drawedVerts.erase (m_drawedVerts.size() - 1); |
| 967 |
985 |
| 968 if (m_drawedVerts.size() == 0) |
986 if (m_drawedVerts.size() == 0) |
| 969 m_rectdraw = false; |
987 m_rectdraw = false; |
| 970 } |
988 } |
| 971 |
989 |
| 972 end: |
990 end: |
| 973 update(); |
991 update(); |
| 974 m_totalmove = 0; |
992 m_totalmove = 0; |
| 975 } |
993 } |
| 976 |
994 |
| 977 // ============================================================================= |
995 // ============================================================================= |
| 978 // ----------------------------------------------------------------------------- |
996 // ----------------------------------------------------------------------------- |
| 979 void GLRenderer::mousePressEvent (QMouseEvent* ev) { |
997 void GLRenderer::mousePressEvent (QMouseEvent* ev) |
| 980 m_totalmove = 0; |
998 { m_totalmove = 0; |
| 981 |
999 |
| 982 if (ev->modifiers() & Qt::ControlModifier) { |
1000 if (ev->modifiers() & Qt::ControlModifier) |
| 983 m_rangepick = true; |
1001 { m_rangepick = true; |
| 984 m_rangeStart.setX (ev->x()); |
1002 m_rangeStart.setX (ev->x()); |
| 985 m_rangeStart.setY (ev->y()); |
1003 m_rangeStart.setY (ev->y()); |
| 986 m_addpick = (m_keymods & Qt::AltModifier); |
1004 m_addpick = (m_keymods & Qt::AltModifier); |
| 987 ev->accept(); |
1005 ev->accept(); |
| 988 } |
1006 } |
| 989 |
1007 |
| 990 m_lastButtons = ev->buttons(); |
1008 m_lastButtons = ev->buttons(); |
| 991 } |
1009 } |
| 992 |
1010 |
| 993 // ============================================================================= |
1011 // ============================================================================= |
| 994 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
1012 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
| 995 // ============================================================================= |
1013 // ============================================================================= |
| 996 void GLRenderer::mouseMoveEvent (QMouseEvent* ev) { |
1014 void GLRenderer::mouseMoveEvent (QMouseEvent* ev) |
| 997 int dx = ev->x() - m_pos.x(); |
1015 { int dx = ev->x() - m_pos.x(); |
| 998 int dy = ev->y() - m_pos.y(); |
1016 int dy = ev->y() - m_pos.y(); |
| 999 m_totalmove += abs (dx) + abs (dy); |
1017 m_totalmove += abs (dx) + abs (dy); |
| 1000 |
1018 |
| 1001 const bool left = ev->buttons() & Qt::LeftButton, |
1019 const bool left = ev->buttons() & Qt::LeftButton, |
| 1002 mid = ev->buttons() & Qt::MidButton, |
1020 mid = ev->buttons() & Qt::MidButton, |
| 1003 shift = ev->modifiers() & Qt::ShiftModifier; |
1021 shift = ev->modifiers() & Qt::ShiftModifier; |
| 1004 |
1022 |
| 1005 if (mid || (left && shift)) { |
1023 if (mid || (left && shift)) |
| 1006 m_panX += 0.03f * dx * (zoom() / 7.5f); |
1024 { m_panX += 0.03f * dx * (zoom() / 7.5f); |
| 1007 m_panY -= 0.03f * dy * (zoom() / 7.5f); |
1025 m_panY -= 0.03f * dy * (zoom() / 7.5f); |
| 1008 m_panning = true; |
1026 m_panning = true; |
| 1009 } elif (left && !m_rangepick && camera() == Free) { |
1027 } elif (left && !m_rangepick && camera() == Free) |
| 1010 m_rotX = m_rotX + (dy); |
1028 |
| |
1029 { m_rotX = m_rotX + (dy); |
| 1011 m_rotY = m_rotY + (dx); |
1030 m_rotY = m_rotY + (dx); |
| 1012 |
1031 |
| 1013 clampAngle (m_rotX); |
1032 clampAngle (m_rotX); |
| 1014 clampAngle (m_rotY); |
1033 clampAngle (m_rotY); |
| 1015 } |
1034 } |
| 1016 |
1035 |
| 1017 // Start the tool tip timer |
1036 // Start the tool tip timer |
| 1018 if (!m_drawToolTip) |
1037 if (!m_drawToolTip) |
| 1019 m_toolTipTimer->start (500); |
1038 m_toolTipTimer->start (500); |
| 1020 |
1039 |
| 1021 // Update 2d position |
1040 // Update 2d position |
| 1022 m_pos = ev->pos(); |
1041 m_pos = ev->pos(); |
| 1023 m_globalpos = ev->globalPos(); |
1042 m_globalpos = ev->globalPos(); |
| 1024 |
1043 |
| 1025 // Calculate 3d position of the cursor |
1044 // Calculate 3d position of the cursor |
| 1026 m_hoverpos = (camera() != Free) ? coordconv2_3 (m_pos, true) : g_origin; |
1045 m_hoverpos = (camera() != Free) ? coordconv2_3 (m_pos, true) : g_origin; |
| 1027 |
1046 |
| 1028 // Update rect vertices since m_hoverpos may have changed |
1047 // Update rect vertices since m_hoverpos may have changed |
| 1029 updateRectVerts(); |
1048 updateRectVerts(); |
| 1030 |
1049 |
| 1031 update(); |
1050 update(); |
| 1032 } |
1051 } |
| 1033 |
1052 |
| 1034 // ============================================================================= |
1053 // ============================================================================= |
| 1035 // ----------------------------------------------------------------------------- |
1054 // ----------------------------------------------------------------------------- |
| 1036 void GLRenderer::keyPressEvent (QKeyEvent* ev) { |
1055 void GLRenderer::keyPressEvent (QKeyEvent* ev) |
| 1037 m_keymods = ev->modifiers(); |
1056 { m_keymods = ev->modifiers(); |
| 1038 } |
1057 } |
| 1039 |
1058 |
| 1040 // ============================================================================= |
1059 // ============================================================================= |
| 1041 // ----------------------------------------------------------------------------- |
1060 // ----------------------------------------------------------------------------- |
| 1042 void GLRenderer::keyReleaseEvent (QKeyEvent* ev) { |
1061 void GLRenderer::keyReleaseEvent (QKeyEvent* ev) |
| 1043 m_keymods = ev->modifiers(); |
1062 { m_keymods = ev->modifiers(); |
| 1044 } |
1063 } |
| 1045 |
1064 |
| 1046 // ============================================================================= |
1065 // ============================================================================= |
| 1047 // ----------------------------------------------------------------------------- |
1066 // ----------------------------------------------------------------------------- |
| 1048 void GLRenderer::wheelEvent (QWheelEvent* ev) { |
1067 void GLRenderer::wheelEvent (QWheelEvent* ev) |
| 1049 makeCurrent(); |
1068 { makeCurrent(); |
| 1050 |
1069 |
| 1051 zoomNotch (ev->delta() > 0); |
1070 zoomNotch (ev->delta() > 0); |
| 1052 setZoom (clamp<double> (zoom(), 0.01f, 10000.0f)); |
1071 setZoom (clamp<double> (zoom(), 0.01f, 10000.0f)); |
| 1053 |
1072 |
| 1054 update(); |
1073 update(); |
| 1055 ev->accept(); |
1074 ev->accept(); |
| 1056 } |
1075 } |
| 1057 |
1076 |
| 1058 // ============================================================================= |
1077 // ============================================================================= |
| 1059 // ----------------------------------------------------------------------------- |
1078 // ----------------------------------------------------------------------------- |
| 1060 void GLRenderer::leaveEvent (QEvent* ev) { |
1079 void GLRenderer::leaveEvent (QEvent* ev) |
| 1061 (void) ev; |
1080 { (void) ev; |
| 1062 m_drawToolTip = false; |
1081 m_drawToolTip = false; |
| 1063 m_toolTipTimer->stop(); |
1082 m_toolTipTimer->stop(); |
| 1064 update(); |
1083 update(); |
| 1065 } |
1084 } |
| 1066 |
1085 |
| 1067 // ============================================================================= |
1086 // ============================================================================= |
| 1068 // ----------------------------------------------------------------------------- |
1087 // ----------------------------------------------------------------------------- |
| 1069 void GLRenderer::contextMenuEvent (QContextMenuEvent* ev) { |
1088 void GLRenderer::contextMenuEvent (QContextMenuEvent* ev) |
| 1070 g_win->spawnContextMenu (ev->globalPos()); |
1089 { g_win->spawnContextMenu (ev->globalPos()); |
| 1071 } |
1090 } |
| 1072 |
1091 |
| 1073 // ============================================================================= |
1092 // ============================================================================= |
| 1074 // ----------------------------------------------------------------------------- |
1093 // ----------------------------------------------------------------------------- |
| 1075 void GLRenderer::setCamera (const GL::Camera cam) { |
1094 void GLRenderer::setCamera (const GL::Camera cam) |
| 1076 m_camera = cam; |
1095 { m_camera = cam; |
| 1077 gl_camera = (int) cam; |
1096 gl_camera = (int) cam; |
| 1078 g_win->updateEditModeActions(); |
1097 g_win->updateEditModeActions(); |
| 1079 } |
1098 } |
| 1080 |
1099 |
| 1081 // ============================================================================= |
1100 // ============================================================================= |
| 1082 // ----------------------------------------------------------------------------- |
1101 // ----------------------------------------------------------------------------- |
| 1083 void GLRenderer::pick (uint mouseX, uint mouseY) { |
1102 void GLRenderer::pick (uint mouseX, uint mouseY) |
| 1084 GLint viewport[4]; |
1103 { GLint viewport[4]; |
| 1085 makeCurrent(); |
1104 makeCurrent(); |
| 1086 |
1105 |
| 1087 // Use particularly thick lines while picking ease up selecting lines. |
1106 // Use particularly thick lines while picking ease up selecting lines. |
| 1088 glLineWidth (max<double> (gl_linethickness, 6.5f)); |
1107 glLineWidth (max<double> (gl_linethickness, 6.5f)); |
| 1089 |
1108 |
| 1090 // Clear the selection if we do not wish to add to it. |
1109 // Clear the selection if we do not wish to add to it. |
| 1091 if (!m_addpick) { |
1110 if (!m_addpick) |
| 1092 List<LDObject*> oldsel = g_win->sel(); |
1111 { List<LDObject*> oldsel = g_win->sel(); |
| 1093 g_win->sel().clear(); |
1112 g_win->sel().clear(); |
| 1094 |
1113 |
| 1095 for (LDObject* obj : oldsel) { |
1114 for (LDObject * obj : oldsel) |
| 1096 obj->setSelected (false); |
1115 { obj->setSelected (false); |
| 1097 compileObject (obj); |
1116 compileObject (obj); |
| 1098 } |
1117 } |
| 1099 } |
1118 } |
| 1100 |
1119 |
| 1101 m_picking = true; |
1120 m_picking = true; |
| 1102 |
1121 |
| 1103 // Paint the picking scene |
1122 // Paint the picking scene |
| 1104 glDisable (GL_DITHER); |
1123 glDisable (GL_DITHER); |
| 1105 glClearColor (1.0f, 1.0f, 1.0f, 1.0f); |
1124 glClearColor (1.0f, 1.0f, 1.0f, 1.0f); |
| 1106 |
1125 |
| 1107 drawGLScene(); |
1126 drawGLScene(); |
| 1108 |
1127 |
| 1109 glGetIntegerv (GL_VIEWPORT, viewport); |
1128 glGetIntegerv (GL_VIEWPORT, viewport); |
| 1110 |
1129 |
| 1111 short x0 = mouseX, |
1130 short x0 = mouseX, |
| 1112 y0 = mouseY; |
1131 y0 = mouseY; |
| 1113 short x1, y1; |
1132 short x1, y1; |
| 1114 |
1133 |
| 1115 // Determine how big an area to read - with range picking, we pick by |
1134 // Determine how big an area to read - with range picking, we pick by |
| 1116 // the area given, with single pixel picking, we use an 1 x 1 area. |
1135 // the area given, with single pixel picking, we use an 1 x 1 area. |
| 1117 if (m_rangepick) { |
1136 if (m_rangepick) |
| 1118 x1 = m_rangeStart.x(); |
1137 { x1 = m_rangeStart.x(); |
| 1119 y1 = m_rangeStart.y(); |
1138 y1 = m_rangeStart.y(); |
| 1120 } else { |
1139 } |
| 1121 x1 = x0 + 1; |
1140 else |
| |
1141 { x1 = x0 + 1; |
| 1122 y1 = y0 + 1; |
1142 y1 = y0 + 1; |
| 1123 } |
1143 } |
| 1124 |
1144 |
| 1125 // x0 and y0 must be less than x1 and y1, respectively. |
1145 // x0 and y0 must be less than x1 and y1, respectively. |
| 1126 if (x0 > x1) |
1146 if (x0 > x1) |
| 1127 dataswap (x0, x1); |
1147 dataswap (x0, x1); |
| 1128 |
1148 |
| 1129 if (y0 > y1) |
1149 if (y0 > y1) |
| 1130 dataswap (y0, y1); |
1150 dataswap (y0, y1); |
| 1131 |
1151 |
| 1132 // Clamp the values to ensure they're within bounds |
1152 // Clamp the values to ensure they're within bounds |
| 1133 x0 = max<short> (0, x0); |
1153 x0 = max<short> (0, x0); |
| 1134 y0 = max<short> (0, y0); |
1154 y0 = max<short> (0, y0); |
| 1135 x1 = min<short> (x1, m_width); |
1155 x1 = min<short> (x1, m_width); |
| 1136 y1 = min<short> (y1, m_height); |
1156 y1 = min<short> (y1, m_height); |
| 1137 |
1157 |
| 1138 const short areawidth = (x1 - x0); |
1158 const short areawidth = (x1 - x0); |
| 1139 const short areaheight = (y1 - y0); |
1159 const short areaheight = (y1 - y0); |
| 1140 const long numpixels = areawidth * areaheight; |
1160 const long numpixels = areawidth * areaheight; |
| 1141 |
1161 |
| 1142 // Allocate space for the pixel data. |
1162 // Allocate space for the pixel data. |
| 1143 uchar* const pixeldata = new uchar[4 * numpixels]; |
1163 uchar* const pixeldata = new uchar[4 * numpixels]; |
| 1144 uchar* pixelptr = &pixeldata[0]; |
1164 uchar* pixelptr = &pixeldata[0]; |
| 1145 |
1165 |
| 1146 assert (viewport[3] == m_height); |
1166 assert (viewport[3] == m_height); |
| 1147 |
1167 |
| 1148 // Read pixels from the color buffer. |
1168 // Read pixels from the color buffer. |
| 1149 glReadPixels (x0, viewport[3] - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); |
1169 glReadPixels (x0, viewport[3] - y1, areawidth, areaheight, GL_RGBA, GL_UNSIGNED_BYTE, pixeldata); |
| 1150 |
1170 |
| 1151 LDObject* removedObj = null; |
1171 LDObject* removedObj = null; |
| 1152 |
1172 |
| 1153 // Go through each pixel read and add them to the selection. |
1173 // Go through each pixel read and add them to the selection. |
| 1154 for (long i = 0; i < numpixels; ++i) { |
1174 for (long i = 0; i < numpixels; ++i) |
| 1155 long idx = |
1175 { long idx = |
| 1156 (*(pixelptr + 0) * 0x10000) + |
1176 (* (pixelptr + 0) * 0x10000) + |
| 1157 (*(pixelptr + 1) * 0x00100) + |
1177 (* (pixelptr + 1) * 0x00100) + |
| 1158 (*(pixelptr + 2) * 0x00001); |
1178 (* (pixelptr + 2) * 0x00001); |
| 1159 pixelptr += 4; |
1179 pixelptr += 4; |
| 1160 |
1180 |
| 1161 if (idx == 0xFFFFFF) |
1181 if (idx == 0xFFFFFF) |
| 1162 continue; // White is background; skip |
1182 continue; // White is background; skip |
| 1163 |
1183 |
| 1164 LDObject* obj = LDObject::fromID (idx); |
1184 LDObject* obj = LDObject::fromID (idx); |
| 1165 |
1185 |
| 1166 // If this is an additive single pick and the object is currently selected, |
1186 // If this is an additive single pick and the object is currently selected, |
| 1167 // we remove it from selection instead. |
1187 // we remove it from selection instead. |
| 1168 if (!m_rangepick && m_addpick) { |
1188 if (!m_rangepick && m_addpick) |
| 1169 bool removed = false; |
1189 { bool removed = false; |
| 1170 |
1190 |
| 1171 for (ulong i = 0; i < g_win->sel().size(); ++i) { |
1191 for (ulong i = 0; i < g_win->sel().size(); ++i) |
| 1172 if (g_win->sel()[i] == obj) { |
1192 { if (g_win->sel() [i] == obj) |
| 1173 g_win->sel().erase (i); |
1193 { g_win->sel().erase (i); |
| 1174 obj->setSelected (false); |
1194 obj->setSelected (false); |
| 1175 removed = true; |
1195 removed = true; |
| 1176 removedObj = obj; |
1196 removedObj = obj; |
| 1177 } |
1197 } |
| 1178 } |
1198 } |
| 1179 |
1199 |
| 1180 if (removed) |
1200 if (removed) |
| 1181 break; |
1201 break; |
| 1182 } |
1202 } |
| 1183 |
1203 |
| 1184 g_win->sel() << obj; |
1204 g_win->sel() << obj; |
| 1185 } |
1205 } |
| 1186 |
1206 |
| 1187 delete[] pixeldata; |
1207 delete[] pixeldata; |
| 1188 |
1208 |
| 1189 // Remove duplicated entries |
1209 // Remove duplicated entries |
| 1190 g_win->sel().makeUnique(); |
1210 g_win->sel().makeUnique(); |
| 1191 |
1211 |
| 1192 // Update everything now. |
1212 // Update everything now. |
| 1193 g_win->updateSelection(); |
1213 g_win->updateSelection(); |
| 1194 |
1214 |
| 1195 // Recompile the objects now to update their color |
1215 // Recompile the objects now to update their color |
| 1196 for (LDObject* obj : g_win->sel()) |
1216 for (LDObject * obj : g_win->sel()) |
| 1197 compileObject (obj); |
1217 compileObject (obj); |
| 1198 |
1218 |
| 1199 if (removedObj) |
1219 if (removedObj) |
| 1200 compileObject (removedObj); |
1220 compileObject (removedObj); |
| 1201 |
1221 |
| 1202 // Restore line thickness |
1222 // Restore line thickness |
| 1203 glLineWidth (gl_linethickness); |
1223 glLineWidth (gl_linethickness); |
| 1204 |
1224 |
| 1205 m_picking = false; |
1225 m_picking = false; |
| 1206 m_rangepick = false; |
1226 m_rangepick = false; |
| 1207 glEnable (GL_DITHER); |
1227 glEnable (GL_DITHER); |
| 1208 |
1228 |
| 1209 setBackground(); |
1229 setBackground(); |
| 1210 repaint(); |
1230 repaint(); |
| 1211 } |
1231 } |
| 1212 |
1232 |
| 1213 // ============================================================================= |
1233 // ============================================================================= |
| 1214 // ----------------------------------------------------------------------------- |
1234 // ----------------------------------------------------------------------------- |
| 1215 READ_ACCESSOR (EditMode, GLRenderer::editMode) { |
1235 READ_ACCESSOR (EditMode, GLRenderer::editMode) |
| 1216 return m_editMode; |
1236 { return m_editMode; |
| 1217 } |
1237 } |
| 1218 |
1238 |
| 1219 // ============================================================================= |
1239 // ============================================================================= |
| 1220 // ----------------------------------------------------------------------------- |
1240 // ----------------------------------------------------------------------------- |
| 1221 SET_ACCESSOR (EditMode, GLRenderer::setEditMode) { |
1241 SET_ACCESSOR (EditMode, GLRenderer::setEditMode) |
| 1222 m_editMode = val; |
1242 { m_editMode = val; |
| 1223 |
1243 |
| 1224 switch (editMode()) { |
1244 switch (editMode()) |
| 1225 case Select: |
1245 { case Select: |
| 1226 unsetCursor(); |
1246 unsetCursor(); |
| 1227 setContextMenuPolicy (Qt::DefaultContextMenu); |
1247 setContextMenuPolicy (Qt::DefaultContextMenu); |
| 1228 break; |
1248 break; |
| 1229 |
1249 |
| 1230 case Draw: |
1250 case Draw: |
| 1231 case CircleMode: |
1251 case CircleMode: |
| 1232 // Cannot draw into the free camera - use top instead. |
1252 |
| 1233 if (m_camera == Free) |
1253 // Cannot draw into the free camera - use top instead. |
| 1234 setCamera (Top); |
1254 if (m_camera == Free) |
| 1235 |
1255 setCamera (Top); |
| 1236 // Disable the context menu - we need the right mouse button |
1256 |
| 1237 // for removing vertices. |
1257 // Disable the context menu - we need the right mouse button |
| 1238 setContextMenuPolicy (Qt::NoContextMenu); |
1258 // for removing vertices. |
| 1239 |
1259 setContextMenuPolicy (Qt::NoContextMenu); |
| 1240 // Use the crosshair cursor when drawing. |
1260 |
| 1241 setCursor (Qt::CrossCursor); |
1261 // Use the crosshair cursor when drawing. |
| 1242 |
1262 setCursor (Qt::CrossCursor); |
| 1243 // Clear the selection when beginning to draw. |
1263 |
| 1244 // FIXME: make the selection clearing stuff in ::pick a method and use it |
1264 // Clear the selection when beginning to draw. |
| 1245 // here! This code doesn't update the GL lists. |
1265 // FIXME: make the selection clearing stuff in ::pick a method and use it |
| 1246 g_win->sel().clear(); |
1266 // here! This code doesn't update the GL lists. |
| 1247 g_win->updateSelection(); |
1267 g_win->sel().clear(); |
| 1248 m_drawedVerts.clear(); |
1268 g_win->updateSelection(); |
| 1249 break; |
1269 m_drawedVerts.clear(); |
| 1250 } |
1270 break; |
| 1251 |
1271 } |
| |
1272 |
| 1252 g_win->updateEditModeActions(); |
1273 g_win->updateEditModeActions(); |
| 1253 update(); |
1274 update(); |
| 1254 } |
1275 } |
| 1255 |
1276 |
| 1256 // ============================================================================= |
1277 // ============================================================================= |
| 1257 // ----------------------------------------------------------------------------- |
1278 // ----------------------------------------------------------------------------- |
| 1258 READ_ACCESSOR (LDFile*, GLRenderer::file) { |
1279 READ_ACCESSOR (LDFile*, GLRenderer::file) |
| 1259 return m_file; |
1280 { return m_file; |
| 1260 } |
1281 } |
| 1261 |
1282 |
| 1262 // ============================================================================= |
1283 // ============================================================================= |
| 1263 // ----------------------------------------------------------------------------- |
1284 // ----------------------------------------------------------------------------- |
| 1264 SET_ACCESSOR (LDFile*, GLRenderer::setFile) { |
1285 SET_ACCESSOR (LDFile*, GLRenderer::setFile) |
| 1265 m_file = val; |
1286 { m_file = val; |
| 1266 |
1287 |
| 1267 if (val != null) |
1288 if (val != null) |
| 1268 overlaysFromObjects(); |
1289 overlaysFromObjects(); |
| 1269 } |
1290 } |
| 1270 |
1291 |
| 1271 // ============================================================================= |
1292 // ============================================================================= |
| 1272 // ----------------------------------------------------------------------------- |
1293 // ----------------------------------------------------------------------------- |
| 1273 void GLRenderer::endDraw (bool accept) { |
1294 void GLRenderer::endDraw (bool accept) |
| 1274 (void) accept; |
1295 { (void) accept; |
| 1275 |
1296 |
| 1276 // Clean the selection and create the object |
1297 // Clean the selection and create the object |
| 1277 List<vertex>& verts = m_drawedVerts; |
1298 List<vertex>& verts = m_drawedVerts; |
| 1278 LDObject* obj = null; |
1299 LDObject* obj = null; |
| 1279 |
1300 |
| 1280 switch (editMode()) |
1301 switch (editMode()) |
| 1281 { case Draw: |
1302 { case Draw: |
| 1282 if (m_rectdraw) { |
1303 |
| 1283 LDQuad* quad = new LDQuad; |
1304 if (m_rectdraw) |
| 1284 |
1305 { LDQuad* quad = new LDQuad; |
| 1285 // Copy the vertices from m_rectverts |
1306 |
| 1286 updateRectVerts(); |
1307 // Copy the vertices from m_rectverts |
| 1287 |
1308 updateRectVerts(); |
| 1288 for (int i = 0; i < quad->vertices(); ++i) |
1309 |
| 1289 quad->setVertex (i, m_rectverts[i]); |
1310 for (int i = 0; i < quad->vertices(); ++i) |
| 1290 |
1311 quad->setVertex (i, m_rectverts[i]); |
| 1291 quad->setColor (maincolor); |
1312 |
| 1292 obj = quad; |
1313 quad->setColor (maincolor); |
| 1293 } else { |
1314 obj = quad; |
| 1294 switch (verts.size()) { |
|
| 1295 case 1: |
|
| 1296 // 1 vertex - add a vertex object |
|
| 1297 obj = new LDVertex; |
|
| 1298 static_cast<LDVertex*> (obj)->pos = verts[0]; |
|
| 1299 obj->setColor (maincolor); |
|
| 1300 break; |
|
| 1301 |
|
| 1302 case 2: |
|
| 1303 // 2 verts - make a line |
|
| 1304 obj = new LDLine (verts[0], verts[1]); |
|
| 1305 obj->setColor (edgecolor); |
|
| 1306 break; |
|
| 1307 |
|
| 1308 case 3: |
|
| 1309 case 4: |
|
| 1310 obj = (verts.size() == 3) ? |
|
| 1311 static_cast<LDObject*> (new LDTriangle) : |
|
| 1312 static_cast<LDObject*> (new LDQuad); |
|
| 1313 |
|
| 1314 obj->setColor (maincolor); |
|
| 1315 for (ushort i = 0; i < obj->vertices(); ++i) |
|
| 1316 obj->setVertex (i, verts[i]); |
|
| 1317 break; |
|
| 1318 } |
1315 } |
| 1319 } |
1316 else |
| 1320 break; |
1317 { switch (verts.size()) |
| |
1318 { case 1: |
| |
1319 // 1 vertex - add a vertex object |
| |
1320 obj = new LDVertex; |
| |
1321 static_cast<LDVertex*> (obj)->pos = verts[0]; |
| |
1322 obj->setColor (maincolor); |
| |
1323 break; |
| |
1324 |
| |
1325 case 2: |
| |
1326 // 2 verts - make a line |
| |
1327 obj = new LDLine (verts[0], verts[1]); |
| |
1328 obj->setColor (edgecolor); |
| |
1329 break; |
| |
1330 |
| |
1331 case 3: |
| |
1332 case 4: |
| |
1333 obj = (verts.size() == 3) ? |
| |
1334 static_cast<LDObject*> (new LDTriangle) : |
| |
1335 static_cast<LDObject*> (new LDQuad); |
| |
1336 |
| |
1337 obj->setColor (maincolor); |
| |
1338 |
| |
1339 for (ushort i = 0; i < obj->vertices(); ++i) |
| |
1340 obj->setVertex (i, verts[i]); |
| |
1341 |
| |
1342 break; |
| |
1343 } |
| |
1344 } |
| |
1345 |
| |
1346 break; |
| 1321 |
1347 |
| 1322 case CircleMode: |
1348 case CircleMode: |
| 1323 { const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
1349 { const staticCameraMeta* cam = &g_staticCameras[m_camera]; |
| 1324 const double dist = circleDrawDist(); |
1350 const double dist = circleDrawDist(); |
| 1325 |
1351 |
| 1326 matrix transform = g_circleDrawTransforms[camera() % 3]; |
1352 matrix transform = g_circleDrawTransforms[camera() % 3]; |
| |
1353 |
| 1327 for (int i = 0; i < 9; ++i) |
1354 for (int i = 0; i < 9; ++i) |
| 1328 { if (transform[i] == 2) |
1355 { if (transform[i] == 2) |
| 1329 transform[i] = dist; |
1356 transform[i] = dist; |
| |
1357 |
| 1330 elif (transform[i] == 1 && camera() >= 3) |
1358 elif (transform[i] == 1 && camera() >= 3) |
| 1331 transform[i] = -1; |
1359 transform[i] = -1; |
| 1332 } |
1360 } |
| 1333 |
1361 |
| 1334 LDSubfile* ref = new LDSubfile; |
1362 LDSubfile* ref = new LDSubfile; |
| 1335 ref->setFileInfo (findLoadedFile ("4-4edge.dat")); |
1363 ref->setFileInfo (findLoadedFile ("4-4edge.dat")); |
| 1336 ref->setTransform (transform); |
1364 ref->setTransform (transform); |
| 1378 relY = cam->axisY; |
1406 relY = cam->axisY; |
| 1379 } |
1407 } |
| 1380 |
1408 |
| 1381 // ============================================================================= |
1409 // ============================================================================= |
| 1382 // ----------------------------------------------------------------------------- |
1410 // ----------------------------------------------------------------------------- |
| 1383 static List<vertex> getVertices (LDObject* obj) { |
1411 static List<vertex> getVertices (LDObject* obj) |
| 1384 List<vertex> verts; |
1412 { List<vertex> verts; |
| 1385 |
1413 |
| 1386 if (obj->vertices() >= 2) { |
1414 if (obj->vertices() >= 2) |
| 1387 for (int i = 0; i < obj->vertices(); ++i) |
1415 { for (int i = 0; i < obj->vertices(); ++i) |
| 1388 verts << obj->getVertex (i); |
1416 verts << obj->getVertex (i); |
| 1389 } elif (obj->getType() == LDObject::Subfile) { |
1417 } elif (obj->getType() == LDObject::Subfile) |
| 1390 LDSubfile* ref = static_cast<LDSubfile*> (obj); |
1418 |
| |
1419 { LDSubfile* ref = static_cast<LDSubfile*> (obj); |
| 1391 List<LDObject*> objs = ref->inlineContents (LDSubfile::DeepCacheInline); |
1420 List<LDObject*> objs = ref->inlineContents (LDSubfile::DeepCacheInline); |
| 1392 |
1421 |
| 1393 for(LDObject* obj : objs) { |
1422 for (LDObject * obj : objs) |
| 1394 verts << getVertices (obj); |
1423 { verts << getVertices (obj); |
| 1395 delete obj; |
1424 delete obj; |
| 1396 } |
1425 } |
| 1397 } |
1426 } |
| 1398 |
1427 |
| 1399 return verts; |
1428 return verts; |
| 1400 } |
1429 } |
| 1401 |
1430 |
| 1402 // ============================================================================= |
1431 // ============================================================================= |
| 1403 // ----------------------------------------------------------------------------- |
1432 // ----------------------------------------------------------------------------- |
| 1404 void GLRenderer::compileObject (LDObject* obj) { |
1433 void GLRenderer::compileObject (LDObject* obj) |
| 1405 deleteLists (obj); |
1434 { deleteLists (obj); |
| 1406 |
1435 |
| 1407 for (const GL::ListType listType : g_glListTypes) { |
1436 for (const GL::ListType listType : g_glListTypes) |
| 1408 if (drawOnly() && listType != GL::NormalList) |
1437 { if (drawOnly() && listType != GL::NormalList) |
| 1409 continue; |
1438 continue; |
| 1410 |
1439 |
| 1411 GLuint list = glGenLists (1); |
1440 GLuint list = glGenLists (1); |
| 1412 glNewList (list, GL_COMPILE); |
1441 glNewList (list, GL_COMPILE); |
| 1413 |
1442 |
| 1414 obj->glLists[listType] = list; |
1443 obj->glLists[listType] = list; |
| 1415 compileList (obj, listType); |
1444 compileList (obj, listType); |
| 1416 |
1445 |
| 1417 glEndList(); |
1446 glEndList(); |
| 1418 } |
1447 } |
| 1419 |
1448 |
| 1420 // Mark in known vertices of this object |
1449 // Mark in known vertices of this object |
| 1421 List<vertex> verts = getVertices (obj); |
1450 List<vertex> verts = getVertices (obj); |
| 1422 m_knownVerts << verts; |
1451 m_knownVerts << verts; |
| 1423 m_knownVerts.makeUnique(); |
1452 m_knownVerts.makeUnique(); |
| 1424 |
1453 |
| 1425 obj->m_glinit = true; |
1454 obj->m_glinit = true; |
| 1426 } |
1455 } |
| 1427 |
1456 |
| 1428 // ============================================================================= |
1457 // ============================================================================= |
| 1429 // ----------------------------------------------------------------------------- |
1458 // ----------------------------------------------------------------------------- |
| 1430 uchar* GLRenderer::screencap (ushort& w, ushort& h) { |
1459 uchar* GLRenderer::screencap (ushort& w, ushort& h) |
| 1431 w = m_width; |
1460 { w = m_width; |
| 1432 h = m_height; |
1461 h = m_height; |
| 1433 uchar* cap = new uchar[4 * w * h]; |
1462 uchar* cap = new uchar[4 * w * h]; |
| 1434 |
1463 |
| 1435 m_screencap = true; |
1464 m_screencap = true; |
| 1436 update(); |
1465 update(); |
| 1437 m_screencap = false; |
1466 m_screencap = false; |
| 1438 |
1467 |
| 1439 // Capture the pixels |
1468 // Capture the pixels |
| 1440 glReadPixels (0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, cap); |
1469 glReadPixels (0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, cap); |
| 1441 |
1470 |
| 1442 return cap; |
1471 return cap; |
| 1443 } |
1472 } |
| 1444 |
1473 |
| 1445 // ============================================================================= |
1474 // ============================================================================= |
| 1446 // ----------------------------------------------------------------------------- |
1475 // ----------------------------------------------------------------------------- |
| 1447 void GLRenderer::slot_toolTipTimer() { |
1476 void GLRenderer::slot_toolTipTimer() |
| 1448 // We come here if the cursor has stayed in one place for longer than a |
1477 { // We come here if the cursor has stayed in one place for longer than a |
| 1449 // a second. Check if we're holding it over a camera icon - if so, draw |
1478 // a second. Check if we're holding it over a camera icon - if so, draw |
| 1450 // a tooltip. |
1479 // a tooltip. |
| 1451 for (CameraIcon& icon : m_cameraIcons) { |
1480 for (CameraIcon & icon : m_cameraIcons) |
| 1452 if (icon.destRect.contains (m_pos)) { |
1481 { if (icon.destRect.contains (m_pos)) |
| 1453 m_toolTipCamera = icon.cam; |
1482 { m_toolTipCamera = icon.cam; |
| 1454 m_drawToolTip = true; |
1483 m_drawToolTip = true; |
| 1455 update(); |
1484 update(); |
| 1456 break; |
1485 break; |
| 1457 } |
1486 } |
| 1458 } |
1487 } |
| 1459 } |
1488 } |
| 1460 |
1489 |
| 1461 // ============================================================================= |
1490 // ============================================================================= |
| 1462 // ----------------------------------------------------------------------------- |
1491 // ----------------------------------------------------------------------------- |
| 1463 void GLRenderer::deleteLists (LDObject* obj) { |
1492 void GLRenderer::deleteLists (LDObject* obj) |
| 1464 // Delete the lists but only if they have been initialized |
1493 { // Delete the lists but only if they have been initialized |
| 1465 if (!obj->m_glinit) |
1494 if (!obj->m_glinit) |
| 1466 return; |
1495 return; |
| 1467 |
1496 |
| 1468 for (const GL::ListType listType : g_glListTypes) |
1497 for (const GL::ListType listType : g_glListTypes) |
| 1469 glDeleteLists (obj->glLists[listType], 1); |
1498 glDeleteLists (obj->glLists[listType], 1); |
| 1470 |
1499 |
| 1471 obj->m_glinit = false; |
1500 obj->m_glinit = false; |
| 1472 } |
1501 } |
| 1473 |
1502 |
| 1474 // ============================================================================= |
1503 // ============================================================================= |
| 1475 // ----------------------------------------------------------------------------- |
1504 // ----------------------------------------------------------------------------- |
| 1476 Axis GLRenderer::cameraAxis (bool y, GL::Camera camid) { |
1505 Axis GLRenderer::cameraAxis (bool y, GL::Camera camid) |
| 1477 if (camid == (GL::Camera) -1) |
1506 { if (camid == (GL::Camera) - 1) |
| 1478 camid = m_camera; |
1507 camid = m_camera; |
| 1479 |
1508 |
| 1480 const staticCameraMeta* cam = &g_staticCameras[camid]; |
1509 const staticCameraMeta* cam = &g_staticCameras[camid]; |
| 1481 return (y) ? cam->axisY : cam->axisX; |
1510 return (y) ? cam->axisY : cam->axisX; |
| 1482 } |
1511 } |
| 1483 |
1512 |
| 1484 // ============================================================================= |
1513 // ============================================================================= |
| 1485 // ----------------------------------------------------------------------------- |
1514 // ----------------------------------------------------------------------------- |
| 1486 bool GLRenderer::setupOverlay (GL::Camera cam, str file, int x, int y, int w, int h) { |
1515 bool GLRenderer::setupOverlay (GL::Camera cam, str file, int x, int y, int w, int h) |
| 1487 QImage* img = new QImage (file); |
1516 { QImage* img = new QImage (file); |
| 1488 overlayMeta& info = getOverlay (cam); |
1517 overlayMeta& info = getOverlay (cam); |
| 1489 |
1518 |
| 1490 if (img->isNull()) { |
1519 if (img->isNull()) |
| 1491 critical (tr ("Failed to load overlay image!")); |
1520 { critical (tr ("Failed to load overlay image!")); |
| 1492 delete img; |
1521 delete img; |
| 1493 return false; |
1522 return false; |
| 1494 } |
1523 } |
| 1495 |
1524 |
| 1496 delete info.img; // delete the old image |
1525 delete info.img; // delete the old image |
| 1497 |
1526 |
| 1498 info.fname = file; |
1527 info.fname = file; |
| 1499 info.lw = w; |
1528 info.lw = w; |
| 1500 info.lh = h; |
1529 info.lh = h; |
| 1501 info.ox = x; |
1530 info.ox = x; |
| 1502 info.oy = y; |
1531 info.oy = y; |
| 1503 info.img = img; |
1532 info.img = img; |
| 1504 |
1533 |
| 1505 if (info.lw == 0) |
1534 if (info.lw == 0) |
| 1506 info.lw = (info.lh * img->width()) / img->height(); |
1535 info.lw = (info.lh * img->width()) / img->height(); |
| |
1536 |
| 1507 elif (info.lh == 0) |
1537 elif (info.lh == 0) |
| 1508 info.lh = (info.lw * img->height()) / img->width(); |
1538 info.lh = (info.lw * img->height()) / img->width(); |
| 1509 |
1539 |
| 1510 const Axis x2d = cameraAxis (false, cam), |
1540 const Axis x2d = cameraAxis (false, cam), |
| 1511 y2d = cameraAxis (true, cam); |
1541 y2d = cameraAxis (true, cam); |
| 1512 |
1542 |
| 1513 double negXFac = g_staticCameras[cam].negX ? -1 : 1, |
1543 double negXFac = g_staticCameras[cam].negX ? -1 : 1, |
| 1514 negYFac = g_staticCameras[cam].negY ? -1 : 1; |
1544 negYFac = g_staticCameras[cam].negY ? -1 : 1; |
| 1515 |
1545 |
| 1516 info.v0 = info.v1 = g_origin; |
1546 info.v0 = info.v1 = g_origin; |
| 1517 info.v0[x2d] = - (info.ox * info.lw * negXFac) / img->width(); |
1547 info.v0[x2d] = - (info.ox * info.lw * negXFac) / img->width(); |
| 1518 info.v0[y2d] = (info.oy * info.lh * negYFac) / img->height(); |
1548 info.v0[y2d] = (info.oy * info.lh * negYFac) / img->height(); |
| 1519 info.v1[x2d] = info.v0[x2d] + info.lw; |
1549 info.v1[x2d] = info.v0[x2d] + info.lw; |
| 1520 info.v1[y2d] = info.v0[y2d] + info.lh; |
1550 info.v1[y2d] = info.v0[y2d] + info.lh; |
| 1521 |
1551 |
| 1522 // Set alpha of all pixels to 0.5 |
1552 // Set alpha of all pixels to 0.5 |
| 1523 for (long i = 0; i < img->width(); ++i) |
1553 for (long i = 0; i < img->width(); ++i) |
| 1524 for (long j = 0; j < img->height(); ++j) { |
1554 for (long j = 0; j < img->height(); ++j) |
| 1525 uint32 pixel = img->pixel (i, j); |
1555 { uint32 pixel = img->pixel (i, j); |
| 1526 img->setPixel (i, j, 0x80000000 | (pixel & 0x00FFFFFF)); |
1556 img->setPixel (i, j, 0x80000000 | (pixel & 0x00FFFFFF)); |
| 1527 } |
1557 } |
| 1528 |
1558 |
| 1529 updateOverlayObjects(); |
1559 updateOverlayObjects(); |
| 1530 return true; |
1560 return true; |
| 1531 } |
1561 } |
| 1532 |
1562 |
| 1533 // ============================================================================= |
1563 // ============================================================================= |
| 1534 // ----------------------------------------------------------------------------- |
1564 // ----------------------------------------------------------------------------- |
| 1535 void GLRenderer::clearOverlay() { |
1565 void GLRenderer::clearOverlay() |
| 1536 if (camera() == Free) |
1566 { if (camera() == Free) |
| 1537 return; |
1567 return; |
| 1538 |
1568 |
| 1539 overlayMeta& info = m_overlays[camera()]; |
1569 overlayMeta& info = m_overlays[camera()]; |
| 1540 delete info.img; |
1570 delete info.img; |
| 1541 info.img = null; |
1571 info.img = null; |
| 1542 |
1572 |
| 1543 updateOverlayObjects(); |
1573 updateOverlayObjects(); |
| 1544 } |
1574 } |
| 1545 |
1575 |
| 1546 // ============================================================================= |
1576 // ============================================================================= |
| 1547 // ----------------------------------------------------------------------------- |
1577 // ----------------------------------------------------------------------------- |
| 1548 void GLRenderer::setDepthValue (double depth) { |
1578 void GLRenderer::setDepthValue (double depth) |
| 1549 assert (camera() < Free); |
1579 { assert (camera() < Free); |
| 1550 m_depthValues[camera()] = depth; |
1580 m_depthValues[camera()] = depth; |
| 1551 } |
1581 } |
| 1552 |
1582 |
| 1553 // ============================================================================= |
1583 // ============================================================================= |
| 1554 // ----------------------------------------------------------------------------- |
1584 // ----------------------------------------------------------------------------- |
| 1555 double GLRenderer::depthValue() const { |
1585 double GLRenderer::depthValue() const |
| 1556 assert (camera() < Free); |
1586 { assert (camera() < Free); |
| 1557 return m_depthValues[camera()]; |
1587 return m_depthValues[camera()]; |
| 1558 } |
1588 } |
| 1559 |
1589 |
| 1560 // ============================================================================= |
1590 // ============================================================================= |
| 1561 // ----------------------------------------------------------------------------- |
1591 // ----------------------------------------------------------------------------- |
| 1562 const char* GLRenderer::cameraName() const { |
1592 const char* GLRenderer::cameraName() const |
| 1563 return g_CameraNames[camera()]; |
1593 { return g_CameraNames[camera()]; |
| 1564 } |
1594 } |
| 1565 |
1595 |
| 1566 // ============================================================================= |
1596 // ============================================================================= |
| 1567 // ----------------------------------------------------------------------------- |
1597 // ----------------------------------------------------------------------------- |
| 1568 overlayMeta& GLRenderer::getOverlay (int newcam) { |
1598 overlayMeta& GLRenderer::getOverlay (int newcam) |
| 1569 return m_overlays[newcam]; |
1599 { return m_overlays[newcam]; |
| 1570 } |
1600 } |
| 1571 |
1601 |
| 1572 // ============================================================================= |
1602 // ============================================================================= |
| 1573 // ----------------------------------------------------------------------------- |
1603 // ----------------------------------------------------------------------------- |
| 1574 void GLRenderer::zoomNotch (bool inward) { |
1604 void GLRenderer::zoomNotch (bool inward) |
| 1575 if (zoom() > 15) |
1605 { if (zoom() > 15) |
| 1576 setZoom (zoom() * (inward ? 0.833f : 1.2f)); |
1606 setZoom (zoom() * (inward ? 0.833f : 1.2f)); |
| 1577 else |
1607 else |
| 1578 setZoom (zoom() + (inward ? -1.2f : 1.2f)); |
1608 setZoom (zoom() + (inward ? -1.2f : 1.2f)); |
| 1579 } |
1609 } |
| 1580 |
1610 |
| 1581 // ============================================================================= |
1611 // ============================================================================= |
| 1582 // ----------------------------------------------------------------------------- |
1612 // ----------------------------------------------------------------------------- |
| 1583 void GLRenderer::zoomToFit() { |
1613 void GLRenderer::zoomToFit() |
| 1584 if (file() == null) { |
1614 { if (file() == null) |
| 1585 setZoom (30.0f); |
1615 { setZoom (30.0f); |
| 1586 return; |
1616 return; |
| 1587 } |
1617 } |
| 1588 |
1618 |
| 1589 bool lastfilled = false; |
1619 bool lastfilled = false; |
| 1590 bool firstrun = true; |
1620 bool firstrun = true; |
| 1591 const uint32 white = 0xFFFFFFFF; |
1621 const uint32 white = 0xFFFFFFFF; |
| 1592 bool inward = true; |
1622 bool inward = true; |
| 1593 ulong run = 0; |
1623 ulong run = 0; |
| 1594 const ushort w = m_width, h = m_height; |
1624 const ushort w = m_width, h = m_height; |
| 1595 |
1625 |
| 1596 glClearColor (1.0, 1.0, 1.0, 1.0); |
1626 glClearColor (1.0, 1.0, 1.0, 1.0); |
| 1597 glDisable (GL_DITHER); |
1627 glDisable (GL_DITHER); |
| 1598 |
1628 |
| 1599 // Use the pick list while drawing the scene, this way we can tell whether borders |
1629 // Use the pick list while drawing the scene, this way we can tell whether borders |
| 1600 // are background or not. |
1630 // are background or not. |
| 1601 m_picking = true; |
1631 m_picking = true; |
| 1602 |
1632 |
| 1603 for (;;) { |
1633 for (;;) |
| 1604 if (zoom() > 10000.0f || zoom() < 0.0f) { |
1634 { if (zoom() > 10000.0f || zoom() < 0.0f) |
| 1605 // Obviously, there's nothing to draw if we get here. |
1635 { // Obviously, there's nothing to draw if we get here. |
| 1606 // Default to 30.0f and break out. |
1636 // Default to 30.0f and break out. |
| 1607 setZoom (30.0f); |
1637 setZoom (30.0f); |
| 1608 break; |
1638 break; |
| 1609 } |
1639 } |
| 1610 |
1640 |
| 1611 zoomNotch (inward); |
1641 zoomNotch (inward); |
| 1612 |
1642 |
| 1613 uchar* cap = new uchar[4 * w * h]; |
1643 uchar* cap = new uchar[4 * w * h]; |
| 1614 drawGLScene(); |
1644 drawGLScene(); |
| 1615 glReadPixels (0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, cap); |
1645 glReadPixels (0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, cap); |
| 1616 uint32* imgdata = reinterpret_cast<uint32*> (cap); |
1646 uint32* imgdata = reinterpret_cast<uint32*> (cap); |
| 1617 bool filled = false; |
1647 bool filled = false; |
| 1618 |
1648 |
| 1619 // Check the top and bottom rows |
1649 // Check the top and bottom rows |
| 1620 for (ushort i = 0; i < w && !filled; ++i) |
1650 for (ushort i = 0; i < w && !filled; ++i) |
| 1621 if (imgdata[i] != white || imgdata[((h - 1) * w) + i] != white) |
1651 if (imgdata[i] != white || imgdata[ ( (h - 1) * w) + i] != white) |
| 1622 filled = true; |
1652 filled = true; |
| 1623 |
1653 |
| 1624 // Left and right edges |
1654 // Left and right edges |
| 1625 for (ushort i = 0; i < h && !filled; ++i) |
1655 for (ushort i = 0; i < h && !filled; ++i) |
| 1626 if (imgdata[i * w] != white || imgdata[(i * w) + (w - 1)] != white) |
1656 if (imgdata[i * w] != white || imgdata[ (i * w) + (w - 1)] != white) |
| 1627 filled = true; |
1657 filled = true; |
| 1628 |
1658 |
| 1629 if (firstrun) { |
1659 if (firstrun) |
| 1630 // If this is the first run, we don't know enough to determine |
1660 { // If this is the first run, we don't know enough to determine |
| 1631 // whether the zoom was to fit, so we mark in our knowledge so |
1661 // whether the zoom was to fit, so we mark in our knowledge so |
| 1632 // far and start over. |
1662 // far and start over. |
| 1633 inward = !filled; |
1663 inward = !filled; |
| 1634 firstrun = false; |
1664 firstrun = false; |
| 1635 } else { |
1665 } |
| 1636 // If this run filled the screen and the last one did not, the |
1666 else |
| |
1667 { // If this run filled the screen and the last one did not, the |
| 1637 // last run had ideal zoom - zoom a bit back and we should reach it. |
1668 // last run had ideal zoom - zoom a bit back and we should reach it. |
| 1638 if (filled && !lastfilled) { |
1669 if (filled && !lastfilled) |
| 1639 zoomNotch (false); |
1670 { zoomNotch (false); |
| 1640 break; |
1671 break; |
| 1641 } |
1672 } |
| 1642 |
1673 |
| 1643 // If this run did not fill the screen and the last one did, we've |
1674 // If this run did not fill the screen and the last one did, we've |
| 1644 // now reached ideal zoom so we're done here. |
1675 // now reached ideal zoom so we're done here. |
| 1645 if (!filled && lastfilled) |
1676 if (!filled && lastfilled) |
| 1646 break; |
1677 break; |
| 1647 |
1678 |
| 1648 inward = !filled; |
1679 inward = !filled; |
| 1649 } |
1680 } |
| 1650 |
1681 |
| 1651 delete[] cap; |
1682 delete[] cap; |
| 1652 lastfilled = filled; |
1683 lastfilled = filled; |
| 1653 ++run; |
1684 ++run; |
| 1654 } |
1685 } |
| 1655 |
1686 |
| 1656 setBackground(); |
1687 setBackground(); |
| 1657 m_picking = false; |
1688 m_picking = false; |
| 1658 } |
1689 } |
| 1659 |
1690 |
| 1660 // ============================================================================= |
1691 // ============================================================================= |
| 1661 // ----------------------------------------------------------------------------- |
1692 // ----------------------------------------------------------------------------- |
| 1662 void GLRenderer::updateRectVerts() { |
1693 void GLRenderer::updateRectVerts() |
| 1663 if (!m_rectdraw) |
1694 { if (!m_rectdraw) |
| 1664 return; |
1695 return; |
| 1665 |
1696 |
| 1666 if (m_drawedVerts.size() == 0) { |
1697 if (m_drawedVerts.size() == 0) |
| 1667 for (int i = 0; i < 4; ++i) |
1698 { for (int i = 0; i < 4; ++i) |
| 1668 m_rectverts[i] = m_hoverpos; |
1699 m_rectverts[i] = m_hoverpos; |
| 1669 |
1700 |
| 1670 return; |
1701 return; |
| 1671 } |
1702 } |
| 1672 |
1703 |
| 1673 vertex v0 = m_drawedVerts[0], |
1704 vertex v0 = m_drawedVerts[0], |
| 1674 v1 = (m_drawedVerts.size() >= 2) ? m_drawedVerts[1] : m_hoverpos; |
1705 v1 = (m_drawedVerts.size() >= 2) ? m_drawedVerts[1] : m_hoverpos; |
| 1675 |
1706 |
| 1676 const Axis ax = cameraAxis (false), |
1707 const Axis ax = cameraAxis (false), |
| 1677 ay = cameraAxis (true), |
1708 ay = cameraAxis (true), |
| 1678 az = (Axis) (3 - ax - ay); |
1709 az = (Axis) (3 - ax - ay); |
| 1679 |
1710 |
| 1680 for (int i = 0; i < 4; ++i) |
1711 for (int i = 0; i < 4; ++i) |
| 1681 m_rectverts[i][az] = depthValue(); |
1712 m_rectverts[i][az] = depthValue(); |
| 1682 |
1713 |
| 1683 m_rectverts[0][ax] = v0[ax]; |
1714 m_rectverts[0][ax] = v0[ax]; |
| 1684 m_rectverts[0][ay] = v0[ay]; |
1715 m_rectverts[0][ay] = v0[ay]; |
| 1685 m_rectverts[1][ax] = v1[ax]; |
1716 m_rectverts[1][ax] = v1[ax]; |
| 1686 m_rectverts[1][ay] = v0[ay]; |
1717 m_rectverts[1][ay] = v0[ay]; |
| 1687 m_rectverts[2][ax] = v1[ax]; |
1718 m_rectverts[2][ax] = v1[ax]; |
| 1690 m_rectverts[3][ay] = v1[ay]; |
1721 m_rectverts[3][ay] = v1[ay]; |
| 1691 } |
1722 } |
| 1692 |
1723 |
| 1693 // ============================================================================= |
1724 // ============================================================================= |
| 1694 // ----------------------------------------------------------------------------- |
1725 // ----------------------------------------------------------------------------- |
| 1695 void GLRenderer::mouseDoubleClickEvent (QMouseEvent* ev) { |
1726 void GLRenderer::mouseDoubleClickEvent (QMouseEvent* ev) |
| 1696 if (!(ev->buttons() & Qt::LeftButton) || editMode() != Select) |
1727 { if (! (ev->buttons() & Qt::LeftButton) || editMode() != Select) |
| 1697 return; |
1728 return; |
| 1698 |
1729 |
| 1699 pick (ev->x(), ev->y()); |
1730 pick (ev->x(), ev->y()); |
| 1700 |
1731 |
| 1701 if (g_win->sel().size() == 0) |
1732 if (g_win->sel().size() == 0) |
| 1702 return; |
1733 return; |
| 1703 |
1734 |
| 1704 g_win->beginAction (null); |
1735 g_win->beginAction (null); |
| 1705 LDObject* obj = g_win->sel()[0]; |
1736 LDObject* obj = g_win->sel() [0]; |
| 1706 AddObjectDialog::staticDialog (obj->getType(), obj); |
1737 AddObjectDialog::staticDialog (obj->getType(), obj); |
| 1707 g_win->endAction(); |
1738 g_win->endAction(); |
| 1708 ev->accept(); |
1739 ev->accept(); |
| 1709 } |
1740 } |
| 1710 |
1741 |
| 1711 // ============================================================================= |
1742 // ============================================================================= |
| 1712 // ----------------------------------------------------------------------------- |
1743 // ----------------------------------------------------------------------------- |
| 1713 LDOverlay* GLRenderer::findOverlayObject (GLRenderer::Camera cam) { |
1744 LDOverlay* GLRenderer::findOverlayObject (GLRenderer::Camera cam) |
| 1714 LDOverlay* ovlobj = null; |
1745 { LDOverlay* ovlobj = null; |
| 1715 |
1746 |
| 1716 for (LDObject * obj : file()->objects()) { |
1747 for (LDObject * obj : file()->objects()) |
| 1717 if (obj->getType() == LDObject::Overlay && static_cast<LDOverlay*> (obj)->camera() == cam) { |
1748 { if (obj->getType() == LDObject::Overlay && static_cast<LDOverlay*> (obj)->camera() == cam) |
| 1718 ovlobj = static_cast<LDOverlay*> (obj); |
1749 { ovlobj = static_cast<LDOverlay*> (obj); |
| 1719 break; |
1750 break; |
| 1720 } |
1751 } |
| 1721 } |
1752 } |
| 1722 |
1753 |
| 1723 return ovlobj; |
1754 return ovlobj; |
| 1724 } |
1755 } |
| 1725 |
1756 |
| 1726 // ============================================================================= |
1757 // ============================================================================= |
| 1727 // ----------------------------------------------------------------------------- |
1758 // ----------------------------------------------------------------------------- |
| 1728 // Read in overlays from the current file and update overlay info accordingly. |
1759 // Read in overlays from the current file and update overlay info accordingly. |
| 1729 // ----------------------------------------------------------------------------- |
1760 // ----------------------------------------------------------------------------- |
| 1730 void GLRenderer::overlaysFromObjects() { |
1761 void GLRenderer::overlaysFromObjects() |
| 1731 for (Camera cam : g_Cameras) { |
1762 { for (Camera cam : g_Cameras) |
| 1732 if (cam == Free) |
1763 { if (cam == Free) |
| 1733 continue; |
1764 continue; |
| 1734 |
1765 |
| 1735 overlayMeta& meta = m_overlays[cam]; |
1766 overlayMeta& meta = m_overlays[cam]; |
| 1736 LDOverlay* ovlobj = findOverlayObject (cam); |
1767 LDOverlay* ovlobj = findOverlayObject (cam); |
| 1737 |
1768 |
| 1738 if (!ovlobj && meta.img) { |
1769 if (!ovlobj && meta.img) |
| 1739 delete meta.img; |
1770 { delete meta.img; |
| 1740 meta.img = null; |
1771 meta.img = null; |
| 1741 } elif (ovlobj && (!meta.img || meta.fname != ovlobj->filename())) |
1772 } elif (ovlobj && (!meta.img || meta.fname != ovlobj->filename())) |
| 1742 setupOverlay (cam, ovlobj->filename(), ovlobj->x(), ovlobj->y(), ovlobj->width(), ovlobj->height()); |
1773 |
| 1743 } |
1774 setupOverlay (cam, ovlobj->filename(), ovlobj->x(), ovlobj->y(), ovlobj->width(), ovlobj->height()); |
| 1744 } |
1775 } |
| 1745 |
1776 } |
| 1746 // ============================================================================= |
1777 |
| 1747 // ----------------------------------------------------------------------------- |
1778 // ============================================================================= |
| 1748 void GLRenderer::updateOverlayObjects() { |
1779 // ----------------------------------------------------------------------------- |
| 1749 for (Camera cam : g_Cameras) { |
1780 void GLRenderer::updateOverlayObjects() |
| 1750 if (cam == Free) |
1781 { for (Camera cam : g_Cameras) |
| |
1782 { if (cam == Free) |
| 1751 continue; |
1783 continue; |
| 1752 |
1784 |
| 1753 overlayMeta& meta = m_overlays[cam]; |
1785 overlayMeta& meta = m_overlays[cam]; |
| 1754 LDOverlay* ovlobj = findOverlayObject (cam); |
1786 LDOverlay* ovlobj = findOverlayObject (cam); |
| 1755 |
1787 |
| 1756 if (!meta.img && ovlobj) { |
1788 if (!meta.img && ovlobj) |
| 1757 // If this is the last overlay image, we need to remove the empty space after it as well. |
1789 { // If this is the last overlay image, we need to remove the empty space after it as well. |
| 1758 LDObject* nextobj = ovlobj->next(); |
1790 LDObject* nextobj = ovlobj->next(); |
| 1759 |
1791 |
| 1760 if (nextobj && nextobj->getType() == LDObject::Empty) { |
1792 if (nextobj && nextobj->getType() == LDObject::Empty) |
| 1761 m_file->forgetObject (nextobj); |
1793 { m_file->forgetObject (nextobj); |
| 1762 delete nextobj; |
1794 delete nextobj; |
| 1763 } |
1795 } |
| 1764 |
1796 |
| 1765 // If the overlay object was there and the overlay itself is |
1797 // If the overlay object was there and the overlay itself is |
| 1766 // not, remove the object. |
1798 // not, remove the object. |
| 1767 m_file->forgetObject (ovlobj); |
1799 m_file->forgetObject (ovlobj); |
| 1768 delete ovlobj; |
1800 delete ovlobj; |
| 1769 } elif (meta.img && !ovlobj) { |
1801 } elif (meta.img && !ovlobj) |
| 1770 // Inverse case: image is there but the overlay object is |
1802 |
| |
1803 { // Inverse case: image is there but the overlay object is |
| 1771 // not, thus create the object. |
1804 // not, thus create the object. |
| 1772 ovlobj = new LDOverlay; |
1805 ovlobj = new LDOverlay; |
| 1773 |
1806 |
| 1774 // Find a suitable position to place this object. We want to place |
1807 // Find a suitable position to place this object. We want to place |
| 1775 // this into the header, which is everything up to the first scemantic |
1808 // this into the header, which is everything up to the first scemantic |
| 1776 // object. If we find another overlay object, place this object after |
1809 // object. If we find another overlay object, place this object after |
| 1777 // the last one found. Otherwise, place it before the first schemantic |
1810 // the last one found. Otherwise, place it before the first schemantic |
| 1778 // object and put an empty object after it (though don't do this if |
1811 // object and put an empty object after it (though don't do this if |
| 1779 // there was no schemantic elements at all) |
1812 // there was no schemantic elements at all) |
| 1780 ulong i, lastOverlay = -1u; |
1813 ulong i, lastOverlay = -1u; |
| 1781 bool found = false; |
1814 bool found = false; |
| 1782 |
1815 |
| 1783 for (i = 0; i < file()->numObjs(); ++i) { |
1816 for (i = 0; i < file()->numObjs(); ++i) |
| 1784 LDObject* obj = file()->obj (i); |
1817 { LDObject* obj = file()->obj (i); |
| 1785 |
1818 |
| 1786 if (obj->isScemantic()) { |
1819 if (obj->isScemantic()) |
| 1787 found = true; |
1820 { found = true; |
| 1788 break; |
1821 break; |
| 1789 } |
1822 } |
| 1790 |
1823 |
| 1791 if (obj->getType() == LDObject::Overlay) |
1824 if (obj->getType() == LDObject::Overlay) |
| 1792 lastOverlay = i; |
1825 lastOverlay = i; |
| 1793 } |
1826 } |
| 1794 |
1827 |
| 1795 if (lastOverlay != -1u) |
1828 if (lastOverlay != -1u) |
| 1796 file()->insertObj (lastOverlay + 1, ovlobj); |
1829 file()->insertObj (lastOverlay + 1, ovlobj); |
| 1797 else { |
1830 else |
| 1798 file()->insertObj (i, ovlobj); |
1831 { file()->insertObj (i, ovlobj); |
| 1799 |
1832 |
| 1800 if (found) |
1833 if (found) |
| 1801 file()->insertObj (i + 1, new LDEmpty); |
1834 file()->insertObj (i + 1, new LDEmpty); |
| 1802 } |
1835 } |
| 1803 } |
1836 } |
| 1804 |
1837 |
| 1805 if (meta.img && ovlobj) { |
1838 if (meta.img && ovlobj) |
| 1806 ovlobj->setCamera (cam); |
1839 { ovlobj->setCamera (cam); |
| 1807 ovlobj->setFilename (meta.fname); |
1840 ovlobj->setFilename (meta.fname); |
| 1808 ovlobj->setX (meta.ox); |
1841 ovlobj->setX (meta.ox); |
| 1809 ovlobj->setY (meta.oy); |
1842 ovlobj->setY (meta.oy); |
| 1810 ovlobj->setWidth (meta.lw); |
1843 ovlobj->setWidth (meta.lw); |
| 1811 ovlobj->setHeight (meta.lh); |
1844 ovlobj->setHeight (meta.lh); |
| 1812 } |
1845 } |
| 1813 } |
1846 } |
| 1814 |
1847 |
| 1815 if (g_win->R() == this) |
1848 if (g_win->R() == this) |
| 1816 g_win->refresh(); |
1849 g_win->refresh(); |
| 1817 } |
1850 } |
| 1818 #include "moc_gldraw.cpp" |
|