FreeCAD

Форк
0
/
InventorNavigationStyle.cpp 
326 строк · 12.6 Кб
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

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

30
#include "NavigationStyle.h"
31
#include "SoMouseWheelEvent.h"
32
#include "View3DInventorViewer.h"
33

34

35
using namespace Gui;
36

37
// ----------------------------------------------------------------------------------
38

39
/* TRANSLATOR Gui::InventorNavigationStyle */
40

41
TYPESYSTEM_SOURCE(Gui::InventorNavigationStyle, Gui::UserNavigationStyle)
42

43
InventorNavigationStyle::InventorNavigationStyle() = default;
44

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

47
const char* InventorNavigationStyle::mouseButtons(ViewerMode mode)
48
{
49
    switch (mode) {
50
    case NavigationStyle::SELECTION:
51
        return QT_TR_NOOP("Press CTRL and 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 left 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
std::string InventorNavigationStyle::userFriendlyName() const
64
{
65
    // do not mark this for translation
66
    return "OpenInventor";
67
}
68

69
SbBool InventorNavigationStyle::processSoEvent(const SoEvent * const ev)
70
{
71
    // Events when in "ready-to-seek" mode are ignored, except those
72
    // which influence the seek mode itself -- these are handled further
73
    // up the inheritance hierarchy.
74
    if (this->isSeekMode()) {
75
        return inherited::processSoEvent(ev);
76
    }
77
    // Switch off viewing mode (Bug #0000911)
78
    if (!this->isSeekMode()&& !this->isAnimating() && this->isViewing() )
79
        this->setViewing(false); // by default disable viewing mode to render the scene
80

81
    const SoType type(ev->getTypeId());
82

83
    const SbViewportRegion & vp = viewer->getSoRenderManager()->getViewportRegion();
84
    const SbVec2s pos(ev->getPosition());
85
    const SbVec2f posn = normalizePixelPos(pos);
86

87
    const SbVec2f prevnormalized = this->lastmouseposition;
88
    this->lastmouseposition = posn;
89

90
    // Set to true if any event processing happened. Note that it is not
91
    // necessary to restrict ourselves to only do one "action" for an
92
    // event, we only need this flag to see if any processing happened
93
    // at all.
94
    SbBool processed = false;
95

96
    const ViewerMode curmode = this->currentmode;
97
    ViewerMode newmode = curmode;
98

99
    // Mismatches in state of the modifier keys happens if the user
100
    // presses or releases them outside the viewer window.
101
    syncModifierKeys(ev);
102

103
    // give the nodes in the foreground root the chance to handle events (e.g color bar)
104
    if (!viewer->isEditing()) {
105
        processed = handleEventInForeground(ev);
106
        if (processed)
107
            return true;
108
    }
109

110
    // Keyboard handling
111
    if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
112
        auto event = static_cast<const SoKeyboardEvent *>(ev);
113
        processed = processKeyboardEvent(event);
114
    }
115

116
    // Mouse Button / Spaceball Button handling
117
    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
118
        const auto event = (const SoMouseButtonEvent *) ev;
119
        const int button = event->getButton();
120
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
121

122
        // SoDebugError::postInfo("processSoEvent", "button = %d", button);
123
        switch (button) {
124
        case SoMouseButtonEvent::BUTTON1:
125
            this->button1down = press;
126
            if (press && ev->wasShiftDown() &&
127
                (this->currentmode != NavigationStyle::SELECTION)) {
128
                this->centerTime = ev->getTime();
129
                float ratio = vp.getViewportAspectRatio();
130
                SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
131
                this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
132
                this->lockrecenter = false;
133
            }
134
            else if (!press && ev->wasShiftDown() &&
135
                (this->currentmode != NavigationStyle::SELECTION)) {
136
                SbTime tmp = (ev->getTime() - this->centerTime);
137
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
138
                // is it just a left click?
139
                if (tmp.getValue() < dci && !this->lockrecenter) {
140
                    if (!this->lookAtPoint(pos)) {
141
                        panToCenter(panningplane, posn);
142
                        this->interactiveCountDec();
143
                    }
144
                    processed = true;
145
                }
146
            }
147
            else if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) {
148
                newmode = NavigationStyle::SEEK_MODE;
149
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
150
                processed = true;
151
                this->lockrecenter = true;
152
            }
153
            else if (press && (this->currentmode == NavigationStyle::IDLE)) {
154
                this->setViewing(true);
155
                processed = true;
156
                this->lockrecenter = true;
157
            }
158
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
159
                this->setViewing(false);
160
                processed = true;
161
                this->lockrecenter = true;
162
            }
163
            else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
164
                processed = true;
165
                this->lockrecenter = true;
166
            }
167
            else {
168
                processed = processClickEvent(event);
169
            }
170
            break;
171
        case SoMouseButtonEvent::BUTTON2:
172
            // If we are in edit mode then simply ignore the RMB events
173
            // to pass the event to the base class.
174
            this->lockrecenter = true;
175

176
            // Don't show the context menu after dragging, panning or zooming
177
            if (!press && (hasDragged || hasPanned || hasZoomed)) {
178
                processed = true;
179
            }
180
            else if (!press && !viewer->isEditing()) {
181
                if (this->currentmode != NavigationStyle::ZOOMING &&
182
                    this->currentmode != NavigationStyle::PANNING &&
183
                    this->currentmode != NavigationStyle::DRAGGING) {
184
                    if (this->isPopupMenuEnabled()) {
185
                        this->openPopupMenu(event->getPosition());
186
                    }
187
                }
188
            }
189
            this->button2down = press;
190
            break;
191
        case SoMouseButtonEvent::BUTTON3:
192
            if (press) {
193
                this->centerTime = ev->getTime();
194
                float ratio = vp.getViewportAspectRatio();
195
                SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
196
                this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
197
                this->lockrecenter = false;
198
            }
199
            else {
200
                SbTime tmp = (ev->getTime() - this->centerTime);
201
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
202
                // is it just a middle click?
203
                if (tmp.getValue() < dci && !this->lockrecenter) {
204
                    if (!this->lookAtPoint(pos)) {
205
                        panToCenter(panningplane, posn);
206
                        this->interactiveCountDec();
207
                    }
208
                    processed = true;
209
                }
210
            }
211
            this->button3down = press;
212
            break;
213
        default:
214
            break;
215
        }
