Gui: add support of TinkerCAD navigation style
This commit is contained in:
@@ -839,6 +839,7 @@ SET(View3D_CPP_SRCS
|
||||
MayaGestureNavigationStyle.cpp
|
||||
OpenCascadeNavigationStyle.cpp
|
||||
OpenSCADNavigationStyle.cpp
|
||||
TinkerCADNavigationStyle.cpp
|
||||
TouchpadNavigationStyle.cpp
|
||||
GestureNavigationStyle.cpp
|
||||
SplitView3DInventor.cpp
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <QEvent>
|
||||
#include <Base/BaseClass.h>
|
||||
#include <Gui/Namespace.h>
|
||||
#include <FCGlobal.h>
|
||||
|
||||
// forward declarations
|
||||
class SoEvent;
|
||||
@@ -429,6 +430,23 @@ private:
|
||||
SoMouseButtonEvent mouseDownConsumedEvent;
|
||||
};
|
||||
|
||||
class GuiExport TinkerCADNavigationStyle : public UserNavigationStyle {
|
||||
typedef UserNavigationStyle inherited;
|
||||
|
||||
TYPESYSTEM_HEADER();
|
||||
|
||||
public:
|
||||
TinkerCADNavigationStyle();
|
||||
~TinkerCADNavigationStyle();
|
||||
const char* mouseButtons(ViewerMode);
|
||||
|
||||
protected:
|
||||
SbBool processSoEvent(const SoEvent * const ev);
|
||||
|
||||
private:
|
||||
SoMouseButtonEvent mouseDownConsumedEvent;
|
||||
};
|
||||
|
||||
} // namespace Gui
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(Gui::NavigationStyle::RotationCenterModes)
|
||||
|
||||
@@ -186,6 +186,7 @@ void Gui::SoFCDB::init()
|
||||
GestureNavigationStyle ::init();
|
||||
OpenCascadeNavigationStyle ::init();
|
||||
OpenSCADNavigationStyle ::init();
|
||||
TinkerCADNavigationStyle ::init();
|
||||
|
||||
GLGraphicsItem ::init();
|
||||
GLFlagWindow ::init();
|
||||
|
||||
285
src/Gui/TinkerCADNavigationStyle.cpp
Normal file
285
src/Gui/TinkerCADNavigationStyle.cpp
Normal file
@@ -0,0 +1,285 @@
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2021 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 <cfloat>
|
||||
# include "InventorAll.h"
|
||||
# include <QAction>
|
||||
# include <QActionGroup>
|
||||
# include <QApplication>
|
||||
# include <QByteArray>
|
||||
# include <QCursor>
|
||||
# include <QList>
|
||||
# include <QMenu>
|
||||
# include <QMetaObject>
|
||||
# include <QRegExp>
|
||||
#endif
|
||||
|
||||
#include <App/Application.h>
|
||||
#include "NavigationStyle.h"
|
||||
#include "View3DInventorViewer.h"
|
||||
#include "Application.h"
|
||||
#include "MenuManager.h"
|
||||
#include "MouseSelection.h"
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
// ----------------------------------------------------------------------------------
|
||||
|
||||
/* TRANSLATOR Gui::TinkerCADNavigationStyle */
|
||||
|
||||
TYPESYSTEM_SOURCE(Gui::TinkerCADNavigationStyle, Gui::UserNavigationStyle)
|
||||
|
||||
TinkerCADNavigationStyle::TinkerCADNavigationStyle()
|
||||
{
|
||||
}
|
||||
|
||||
TinkerCADNavigationStyle::~TinkerCADNavigationStyle()
|
||||
{
|
||||
}
|
||||
|
||||
const char* TinkerCADNavigationStyle::mouseButtons(ViewerMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case NavigationStyle::SELECTION:
|
||||
return QT_TR_NOOP("Press left mouse button");
|
||||
case NavigationStyle::PANNING:
|
||||
return QT_TR_NOOP("Press middle mouse button");
|
||||
case NavigationStyle::DRAGGING:
|
||||
return QT_TR_NOOP("Press right mouse button");
|
||||
case NavigationStyle::ZOOMING:
|
||||
return QT_TR_NOOP("Scroll middle mouse button");
|
||||
default:
|
||||
return "No description";
|
||||
}
|
||||
}
|
||||
|
||||
SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev)
|
||||
{
|
||||
// Events when in "ready-to-seek" mode are ignored, except those
|
||||
// which influence the seek mode itself -- these are handled further
|
||||
// up the inheritance hierarchy.
|
||||
if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
|
||||
// Switch off viewing mode
|
||||
if (!this->isSeekMode() && !this->isAnimating() && this->isViewing())
|
||||
this->setViewing(false); // by default disable viewing mode to render the scene
|
||||
|
||||
const SoType type(ev->getTypeId());
|
||||
|
||||
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
|
||||
const SbVec2s pos(ev->getPosition());
|
||||
const SbVec2f posn = normalizePixelPos(pos);
|
||||
|
||||
const SbVec2f prevnormalized = this->lastmouseposition;
|
||||
this->lastmouseposition = posn;
|
||||
|
||||
// Set to true if any event processing happened. Note that it is not
|
||||
// necessary to restrict ourselves to only do one "action" for an
|
||||
// event, we only need this flag to see if any processing happened
|
||||
// at all.
|
||||
SbBool processed = false;
|
||||
|
||||
const ViewerMode curmode = this->currentmode;
|
||||
ViewerMode newmode = curmode;
|
||||
|
||||
// Mismatches in state of the modifier keys happens if the user
|
||||
// presses or releases them outside the viewer window.
|
||||
syncModifierKeys(ev);
|
||||
|
||||
// give the nodes in the foreground root the chance to handle events (e.g color bar)
|
||||
if (!viewer->isEditing()) {
|
||||
processed = handleEventInForeground(ev);
|
||||
if (processed)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Keyboard handling
|
||||
if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
|
||||
const SoKeyboardEvent * const event = static_cast<const SoKeyboardEvent *>(ev);
|
||||
processed = handleKeyboardEvent(event, posn);
|
||||
}
|
||||
|
||||
// Mouse Button / Spaceball Button handling
|
||||
if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
|
||||
const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
|
||||
const int button = event->getButton();
|
||||
const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
|
||||
SbBool canOpenPopupMenu = false;
|
||||
|
||||
switch (button) {
|
||||
case SoMouseButtonEvent::BUTTON1:
|
||||
this->button1down = press;
|
||||
if (press && (curmode == NavigationStyle::SEEK_WAIT_MODE)) {
|
||||
newmode = NavigationStyle::SEEK_MODE;
|
||||
this->seekToPoint(pos); // implicitly calls interactiveCountInc()
|
||||
processed = true;
|
||||
}
|
||||
else if (viewer->isEditing() && (curmode == NavigationStyle::SPINNING)) {
|
||||
processed = true;
|
||||
}
|
||||
// issue #0002433: avoid to swallow the UP event if down the
|
||||
// scene graph somewhere a dialog gets opened
|
||||
else if (press) {
|
||||
SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime());
|
||||
float dci = (float)QApplication::doubleClickInterval()/1000.0f;
|
||||
// a double-click?
|
||||
if (tmp.getValue() < dci) {
|
||||
mouseDownConsumedEvent = *event;
|
||||
mouseDownConsumedEvent.setTime(ev->getTime());
|
||||
processed = true;
|
||||
}
|
||||
else {
|
||||
mouseDownConsumedEvent.setTime(ev->getTime());
|
||||
// 'ANY' is used to mark that we don't know yet if it will
|
||||
// be a double-click event.
|
||||
mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY);
|
||||
}
|
||||
}
|
||||
else if (!press) {
|
||||
if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON1) {
|
||||
// now handle the postponed event
|
||||
inherited::processSoEvent(&mouseDownConsumedEvent);
|
||||
mouseDownConsumedEvent.setButton(SoMouseButtonEvent::ANY);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SoMouseButtonEvent::BUTTON2:
|
||||
// If we are in edit mode then simply ignore the RMB events
|
||||
// to pass the event to the base class.
|
||||
this->button2down = press;
|
||||
if (press) {
|
||||
mouseDownConsumedEvent = *event;
|
||||
mouseDownConsumedEvent.setTime(ev->getTime());
|
||||
}
|
||||
else if (mouseDownConsumedEvent.getButton() == SoMouseButtonEvent::BUTTON2) {
|
||||
SbTime tmp = (ev->getTime() - mouseDownConsumedEvent.getTime());
|
||||
float dci = float(QApplication::doubleClickInterval())/1000.0f;
|
||||
// time between press and release event
|
||||
if (tmp.getValue() < dci) {
|
||||
canOpenPopupMenu = true;
|
||||
}
|
||||
}
|
||||
|
||||
// About to start rotating
|
||||
if (press && (curmode == NavigationStyle::IDLE)) {
|
||||
// Use this variable to spot move events
|
||||
saveCursorPosition(ev);
|
||||
this->centerTime = ev->getTime();
|
||||
processed = true;
|
||||
}
|
||||
else if (!press && (curmode == NavigationStyle::DRAGGING)) {
|
||||
if (!viewer->isEditing() && canOpenPopupMenu) {
|
||||
// If we are in drag mode but mouse hasn't been moved open the context-menu
|
||||
if (this->isPopupMenuEnabled()) {
|
||||
this->openPopupMenu(event->getPosition());
|
||||
}
|
||||
}
|
||||
newmode = NavigationStyle::IDLE;
|
||||
processed = true;
|
||||
}
|
||||
break;
|
||||
case SoMouseButtonEvent::BUTTON3:
|
||||
this->button3down = press;
|
||||
if (press) {
|
||||
this->centerTime = ev->getTime();
|
||||
float ratio = vp.getViewportAspectRatio();
|
||||
SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
|
||||
this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
|
||||
}
|
||||
else if (curmode == NavigationStyle::PANNING) {
|
||||
newmode = NavigationStyle::IDLE;
|
||||
processed = true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Mouse Movement handling
|
||||
if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
|
||||
const SoLocation2Event * const event = (const SoLocation2Event *) ev;
|
||||
if (curmode == NavigationStyle::PANNING) {
|
||||
float ratio = vp.getViewportAspectRatio();
|
||||
panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
|
||||
processed = true;
|
||||
}
|
||||
else if (curmode == NavigationStyle::DRAGGING) {
|
||||
this->addToLog(event->getPosition(), event->getTime());
|
||||
this->spin(posn);
|
||||
moveCursorPosition();
|
||||
processed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Spaceball & Joystick handling
|
||||
if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
|
||||
const SoMotion3Event * const event = static_cast<const SoMotion3Event *>(ev);
|
||||
if (event)
|
||||
this->processMotionEvent(event);
|
||||
processed = true;
|
||||
}
|
||||
|
||||
enum {
|
||||
BUTTON1DOWN = 1 << 0,
|
||||
BUTTON3DOWN = 1 << 1,
|
||||
CTRLDOWN = 1 << 2,
|
||||
SHIFTDOWN = 1 << 3,
|
||||
BUTTON2DOWN = 1 << 4
|
||||
};
|
||||
unsigned int combo =
|
||||
(this->button1down ? BUTTON1DOWN : 0) |
|
||||
(this->button2down ? BUTTON2DOWN : 0) |
|
||||
(this->button3down ? BUTTON3DOWN : 0) |
|
||||
(this->ctrldown ? CTRLDOWN : 0) |
|
||||
(this->shiftdown ? SHIFTDOWN : 0);
|
||||
|
||||
switch (combo) {
|
||||
case 0:
|
||||
if (curmode == NavigationStyle::SPINNING) { break; }
|
||||
newmode = NavigationStyle::IDLE;
|
||||
break;
|
||||
case BUTTON1DOWN:
|
||||
newmode = NavigationStyle::SELECTION;
|
||||
break;
|
||||
case BUTTON2DOWN:
|
||||
newmode = NavigationStyle::DRAGGING;
|
||||
break;
|
||||
case BUTTON3DOWN:
|
||||
newmode = NavigationStyle::PANNING;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (newmode != curmode) {
|
||||
this->setViewingMode(newmode);
|
||||
}
|
||||
|
||||
// If not handled in this class, pass on upwards in the inheritance
|
||||
// hierarchy.
|
||||
if (!processed)
|
||||
processed = inherited::processSoEvent(ev);
|
||||
return processed;
|
||||
}
|
||||
Reference in New Issue
Block a user