Mon, 15 Apr 2013 01:51:53 +0300
Added additive selection blending, with a toggable flash effect. :P
gldraw.cpp | file | annotate | diff | comparison | revisions | |
gldraw.h | file | annotate | diff | comparison | revisions | |
gui.cpp | file | annotate | diff | comparison | revisions | |
gui.h | file | annotate | diff | comparison | revisions | |
zz_configDialog.cpp | file | annotate | diff | comparison | revisions | |
zz_configDialog.h | file | annotate | diff | comparison | revisions |
--- a/gldraw.cpp Sun Apr 14 17:31:09 2013 +0300 +++ b/gldraw.cpp Mon Apr 15 01:51:53 2013 +0300 @@ -31,25 +31,33 @@ static double g_StoredBBoxSize; static bool g_bPicking = false; +static short g_dPulseTick = 0; +static const short g_dNumPulseTicks = 8; +static const short g_dPulseInterval = 65; + cfg (str, gl_bgcolor, "#CCCCD9"); cfg (str, gl_maincolor, "#707078"); cfg (float, gl_maincolor_alpha, 1.0); cfg (int, gl_linethickness, 2); cfg (bool, gl_colorbfc, true); +cfg (bool, gl_selflash, false); // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -renderer::renderer (QWidget* parent) { +GLRenderer::GLRenderer (QWidget* parent) { parent = parent; // shhh, GCC fRotX = fRotY = fRotZ = 0.0f; fZoom = 1.0f; + + qPulseTimer = new QTimer (this); + connect (qPulseTimer, SIGNAL (timeout ()), this, SLOT (slot_timerUpdate ())); } // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::initializeGL () { +void GLRenderer::initializeGL () { glLoadIdentity(); glMatrixMode (GL_MODELVIEW); @@ -62,23 +70,22 @@ glShadeModel (GL_SMOOTH); glEnable (GL_MULTISAMPLE); - glEnable (GL_DITHER); glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable (GL_LINE_SMOOTH); glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glLineWidth (gl_linethickness); setMouseTracking (true); - compileObjects (); } // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -QColor renderer::getMainColor () { +QColor GLRenderer::getMainColor () { QColor col (gl_maincolor.value.chars()); if (!col.isValid ()) @@ -89,7 +96,7 @@ } // ------------------------------------------------------------------------- // -void renderer::setBackground () { +void GLRenderer::setBackground () { QColor col (gl_bgcolor.value.chars()); if (!col.isValid ()) @@ -106,7 +113,7 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // static vector<short> g_daWarnedColors; -void renderer::setObjectColor (LDObject* obj) { +void GLRenderer::setObjectColor (LDObject* obj) { QColor qCol; if (g_bPicking) { @@ -178,11 +185,23 @@ b = qCol.blue (), a = qCol.alpha (); - // If it's selected, brighten it up - if (g_ForgeWindow->isSelected (obj) && obj->dColor != dEdgeColor) { - r = ((r * 3) + (255 * 2)) / 5; - g = ((g * 3) + (255 * 2)) / 5; - b = ((b * 3) + (255 * 2)) / 5; + // If it's selected, brighten it up, also pulse flash it if desired. + if (g_ForgeWindow->isSelected (obj)) { + short dTick, dNumTicks; + + if (gl_selflash) { + dTick = (g_dPulseTick < (g_dNumPulseTicks / 2)) ? g_dPulseTick : (g_dNumPulseTicks - g_dPulseTick); + dNumTicks = g_dNumPulseTicks; + } else { + dTick = 2; + dNumTicks = 5; + } + + const long lAdd = ((dTick * 128) / dNumTicks); + r = min (r + lAdd, 255l); + g = min (g + lAdd, 255l); + b = min (b + lAdd, 255l); + a = 255; } @@ -196,7 +215,7 @@ // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::hardRefresh () { +void GLRenderer::hardRefresh () { compileObjects (); paintGL (); swapBuffers (); @@ -207,7 +226,7 @@ // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::resizeGL (int w, int h) { +void GLRenderer::resizeGL (int w, int h) { glViewport (0, 0, w, h); glLoadIdentity (); glMatrixMode (GL_PROJECTION); @@ -217,10 +236,13 @@ // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::paintGL () { +void GLRenderer::paintGL () { glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode (GL_MODELVIEW); + if (g_CurrentFile == null) + return; + glPushMatrix (); glLoadIdentity (); @@ -231,39 +253,45 @@ glRotatef (fRotY, 0.0f, 1.0f, 0.0f); glRotatef (fRotZ, 0.0f, 0.0f, 1.0f); - for (GLuint uList : uaObjLists) - glCallList (uList); + for (LDObject* obj : g_CurrentFile->objects) + glCallList (obj->uGLList); glPopMatrix (); } // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::compileObjects () { +void GLRenderer::compileObjects () { uaObjLists.clear (); g_faObjectOffset[0] = -(g_BBox.v0.x + g_BBox.v1.x) / 2; g_faObjectOffset[1] = -(g_BBox.v0.y + g_BBox.v1.y) / 2; g_faObjectOffset[2] = -(g_BBox.v0.z + g_BBox.v1.z) / 2; g_StoredBBoxSize = g_BBox.calcSize (); - printf ("bbox size is %f\n", g_StoredBBoxSize); if (!g_CurrentFile) { printf ("renderer: no files loaded, cannot compile anything\n"); return; } - for (LDObject* obj : g_CurrentFile->objects) + for (LDObject* obj : g_CurrentFile->objects) { + GLuint uList = glGenLists (1); + glNewList (uList, GL_COMPILE); + compileOneObject (obj); + + glEndList (); + uaObjLists.push_back (uList); + obj->uGLList = uList; + } } // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -template<class T> void renderer::compileSubObject (LDObject* obj, +template<class T> void GLRenderer::compileSubObject (LDObject* obj, const GLenum eGLType, const short dVerts) { - setObjectColor (obj); T* newobj = static_cast<T*> (obj); glBegin (eGLType); @@ -276,9 +304,8 @@ // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::compileOneObject (LDObject* obj) { - GLuint uList = glGenLists (1); - glNewList (uList, GL_COMPILE); +void GLRenderer::compileOneObject (LDObject* obj) { + setObjectColor (obj); switch (obj->getType ()) { case OBJ_Line: @@ -352,16 +379,12 @@ default: break; } - - glEndList (); - uaObjLists.push_back (uList); - obj->uGLList = uList; } // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::compileVertex (vertex& vrt) { +void GLRenderer::compileVertex (vertex& vrt) { glVertex3d ( (vrt.x + g_faObjectOffset[0]) / g_StoredBBoxSize, -(vrt.y + g_faObjectOffset[1]) / g_StoredBBoxSize, @@ -371,7 +394,7 @@ // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::clampAngle (double& fAngle) { +void GLRenderer::clampAngle (double& fAngle) { while (fAngle < 0) fAngle += 360.0; while (fAngle > 360.0) @@ -381,7 +404,7 @@ // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::mouseReleaseEvent (QMouseEvent* event) { +void GLRenderer::mouseReleaseEvent (QMouseEvent* event) { if ((qMouseButtons & Qt::LeftButton) && !(event->buttons() & Qt::LeftButton)) { if (ulTotalMouseMove < 10) pick (event->x(), event->y()); @@ -390,7 +413,7 @@ } } -void renderer::mousePressEvent (QMouseEvent* event) { +void GLRenderer::mousePressEvent (QMouseEvent* event) { qMouseButtons = event->buttons(); if (event->buttons() & Qt::LeftButton) ulTotalMouseMove = 0; @@ -399,7 +422,7 @@ // ========================================================================= // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // -void renderer::mouseMoveEvent (QMouseEvent *event) { +void GLRenderer::mouseMoveEvent (QMouseEvent *event) { int dx = event->x () - lastPos.x (); int dy = event->y () - lastPos.y (); ulTotalMouseMove += abs (dx) + abs (dy); @@ -428,7 +451,9 @@ } // ========================================================================= // -void renderer::pick (uint mx, uint my) { +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// ========================================================================= // +void GLRenderer::pick (uint mx, uint my) { g_ForgeWindow->paSelection.clear (); glDisable (GL_DITHER); @@ -442,15 +467,26 @@ GLubyte pixel[3]; GLint viewport[4]; glGetIntegerv (GL_VIEWPORT, viewport); - glReadPixels (mx, viewport[3] - my, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, reinterpret_cast<GLvoid*> (pixel)); + glReadPixels (mx, viewport[3] - my, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, + reinterpret_cast<GLvoid*> (pixel)); - if (pixel[0] != 255 || pixel[1] != 255 || pixel[2] != 255) { + const bool bHasSelection = (pixel[0] != 255 || pixel[1] != 255 || pixel[2] != 255); + + if (bHasSelection) { ulong idx = pixel[0] + (pixel[1] * 256) + (pixel[2] * 256 * 256); LDObject* obj = g_CurrentFile->object (idx); g_ForgeWindow->paSelection.push_back (obj); } + if (gl_selflash) { + if (bHasSelection) { + qPulseTimer->start (g_dPulseInterval); + g_dPulseTick = 0; + } else + qPulseTimer->stop (); + } + g_bPicking = false; glEnable (GL_DITHER); @@ -458,4 +494,35 @@ setBackground (); hardRefresh (); +} + +// ========================================================================= // +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// ========================================================================= // +void GLRenderer::updateObjectColors() { + for (LDObject* obj : g_ForgeWindow->getSelectedObjects ()) { + // Replace the old list with the new one. + for (ulong i = 0; i < uaObjLists.size(); ++i) + if (uaObjLists[i] == obj->uGLList) + uaObjLists.erase (uaObjLists.begin() + i); + + GLuint uList = glGenLists (1); + glNewList (uList, GL_COMPILE); + + compileOneObject (obj); + + glEndList (); + uaObjLists.push_back (uList); + obj->uGLList = uList; + } +} + +// ========================================================================= // +void GLRenderer::slot_timerUpdate () { + ++g_dPulseTick %= g_dNumPulseTicks; + printf ("%d\n", g_dPulseTick); + + updateObjectColors (); + paintGL (); + swapBuffers (); } \ No newline at end of file
--- a/gldraw.h Sun Apr 14 17:31:09 2013 +0300 +++ b/gldraw.h Mon Apr 15 01:51:53 2013 +0300 @@ -20,14 +20,22 @@ #define __GLDRAW_H__ #include <QGLWidget> +#include <qtimer.h> #include "common.h" #include "ldtypes.h" -class renderer : public QGLWidget { +// ============================================================================= +// GLRenderer +// +// The main renderer object, draws the brick on the screen, manages the camera +// and selection picking. The instance of GLRenderer is accessible as +// g_ForgeWindow->R +// ============================================================================= +class GLRenderer : public QGLWidget { Q_OBJECT public: - renderer (QWidget* parent = null); + GLRenderer (QWidget* parent = null); void hardRefresh (); void compileObjects (); void setBackground (); @@ -55,10 +63,16 @@ void compileVertex (vertex& vrt); void clampAngle (double& fAngle); void setObjectColor (LDObject* obj); + void updateObjectColors (); + + QTimer* qPulseTimer; Qt::MouseButtons qMouseButtons; Qt::KeyboardModifiers qKeyMods; ulong ulTotalMouseMove; + +private slots: + void slot_timerUpdate (); }; #endif // __GLDRAW_H__ \ No newline at end of file
--- a/gui.cpp Sun Apr 14 17:31:09 2013 +0300 +++ b/gui.cpp Mon Apr 15 01:51:53 2013 +0300 @@ -83,7 +83,7 @@ // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // ========================================================================= // ForgeWindow::ForgeWindow () { - R = new renderer; + R = new GLRenderer; qObjList = new QTreeWidget; qObjList->setHeaderHidden (true);
--- a/gui.h Sun Apr 14 17:31:09 2013 +0300 +++ b/gui.h Mon Apr 15 01:51:53 2013 +0300 @@ -102,7 +102,7 @@ Q_OBJECT public: - renderer* R; + GLRenderer* R; // Object list view QTreeWidget* qObjList;
--- a/zz_configDialog.cpp Sun Apr 14 17:31:09 2013 +0300 +++ b/zz_configDialog.cpp Mon Apr 15 01:51:53 2013 +0300 @@ -38,6 +38,7 @@ extern_cfg (int, gl_linethickness); extern_cfg (int, gui_toolbar_iconsize); extern_cfg (str, gui_colortoolbar); +extern_cfg (bool, gl_selflash); ConfigDialog* g_ConfigDialog = null; @@ -122,6 +123,9 @@ qGLColorBFC = new QCheckBox ("Red/green BFC view"); INIT_CHECKBOX (qGLColorBFC, gl_colorbfc) + qGLSelFlash = new QCheckBox ("Selection flash"); + INIT_CHECKBOX (qGLSelFlash, gl_selflash) + QGridLayout* layout = new QGridLayout; layout->addWidget (qLDrawPathLabel, 0, 0); layout->addWidget (qLDrawPath, 0, 1, 1, 2); @@ -140,8 +144,9 @@ layout->addWidget (qToolBarIconSizeLabel, 3, 0); layout->addWidget (qToolBarIconSize, 3, 1); - layout->addWidget (qLVColorize, 4, 0, 1, 2); - layout->addWidget (qGLColorBFC, 4, 2, 1, 2); + layout->addWidget (qLVColorize, 4, 0); + layout->addWidget (qGLColorBFC, 5, 0); + layout->addWidget (qGLSelFlash, 6, 0); qMainTab->setLayout (layout); // Add the tab to the manager @@ -545,6 +550,7 @@ APPLY_CHECKBOX (dlg.qLVColorize, lv_colorize) APPLY_CHECKBOX (dlg.qGLColorBFC, gl_colorbfc) + APPLY_CHECKBOX (dlg.qGLSelFlash, gl_selflash) gl_maincolor_alpha = ((double)dlg.qGLForegroundAlpha->value ()) / 10.0f; gl_linethickness = dlg.qGLLineThickness->value ();
--- a/zz_configDialog.h Sun Apr 14 17:31:09 2013 +0300 +++ b/zz_configDialog.h Mon Apr 15 01:51:53 2013 +0300 @@ -40,7 +40,7 @@ QLineEdit* qLDrawPath; QPushButton* qLDrawPathFindButton; QPushButton* qGLBackgroundButton, *qGLForegroundButton; - QCheckBox* qLVColorize, *qGLColorBFC; + QCheckBox* qLVColorize, *qGLColorBFC, *qGLSelFlash; QSlider* qGLForegroundAlpha, *qGLLineThickness, *qToolBarIconSize; // =========================================================================