FreeCAD

Форк
0
/
MayaGestureNavigationStyle.cpp 
621 строка · 29.0 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2015 Victor Titov (DeepSOIC) <vv.titov@gmail.com>       *
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
 *   Minor modifications made by Pablo Gil (pablogil) in order to create   *
24
 *   a Maya or Unity 3D mouse navigation style:                            *
25
 *         ALT + left mouse button    = orbit                              *
26
 *         ALT + right mouse button   = zoom                               *
27
 *         ALT + middle mouse button  = pan                                *
28
 *                                                                         *
29
 *   Thanks Victor for your help!                                          *
30
 *                                                                         *
31
 ***************************************************************************/
32

33
/*
34
 *A few notes on this style. (by DeepSOIC)
35
 *
36
 * In this style, LMB serves dual purpose. It is selecting objects, as well as
37
 * spinning the view. The trick that enables it is as follows: The mousedown
38
 * event is consumed an saved, but otherwise remains unprocessed. If a drag is
39
 * detected while the button is down, the event is finally consumed (the saved
40
 * one is discarded), and spinning starts. If there is no drag detected before
41
 * the button is released, the saved mousedown is propagated to inherited,
42
 * followed by the mouseup. The same trick is used for RMB, so up to two
43
 * mousedown can be postponed.
44
 *
45
 * This navigation style does not exactly follow the structure of other
46
 * navigation styles, it does not fill many of the global variables defined in
47
 * NavigationStyle.
48
 *
49
 * This mode does not support locking cursor position on screen when
50
 * navigating, since with absolute pointing devices like pen and touch it makes
51
 * no sense (this style was specifically crafted for such devices).
52
 *
53
 * In this style, setViewing is not used (because I could not figure out how to
54
 * use it properly, and it seems to just work without it).
55
 *
56
 * This style wasn't tested with space during development (I don't have one).
57
 */
58

59
#include "PreCompiled.h"
60
#ifndef _PreComp_
61
# include <QApplication>
62
#endif
63

64
#include <Base/Console.h>
65

66
#include "NavigationStyle.h"
67
#include "SoTouchEvents.h"
68
#include "View3DInventorViewer.h"
69

70

71
using namespace Gui;
72

73
// ----------------------------------------------------------------------------------
74

75
/* TRANSLATOR Gui::MayaGestureNavigationStyle */
76

77
TYPESYSTEM_SOURCE(Gui::MayaGestureNavigationStyle, Gui::UserNavigationStyle)
78

79
MayaGestureNavigationStyle::MayaGestureNavigationStyle()
80
{
81
    mouseMoveThreshold = QApplication::startDragDistance();
82
    mouseMoveThresholdBroken = false;
83
    mousedownConsumedCount = 0;
84
    thisClickIsComplex = false;
85
    inGesture = false;
86
}
87

88
MayaGestureNavigationStyle::~MayaGestureNavigationStyle() = default;
89

90
const char* MayaGestureNavigationStyle::mouseButtons(ViewerMode mode)
91
{
92
    switch (mode) {
93
    case NavigationStyle::SELECTION:
94
        return QT_TR_NOOP("Tap OR click left mouse button.");
95
    case NavigationStyle::PANNING:
96
        return QT_TR_NOOP("Drag screen with two fingers OR press ALT + middle mouse button.");
97
    case NavigationStyle::DRAGGING:
98
        return QT_TR_NOOP("Drag screen with one finger OR press ALT + left mouse button. In Sketcher and other edit modes, hold Alt in addition.");
99
    case NavigationStyle::ZOOMING:
100
        return QT_TR_NOOP("Pinch (place two fingers on the screen and drag them apart from or towards each other) OR scroll middle mouse button OR press ALT + right mouse button OR PgUp/PgDown on keyboard.");
101
    default:
102
        return "No description";
103
    }
104
}
105

106
/*!
107
 * \brief MayaGestureNavigationStyle::testMoveThreshold tests if the mouse has moved far enough to constder it a drag.
108
 * \param currentPos current position of mouse cursor, in local pixel coordinates.
109
 * \return true if the mouse was moved far enough. False if it's within the boundary. Ignores MayaGestureNavigationStyle::mouseMoveThresholdBroken flag.
110
 */
