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" |
|