1
/***************************************************************************
2
* Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net> *
4
* This file is part of the FreeCAD CAx development system. *
6
* This library is free software; you can redistribute it and/or *
7
* modify it under the terms of the GNU Library General Public *
8
* License as published by the Free Software Foundation; either *
9
* version 2 of the License, or (at your option) any later version. *
11
* This library is distributed in the hope that it will be useful, *
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14
* GNU Library General Public License for more details. *
16
* You should have received a copy of the GNU Library General Public *
17
* License along with this library; see the file COPYING.LIB. If not, *
18
* write to the Free Software Foundation, Inc., 59 Temple Place, *
19
* Suite 330, Boston, MA 02111-1307, USA *
21
***************************************************************************/
23
#include "PreCompiled.h"
25
# include <Inventor/nodes/SoCamera.h>
26
# include <QApplication>
29
#include "NavigationStyle.h"
30
#include "View3DInventorViewer.h"
35
// ----------------------------------------------------------------------------------
37
/* TRANSLATOR Gui::RevitNavigationStyle */
39
TYPESYSTEM_SOURCE(Gui::RevitNavigationStyle, Gui::UserNavigationStyle)
41
RevitNavigationStyle::RevitNavigationStyle() : lockButton1(false)
45
RevitNavigationStyle::~RevitNavigationStyle() = default;
47
const char* RevitNavigationStyle::mouseButtons(ViewerMode mode)
50
case NavigationStyle::SELECTION:
51
return QT_TR_NOOP("Press left mouse button");
52
case NavigationStyle::PANNING:
53
return QT_TR_NOOP("Press middle mouse button");
54
case NavigationStyle::DRAGGING:
55
return QT_TR_NOOP("Press SHIFT and middle mouse button");
56
case NavigationStyle::ZOOMING:
57
return QT_TR_NOOP("Scroll middle mouse button");
59
return "No description";
63
SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev)
65
// Events when in "ready-to-seek" mode are ignored, except those
66
// which influence the seek mode itself -- these are handled further
67
// up the inheritance hierarchy.
68
if (this->isSeekMode()) {
69
return inherited::processSoEvent(ev);
71
// Switch off viewing mode (Bug #0000911)
72
if (!this->isSeekMode() && !this->isAnimating() && this->isViewing())
73
this->setViewing(false); // by default disable viewing mode to render the scene
75
const SoType type(ev->getTypeId());
77
const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
78
const SbVec2s pos(ev->getPosition());
79
const SbVec2f posn = normalizePixelPos(pos);
81
const SbVec2f prevnormalized = this->lastmouseposition;
82
this->lastmouseposition = posn;
84
// Set to true if any event processing happened. Note that it is not
85
// necessary to restrict ourselves to only do one "action" for an
86
// event, we only need this flag to see if any processing happened
88
SbBool processed = false;
90
const ViewerMode curmode = this->currentmode;
91
ViewerMode newmode = curmode;
93
// Mismatches in state of the modifier keys happens if the user
94
// presses or releases them outside the viewer window.
97
// give the nodes in the foreground root the chance to handle events (e.g color bar)
98
if (!viewer->isEditing()) {
99
processed = handleEventInForeground(ev);
105
if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
106
const auto event = static_cast<const SoKeyboardEvent *>(ev);
107
processed = processKeyboardEvent(event);
110
// Mouse Button / Spaceball Button handling
111
if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
112
const auto event = (const SoMouseButtonEvent *) ev;
113
const int button = event->getButton();
114
const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
116
//SoDebugError::postInfo("processSoEvent", "button = %d", button);
118
case SoMouseButtonEvent::BUTTON1:
119
this->lockrecenter = true;
120
this->button1down = press;
121
if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) {
122
newmode = NavigationStyle::SEEK_MODE;
123
this->seekToPoint(pos); // implicitly calls interactiveCountInc()
126
else if (press && (this->currentmode == NavigationStyle::PANNING ||
127
this->currentmode == NavigationStyle::ZOOMING)) {
128
newmode = NavigationStyle::DRAGGING;
129
saveCursorPosition(ev);
130
this->centerTime = ev->getTime();
133
else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
136
else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
140
processed = processClickEvent(event);
143
case SoMouseButtonEvent::BUTTON2:
144
// If we are in edit mode then simply ignore the RMB events
145
// to pass the event to the base class.
146
this->lockrecenter = true;
148
// Don't show the context menu after dragging, panning or zooming
149
if (!press && (hasDragged || hasPanned || hasZoomed)) {
152
else if (!press && !viewer->isEditing()) {
153
if (this->currentmode != NavigationStyle::ZOOMING &&
154
this->currentmode != NavigationStyle::PANNING &&
155
this->currentmode != NavigationStyle::DRAGGING) {
156
if (this->isPopupMenuEnabled()) {
157
this->openPopupMenu(event->getPosition());
161
// Alternative way of rotating & zooming
162
if (press && (this->currentmode == NavigationStyle::PANNING ||
163
this->currentmode == NavigationStyle::ZOOMING)) {
164
newmode = NavigationStyle::DRAGGING;
165
saveCursorPosition(ev);
166
this->centerTime = ev->getTime();
169
this->button2down = press;
171
case SoMouseButtonEvent::BUTTON3:
173
this->centerTime = ev->getTime();
174
setupPanningPlane(getCamera());
175
this->lockrecenter = false;
178
SbTime tmp = (ev->getTime() - this->centerTime);
179
float dci = (float)QApplication::doubleClickInterval()/1000.0f;
180
// is it just a middle click?
181
if (tmp.getValue() < dci && !this->lockrecenter) {
186
this->button3down = press;
193
// Mouse Movement handling
194
if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
195
this->lockrecenter = true;
196
const auto event = (const SoLocation2Event *) ev;
197
if (this->currentmode == NavigationStyle::ZOOMING) {
198
this->zoomByCursor(posn, prevnormalized);
201
else if (this->currentmode == NavigationStyle::PANNING) {
202
float ratio = vp.getViewportAspectRatio();
203
panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
206
else if (this->currentmode == NavigationStyle::DRAGGING) {
207
this->addToLog(event->getPosition(), event->getTime());
209
moveCursorPosition();
214
// Spaceball & Joystick handling
215
if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
216
const auto event = static_cast<const SoMotion3Event *>(ev);
218
this->processMotionEvent(event);
223
BUTTON1DOWN = 1 << 0,
224
BUTTON3DOWN = 1 << 1,
230
(this->button1down ? BUTTON1DOWN : 0) |
231
(this->button2down ? BUTTON2DOWN : 0) |
232
(this->button3down ? BUTTON3DOWN : 0) |
233
(this->ctrldown ? CTRLDOWN : 0) |
234
(this->shiftdown ? SHIFTDOWN : 0);
238
if (curmode == NavigationStyle::SPINNING) { break; }
239
newmode = NavigationStyle::IDLE;
240
// The left mouse button has been released right now
241
if (this->lockButton1) {
242
this->lockButton1 = false;
243
if (curmode != NavigationStyle::SELECTION) {
249
case CTRLDOWN|BUTTON1DOWN:
250
// make sure not to change the selection when stopping spinning
251
if (curmode == NavigationStyle::SPINNING
252
|| (this->lockButton1 && curmode != NavigationStyle::SELECTION)) {
253
newmode = NavigationStyle::IDLE;
256
newmode = NavigationStyle::SELECTION;
259
case BUTTON1DOWN|BUTTON2DOWN:
261
newmode = NavigationStyle::PANNING;
263
case SHIFTDOWN|BUTTON3DOWN:
264
if (newmode != NavigationStyle::DRAGGING) {
265
saveCursorPosition(ev);
267
newmode = NavigationStyle::DRAGGING;
269
case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN:
270
case CTRLDOWN|BUTTON3DOWN:
271
newmode = NavigationStyle::ZOOMING;
275
// Reset mode to SELECTION when button 3 is released
276
// This stops the DRAGGING when button 3 is released but SHIFT is still pressed
277
// This stops the ZOOMING when button 3 is released but CTRL is still pressed
278
if ((curmode == NavigationStyle::DRAGGING || curmode == NavigationStyle::ZOOMING)
279
&& !this->button3down) {
280
newmode = NavigationStyle::SELECTION;
285
// If the selection button is pressed together with another button
286
// and the other button is released, don't switch to selection mode.
287
// Process when selection button is pressed together with other buttons that could trigger different actions.
288
if (this->button1down && (this->button2down || this->button3down)) {
289
this->lockButton1 = true;
293
// Prevent interrupting rubber-band selection in sketcher
294
if (viewer->isEditing() && curmode == NavigationStyle::SELECTION && newmode != NavigationStyle::IDLE) {
295
newmode = NavigationStyle::SELECTION;
299
if (newmode != curmode) {
300
this->setViewingMode(newmode);
303
// If not handled in this class, pass on upwards in the inheritance
306
processed = inherited::processSoEvent(ev);