111
bool MayaGestureNavigationStyle::testMoveThreshold(const SbVec2s currentPos) const {
112
    SbVec2s movedBy = currentPos - this->mousedownPos;
113
    return SbVec2f(movedBy).length() >= this->mouseMoveThreshold;
114
}
115

116
SbBool MayaGestureNavigationStyle::processSoEvent(const SoEvent * const ev)
117
{
118
    // Events when in "ready-to-seek" mode are ignored, except those
119
    // which influence the seek mode itself -- these are handled further
120
    // up the inheritance hierarchy.
121
    if (this->isSeekMode()) {
122
        return inherited::processSoEvent(ev);
123
    }
124
    // Switch off viewing mode (Bug #0000911)
125
    if (!this->isSeekMode()&& !this->isAnimating() && this->isViewing() )
126
        this->setViewing(false); // by default disable viewing mode to render the scene
127
    //setViewing() is never used in this style, so the previous if is very unlikely to be hit.
128

129
    const SoType type(ev->getTypeId());
130
    //define some shortcuts...
131
    bool evIsButton = type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId());
132
    bool evIsKeyboard = type.isDerivedFrom(SoKeyboardEvent::getClassTypeId());
133
    bool evIsLoc2 = type.isDerivedFrom(SoLocation2Event::getClassTypeId());//mouse movement
134
    bool evIsLoc3 = type.isDerivedFrom(SoMotion3Event::getClassTypeId());//spaceball/joystick movement
135
    bool evIsGesture = type.isDerivedFrom(SoGestureEvent::getClassTypeId());//touchscreen gesture
136

137
    const SbVec2f prevnormalized = this->lastmouseposition;
138
    const SbVec2s pos(ev->getPosition());//not valid for gestures
139
    const SbVec2f posn = this->normalizePixelPos(pos);
140
    //pos: local coordinates of event, in pixels
141
    //posn: normalized local coordinates of event ((0,0) = lower left corner, (1,1) = upper right corner)
142
    float ratio = viewer->getSoRenderManager()->getViewportRegion().getViewportAspectRatio();
143

144
    if (evIsButton || evIsLoc2){
145
        this->lastmouseposition = posn;
146
    }
147

148
    const ViewerMode curmode = this->currentmode;
149
    //ViewerMode newmode = curmode;
150

151
    //make a unified mouse+modifiers state value (combo)
152
    enum {
153
        BUTTON1DOWN = 1 << 0,
154
        BUTTON2DOWN = 1 << 1,
155
        BUTTON3DOWN = 1 << 2,
156
        CTRLDOWN =    1 << 3,
157
        SHIFTDOWN =   1 << 4,
158
        ALTDOWN =     1 << 5,
159
        MASKBUTTONS = BUTTON1DOWN | BUTTON2DOWN | BUTTON3DOWN,
160
        MASKMODIFIERS = CTRLDOWN | SHIFTDOWN | ALTDOWN
161
    };
162
    unsigned int comboBefore = //before = state before this event
163
        (this->button1down ? BUTTON1DOWN : 0) |
164
        (this->button2down ? BUTTON2DOWN : 0) |
165
        (this->button3down ? BUTTON3DOWN : 0) |
166
        (this->ctrldown ? CTRLDOWN : 0) |
167
        (this->shiftdown ? SHIFTDOWN : 0) |
168
        (this->altdown ? ALTDOWN : 0);
169

170
    //test for complex clicks
171
    int cntMBBefore = (comboBefore & BUTTON1DOWN ? 1 : 0 ) //cntMBBefore = how many buttons were down when this event arrived?
172
                  +(comboBefore & BUTTON2DOWN ? 1 : 0 )
173
                  +(comboBefore & BUTTON3DOWN ? 1 : 0 );
174
    if (cntMBBefore>=2) this->thisClickIsComplex = true;
175
    if (cntMBBefore==0) {//a good chance to reset some click-related stuff
176
        this->thisClickIsComplex = false;
177
        this->mousedownConsumedCount = 0;//shouldn't be necessary, just a fail-safe.
178
    }
