FreeCAD

Форк
0
/
TinkerCADNavigationStyle.cpp 
259 строк · 9.8 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2021 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::TinkerCADNavigationStyle */
38

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

41
TinkerCADNavigationStyle::TinkerCADNavigationStyle() = default;
42

43
TinkerCADNavigationStyle::~TinkerCADNavigationStyle() = default;
44

45
const char* TinkerCADNavigationStyle::mouseButtons(ViewerMode mode)
46
{
47
    switch (mode) {
48
    case NavigationStyle::SELECTION:
49
        return QT_TR_NOOP("Press left mouse button");
50
    case NavigationStyle::PANNING:
51
        return QT_TR_NOOP("Press middle mouse button");
52
    case NavigationStyle::DRAGGING:
53
        return QT_TR_NOOP("Press right mouse button");
54
    case NavigationStyle::ZOOMING:
55
        return QT_TR_NOOP("Scroll middle mouse button");
56
    default:
57
        return "No description";
58
    }
59
}
60

61
SbBool TinkerCADNavigationStyle::processSoEvent(const SoEvent * const ev)
62
{
63
    // Events when in "ready-to-seek" mode are ignored, except those
64
    // which influence the seek mode itself -- these are handled further
65
    // up the inheritance hierarchy.
66
    if (this->isSeekMode()) {
67
        return inherited::processSoEvent(ev);
68
    }
69
    // Switch off viewing mode
70
    if (!this->isSeekMode() && !this->isAnimating() && this->isViewing())
71
        this->setViewing(false); // by default disable viewing mode to render the scene
72

73
    const SoType type(ev->getTypeId());
74

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

79
    const SbVec2f prevnormalized = this->lastmouseposition;
80
    this->lastmouseposition = posn;
81

82
    // Set to true if any event processing happened. Note that it is not
83
    // necessary to restrict ourselves to only do one "action" for an
84
    // event, we only need this flag to see if any processing happened
85
    // at all.
86
    SbBool processed = false;
87

88
    const ViewerMode curmode = this->currentmode;
89
    ViewerMode newmode = curmode;
90

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

95
    // give the nodes in the foreground root the chance to handle events (e.g color bar)
96
    if (!viewer->isEditing()) {
97
        processed = handleEventInForeground(ev);
98
        if (processed)
99
            return true;
100
    }
101

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

108
    // Mouse Button / Spaceball Button handling
109
    if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
110
        const auto event = (const SoMouseButtonEvent *) ev;
111
        const int button = event->getButton();
112
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
113

114
        switch (button) {
115
        case SoMouseButtonEvent::BUTTON1:
116
            this->button1down = press;
117
            if (press && (curmode == NavigationStyle::SEEK_WAIT_MODE)) {
118
                newmode = NavigationStyle::SEEK_MODE;
119
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
120
                processed = true;
121
            }
122
            else if (viewer->isEditing() && (curmode == NavigationStyle::SPINNING)) {
123
                processed = true;
124
            }
125
            else {
126
                processed = processClickEvent(event);
127
            }
128
            break;
129
        case SoMouseButtonEvent::BUTTON2:
130
            // If we are in edit mode then simply ignore the RMB events
131
            // to pass the event to the base class.
132
            this->button2down = press;
133
            if (press) {
134
                mouseDownConsumedEvent = *event;
135
                mouseDownConsumedEvent.setTime(ev->getTime());
136
            }
137

138
            // About to start rotating
139
            if (press && (curmode == NavigationStyle::IDLE)) {
140
                // Use this variable to spot move events
141
                saveCursorPosition(ev);
142
                this->centerTime = ev->getTime();
143
                processed = true;
144
            }
145
            // Don't show the context menu after dragging, panning or zooming
146
            else if (!press && (hasDragged || hasPanned || hasZoomed)) {
147
                processed = true;
148
            }
149
            else if (!press) {
150
                newmode = NavigationStyle::IDLE;
151
                if (!viewer->isEditing()) {
152
                    if (this->currentmode != NavigationStyle::ZOOMING &&
153
                        this->currentmode != NavigationStyle::PANNING) {
154
                        if (this->isPopupMenuEnabled()) {
155
                            this->openPopupMenu(event->getPosition());
156
                        }
157
                    }
158
                    processed = true;
159
                }
160
            }
161
            break;
162
        case SoMouseButtonEvent::BUTTON3:
163
            this->button3down = press;
164
            if (press) {
165
                this->centerTime = ev->getTime();
166
                float ratio = vp.getViewportAspectRatio();
167
                SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
168
                this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
169
            }
170
            else if (curmode == NavigationStyle::PANNING) {
171
                newmode = NavigationStyle::IDLE;
172
                processed = true;
173
            }
174
            break;
175
        default:
176
            break;
177
        }
178
    }
179

180
    // Mouse Movement handling
181
    if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
182
        const auto event = (const SoLocation2Event *) ev;
183
        if (curmode == NavigationStyle::PANNING) {
184
            float ratio = vp.getViewportAspectRatio();
185
            panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
186
            processed = true;
187
        }
188
        else if (curmode == NavigationStyle::DRAGGING) {
189
            this->addToLog(event->getPosition(), event->getTime());
190
            this->spin(posn);
191
            moveCursorPosition();
192
            processed = true;
193
        }
194
    }
195

196
    // Spaceball & Joystick handling
197
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
198
        const auto event = static_cast<const SoMotion3Event *>(ev);
199
        if (event)
200
            this->processMotionEvent(event);
201
        processed = true;
202
    }
203

204
    enum {
205
        BUTTON1DOWN = 1 << 0,
206
        BUTTON3DOWN = 1 << 1,
207
        CTRLDOWN =    1 << 2,
208
        SHIFTDOWN =   1 << 3,
209
        BUTTON2DOWN = 1 << 4
210
    };
211
    unsigned int combo =
212
        (this->button1down ? BUTTON1DOWN : 0) |
213
        (this->button2down ? BUTTON2DOWN : 0) |
214
        (this->button3down ? BUTTON3DOWN : 0) |
215
        (this->ctrldown ? CTRLDOWN : 0) |
216
        (this->shiftdown ? SHIFTDOWN : 0);
217

218
    switch (combo) {
219
    case 0:
220
        if (curmode == NavigationStyle::SPINNING) { break; }
221
        newmode = NavigationStyle::IDLE;
222
        break;
223
    case BUTTON1DOWN:
224
        newmode = NavigationStyle::SELECTION;
225
        break;
226
    case BUTTON2DOWN:
227
        if (newmode != NavigationStyle::DRAGGING) {
228
            saveCursorPosition(ev);
229
        }
230
        newmode = NavigationStyle::DRAGGING;
231
        break;
232
    case BUTTON3DOWN:
233
        newmode = NavigationStyle::PANNING;
234
        break;
235
    default:
236
        break;
237
    }
238

239
    // Process when selection button is pressed together with other buttons that could trigger different actions.
240
    if (this->button1down && (this->button2down || this->button3down)) {
241
        processed = true;
242
    }
243

244
    // Prevent interrupting rubber-band selection in sketcher
245
    if (viewer->isEditing() && curmode == NavigationStyle::SELECTION && newmode != NavigationStyle::IDLE) {
246
        newmode = NavigationStyle::SELECTION;
247
        processed = false;
248
    }
249

250
    if (newmode != curmode) {
251
        this->setViewingMode(newmode);
252
    }
253

254
    // If not handled in this class, pass on upwards in the inheritance
255
    // hierarchy.
256
    if (!processed)
257
        processed = inherited::processSoEvent(ev);
258
    return processed;
259
}
260

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

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

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

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