Implement a more user-friendly selection tool
This commit is contained in:
@@ -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<QPoint>::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;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <vector>
|
||||
#include <Inventor/SbLinear.h>
|
||||
#include <Inventor/SbVec2f.h>
|
||||
#include <QCursor>
|
||||
|
||||
// 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<QPoint> _cNodeVector;
|
||||
int m_iNodes;
|
||||
bool m_bWorking;
|
||||
|
||||
private:
|
||||
float r,g,b,a,l;
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* The selection mouse model class
|
||||
* Draws a rectangle for selection
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user