179

180
    // Mismatches in state of the modifier keys happens if the user
181
    // presses or releases them outside the viewer window.
182
    syncModifierKeys(ev);
183
    //before this block, mouse button states in NavigationStyle::buttonXdown reflected those before current event arrived.
184
    //track mouse button states
185
    if (evIsButton) {
186
        auto const event = (const SoMouseButtonEvent *) ev;
187
        const int button = event->getButton();
188
        const SbBool press //the button was pressed (if false -> released)
189
                = event->getState() == SoButtonEvent::DOWN ? true : false;
190
        switch (button) {
191
        case SoMouseButtonEvent::BUTTON1:
192
            this->button1down = press;
193
            break;
194
        case SoMouseButtonEvent::BUTTON2:
195
            this->button2down = press;
196
            break;
197
        case SoMouseButtonEvent::BUTTON3:
198
            this->button3down = press;
199
            break;
200
        //whatever else, we don't track
201
        }
202
    }
203
    //after this block, the new states of the buttons are already in.
204

205
    unsigned int comboAfter = //after = state after this event (current, essentially)
206
        (this->button1down ? BUTTON1DOWN : 0) |
207
        (this->button2down ? BUTTON2DOWN : 0) |
208
        (this->button3down ? BUTTON3DOWN : 0) |
209
        (this->ctrldown ? CTRLDOWN : 0) |
210
        (this->shiftdown ? SHIFTDOWN : 0) |
211
        (this->altdown ? ALTDOWN : 0);
212

213
    //test for complex clicks (again)
214
    int cntMBAfter = (comboAfter & BUTTON1DOWN ? 1 : 0 ) //cntMBAfter = how many buttons were down when this event arrived?
215
                  +(comboAfter & BUTTON2DOWN ? 1 : 0 )
216
                  +(comboAfter & BUTTON3DOWN ? 1 : 0 );
217
    if (cntMBAfter>=2) this->thisClickIsComplex = true;
218
    //if (cntMBAfter==0) this->thisClickIsComplex = false;//don't reset the flag now, we need to know that this mouseUp was an end of a click that was complex. The flag will reset by the before-check in the next event.
219

220
    //test for move detection
221
    if (evIsLoc2 || evIsButton){
222
        this->mouseMoveThresholdBroken |= this->testMoveThreshold(pos);
223
    }
224

225
    //track gestures
226
    if (evIsGesture) {
227
        auto gesture = static_cast<const SoGestureEvent*>(ev);
228
        switch(gesture->state) {
229
        case SoGestureEvent::SbGSStart:
230
            //assert(!inGesture);//start of another gesture before the first finished? Happens all the time for Pan gesture... No idea why!  --DeepSOIC
231
            inGesture = true;
232
        break;
233
        case SoGestureEvent::SbGSUpdate:
234
            assert(inGesture);//gesture update without start?
235
            inGesture = true;
236
        break;
237
        case SoGestureEvent::SbGSEnd:
238
            assert(inGesture);//gesture ended without starting?
239
            inGesture = false;
240
        break;
241
        case SoGestureEvent::SbGsCanceled:
242
            assert(inGesture);//gesture canceled without starting?
243
            inGesture=false;
244
        break;
245
        default:
246
            assert(0);//shouldn't happen
247
            inGesture = false;
248
        }
249
    }
250
    if (evIsButton) {
251
        if(inGesture){
252
            inGesture = false;//reset the flag when mouse clicks are received, to ensure enabling mouse navigation back.
253
            setViewingMode(NavigationStyle::SELECTION);//exit navigation asap, to proceed with regular processing of the click
254
        }
255
    }
256

257
    bool suppressLMBDrag = false;
258
    if(viewer->isEditing()){
259
        //in edit mode, disable lmb dragging (spinning). Holding Alt enables it.
260
        suppressLMBDrag = !(comboAfter & ALTDOWN);
261
    }
262

263
    //----------all this were preparations. Now comes the event handling! ----------
264

265
    SbBool processed = false;//a return value for the  BlahblahblahNavigationStyle::processSoEvent
266
    bool propagated = false;//an internal flag indicating that the event has been already passed to inherited, to suppress the automatic doing of this at the end.
