FreeCAD

Форк
0
/
BlenderNavigationStyle.cpp 
312 строк · 12.0 Кб
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 "View3DInventorViewer.h"
32

33

34
using namespace Gui;
35

36
// ----------------------------------------------------------------------------------
37

38
/* TRANSLATOR Gui::BlenderNavigationStyle */
39

40
TYPESYSTEM_SOURCE(Gui::BlenderNavigationStyle, Gui::UserNavigationStyle)
41

42
BlenderNavigationStyle::BlenderNavigationStyle() : lockButton1(false)
43
{
44
}
45

46
BlenderNavigationStyle::~BlenderNavigationStyle() = default;
47

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

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

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

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

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

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

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

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

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

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

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

117
        //SoDebugError::postInfo("processSoEvent", "button = %d", button);
118
        switch (button) {
119
        case SoMouseButtonEvent::BUTTON1:
120
            this->lockrecenter = true;
121
            this->button1down = press;
122
            if (press && (this->currentmode == NavigationStyle::SEEK_WAIT_MODE)) {
123
                newmode = NavigationStyle::SEEK_MODE;
124
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
125
                processed = true;
126
            }
127
            else if (press && (this->currentmode == NavigationStyle::PANNING ||
128
                               this->currentmode == NavigationStyle::ZOOMING)) {
129
                newmode = NavigationStyle::DRAGGING;
130
                saveCursorPosition(ev);
131
                this->centerTime = ev->getTime();
132
                processed = true;
133
            }
134
            else if (!press && (this->currentmode == NavigationStyle::DRAGGING)) {
135
                processed = true;
136
            }
137
            else if (viewer->isEditing() && (this->currentmode == NavigationStyle::SPINNING)) {
138
                processed = true;
139
            }
140
            else {
141
                processed = processClickEvent(event);
142
            }
143
            break;
144
        case SoMouseButtonEvent::BUTTON2:
145
            // If we are in edit mode then simply ignore the RMB events
146
            // to pass the event to the base class.
147
            this->lockrecenter = true;
148

149
            // Don't show the context menu after dragging, panning or zooming
150
            if (!press && (hasDragged || hasPanned || hasZoomed)) {
151
                processed = true;
152
            }
153
            else if (!press && !viewer->isEditing()) {
154
                if (this->currentmode != NavigationStyle::ZOOMING &&
155
                    this->currentmode != NavigationStyle::PANNING &&
156
                    this->currentmode != NavigationStyle::DRAGGING) {
157
                    if (this->isPopupMenuEnabled()) {
158
                        this->openPopupMenu(event->getPosition());
159
                    }
160
                }
161
            }
162
            // Alternative way of rotating & zooming
163
            if (press && (this->currentmode == NavigationStyle::PANNING ||
164
                          this->currentmode == NavigationStyle::ZOOMING)) {
165
                newmode = NavigationStyle::DRAGGING;
166
                saveCursorPosition(ev);
167
                this->centerTime = ev->getTime();
168
                processed = true;
169
            }
170
            this->button2down = press;
171
            break;
172
        case SoMouseButtonEvent::BUTTON3:
173
            if (press) {
174
                this->centerTime = ev->getTime();
175
                float ratio = vp.getViewportAspectRatio();
176
                SbViewVolume vv = viewer->getSoRenderManager()->getCamera()->getViewVolume(ratio);
177
                this->panningplane = vv.getPlane(viewer->getSoRenderManager()->getCamera()->focalDistance.getValue());
178
                this->lockrecenter = false;
179
            }
180
            else {
181
                SbTime tmp = (ev->getTime() - this->centerTime);
182
                float dci = (float)QApplication::doubleClickInterval()/1000.0f;
183
                // is it just a middle click?
184
                if (tmp.getValue() < dci && !this->lockrecenter) {
185
                    if (!this->lookAtPoint(pos)) {
186
                        panToCenter(panningplane, posn);
187
                        this->interactiveCountDec();
188
                    }
189
                    processed = true;
190
                }
191
            }
192
            this->button3down = press;
193
            break;
194
        default:
195
            break;
196
        }