216
    }
217

218
    // Mouse Movement handling
219
    if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
220
        this->lockrecenter = true;
221
        const auto event = (const SoLocation2Event *) ev;
222
        if (this->currentmode == NavigationStyle::ZOOMING) {
223
            this->zoomByCursor(posn, prevnormalized);
224
            processed = true;
225
        }
226
        else if (this->currentmode == NavigationStyle::PANNING) {
227
            float ratio = vp.getViewportAspectRatio();
228
            panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
229
            processed = true;
230
        }
231
        else if (this->currentmode == NavigationStyle::DRAGGING) {
232
            this->addToLog(event->getPosition(), event->getTime());
233
            this->spin(posn);
234
            moveCursorPosition();
235
            processed = true;
236
        }
237
    }
238

239
    // Spaceball & Joystick handling
240
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
241
        const auto event = static_cast<const SoMotion3Event *>(ev);
242
        if (event)
243
            this->processMotionEvent(event);
244
        processed = true;
245
    }
246

247
    enum {
248
        BUTTON1DOWN = 1 << 0,
249
        BUTTON3DOWN = 1 << 1,
250
        CTRLDOWN =    1 << 2,
251
        SHIFTDOWN =   1 << 3,
252
        BUTTON2DOWN = 1 << 4
253
    };
254
    unsigned int combo =
255
        (this->button1down ? BUTTON1DOWN : 0) |
256
        (this->button2down ? BUTTON2DOWN : 0) |
257
        (this->button3down ? BUTTON3DOWN : 0) |
258
        (this->ctrldown ? CTRLDOWN : 0) |
259
        (this->shiftdown ? SHIFTDOWN : 0);
260

261
    switch (combo) {
262
    case 0:
263
        if (curmode == NavigationStyle::SPINNING) { break; }
264
        newmode = NavigationStyle::IDLE;
265

266
        if (curmode == NavigationStyle::DRAGGING) {
267
            if (doSpin())
268
                newmode = NavigationStyle::SPINNING;
269
        }
270
        break;
271
    case BUTTON1DOWN:
272
        if (curmode == NavigationStyle::SELECTION) { break; }
273
        if (newmode != NavigationStyle::DRAGGING) {
274
            saveCursorPosition(ev);
275
        }
276
        newmode = NavigationStyle::DRAGGING;
277
        break;
278
    case BUTTON3DOWN:
279
    case CTRLDOWN|SHIFTDOWN:
280
    case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
281
        newmode = NavigationStyle::PANNING;
282
        break;
283
    case CTRLDOWN:
284
    case CTRLDOWN|BUTTON1DOWN:
285
    case SHIFTDOWN:
286
    case SHIFTDOWN|BUTTON1DOWN:
287
        newmode = NavigationStyle::SELECTION;
288
        break;
289
    case BUTTON1DOWN|BUTTON3DOWN:
290
    case CTRLDOWN|BUTTON3DOWN:
291
    case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN:
292
        newmode = NavigationStyle::ZOOMING;
293
        break;
294

295
    default:
296
        break;
297
    }
298

299
    // Process when selection button is pressed together with other buttons that could trigger different actions.
300
    if (this->button1down && (this->button2down || this->button3down)) {
301
        processed = true;
302
    }
303

304
    // Prevent interrupting rubber-band selection in sketcher
305
    if (viewer->isEditing() && curmode == NavigationStyle::SELECTION && newmode != NavigationStyle::IDLE) {
306
        newmode = NavigationStyle::SELECTION;
307
        processed = false;
308
    }
309

310
    if (newmode != curmode) {
311
        this->setViewingMode(newmode);
312
    }
313

314
    // If not handled in this class, pass on upwards in the inheritance
315
    // hierarchy.
316
    if (ev->isOfType(SoMouseWheelEvent::getClassTypeId()))
317
        processed = inherited::processSoEvent(ev);
318
    else if ((curmode == NavigationStyle::SELECTION ||
319
         newmode == NavigationStyle::SELECTION ||
320
         viewer->isEditing()) && !processed)
321
        processed = inherited::processSoEvent(ev);
322
    else
323
        return true;
324

325
    return processed;
326
}
327

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

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

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

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