From 60eeb811835bd285f289c1cc03a7853b775ae24f Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 26 Apr 2013 17:13:20 +0200 Subject: [PATCH] Implement a more user-friendly selection tool --- src/Gui/MouseSelection.cpp | 187 +++++++++++++++++++++++++++++++ src/Gui/MouseSelection.h | 40 +++++++ src/Gui/View3DInventorViewer.cpp | 61 ++++++++++ src/Gui/View3DInventorViewer.h | 3 + 4 files changed, 291 insertions(+) diff --git a/src/Gui/MouseSelection.cpp b/src/Gui/MouseSelection.cpp index a4733b5451..e5b92b0796 100644 --- a/src/Gui/MouseSelection.cpp +++ b/src/Gui/MouseSelection.cpp @@ -458,6 +458,193 @@ int PolyClipSelection::popupMenu() // ----------------------------------------------------------------------------------- +BrushSelection::BrushSelection() + : r(1.0f), g(0.0f), b(0.0f), a(0.0f), l(2.0f) +{ + m_iNodes = 0; + m_bWorking = false; +} + +void BrushSelection::initialize() +{ + QPixmap p(cursor_cut_scissors); + QCursor cursor(p, 4, 4); + _pcView3D->getWidget()->setCursor(cursor); +} + +void BrushSelection::terminate() +{ +} + +void BrushSelection::setColor(float r, float g, float b, float a) +{ + this->r = r; + this->g = g; + this->b = b; + this->a = a; +} + +void BrushSelection::setLineWidth(float l) +{ + this->l = l; +} + +void BrushSelection::draw () +{ + if (mustRedraw){ + if (_cNodeVector.size() > 1) { + QPoint start = _cNodeVector.front(); + for (std::vector::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) { + _pcView3D->drawLine(start.x(),start.y(),it->x(), it->y(), + this->l, this->r, this->g, this->b, this->a); + start = *it; + } + } + + // recursive call, but no infinite loop + mustRedraw = false; + draw(); + } + if (m_bWorking) { + _pcView3D->drawLine(m_iXnew, m_iYnew, m_iXold, m_iYold, + this->l, this->r, this->g, this->b, this->a); + } +} + +BrushSelection::~BrushSelection() +{ +} + +int BrushSelection::popupMenu() +{ + QMenu menu; + QAction* fi = menu.addAction(QObject::tr("Finish")); + menu.addAction(QObject::tr("Clear")); + QAction* ca = menu.addAction(QObject::tr("Cancel")); + if (getPositions().size() < 3) + fi->setEnabled(false); + QAction* id = menu.exec(QCursor::pos()); + if (id == fi) + return Finish; + else if (id == ca) + return Cancel; + else + return Restart; +} + +int BrushSelection::mouseButtonEvent(const SoMouseButtonEvent * const e, const QPoint& pos) +{ + const int button = e->getButton(); + const SbBool press = e->getState() == SoButtonEvent::DOWN ? TRUE : FALSE; + + if (press) { + switch (button) + { + case SoMouseButtonEvent::BUTTON1: + { + // start working from now on + if (!m_bWorking) { + m_bWorking = true; + // clear the old polygon + _cNodeVector.clear(); + _pcView3D->getGLWidget()->update(); + + _cNodeVector.push_back(pos); + + m_iXnew = pos.x(); m_iYnew = pos.y(); + m_iXold = pos.x(); m_iYold = pos.y(); + } + } break; + case SoMouseButtonEvent::BUTTON2: + { + if (_cNodeVector.size() > 0) { + if (_cNodeVector.back() != pos) + _cNodeVector.push_back(pos); + m_iXnew = pos.x(); m_iYnew = pos.y(); + m_iXold = pos.x(); m_iYold = pos.y(); + } + } break; + default: + { + } break; + } + } + // release + else { + switch (button) + { + case SoMouseButtonEvent::BUTTON1: + return Finish; + case SoMouseButtonEvent::BUTTON2: + { + QCursor cur = _pcView3D->getWidget()->cursor(); + _pcView3D->getWidget()->setCursor(m_cPrevCursor); + + // The pop-up menu should be shown when releasing mouse button because + // otherwise the navigation style doesn't get the UP event and gets into + // an inconsistent state. + int id = popupMenu(); + if (id == Finish || id == Cancel) { + releaseMouseModel(); + } + else if (id == Restart) { + m_bWorking = false; + m_iNodes = 0; + _pcView3D->getWidget()->setCursor(cur); + } + return id; + } break; + default: + { + } break; + } + } + + return Continue; +} + +int BrushSelection::locationEvent(const SoLocation2Event * const e, const QPoint& pos) +{ + // do all the drawing stuff for us + QPoint clPoint = pos; + + if (m_bWorking) { + // check the position + QRect r = _pcView3D->getGLWidget()->rect(); + if (!r.contains(clPoint)) { + if (clPoint.x() < r.left()) + clPoint.setX( r.left()); + if (clPoint.x() > r.right()) + clPoint.setX(r.right()); + if (clPoint.y() < r.top()) + clPoint.setY(r.top()); + if (clPoint.y() > r.bottom()) + clPoint.setY(r.bottom()); + } + + SbVec2s last = _clPoly.back(); + SbVec2s curr = e->getPosition(); + if (abs(last[0]-curr[0]) > 20 || abs(last[1]-curr[1]) > 20) + _clPoly.push_back(curr); + _cNodeVector.push_back(clPoint); + } + + m_iXnew = clPoint.x(); + m_iYnew = clPoint.y(); + draw(); + m_iXold = clPoint.x(); + m_iYold = clPoint.y(); + + return Continue; +} + +int BrushSelection::keyboardEvent( const SoKeyboardEvent * const e ) +{ + return Continue; +} + +// ----------------------------------------------------------------------------------- + RectangleSelection::RectangleSelection() { m_bWorking = false; diff --git a/src/Gui/MouseSelection.h b/src/Gui/MouseSelection.h index fd8716e728..b26cdea30b 100644 --- a/src/Gui/MouseSelection.h +++ b/src/Gui/MouseSelection.h @@ -27,6 +27,7 @@ #include #include #include +#include // forwards class QMouseEvent; @@ -156,6 +157,45 @@ protected: // ----------------------------------------------------------------------------------- +/** + * The brush selection class + * \author Werner Mayer + */ +class GuiExport BrushSelection : public BaseMouseSelection +{ +public: + BrushSelection(); + virtual ~BrushSelection(); + + /// set the new mouse cursor + virtual void initialize(); + /// do nothing + virtual void terminate(); + + // Settings + void setColor(float r, float g, float b, float a=0); + void setLineWidth(float); + +protected: + virtual int mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos ); + virtual int locationEvent ( const SoLocation2Event * const e, const QPoint& pos ); + virtual int keyboardEvent ( const SoKeyboardEvent * const e ); + + /// draw the polygon + virtual void draw (); + virtual int popupMenu(); + +protected: + std::vector _cNodeVector; + int m_iNodes; + bool m_bWorking; + +private: + float r,g,b,a,l; +}; + +// ----------------------------------------------------------------------------------- + /** * The selection mouse model class * Draws a rectangle for selection diff --git a/src/Gui/View3DInventorViewer.cpp b/src/Gui/View3DInventorViewer.cpp index 5e1963687e..5843f4bea3 100644 --- a/src/Gui/View3DInventorViewer.cpp +++ b/src/Gui/View3DInventorViewer.cpp @@ -1620,6 +1620,67 @@ void View3DInventorViewer::drawLine (int x1, int y1, int x2, int y2) this->glUnlockNormal(); } +void View3DInventorViewer::drawLine (int x1, int y1, int x2, int y2, GLfloat line, + GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha, + GLenum op) +{ + // Make current context + SbVec2s view = this->getGLSize(); + this->glLockNormal(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + glOrtho(0, view[0], 0, view[1], -1, 1); + + // Store GL state + glPushAttrib(GL_ALL_ATTRIB_BITS); + GLfloat depthrange[2]; + glGetFloatv(GL_DEPTH_RANGE, depthrange); + GLdouble projectionmatrix[16]; + glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix); + + glDepthFunc(GL_ALWAYS); + glDepthMask(GL_TRUE); + glDepthRange(0,0); + glEnable(GL_DEPTH_TEST); + glDisable(GL_LIGHTING); + glEnable(GL_COLOR_MATERIAL); + glDisable(GL_BLEND); + + glLineWidth(line); + glColor4f(red, green, blue, alpha); + glViewport(0, 0, view[0], view[1]); + + if (op > 0) { + glEnable(GL_COLOR_LOGIC_OP); + glLogicOp(op); + } + glDrawBuffer(GL_FRONT); + + glBegin(GL_LINES); + glVertex3i(x1, view[1]-y1, 0); + glVertex3i(x2, view[1]-y2, 0); + glEnd(); + + glFlush(); + if (op) { + glLogicOp(GL_COPY); + glDisable(GL_COLOR_LOGIC_OP); + } + + // Reset original state + glDepthRange(depthrange[0], depthrange[1]); + glMatrixMode(GL_PROJECTION); + glLoadMatrixd(projectionmatrix); + + glPopAttrib(); + glPopMatrix(); + + // Release the context + this->glUnlockNormal(); +} + /*! Decide if it should be possible to start a spin animation of the model in the viewer by releasing the mouse button while dragging. diff --git a/src/Gui/View3DInventorViewer.h b/src/Gui/View3DInventorViewer.h index 47cb11de90..88985f8462 100644 --- a/src/Gui/View3DInventorViewer.h +++ b/src/Gui/View3DInventorViewer.h @@ -256,6 +256,9 @@ public: //@{ void drawRect (int x, int y, int w, int h); void drawLine (int x1, int y1, int x2, int y2); + void drawLine (int x1, int y1, int x2, int y2, + GLfloat line, GLfloat red, GLfloat green, + GLfloat blue, GLfloat alpha, GLenum op=0); //@} void setGradientBackgroud(bool b);