267
    //goto finalize = return processed. Might be important to do something before done (none now).
268

269
    // give the nodes in the foreground root the chance to handle events (e.g color bar)
270
    if (!viewer->isEditing()) {
271
        processed = handleEventInForeground(ev);
272
    }
273
    if (processed)
274
        goto finalize;
275

276
    // Mode-independent keyboard handling
277
    if (evIsKeyboard) {
278
        auto const event = (const SoKeyboardEvent *) ev;
279
        const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
280
        switch (event->getKey()) {
281
        case SoKeyboardEvent::H:
282
            processed = true;
283
            if (!press) {
284
                setupPanningPlane(viewer->getCamera());
285
                lookAtPoint(event->getPosition());
286
            }
287
            break;
288
        default:
289
            break;
290
        }
291
    }
292
    if (processed)
293
        goto finalize;
294

295
    //mode-independent spaceball/joystick handling
296
    if (evIsLoc3) {
297
        auto const event = static_cast<const SoMotion3Event *>(ev);
298
        if (event)
299
            this->processMotionEvent(event);
300
        processed = true;
301
    }
302
    if (processed)
303
        goto finalize;
304

305
    //all mode-dependent stuff is within this switch.
306
    switch(curmode){
307
    case NavigationStyle::SELECTION:
308
        // Prevent interrupting rubber-band selection in sketcher
309
        if (viewer->isEditing()) {
310
            if (evIsButton) {
311
                auto const event = (const SoMouseButtonEvent*)ev;
312
                const SbBool press = event->getState() == SoButtonEvent::DOWN;
313
                const int button = event->getButton();
314

315
                if (!press && button == SoMouseButtonEvent::BUTTON1) {
316
                    setViewingMode(NavigationStyle::IDLE);
317
                    break;
318
                }
319
            }
320

321
            if (this->button1down) {
322
                break;
323
            }
324
        }
325
        [[fallthrough]];
326
    case NavigationStyle::IDLE:
327
        // Prevent interrupting rubber-band selection in sketcher
328
        if (viewer->isEditing()) {
329
            if (evIsButton) {
330
                auto const event = (const SoMouseButtonEvent*)ev;
331
                const SbBool press = event->getState() == SoButtonEvent::DOWN;
332
                const int button = event->getButton();
333

334
                if (press && button == SoMouseButtonEvent::BUTTON1 && !this->altdown) {
335
                    setViewingMode(NavigationStyle::SELECTION);
336
                    break;
337
                }
338
            }
339
        }
340
        [[fallthrough]];
341
    case NavigationStyle::INTERACT: {
342
        //idle and interaction
343

344
        //keyboard
345
        if (evIsKeyboard) {
346
            auto const event = (const SoKeyboardEvent *) ev;
347
            const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
348

349
            switch(event->getKey()){
350
            case SoKeyboardEvent::S:
351
            case SoKeyboardEvent::HOME:
352
            case SoKeyboardEvent::LEFT_ARROW:
353
            case SoKeyboardEvent::UP_ARROW:
354
            case SoKeyboardEvent::RIGHT_ARROW:
355
            case SoKeyboardEvent::DOWN_ARROW:
356
                processed = inherited::processSoEvent(ev);
357
                propagated = true;
358
                break;
359
            case SoKeyboardEvent::PAGE_UP:
360
                if(press){
361
                    doZoom(viewer->getSoRenderManager()->getCamera(), getDelta(), posn);
362
                }
363
                processed = true;
364
                break;
365
            case SoKeyboardEvent::PAGE_DOWN:
366
                if(press){
367
                    doZoom(viewer->getSoRenderManager()->getCamera(), -getDelta(), posn);
368
                }
369
                processed = true;
370
                break;
371
            default:
372
                break;
373
            }//switch key
374
        }
375
        if (processed)
376
            goto finalize;
377

378

379
        // Mouse Button / Spaceball Button handling
380
        if (evIsButton) {
381
            auto const event = (const SoMouseButtonEvent *) ev;
382
            const int button = event->getButton();
383
            const SbBool press //the button was pressed (if false -> released)
384
                    = event->getState() == SoButtonEvent::DOWN ? true : false;
385
            switch(button){
386
            case SoMouseButtonEvent::BUTTON1:
387
            case SoMouseButtonEvent::BUTTON2:
388
                if(press){
389
                    if(this->thisClickIsComplex && this->mouseMoveThresholdBroken){
390
                        //this should prevent re-attempts to enter navigation when doing more clicks after a move.
391
                    } else {
392
                        //on LMB-down or RMB-down, we don't know yet if we should propagate it or process it. Save the event to be refired later, when it becomes clear.
393
                        //reset/start move detection machine
394
                        this->mousedownPos = pos;
395
                        this->mouseMoveThresholdBroken = false;
396
                        setupPanningPlane(viewer->getSoRenderManager()->getCamera());//set up panningplane
397
                        int &cnt = this->mousedownConsumedCount;
398
                        this->mousedownConsumedEvents[cnt] = *event;//hopefully, a shallow copy is enough. There are no pointers stored in events, apparently. Will lose a subclass, though.
399
                        cnt++;
400
                        assert(cnt<=2);
401
                        if(cnt>static_cast<int>(sizeof(mousedownConsumedEvents))){
402
                            cnt=sizeof(mousedownConsumedEvents);//we are in trouble
403
                        }
404
                        processed = true;//just consume this event, and wait for the move threshold to be broken to start dragging/panning
405
                    }
406
                } else {//release
407
                    if (button == SoMouseButtonEvent::BUTTON2 && !this->thisClickIsComplex) {
408
                        if (!viewer->isEditing() && this->isPopupMenuEnabled()) {
409
                            processed=true;
410
                            this->openPopupMenu(event->getPosition());
411
                        }
412
                    }
413
                    if(! processed) {
414
                        //re-synthesize all previously-consumed mouseDowns, if any. They might have been re-synthesized already when threshold was broken.
415
                        for( int i=0;   i < this->mousedownConsumedCount;   i++ ){
416
                            inherited::processSoEvent(& (this->mousedownConsumedEvents[i]));//simulate the previously-comsumed mousedown.
417
                        }
418
                        this->mousedownConsumedCount = 0;
419
                        processed = inherited::processSoEvent(ev);//explicitly, just for clarity that we are sending a full click sequence.
420
                        propagated = true;
421
                    }
422
                }
423
                break;
424
            case SoMouseButtonEvent::BUTTON3://press the wheel
425
                // starts PANNING mode
426
                if(press & this->altdown){
427
                    setViewingMode(NavigationStyle::PANNING);
428
                } else if(press){
429
                    // if not PANNING then look at point
430
                    setupPanningPlane(viewer->getCamera());
431
                    lookAtPoint(event->getPosition());
432
                }
433
                processed = true;
434
                break;
435
            }
436
        }
437

438
        //mouse moves - test for move threshold breaking
439
        if (evIsLoc2) {
440
            if (this->mouseMoveThresholdBroken && (this->button1down || this->button2down) && mousedownConsumedCount > 0) {
441
                //mousemovethreshold has JUST been broken
442

443
                //test if we should enter navigation
444
                if ((this->button1down && !suppressLMBDrag && this->altdown) || (this->button2down && this->altdown)) {
445
                    //yes, we are entering navigation.
446
                    //throw away consumed mousedowns.
447
                    this->mousedownConsumedCount = 0;
448

449
                    // start DRAGGING mode (orbit)
450
                    // if not pressing left mouse button then it assumes is right mouse button and starts ZOOMING mode
451
                    saveCursorPosition(ev);
452
                    setViewingMode(this->button1down ? NavigationStyle::DRAGGING : NavigationStyle::ZOOMING);
453
                    processed = true;
454
                } else {
455
                    //no, we are not entering navigation.
456
                    //re-synthesize all previously-consumed mouseDowns, if any, and propagate this mousemove.
457
                    for( int i=0;   i < this->mousedownConsumedCount;   i++ ){
458
                        inherited::processSoEvent(& (this->mousedownConsumedEvents[i]));//simulate the previously-comsumed mousedown.
459
                    }
460
                    this->mousedownConsumedCount = 0;
461
                    processed = inherited::processSoEvent(ev);//explicitly, just for clarity that we are sending a full click sequence.
462
                    propagated = true;
463
                }
464
            }
465
            if (mousedownConsumedCount  > 0)
466
                processed = true;//if we are still deciding if it's a drag or not, consume mouseMoves.
467
        }
468

469
        //gesture start
470
        if (evIsGesture && /*!this->button1down &&*/ !this->button2down){//ignore gestures when mouse buttons are down. Button1down check was disabled because of wrong state after doubleclick on sketcher constraint to edit datum
471
            auto gesture = static_cast<const SoGestureEvent*>(ev);
472
            if (gesture->state == SoGestureEvent::SbGSStart
473
                    || gesture->state == SoGestureEvent::SbGSUpdate) {//even if we didn't get a start, assume the first update is a start (sort-of fail-safe).
474
                if (type.isDerivedFrom(SoGesturePanEvent::getClassTypeId())) {
475
                    setupPanningPlane(viewer->getSoRenderManager()->getCamera());//set up panning plane
476
                    setViewingMode(NavigationStyle::PANNING);
477
                    processed = true;
478
                } else if (type.isDerivedFrom(SoGesturePinchEvent::getClassTypeId())) {
479
                    setupPanningPlane(viewer->getSoRenderManager()->getCamera());//set up panning plane
480
                    saveCursorPosition(ev);
481
                    setViewingMode(NavigationStyle::DRAGGING);
482
                    processed = true;
483
                } //all other gestures - ignore!
484
            }
485
        }
486

487
        //loc2 (mousemove) - ignore.
488

489
    } break;//end of idle and interaction
490
    case NavigationStyle::DRAGGING:
491
    case NavigationStyle::ZOOMING:
492
    case NavigationStyle::PANNING:{
493
        //actual navigation
494

495
        //no keyboard.
496

497
        // Mouse Button / Spaceball Button handling
498
        if (evIsButton) {
499
            auto const event = (const SoMouseButtonEvent *) ev;
500
            const int button = event->getButton();
501
            switch(button){
502
                case SoMouseButtonEvent::BUTTON1:
503
                case SoMouseButtonEvent::BUTTON2:
504
                case SoMouseButtonEvent::BUTTON3: // allows to release button3 into SELECTION mode
505
                    if(comboAfter & BUTTON1DOWN || comboAfter & BUTTON2DOWN) {
506
                        //don't leave navigation till all buttons have been released
507
                        if (comboAfter & BUTTON1DOWN && comboAfter & BUTTON2DOWN) {
508
                            setRotationCenter(getFocalPoint());
509
                        }
510
                        else {
511
                            saveCursorPosition(ev);
512
                        }
513
                        setViewingMode((comboAfter & BUTTON1DOWN) ? NavigationStyle::DRAGGING : NavigationStyle::PANNING);
514
                        processed = true;
515
                    } else { //all buttons are released
516
                        //end of dragging/panning/whatever
517
                        setViewingMode(NavigationStyle::SELECTION);
518
                        processed = true;
519
                    } //end of else (some buttons down)
520
                break;
521
            } //switch(button)
522
        } //if(evIsButton)
523

524
        //the essence part 1!
525
        //mouse movement into camera motion. Suppress if in gesture. Ignore until threshold is surpassed.
526
        if (evIsLoc2 && ! this->inGesture && this->mouseMoveThresholdBroken) {
527
            if (curmode == NavigationStyle::ZOOMING) {//doesn't happen
528
                this->zoomByCursor(posn, prevnormalized);
529
                processed = true;
530
            } else if (curmode == NavigationStyle::PANNING) {
531
                panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, posn, prevnormalized);
532
                processed = true;
533
            } else if (curmode == NavigationStyle::DRAGGING) {
534
                if (comboAfter & BUTTON1DOWN && comboAfter & BUTTON2DOWN) {
535
                    //two mouse buttons down - tilting!
536
                    NavigationStyle::doRotate(viewer->getSoRenderManager()->getCamera(),
537
                                              (posn - prevnormalized)[0]*(-2),
538
                                              SbVec2f(0.5,0.5));
539
                    processed = true;
540
                } else {//one mouse button - normal spinning
541
                    //this will also handle the single-finger drag (there's no gesture used, pseudomouse is enough)
542
                    //this->addToLog(event->getPosition(), event->getTime());
543
                    this->spin_simplified(viewer->getSoRenderManager()->getCamera(),
544
                                          posn, prevnormalized);
545
                    processed = true;
546
                }
547
            }
548
        }
549

550
        //the essence part 2!
551
        //gesture into camera motion
552
        if (evIsGesture){
553
            auto gesture = static_cast<const SoGestureEvent*>(ev);
554
            assert(gesture);
555
            if (gesture->state == SoGestureEvent::SbGSEnd) {
556
                setViewingMode(NavigationStyle::SELECTION);
557
                processed=true;
558
            } else if (gesture->state == SoGestureEvent::SbGSUpdate){
559
                if(type.isDerivedFrom(SoGesturePinchEvent::getClassTypeId())){
560
                    auto const event = static_cast<const SoGesturePinchEvent*>(ev);
561
                    if (this->zoomAtCursor){
562
                        //this is just dealing with the pan part of pinch gesture. Taking care of zooming to pos is done in doZoom.
563
                        SbVec2f panDist = this->normalizePixelPos(event->deltaCenter.getValue());
564
                        NavigationStyle::panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, panDist, SbVec2f(0,0));
565
                    }
566
                    NavigationStyle::doZoom(viewer->getSoRenderManager()->getCamera(),-logf(event->deltaZoom),this->normalizePixelPos(event->curCenter));
567
                    if (event->deltaAngle != 0)
568
                        NavigationStyle::doRotate(viewer->getSoRenderManager()->getCamera(),event->deltaAngle,this->normalizePixelPos(event->curCenter));
569
                    processed = true;
570
                }
571
                if(type.isDerivedFrom(SoGesturePanEvent::getClassTypeId())){
572
                    auto const event = static_cast<const SoGesturePanEvent*>(ev);
573
                        //this is just dealing with the pan part of pinch gesture. Taking care of zooming to pos is done in doZoom.
574
                    SbVec2f panDist = this->normalizePixelPos(event->deltaOffset);
575
                    NavigationStyle::panCamera(viewer->getSoRenderManager()->getCamera(), ratio, this->panningplane, panDist, SbVec2f(0,0));
576
                    processed = true;
577
                }
578
            } else {
579
                //shouldn't happen. Gestures are not expected to start in the middle of navigation.
580
                //we'll consume it, without reacting.
581
                processed=true;
582
            }
583
        }
