47 // ============================================================================= |
47 // ============================================================================= |
48 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) { |
48 GLRenderer::GLRenderer (QWidget* parent) : QGLWidget (parent) { |
49 resetAngles (); |
49 resetAngles (); |
50 picking = rangepick = false; |
50 picking = rangepick = false; |
51 |
51 |
52 qPulseTimer = new QTimer (this); |
52 pulseTimer = new QTimer (this); |
53 connect (qPulseTimer, SIGNAL (timeout ()), this, SLOT (slot_timerUpdate ())); |
53 connect (pulseTimer, SIGNAL (timeout ()), this, SLOT (slot_timerUpdate ())); |
54 } |
54 } |
55 |
55 |
56 // ============================================================================= |
56 // ============================================================================= |
57 void GLRenderer::resetAngles () { |
57 void GLRenderer::resetAngles () { |
58 rotX = 30.0f; |
58 rotX = 30.0f; |
84 glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); |
84 glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); |
85 |
85 |
86 glLineWidth (gl_linethickness); |
86 glLineWidth (gl_linethickness); |
87 |
87 |
88 setMouseTracking (true); |
88 setMouseTracking (true); |
|
89 setFocusPolicy (Qt::WheelFocus); |
89 compileObjects (); |
90 compileObjects (); |
90 } |
91 } |
91 |
92 |
92 // ============================================================================= |
93 // ============================================================================= |
93 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
94 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
106 void GLRenderer::setBackground () { |
107 void GLRenderer::setBackground () { |
107 QColor col (gl_bgcolor.value.chars()); |
108 QColor col (gl_bgcolor.value.chars()); |
108 |
109 |
109 if (!col.isValid ()) |
110 if (!col.isValid ()) |
110 return; |
111 return; |
|
112 |
|
113 darkbg = luma (col) < 80; |
111 |
114 |
112 glClearColor ( |
115 glClearColor ( |
113 ((double)col.red()) / 255.0f, |
116 ((double)col.red()) / 255.0f, |
114 ((double)col.green()) / 255.0f, |
117 ((double)col.green()) / 255.0f, |
115 ((double)col.blue()) / 255.0f, |
118 ((double)col.blue()) / 255.0f, |
284 glPushMatrix (); |
287 glPushMatrix (); |
285 glLoadIdentity (); |
288 glLoadIdentity (); |
286 glOrtho (.0, width, height, .0, -1.0, 1.0); |
289 glOrtho (.0, width, height, .0, -1.0, 1.0); |
287 |
290 |
288 for (int x : {GL_QUADS, GL_LINE_LOOP}) { |
291 for (int x : {GL_QUADS, GL_LINE_LOOP}) { |
289 if (x == GL_QUADS) |
292 if (x == GL_QUADS) { |
290 glColor4f (.0, .8, 1.0, .6); |
293 // Use a green color when picking additive, a blue color when normally. |
291 else |
294 if (addpick) |
292 glColor4f (1.0, 1.0, 1.0, 1.0); |
295 glColor4f (0.5f, 1.f, 0.f, 0.2f); |
|
296 else |
|
297 glColor4f (0.f, 0.8f, 1.f, 0.2f); |
|
298 } else { |
|
299 if (darkbg) |
|
300 glColor4f (1.f, 1.f, 1.f, 0.7f); |
|
301 else |
|
302 glColor4f (0.f, 0.f, 0.f, 0.7f); |
|
303 } |
293 |
304 |
294 glBegin (x); |
305 glBegin (x); |
295 glVertex2i (x0, y0); |
306 glVertex2i (x0, y0); |
296 glVertex2i (x1, y0); |
307 glVertex2i (x1, y0); |
297 glVertex2i (x1, y1); |
308 glVertex2i (x1, y1); |
306 |
317 |
307 // ============================================================================= |
318 // ============================================================================= |
308 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
319 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
309 // ============================================================================= |
320 // ============================================================================= |
310 void GLRenderer::compileObjects () { |
321 void GLRenderer::compileObjects () { |
311 uaObjLists.clear (); |
322 objLists.clear (); |
312 |
323 |
313 g_faObjectOffset[0] = -(g_BBox.v0.x + g_BBox.v1.x) / 2; |
324 g_faObjectOffset[0] = -(g_BBox.v0.x + g_BBox.v1.x) / 2; |
314 g_faObjectOffset[1] = -(g_BBox.v0.y + g_BBox.v1.y) / 2; |
325 g_faObjectOffset[1] = -(g_BBox.v0.y + g_BBox.v1.y) / 2; |
315 g_faObjectOffset[2] = -(g_BBox.v0.z + g_BBox.v1.z) / 2; |
326 g_faObjectOffset[2] = -(g_BBox.v0.z + g_BBox.v1.z) / 2; |
316 g_StoredBBoxSize = g_BBox.size (); |
327 g_StoredBBoxSize = g_BBox.size (); |
471 // ============================================================================= |
482 // ============================================================================= |
472 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
483 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
473 // ============================================================================= |
484 // ============================================================================= |
474 void GLRenderer::mouseReleaseEvent (QMouseEvent* ev) { |
485 void GLRenderer::mouseReleaseEvent (QMouseEvent* ev) { |
475 if ((lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton)) { |
486 if ((lastButtons & Qt::LeftButton) && !(ev->buttons() & Qt::LeftButton)) { |
476 if (ulTotalMouseMove < 10 || rangepick) |
487 if (!rangepick) |
477 pick (ev->x (), ev->y (), (qKeyMods & Qt::ControlModifier)); |
488 addpick = (keymods & Qt::ControlModifier); |
|
489 |
|
490 if (totalmove < 10 || rangepick) |
|
491 pick (ev->x (), ev->y ()); |
478 |
492 |
479 rangepick = false; |
493 rangepick = false; |
480 ulTotalMouseMove = 0; |
494 totalmove = 0; |
481 } |
495 } |
482 } |
496 } |
483 |
497 |
484 // ============================================================================= |
498 // ============================================================================= |
485 void GLRenderer::mousePressEvent (QMouseEvent* ev) { |
499 void GLRenderer::mousePressEvent (QMouseEvent* ev) { |
486 if (ev->buttons () & Qt::LeftButton) |
500 if (ev->buttons () & Qt::LeftButton) |
487 ulTotalMouseMove = 0; |
501 totalmove = 0; |
488 |
502 |
489 if (ev->modifiers () & Qt::ShiftModifier) { |
503 if (ev->modifiers () & Qt::ShiftModifier) { |
490 rangepick = true; |
504 rangepick = true; |
491 rangeStart.setX (ev->x ()); |
505 rangeStart.setX (ev->x ()); |
492 rangeStart.setY (ev->y ()); |
506 rangeStart.setY (ev->y ()); |
|
507 |
|
508 addpick = (keymods & Qt::ControlModifier); |
493 } |
509 } |
494 |
510 |
495 lastButtons = ev->buttons (); |
511 lastButtons = ev->buttons (); |
496 } |
512 } |
497 |
513 |
499 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
515 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
500 // ============================================================================= |
516 // ============================================================================= |
501 void GLRenderer::mouseMoveEvent (QMouseEvent* ev) { |
517 void GLRenderer::mouseMoveEvent (QMouseEvent* ev) { |
502 int dx = ev->x () - pos.x (); |
518 int dx = ev->x () - pos.x (); |
503 int dy = ev->y () - pos.y (); |
519 int dy = ev->y () - pos.y (); |
504 ulTotalMouseMove += abs (dx) + abs (dy); |
520 totalmove += abs (dx) + abs (dy); |
505 |
521 |
506 if (ev->buttons () & Qt::LeftButton && !rangepick) { |
522 if (ev->buttons () & Qt::LeftButton && !rangepick) { |
507 rotX = rotX + (dy); |
523 rotX = rotX + (dy); |
508 rotY = rotY + (dx); |
524 rotY = rotY + (dx); |
509 |
525 |
522 |
538 |
523 // ============================================================================= |
539 // ============================================================================= |
524 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
540 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
525 // ============================================================================= |
541 // ============================================================================= |
526 void GLRenderer::keyPressEvent (QKeyEvent* ev) { |
542 void GLRenderer::keyPressEvent (QKeyEvent* ev) { |
527 qKeyMods = ev->modifiers (); |
543 keymods = ev->modifiers (); |
528 } |
544 } |
529 |
545 |
530 void GLRenderer::keyReleaseEvent (QKeyEvent* ev) { |
546 void GLRenderer::keyReleaseEvent (QKeyEvent* ev) { |
531 qKeyMods = ev->modifiers (); |
547 keymods = ev->modifiers (); |
532 } |
548 } |
533 |
549 |
534 // ============================================================================= |
550 // ============================================================================= |
535 void GLRenderer::wheelEvent (QWheelEvent* ev) { |
551 void GLRenderer::wheelEvent (QWheelEvent* ev) { |
536 zoom += (-ev->delta () / 100.0); |
552 zoom += (-ev->delta () / 100.0); |
542 // ============================================================================= |
558 // ============================================================================= |
543 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
559 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * |
544 // ============================================================================= |
560 // ============================================================================= |
545 void GLRenderer::updateSelFlash () { |
561 void GLRenderer::updateSelFlash () { |
546 if (gl_selflash && g_ForgeWindow->sel.size() > 0) { |
562 if (gl_selflash && g_ForgeWindow->sel.size() > 0) { |
547 qPulseTimer->start (g_dPulseInterval); |
563 pulseTimer->start (g_dPulseInterval); |
548 g_dPulseTick = 0; |
564 g_dPulseTick = 0; |
549 } else |
565 } else |
550 qPulseTimer->stop (); |
566 pulseTimer->stop (); |
551 } |
567 } |
552 |
568 |
553 // ========================================================================= // |
569 // ========================================================================= // |
554 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
570 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
555 // ========================================================================= // |
571 // ========================================================================= // |
556 void GLRenderer::pick (uint mx, uint my, bool add) { |
572 void GLRenderer::pick (uint mouseX, uint mouseY) { |
557 GLint viewport[4]; |
573 GLint viewport[4]; |
|
574 LDObject* removedObject = null; |
558 |
575 |
559 // Clear the selection if we do not wish to add to it. |
576 // Clear the selection if we do not wish to add to it. |
560 if (add == false) { |
577 if (addpick == false) { |
561 std::vector<LDObject*> paOldSelection = g_ForgeWindow->sel; |
578 std::vector<LDObject*> paOldSelection = g_ForgeWindow->sel; |
562 g_ForgeWindow->sel.clear (); |
579 g_ForgeWindow->sel.clear (); |
563 |
580 |
564 // Recompile the prior selection to remove the highlight color |
581 // Recompile the prior selection to remove the highlight color |
565 for (LDObject* obj : paOldSelection) |
582 for (LDObject* obj : paOldSelection) |
573 glClearColor (1.0f, 1.0f, 1.0f, 1.0f); |
590 glClearColor (1.0f, 1.0f, 1.0f, 1.0f); |
574 paintGL (); |
591 paintGL (); |
575 |
592 |
576 glGetIntegerv (GL_VIEWPORT, viewport); |
593 glGetIntegerv (GL_VIEWPORT, viewport); |
577 |
594 |
578 short x0 = mx, |
595 short x0 = mouseX, |
579 y0 = my; |
596 y0 = mouseY; |
580 short x1, y1; |
597 short x1, y1; |
581 |
598 |
582 // Determine how big an area to read - with range picking, we pick by |
599 // Determine how big an area to read - with range picking, we pick by |
583 // the area given, with single pixel picking, we use an 1 x 1 area. |
600 // the area given, with single pixel picking, we use an 1 x 1 area. |
584 if (rangepick) { |
601 if (rangepick) { |
625 |
642 |
626 if (idx == 0xFFFFFF) |
643 if (idx == 0xFFFFFF) |
627 continue; // White is background; skip |
644 continue; // White is background; skip |
628 |
645 |
629 LDObject* obj = g_CurrentFile->object (idx); |
646 LDObject* obj = g_CurrentFile->object (idx); |
|
647 |
|
648 // If this is an additive single pick and the object is currently selected, |
|
649 // we remove it from selection instead. |
|
650 if (!rangepick && addpick) { |
|
651 bool removed = false; |
|
652 |
|
653 for (ulong i = 0; i < g_ForgeWindow->sel.size(); ++i) { |
|
654 if (g_ForgeWindow->sel[i] == obj) { |
|
655 g_ForgeWindow->sel.erase (g_ForgeWindow->sel.begin () + i); |
|
656 removedObject = obj; |
|
657 removed = true; |
|
658 } |
|
659 } |
|
660 |
|
661 if (removed) |
|
662 break; |
|
663 } |
|
664 |
630 g_ForgeWindow->sel.push_back (obj); |
665 g_ForgeWindow->sel.push_back (obj); |
631 } |
666 } |
632 |
667 |
633 delete[] pixeldata; |
668 delete[] pixeldata; |
634 |
669 |
650 updateSelFlash (); |
685 updateSelFlash (); |
651 |
686 |
652 for (LDObject* obj : g_ForgeWindow->sel) |
687 for (LDObject* obj : g_ForgeWindow->sel) |
653 recompileObject (obj); |
688 recompileObject (obj); |
654 |
689 |
|
690 if (removedObject != null) |
|
691 recompileObject (removedObject); |
|
692 |
655 paintGL (); |
693 paintGL (); |
656 swapBuffers (); |
694 swapBuffers (); |
657 } |
695 } |
658 |
696 |
659 // ========================================================================= // |
697 // ========================================================================= // |
660 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
698 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // |
661 // ========================================================================= // |
699 // ========================================================================= // |
662 void GLRenderer::recompileObject (LDObject* obj) { |
700 void GLRenderer::recompileObject (LDObject* obj) { |
663 // Replace the old list with the new one. |
701 // Replace the old list with the new one. |
664 for (ulong i = 0; i < uaObjLists.size(); ++i) |
702 for (ulong i = 0; i < objLists.size(); ++i) |
665 if (uaObjLists[i] == obj->uGLList) |
703 if (objLists[i] == obj->uGLList) |
666 uaObjLists.erase (uaObjLists.begin() + i); |
704 objLists.erase (objLists.begin() + i); |
667 |
705 |
668 GLuint uList = glGenLists (1); |
706 GLuint uList = glGenLists (1); |
669 glNewList (uList, GL_COMPILE); |
707 glNewList (uList, GL_COMPILE); |
670 |
708 |
671 compileOneObject (obj); |
709 compileOneObject (obj); |
672 |
710 |
673 glEndList (); |
711 glEndList (); |
674 uaObjLists.push_back (uList); |
712 objLists.push_back (uList); |
675 obj->uGLList = uList; |
713 obj->uGLList = uList; |
676 } |
714 } |
677 |
715 |
678 // ============================================================================= |
716 // ============================================================================= |
679 void GLRenderer::slot_timerUpdate () { |
717 void GLRenderer::slot_timerUpdate () { |