950 lines
27 KiB
C++
950 lines
27 KiB
C++
/***************************************************************************
|
|
* Copyright (c) 2005 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
|
* *
|
|
* This file is part of the FreeCAD CAx development system. *
|
|
* *
|
|
* This library is free software; you can redistribute it and/or *
|
|
* modify it under the terms of the GNU Library General Public *
|
|
* License as published by the Free Software Foundation; either *
|
|
* version 2 of the License, or (at your option) any later version. *
|
|
* *
|
|
* This library is distributed in the hope that it will be useful, *
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
* GNU Library General Public License for more details. *
|
|
* *
|
|
* You should have received a copy of the GNU Library General Public *
|
|
* License along with this library; see the file COPYING.LIB. If not, *
|
|
* write to the Free Software Foundation, Inc., 59 Temple Place, *
|
|
* Suite 330, Boston, MA 02111-1307, USA *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
|
|
#include "PreCompiled.h"
|
|
|
|
#ifndef _PreComp_
|
|
# include <qapplication.h>
|
|
# include <qevent.h>
|
|
# include <qpainter.h>
|
|
# include <qpixmap.h>
|
|
# include <QGLFramebufferObject>
|
|
# include <QMenu>
|
|
# include <Inventor/SbBox.h>
|
|
# include <Inventor/events/SoEvent.h>
|
|
# include <Inventor/events/SoKeyboardEvent.h>
|
|
# include <Inventor/events/SoLocation2Event.h>
|
|
# include <Inventor/events/SoMouseButtonEvent.h>
|
|
#endif
|
|
|
|
#include <Base/Console.h>
|
|
|
|
#include "MouseSelection.h"
|
|
#include "View3DInventor.h"
|
|
#include "View3DInventorViewer.h"
|
|
#include "GLPainter.h"
|
|
|
|
using namespace Gui;
|
|
|
|
AbstractMouseSelection::AbstractMouseSelection() : _pcView3D(0)
|
|
{
|
|
m_bInner = true;
|
|
mustRedraw = false;
|
|
}
|
|
|
|
void AbstractMouseSelection::grabMouseModel( Gui::View3DInventorViewer* viewer )
|
|
{
|
|
_pcView3D = viewer;
|
|
m_cPrevCursor = _pcView3D->getWidget()->cursor();
|
|
m_antiAliasing = (int)_pcView3D->getAntiAliasingMode();
|
|
_pcView3D->setAntiAliasingMode(View3DInventorViewer::None);
|
|
|
|
// do initialization of your mousemodel
|
|
initialize();
|
|
}
|
|
|
|
void AbstractMouseSelection::releaseMouseModel()
|
|
{
|
|
if (_pcView3D) {
|
|
// do termination of your mousemodel
|
|
terminate();
|
|
|
|
_pcView3D->getWidget()->setCursor(m_cPrevCursor);
|
|
_pcView3D->setAntiAliasingMode(View3DInventorViewer::AntiAliasing(m_antiAliasing));
|
|
_pcView3D = 0;
|
|
}
|
|
}
|
|
|
|
void AbstractMouseSelection::redraw()
|
|
{
|
|
// Note: For any reason it does not work to do a redraw in the actualRedraw() method of the
|
|
// viewer class. So, we do the redraw when the user continues moving the cursor. E.g. have
|
|
// a look to PolyPickerSelection::draw()
|
|
mustRedraw = true;
|
|
}
|
|
|
|
int AbstractMouseSelection::handleEvent(const SoEvent * const ev, const SbViewportRegion& vp)
|
|
{
|
|
int ret=Continue;
|
|
|
|
const SbVec2s& sz = vp.getWindowSize();
|
|
short w,h; sz.getValue(w,h);
|
|
|
|
SbVec2s loc = ev->getPosition();
|
|
short x,y; loc.getValue(x,y);
|
|
y = h-y; // the origin is at the left bottom corner (instead of left top corner)
|
|
|
|
if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
|
|
const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
|
|
const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
|
|
|
|
if (press) {
|
|
_clPoly.push_back(ev->getPosition());
|
|
ret = mouseButtonEvent(static_cast<const SoMouseButtonEvent*>(ev), QPoint(x,y));
|
|
}
|
|
else {
|
|
ret = mouseButtonEvent(static_cast<const SoMouseButtonEvent*>(ev), QPoint(x,y));
|
|
}
|
|
}
|
|
else if (ev->getTypeId().isDerivedFrom(SoLocation2Event::getClassTypeId())) {
|
|
ret = locationEvent(static_cast<const SoLocation2Event*>(ev), QPoint(x,y));
|
|
}
|
|
else if (ev->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
|
|
ret = keyboardEvent(static_cast<const SoKeyboardEvent*>(ev));
|
|
}
|
|
|
|
if (ret == Restart)
|
|
_clPoly.clear();
|
|
|
|
return ret;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
BaseMouseSelection::BaseMouseSelection()
|
|
: AbstractMouseSelection()
|
|
{
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
#if 0
|
|
/* XPM */
|
|
static const char *cursor_polypick[]={
|
|
"32 32 2 1",
|
|
"# c #646464",
|
|
". c None",
|
|
"................................",
|
|
"................................",
|
|
".......#........................",
|
|
".......#........................",
|
|
".......#........................",
|
|
"................................",
|
|
".......#........................",
|
|
"..###.###.###...................",
|
|
".......#...............#........",
|
|
"......................##........",
|
|
".......#..............#.#.......",
|
|
".......#.............#..#.......",
|
|
".......#............#...#.......",
|
|
"....................#....#......",
|
|
"...................#.....#......",
|
|
"..................#......#......",
|
|
"............#.....#.......#.....",
|
|
"...........#.##..#........#.....",
|
|
"..........#....##.........#.....",
|
|
".........#...............#......",
|
|
"........#................#......",
|
|
".......#................#.......",
|
|
"......#.................#.......",
|
|
".....#.................#........",
|
|
"....#####..............#........",
|
|
".........#########....#.........",
|
|
"..................#####.........",
|
|
"................................",
|
|
"................................",
|
|
"................................",
|
|
"................................",
|
|
"................................"};
|
|
|
|
/* XPM */
|
|
static const char *cursor_scissors[]={
|
|
"32 32 3 1",
|
|
"# c #000000",
|
|
"+ c #ffffff",
|
|
". c None",
|
|
"....+...........................",
|
|
"....+...........................",
|
|
"....+...........................",
|
|
"................................",
|
|
"+++.+.+++.......................",
|
|
"................................",
|
|
"....+...........................",
|
|
"....+...................#####...",
|
|
"....+.................########..",
|
|
".....................#########..",
|
|
".....###............##########..",
|
|
"....##++##.........#####...###..",
|
|
"...#++++++##.......####...####..",
|
|
"...##+++++++#......####.######..",
|
|
".....#+++++++##....##########...",
|
|
"......##+++++++##.##########....",
|
|
"........##+++++++#########......",
|
|
"..........#+++++++#####.........",
|
|
"...........##+++++####..........",
|
|
"...........##+++++###...........",
|
|
".........##+++++++########......",
|
|
"........##+++++++###########....",
|
|
"......##+++++++##.###########...",
|
|
"....##+++++++##....##########...",
|
|
"...#+++++++##......####..#####..",
|
|
"...#++++++#........#####..####..",
|
|
"....##++##..........#####..###..",
|
|
"......#.............##########..",
|
|
".....................#########..",
|
|
".......................######...",
|
|
"................................",
|
|
"................................"};
|
|
#endif
|
|
static const char *cursor_cut_scissors[]={
|
|
"32 32 6 1",
|
|
"a c #800000",
|
|
"c c #808080",
|
|
"+ c #c0c0c0",
|
|
"b c #ff0000",
|
|
"# c #ffffff",
|
|
". c None",
|
|
"....#...........................",
|
|
"....#...........................",
|
|
"....#...........................",
|
|
"................................",
|
|
"###.#.###.......................",
|
|
"................................",
|
|
"....#...........................",
|
|
"....#...................aaaaa...",
|
|
"....#.................aabbbbba..",
|
|
".....................abbbbbbba..",
|
|
".....ccc............abbaaaaabb..",
|
|
"....cc++cc.........babaa...aba..",
|
|
"...c+#++++cc.......abba...abba..",
|
|
"...cc+#+++++c......abba.aabbaa..",
|
|
".....c+++++#+cc....abbaaabbaa...",
|
|
"......cc+#+++#+cc.aabbbbbbaa....",
|
|
"........cc+#+++#+cabbbaaaa......",
|
|
"..........c+++++++abbaa.........",
|
|
"...........cc+++#+aaaa..........",
|
|
"...........cc+#+++caa...........",
|
|
".........cc+++++#+cbbaaaaa......",
|
|
"........cc+#+++#+cabbabbbaaa....",
|
|
"......cc+#+++#+cc.aaabbbbbbaa...",
|
|
"....cc+#+++#+cc....abbaaaabba...",
|
|
"...c++#++#+cc......abba..aabba..",
|
|
"...c+###++c........aabaa..aaba..",
|
|
"....cc++cc..........abbaa..aba..",
|
|
"......c.............aabbaaaaba..",
|
|
".....................baabbbbba..",
|
|
".......................aaaaaa...",
|
|
"................................",
|
|
"................................"};
|
|
|
|
PolyPickerSelection::PolyPickerSelection()
|
|
{
|
|
m_iRadius = 2;
|
|
m_iNodes = 0;
|
|
m_bWorking = false;
|
|
}
|
|
|
|
void PolyPickerSelection::initialize()
|
|
{
|
|
QPixmap p(cursor_cut_scissors);
|
|
QCursor cursor(p, 4, 4);
|
|
_pcView3D->getWidget()->setCursor(cursor);
|
|
}
|
|
|
|
void PolyPickerSelection::terminate()
|
|
{
|
|
// _pcView3D->getGLWidget()->releaseMouse();
|
|
}
|
|
|
|
void PolyPickerSelection::draw ()
|
|
{
|
|
if (mustRedraw){
|
|
if (_cNodeVector.size() > 1) {
|
|
QPoint start = _cNodeVector.front();
|
|
GLPainter p;
|
|
p.begin(_pcView3D);
|
|
p.setColor(1.0f,1.0f,1.0f);
|
|
p.setLogicOp(GL_XOR);
|
|
for (std::vector<QPoint>::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) {
|
|
p.drawLine(start.x(),start.y(),it->x(), it->y());
|
|
start = *it;
|
|
}
|
|
p.end();
|
|
}
|
|
|
|
// recursive call, but no infinite loop
|
|
mustRedraw = false;
|
|
draw();
|
|
}
|
|
if (m_bWorking) {
|
|
if (m_iNodes < int(_cNodeVector.size())) {
|
|
m_iNodes = int(_cNodeVector.size());
|
|
|
|
if (_cNodeVector.size() > 2) {
|
|
QPoint start = _cNodeVector.front();
|
|
GLPainter p;
|
|
p.begin(_pcView3D);
|
|
p.setColor(1.0f,1.0f,1.0f);
|
|
p.setLogicOp(GL_XOR);
|
|
p.drawLine(m_iXnew,m_iYnew,start.x(), start.y());
|
|
p.end();
|
|
}
|
|
}
|
|
else {
|
|
GLPainter p;
|
|
p.begin(_pcView3D);
|
|
p.setColor(1.0f,1.0f,1.0f);
|
|
p.setLogicOp(GL_XOR);
|
|
p.drawLine(m_iXnew,m_iYnew,m_iXold,m_iYold);
|
|
if (_cNodeVector.size() > 1) {
|
|
QPoint start = _cNodeVector.front();
|
|
p.drawLine(m_iXnew,m_iYnew,start.x(), start.y());
|
|
}
|
|
p.end();
|
|
}
|
|
}
|
|
}
|
|
|
|
PolyPickerSelection::~PolyPickerSelection()
|
|
{
|
|
}
|
|
|
|
int PolyPickerSelection::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 PolyPickerSelection::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();
|
|
// _pcView3D->getGLWidget()->grabMouse();
|
|
}
|
|
|
|
_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::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 PolyPickerSelection::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());
|
|
|
|
#ifdef FC_OS_WINDOWS
|
|
QPoint newPos = _pcView3D->getGLWidget()->mapToGlobal(clPoint);
|
|
QCursor::setPos(newPos);
|
|
#endif
|
|
}
|
|
}
|
|
|
|
draw();
|
|
m_iXnew = clPoint.x();
|
|
m_iYnew = clPoint.y();
|
|
draw();
|
|
|
|
return Continue;
|
|
}
|
|
|
|
int PolyPickerSelection::keyboardEvent( const SoKeyboardEvent * const e )
|
|
{
|
|
return Continue;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
PolyClipSelection::PolyClipSelection()
|
|
{
|
|
}
|
|
|
|
PolyClipSelection::~PolyClipSelection()
|
|
{
|
|
}
|
|
|
|
int PolyClipSelection::popupMenu()
|
|
{
|
|
QMenu menu;
|
|
QAction* ci = menu.addAction(QObject::tr("Inner"));
|
|
QAction* co = menu.addAction(QObject::tr("Outer"));
|
|
QAction* ca = menu.addAction(QObject::tr("Cancel"));
|
|
if (getPositions().size() < 3) {
|
|
ci->setEnabled(false);
|
|
co->setEnabled(false);
|
|
}
|
|
QAction* id = menu.exec(QCursor::pos());
|
|
if (id == ci) {
|
|
m_bInner = true;
|
|
return Finish;
|
|
}
|
|
else if (id == co) {
|
|
m_bInner = false;
|
|
return Finish;
|
|
}
|
|
else if (id == ca)
|
|
return Cancel;
|
|
else
|
|
return Restart;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
BrushSelection::BrushSelection()
|
|
: r(1.0f), g(0.0f), b(0.0f), a(0.0f), l(2.0f)
|
|
{
|
|
m_iNodes = 0;
|
|
m_bWorking = false;
|
|
m_bClose = 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::setClosed(bool on)
|
|
{
|
|
this->m_bClose = on;
|
|
}
|
|
|
|
void BrushSelection::draw ()
|
|
{
|
|
if (mustRedraw){
|
|
if (_cNodeVector.size() > 1) {
|
|
QPoint start = _cNodeVector.front();
|
|
GLPainter p;
|
|
p.begin(_pcView3D);
|
|
p.setLineWidth(this->l);
|
|
p.setColor(this->r, this->g, this->b, this->a);
|
|
for (std::vector<QPoint>::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) {
|
|
p.drawLine(start.x(),start.y(),it->x(), it->y());
|
|
start = *it;
|
|
}
|
|
p.end();
|
|
}
|
|
|
|
// recursive call, but no infinite loop
|
|
mustRedraw = false;
|
|
draw();
|
|
}
|
|
if (m_bWorking) {
|
|
GLPainter p;
|
|
p.begin(_pcView3D);
|
|
p.setLineWidth(this->l);
|
|
p.setColor(this->r, this->g, this->b, this->a);
|
|
if (m_bClose && !_cNodeVector.empty()) {
|
|
// We have to redraw the whole polyline when using XOR because otherwise the curve looks 'dirty'.
|
|
QPoint start = _cNodeVector.front();
|
|
for (std::vector<QPoint>::iterator it = _cNodeVector.begin()+1; it != _cNodeVector.end(); ++it) {
|
|
p.drawLine(start.x(),start.y(),it->x(), it->y());
|
|
start = *it;
|
|
}
|
|
start = _cNodeVector.front();
|
|
p.setLineStipple(2, 0x3F3F);
|
|
p.setLogicOp(GL_XOR);
|
|
p.drawLine(m_iXold, m_iYold, start.x(),start.y());
|
|
p.drawLine(m_iXnew, m_iYnew, start.x(),start.y());
|
|
p.resetLogicOp();
|
|
p.resetLineStipple();
|
|
}
|
|
p.drawLine(m_iXnew, m_iYnew, m_iXold, m_iYold);
|
|
p.end();
|
|
}
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
RectangleSelection::~RectangleSelection()
|
|
{
|
|
}
|
|
|
|
void RectangleSelection::initialize()
|
|
{
|
|
}
|
|
|
|
void RectangleSelection::terminate()
|
|
{
|
|
}
|
|
|
|
void RectangleSelection::draw ()
|
|
{
|
|
if (m_bWorking) {
|
|
GLPainter p;
|
|
p.begin(_pcView3D);
|
|
p.setColor(1.0, 1.0, 0.0, 0.0);
|
|
p.setLogicOp(GL_XOR);
|
|
p.setLineWidth(3.0f);
|
|
p.setLineStipple(2, 0x3F3F);
|
|
p.drawRect(m_iXold, m_iYold, m_iXnew, m_iYnew);
|
|
p.end();
|
|
}
|
|
}
|
|
|
|
int RectangleSelection::mouseButtonEvent( const SoMouseButtonEvent * const e, const QPoint& pos )
|
|
{
|
|
const int button = e->getButton();
|
|
const SbBool press = e->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
|
|
|
|
int ret = Continue;
|
|
|
|
if (press) {
|
|
switch ( button )
|
|
{
|
|
case SoMouseButtonEvent::BUTTON1:
|
|
{
|
|
m_bWorking = true;
|
|
m_iXold = m_iXnew = pos.x();
|
|
m_iYold = m_iYnew = pos.y();
|
|
} break;
|
|
default:
|
|
{
|
|
} break;
|
|
}
|
|
}
|
|
else {
|
|
switch (button) {
|
|
case SoMouseButtonEvent::BUTTON1:
|
|
{
|
|
releaseMouseModel();
|
|
m_bWorking = false;
|
|
_clPoly.push_back(e->getPosition());
|
|
ret = Finish;
|
|
} break;
|
|
default:
|
|
{
|
|
} break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int RectangleSelection::locationEvent( const SoLocation2Event * const e, const QPoint& pos )
|
|
{
|
|
draw();
|
|
m_iXnew = pos.x();
|
|
m_iYnew = pos.y();
|
|
draw();
|
|
return Continue;
|
|
}
|
|
|
|
int RectangleSelection::keyboardEvent( const SoKeyboardEvent * const e )
|
|
{
|
|
return Continue;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
class RubberbandSelection::Private : public Gui::GLGraphicsItem
|
|
{
|
|
Gui::View3DInventorViewer* viewer;
|
|
int x_old, y_old, x_new, y_new;
|
|
bool working;
|
|
public:
|
|
Private(Gui::View3DInventorViewer* v) : viewer(v)
|
|
{
|
|
x_old = y_old = x_new = y_new = 0;
|
|
working = false;
|
|
}
|
|
~Private()
|
|
{
|
|
}
|
|
void setWorking(bool on)
|
|
{
|
|
working = on;
|
|
}
|
|
void setCoords(int x1, int y1, int x2, int y2)
|
|
{
|
|
x_old = x1;
|
|
y_old = y1;
|
|
x_new = x2;
|
|
y_new = y2;
|
|
}
|
|
void paintGL()
|
|
{
|
|
if (!working)
|
|
return;
|
|
const SbViewportRegion vp = viewer->getViewportRegion();
|
|
SbVec2s size = vp.getViewportSizePixels();
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
glOrtho(0, size[0], size[1], 0, 0, 100);
|
|
glMatrixMode(GL_MODELVIEW);
|
|
glDisable(GL_TEXTURE_2D);
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
glLineWidth(4.0);
|
|
glColor4f(1.0f, 1.0f, 1.0f, 0.2f);
|
|
glRecti(x_old, y_old, x_new, y_new);
|
|
glColor4f(1.0, 1.0, 0.0, 0.5);
|
|
glLineStipple(3, 0xAAAA);
|
|
glEnable(GL_LINE_STIPPLE);
|
|
|
|
glBegin(GL_LINE_LOOP);
|
|
glVertex2i(x_old, y_old);
|
|
glVertex2i(x_new, y_old);
|
|
glVertex2i(x_new, y_new);
|
|
glVertex2i(x_old, y_new);
|
|
glEnd();
|
|
|
|
glLineWidth(1.0);
|
|
glDisable(GL_LINE_STIPPLE);
|
|
glDisable(GL_BLEND);
|
|
}
|
|
};
|
|
|
|
RubberbandSelection::RubberbandSelection()
|
|
{
|
|
d = 0;
|
|
}
|
|
|
|
RubberbandSelection::~RubberbandSelection()
|
|
{
|
|
}
|
|
|
|
void RubberbandSelection::initialize()
|
|
{
|
|
d = new Private(_pcView3D);
|
|
_pcView3D->addGraphicsItem(d);
|
|
if (QGLFramebufferObject::hasOpenGLFramebufferObjects()) {
|
|
_pcView3D->setRenderFramebuffer(true);
|
|
}
|
|
_pcView3D->scheduleRedraw();
|
|
}
|
|
|
|
void RubberbandSelection::terminate()
|
|
{
|
|
_pcView3D->removeGraphicsItem(d);
|
|
delete d; d = 0;
|
|
if (QGLFramebufferObject::hasOpenGLFramebufferObjects()) {
|
|
_pcView3D->setRenderFramebuffer(false);
|
|
}
|
|
_pcView3D->scheduleRedraw();
|
|
}
|
|
|
|
void RubberbandSelection::draw ()
|
|
{
|
|
}
|
|
|
|
int RubberbandSelection::mouseButtonEvent(const SoMouseButtonEvent * const e, const QPoint& pos)
|
|
{
|
|
const int button = e->getButton();
|
|
const SbBool press = e->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
|
|
|
|
int ret = Continue;
|
|
|
|
if (press) {
|
|
switch (button)
|
|
{
|
|
case SoMouseButtonEvent::BUTTON1:
|
|
{
|
|
d->setWorking(true);
|
|
m_iXold = m_iXnew = pos.x();
|
|
m_iYold = m_iYnew = pos.y();
|
|
} break;
|
|
default:
|
|
{
|
|
} break;
|
|
}
|
|
}
|
|
else {
|
|
switch (button) {
|
|
case SoMouseButtonEvent::BUTTON1:
|
|
{
|
|
d->setWorking(false);
|
|
releaseMouseModel();
|
|
_clPoly.push_back(e->getPosition());
|
|
ret = Finish;
|
|
} break;
|
|
default:
|
|
{
|
|
} break;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
int RubberbandSelection::locationEvent(const SoLocation2Event * const e, const QPoint& pos)
|
|
{
|
|
m_iXnew = pos.x();
|
|
m_iYnew = pos.y();
|
|
d->setCoords(m_iXold, m_iYold, m_iXnew, m_iYnew);
|
|
_pcView3D->render();
|
|
return Continue;
|
|
}
|
|
|
|
int RubberbandSelection::keyboardEvent(const SoKeyboardEvent * const e)
|
|
{
|
|
return Continue;
|
|
}
|
|
|
|
// -----------------------------------------------------------------------------------
|
|
|
|
BoxZoomSelection::BoxZoomSelection()
|
|
{
|
|
}
|
|
|
|
BoxZoomSelection::~BoxZoomSelection()
|
|
{
|
|
}
|
|
|
|
void BoxZoomSelection::terminate()
|
|
{
|
|
RubberbandSelection::terminate();
|
|
|
|
int xmin = std::min<int>(m_iXold, m_iXnew);
|
|
int xmax = std::max<int>(m_iXold, m_iXnew);
|
|
int ymin = std::min<int>(m_iYold, m_iYnew);
|
|
int ymax = std::max<int>(m_iYold, m_iYnew);
|
|
SbBox2s box(xmin, ymin, xmax, ymax);
|
|
_pcView3D->boxZoom(box);
|
|
}
|