584

585
    } break;//end of actual navigation
586
    case NavigationStyle::SEEK_WAIT_MODE:{
587
        if (evIsButton) {
588
            auto const event = (const SoMouseButtonEvent *) ev;
589
            const int button = event->getButton();
590
            const SbBool press = event->getState() == SoButtonEvent::DOWN ? true : false;
591
            if (button == SoMouseButtonEvent::BUTTON1 && press) {
592
                this->seekToPoint(pos); // implicitly calls interactiveCountInc()
593
                this->setViewingMode(NavigationStyle::SEEK_MODE);
594
                processed = true;
595
            }
596
        }
597
    } ; //not end of SEEK_WAIT_MODE. Fall through by design!!!
598
        /* FALLTHRU */
599
    case NavigationStyle::SPINNING:
600
    case NavigationStyle::SEEK_MODE: {
601
        //animation modes
602
        if (!processed) {
603
            if (evIsButton || evIsGesture || evIsKeyboard || evIsLoc3)
604
                setViewingMode(NavigationStyle::SELECTION);
605
        }
606
    } break; //end of animation modes
607
    case NavigationStyle::BOXZOOM:
608
    default:
609
        //all the rest - will be pass on to inherited, later.
610
        break;
611
    }
612

613
    if (! processed && ! propagated) {
614
        processed = inherited::processSoEvent(ev);
615
        propagated = true;
616
    }
617

618
    //-----------------------end of event handling---------------------
619
finalize:
620
    return processed;
621
}
622

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

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

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

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