197
    }
198

199
    // Mouse Movement handling
200
    if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
201
        this->lockrecenter = true;
202
        const auto * const event = (const SoLocation2Event *) ev;
203
        if (this->currentmode == NavigationStyle::ZOOMING) {
204
            this->zoomByCursor(posn, prevnormalized);
205
            newmode = NavigationStyle::SELECTION;
206
            processed = true;
207
        }
208
        else if (this->currentmode == NavigationStyle::PANNING) {
209
            float ratio = vp.getViewportAspectRatio();
210
            panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
211
            newmode = NavigationStyle::SELECTION;
212
            processed = true;
213
        }
214
        else if (this->currentmode == NavigationStyle::DRAGGING) {
215
            this->addToLog(event->getPosition(), event->getTime());
216
            this->spin(posn);
217
            moveCursorPosition();
218
            processed = true;
219
        }
220
    }
221

222
    // Spaceball & Joystick handling
223
    if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
224
        const auto * const event = static_cast<const SoMotion3Event *>(ev);
225
        if (event)
226
            this->processMotionEvent(event);
227
        processed = true;
228
    }
229

230
    enum {
231
        BUTTON1DOWN = 1 << 0,
232
        BUTTON3DOWN = 1 << 1,
233
        CTRLDOWN =    1 << 2,
234
        SHIFTDOWN =   1 << 3,
235
        BUTTON2DOWN = 1 << 4
236
    };
237
    unsigned int combo =
238
        (this->button1down ? BUTTON1DOWN : 0) |
239
        (this->button2down ? BUTTON2DOWN : 0) |
240
        (this->button3down ? BUTTON3DOWN : 0) |
241
        (this->ctrldown ? CTRLDOWN : 0) |
242
        (this->shiftdown ? SHIFTDOWN : 0);
243

244
    switch (combo) {
245
    case 0:
246
        if (curmode == NavigationStyle::SPINNING) { break; }
247
        newmode = NavigationStyle::IDLE;
248
        // The left mouse button has been released right now
249
        if (this->lockButton1) {
250
            this->lockButton1 = false;
251
            if (curmode != NavigationStyle::SELECTION) {
252
                processed = true;
253
            }
254
        }
255
        break;
256
    case BUTTON1DOWN:
257
    case CTRLDOWN|BUTTON1DOWN:
258
        // make sure not to change the selection when stopping spinning
259
        if (curmode == NavigationStyle::SPINNING
260
            || (this->lockButton1 && curmode != NavigationStyle::SELECTION)) {
261
            newmode = NavigationStyle::IDLE;
262
        }
263
        else {
264
            newmode = NavigationStyle::SELECTION;
265
        }
266
        break;
267
    case BUTTON1DOWN|BUTTON2DOWN:
268
        newmode = NavigationStyle::PANNING;
269
        break;
270
    case SHIFTDOWN|BUTTON3DOWN:
271
        newmode = NavigationStyle::PANNING;
272
        break;
273
    case BUTTON3DOWN:
274
        if (newmode != NavigationStyle::DRAGGING) {
275
            saveCursorPosition(ev);
276
        }
277
        newmode = NavigationStyle::DRAGGING;
278
        break;
279
    case CTRLDOWN|SHIFTDOWN|BUTTON2DOWN:
280
    case CTRLDOWN|BUTTON3DOWN:
281
        newmode = NavigationStyle::ZOOMING;
282
        break;
283

284
    default:
285
        break;
286
    }
287

288
    // If the selection button is pressed together with another button
289
    // and the other button is released, don't switch to selection mode.
290
    // Process when selection button is pressed together with other buttons that could trigger different actions.
291
    if (this->button1down && (this->button2down || this->button3down)) {
292
        this->lockButton1 = true;
293
        processed = true;
294
    }
295

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

302
    if (newmode != curmode) {
303
        this->setViewingMode(newmode);
304
    }
305

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

311
    return processed;
312
}
313

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

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

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

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