FreeCAD

Форк
0
/
RevitNavigationStyle.cpp 
308 строк · 11.9 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2011 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
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.      *
10
 *                                                                         *
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.                  *
15
 *                                                                         *
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                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24
#ifndef _PreComp_
25
# include <Inventor/nodes/SoCamera.h>
26
# include <QApplication>
27
#endif
28

29
#include "NavigationStyle.h"
30
#include "View3DInventorViewer.h"
31

32

33
using namespace Gui;
34

35
// ----------------------------------------------------------------------------------
36

37
/* TRANSLATOR Gui::RevitNavigationStyle */
38

39
TYPESYSTEM_SOURCE(Gui::RevitNavigationStyle, Gui::UserNavigationStyle)
40

41
RevitNavigationStyle::RevitNavigationStyle() : lockButton1(false)
42
{
43
}
44

45
RevitNavigationStyle::~RevitNavigationStyle() = default;
46

47
const char* RevitNavigationStyle::mouseButtons(ViewerMode mode)
48
{
49
    switch (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");
58
    default:
59
        return "No description";
60
    }
61
}
62

63
SbBool RevitNavigationStyle::processSoEvent(const SoEvent * const ev)
64
{
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);
70
    }
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
74

75
    const SoType type(ev->getTypeId());
76

77
    const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
78
    const SbVec2s pos(ev->getPosition());
79
    const SbVec2f posn = normalizePixelPos(pos);
80

81
    const SbVec2f prevnormalized = this->lastmouseposition;
82
    this->lastmouseposition = posn;
83

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
87
    // at all.
88
    SbBool processed = false;
89

90
    const ViewerMode curmode = this->currentmode;
91
    ViewerMode newmode = curmode;
92

93
    // Mismatches in state of the modifier keys happens if the user
94
    // presses or releases them outside the viewer window.
95
    syncModifierKeys(ev);
96

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);
100
        if (processed)
101
            return true;
102
    }
103

104
    // Keyboard handling
105
    if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
106
        const auto event = static_cast<const SoKeyboardEvent *>(ev);
107
        processed = processKeyboardEvent(event);
108
    }
109

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;
115

116
        //SoDebugError::postInfo("processSoEvent", "button = %d", button);
117
        switch (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()
124
                processed = true;
125
            }
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();
131
                processed = true;
132
            }
133
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
134
                processed = true;
135
            }
136
            else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
137
                processed = true;
138
            }
139
            else {
140
                processed = processClickEvent(event);
141
            }
142
            break;
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;
147

148
            // Don't show the context menu after dragging, panning or zooming
149
            if (!press && (hasDragged || hasPanned || hasZoomed)) {
150
                processed = true;
151
            }
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());
158
                    }
159
                }
160
            }
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();
167
                processed = true;
168
            }
169
            this->button2down = press;
170
            break;
171
        case SoMouseButtonEvent::BUTTON3:
172
            if (press) {
173
                this->centerTime = ev->getTime();
174
                setupPanningPlane(getCamera());
175
                this->lockrecenter = false;
176
            }
177
            else {
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) {
182
                    lookAtPoint(pos);
183
                    processed = true;
184
                }
185
            }
186
            this->button3down = press;
187
            break;
188
        default:
189
            break;
190
        }
191
    }
192

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);
199
            processed = true;
200
        }
201
        else if (this->currentmode == NavigationStyle::PANNING) {
202
            float ratio = vp.getViewportAspectRatio();
203
            panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
204
            processed = true;
205
        }
206
        else if (this->currentmode == NavigationStyle::DRAGGING) {
207
            this->addToLog(event->getPosition(), event->getTime());
208
            this->spin(posn);
209
            moveCursorPosition();
210
            processed = true;
211
        }
212
    }
213

214
    // Spaceball & Joystick handling
215
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
216
        const auto event = static_cast<const SoMotion3Event *>(ev);
217
        if (event)
218
            this->processMotionEvent(event);
219
        processed = true;
220
    }
221

222
    enum {
223
        BUTTON1DOWN = 1 << 0,
224
        BUTTON3DOWN = 1 << 1,
225
        CTRLDOWN =    1 << 2,
226
        SHIFTDOWN =   1 << 3,
227
        BUTTON2DOWN = 1 << 4
228
    };
229
    unsigned int combo =
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);
235

236
    switch (combo) {
237
    case 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) {
244
                processed = true;
245
            }
246
        }
247
        break;
248
    case BUTTON1DOWN:
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;
254
        }
255
        else {
256
            newmode = NavigationStyle::SELECTION;
257
        }
258
        break;
259
    case BUTTON1DOWN|BUTTON2DOWN:
260
    case BUTTON3DOWN:
261
        newmode = NavigationStyle::PANNING;
262
        break;
263
    case SHIFTDOWN|BUTTON3DOWN:
264
        if (newmode != NavigationStyle::DRAGGING) {
265
            saveCursorPosition(ev);
266
        }
267
        newmode = NavigationStyle::DRAGGING;
268
        break;
269
    case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN:
270
    case CTRLDOWN|BUTTON3DOWN:
271
        newmode = NavigationStyle::ZOOMING;
272
        break;
273

274
    default:
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;
281
        }
282
        break;
283
    }
284

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;
290
        processed = true;
291
    }
292

293
    // Prevent interrupting rubber-band selection in sketcher
294
    if (viewer->isEditing() && curmode == NavigationStyle::SELECTION && newmode != NavigationStyle::IDLE) {
295
        newmode = NavigationStyle::SELECTION;
296
        processed = false;
297
    }
298

299
    if (newmode != curmode) {
300
        this->setViewingMode(newmode);
301
    }
302

303
    // If not handled in this class, pass on upwards in the inheritance
304
    // hierarchy.
305
    if (!processed)
306
        processed = inherited::processSoEvent(ev);
307
    return processed;
308
}
309

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.