~ubuntu-branches/ubuntu/oneiric/soqt/oneiric

« back to all changes in this revision

Viewing changes to build/msvc6/src/Inventor/Qt/viewers/SoQtFlyViewer.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Steve M. Robbins
  • Date: 2009-03-01 11:41:00 UTC
  • mfrom: (1.1.4 upstream) (5.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20090301114100-f4zz3n1oasa52fgk
Tags: 1.4.2~svn20090224-2
* Upload upstream SVN head version containing fixes to build with Coin 3
  (Closes: #515729, #515736, #515742).  Upstream indicated to me that
  SVN is stable enough to release.

* control: Update Standards-Version to 3.8.0; no changes required.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************\
2
 
 *
3
 
 *  This file is part of the Coin 3D visualization library.
4
 
 *  Copyright (C) 1998-2005 by Systems in Motion.  All rights reserved.
5
 
 *
6
 
 *  This library is free software; you can redistribute it and/or
7
 
 *  modify it under the terms of the GNU General Public License
8
 
 *  ("GPL") version 2 as published by the Free Software Foundation.
9
 
 *  See the file LICENSE.GPL at the root directory of this source
10
 
 *  distribution for additional information about the GNU GPL.
11
 
 *
12
 
 *  For using Coin with software that can not be combined with the GNU
13
 
 *  GPL, and for taking advantage of the additional benefits of our
14
 
 *  support services, please contact Systems in Motion about acquiring
15
 
 *  a Coin Professional Edition License.
16
 
 *
17
 
 *  See <URL:http://www.coin3d.org/> for more information.
18
 
 *
19
 
 *  Systems in Motion, Postboks 1283, Pirsenteret, 7462 Trondheim, NORWAY.
20
 
 *  <URL:http://www.sim.no/>.
21
 
 *
22
 
\**************************************************************************/
23
 
 
24
 
// src/Inventor/Qt/viewers/SoQtFlyViewer.cpp.  Generated from SoGuiFlyViewer.cpp.in by configure.
25
 
 
26
 
/*!
27
 
  \class SoQtFlyViewer Inventor/Qt/viewers/SoQtFlyViewer.h
28
 
  \brief The SoQtFlyViewer class implements controls for moving
29
 
  the camera in a "flying" motion.
30
 
  \ingroup viewers
31
 
 
32
 
  Controls:
33
 
  <ul>
34
 
 
35
 
  <li>Left mouse button increases the speed.</li>
36
 
 
37
 
  <li>Middle mouse button decreases the speed.</li>
38
 
 
39
 
  <li>Left and middle mouse button together sets the speed to zero.</li>
40
 
 
41
 
  <li>"s" puts the viewer in seek mode. Click some geometry with the
42
 
      left mouse button to start the seek zoom animation. (Hitting "s"
43
 
      again before clicking will cancel the seek operation.)</li>
44
 
 
45
 
  <li>"u" puts the viewer in up-vector pick mode. Click some geometry
46
 
      with the left mouse button to set the camera's up-vector to the
47
 
      normal vector of the face you pick.
48
 
      (Hitting "u" again before clicking will cancel the pick operation.)</li>
49
 
 
50
 
  <li>The control key stops the flying and lets you tilt the camera by moving
51
 
      the pointer.</li>
52
 
 
53
 
  </ul>
54
 
*/
55
 
 
56
 
/*
57
 
  FIXME:
58
 
  - animate camera when setting up-vector so the scene doesn't just
59
 
    suddenly change.
60
 
*/
61
 
 
62
 
#include <soqtdefs.h>
63
 
#include <Inventor/Qt/viewers/SoQtFlyViewer.h>
64
 
#include <Inventor/events/SoKeyboardEvent.h>
65
 
#include <Inventor/events/SoLocation2Event.h>
66
 
#include <Inventor/events/SoMouseButtonEvent.h>
67
 
#include <Inventor/nodes/SoCamera.h>
68
 
#include <Inventor/nodes/SoCallback.h>
69
 
#include <Inventor/nodes/SoCoordinate3.h>
70
 
#include <Inventor/nodes/SoSwitch.h>
71
 
#include <Inventor/nodes/SoScale.h>
72
 
#include <Inventor/nodes/SoTranslation.h>
73
 
#include <Inventor/errors/SoDebugError.h>
74
 
#include <Inventor/actions/SoSearchAction.h>
75
 
#include <Inventor/actions/SoHandleEventAction.h>
76
 
#include <Inventor/actions/SoGetBoundingBoxAction.h>
77
 
#include <string.h> // strlen() etc
78
 
#include <stdlib.h> // abs() 
79
 
#include <Inventor/Qt/SoQtCursor.h>
80
 
 
81
 
 
82
 
// ************************************************************************
83
 
 
84
 
#ifndef DOXYGEN_SKIP_THIS
85
 
 
86
 
// FIXME: We should probably move this class out of this
87
 
// impl-file. There is code here that could be factored out and reused
88
 
// in other modules, for example camera handling. Now there is a
89
 
// duplication with some of the code in SoQtConstrainedViewerP, for
90
 
// example. 20021017 rolvs
91
 
class SoQtFlyViewerP {
92
 
public:
93
 
  SoQtFlyViewerP(SoQtFlyViewer * owner);
94
 
  ~SoQtFlyViewerP();
95
 
 
96
 
  enum ViewerMode {
97
 
    FLYING, TILTING, WAITING_FOR_SEEK, WAITING_FOR_UP_PICK
98
 
  };
99
 
 
100
 
  void constructor(SbBool build);
101
 
 
102
 
  void dolly(const float delta) const;
103
 
  void updateCursorRepresentation(void); // in SoNativeFlyViewer.cpp
104
 
  void setMode(ViewerMode newmode);
105
 
  int getMode(void) { return this->viewermode; }
106
 
 
107
 
#define SOQT_MIN_STEP     0.2f
108
 
#define SOQT_INC_FACTOR   1.2f
109
 
#define SOQT_MAX_SPEED   20.0f
110
 
 
111
 
  SbTime * lastrender;
112
 
 
113
 
  float currentspeed;
114
 
  
115
 
  // Maximum speed, target for currentspeed during
116
 
  // acceleration/decceleration.
117
 
  float maxspeed; 
118
 
 
119
 
  // Scales speed. Calculated in updateSpeedScalingFactor.
120
 
  float speed_scaling_factor; 
121
 
  
122
 
  // Used to calculate a new max_speed, on the basis on 'where' we are
123
 
  // in the speed landscape, see {increment|decrement}MaxSpeed(). 
124
 
  int max_speed_factor; 
125
 
 
126
 
  // Speed
127
 
  void incrementMaxSpeed();
128
 
  void decrementMaxSpeed();
129
 
  void updateMaxSpeed();
130
 
  void updateSpeedScalingFactor();
131
 
  void stopMoving();
132
 
 
133
 
  void updateSpeedIndicator(void);
134
 
  void updateCameraPosition( SoCamera * camera, float speed, float dt ); 
135
 
  void updateCameraOrientation( SoCamera * camera, 
136
 
                                float d_tilt, 
137
 
                                float d_pan, 
138
 
                                float dt );
139
 
  float calculateChangeInTime();
140
 
  void  updateCurrentSpeed( float dt );
141
 
 
142
 
 
143
 
  // Current keyboard state.
144
 
  SbBool button1down;
145
 
  SbBool button3down;
146
 
  int lctrldown;
147
 
  int rctrldown;
148
 
  SbBool lshiftdown;
149
 
  SbBool rshiftdown;
150
 
 
151
 
  // View, speed display, renderingstate.
152
 
  SoSearchAction * searcher;
153
 
 
154
 
  SoNode * superimposition;
155
 
  SoCoordinate3 * sgeometry;
156
 
 
157
 
  SoScale * sscale;
158
 
  SoScale * crossscale;
159
 
 
160
 
  SoTranslation * stranslation;
161
 
  SoTranslation * crossposition;
162
 
 
163
 
  SoSwitch * smaxspeedswitch; 
164
 
  SoSwitch * scurrentspeedswitch;
165
 
  SoSwitch * crossswitch;
166
 
 
167
 
  SoNode * getSuperimpositionNode(const char * name);
168
 
 
169
 
  void superimpositionevent(SoAction * action);
170
 
  static void superimposition_cb(void * closure, SoAction * action);
171
 
 
172
 
 
173
 
  // 
174
 
  float tilt_increment; // Angle-adjustment between View-up and direction 
175
 
  float pan_increment;  // Rotation-adjustment around View-up
176
 
 
177
 
  SbVec2s mouseloc;
178
 
  SbVec2s lastpos;
179
 
  SbVec2s tiltpos;
180
 
 
181
 
  // FIXME: Refactor event handlers and PUBLIC(this)->processSoEvent
182
 
  // in a way similar to that in SoGuiExaminerViewer, where only
183
 
  // internal state is red/set. 20021017 rolvs
184
 
  SbBool processKeyboardEvent( const SoKeyboardEvent * const kevt );
185
 
  SbBool processMouseButtonEvent( const SoMouseButtonEvent * const mevt );
186
 
  SbBool processLocation2Event( const SoLocation2Event * const levt );
187
 
private:
188
 
  SoQtFlyViewer * publ;
189
 
  ViewerMode viewermode;
190
 
};
191
 
 
192
 
SoQtFlyViewerP::SoQtFlyViewerP( SoQtFlyViewer * owner )
193
 
{
194
 
  this->searcher = NULL;
195
 
  this->publ = owner;
196
 
  this->viewermode = FLYING;
197
 
  this->currentspeed = 0.0f;
198
 
  this->maxspeed = 0.0f;
199
 
  this->speed_scaling_factor = 0.4f;
200
 
  this->max_speed_factor = 0;
201
 
  this->stranslation = NULL;
202
 
  this->sscale = NULL;
203
 
  this->button1down = FALSE;
204
 
  this->button3down = FALSE;
205
 
  this->lctrldown = 0;
206
 
  this->rctrldown = 0;
207
 
  this->lshiftdown = FALSE;
208
 
  this->rshiftdown = FALSE;
209
 
  this->lastrender = new SbTime;
210
 
  this->tilt_increment = 0;
211
 
  this->pan_increment = 0;
212
 
}
213
 
 
214
 
SoQtFlyViewerP::~SoQtFlyViewerP(void)
215
 
{
216
 
  if ( this->searcher != NULL )
217
 
    delete this->searcher;
218
 
  delete this->lastrender;
219
 
 
220
 
  // superimposition unrefed in other destructor
221
 
}
222
 
 
223
 
#define PRIVATE(o) (o->pimpl)
224
 
#define PUBLIC(o) (o->publ)
225
 
 
226
 
 
227
 
// Common constructor code.
228
 
void
229
 
SoQtFlyViewerP::constructor(SbBool build)
230
 
{
231
 
  PUBLIC(this)->setClassName(PUBLIC(this)->getDefaultWidgetName());
232
 
 
233
 
  static const char * superimposed[] = {
234
 
    "#Inventor V2.1 ascii",
235
 
    "",
236
 
    "Separator {",
237
 
    "  MaterialBinding {",
238
 
    "    value OVERALL",
239
 
    "  }",
240
 
    "  OrthographicCamera {",
241
 
    "    height 1",
242
 
    "    nearDistance 0",
243
 
    "    farDistance 1",
244
 
    "  }",
245
 
    "  DEF soqt->callback Callback { }",
246
 
    "  Separator {",
247
 
    "    DEF soqt->translation Translation {",
248
 
    "      translation 0 0 0",
249
 
    "    }",
250
 
    "    DEF soqt->scale Scale {",
251
 
    "      scaleFactor 1 1 1",
252
 
    "    }",
253
 
    "    DEF soqt->geometry Coordinate3 {",
254
 
    "      point [",
255
 
    "       -0.8 -0.04 0,",
256
 
    "       -0.8  0    0,",
257
 
    "       -0.8  0.04 0,",
258
 
    "        0   -0.04 0,",
259
 
    "        0    0    0,",
260
 
    "        0    0.04 0,",
261
 
    "        0.8 -0.04 0,",
262
 
    "        0.8  0    0,",
263
 
    "        0.8  0.04 0,", 
264
 
    "        0    0.02 0,", // idx 9
265
 
    "        0.8  0.02 0,",
266
 
    "        0.8 -0.02 0,",
267
 
    "        0   -0.02 0,",
268
 
    "        0    0.01 0,", // idx 13
269
 
    "        0.4  0.01 0,",
270
 
    "        0.4 -0.01 0,",
271
 
    "        0   -0.01 0",
272
 
    "      ]",
273
 
    "    }",
274
 
    "    DEF soqt->maxspeedswitch Switch {",
275
 
    "      whichChild -3",
276
 
    // max speed indicator
277
 
    "      Material {",
278
 
    "        emissiveColor 1 0 0",
279
 
    "      }",
280
 
    "      IndexedFaceSet {",
281
 
    "        coordIndex [",
282
 
    "          12, 11, 10, 9, -1",
283
 
    "        ]",
284
 
    "      }",
285
 
    "    }",
286
 
    // the coordinate system
287
 
    "    BaseColor {",
288
 
    "      rgb 1 1 1",
289
 
    "    }",
290
 
    "    IndexedLineSet {",
291
 
    "      coordIndex [",
292
 
    "        0, 2, -1,",
293
 
    "        3, 5, -1,",
294
 
    "        6, 8, -1,",
295
 
    "        1, 7, -1",
296
 
    "      ]",
297
 
    "    }",
298
 
    // current speed indicator
299
 
    "    DEF soqt->currentspeedswitch Switch {",
300
 
    "      whichChild -3",
301
 
    "      Material {",
302
 
    "        emissiveColor 0 0 1",
303
 
    "      }",
304
 
    "      IndexedFaceSet {",
305
 
    "        coordIndex [",
306
 
    "          16, 15, 14, 13, -1",
307
 
    "        ]",
308
 
    "      }",
309
 
    "    }",
310
 
    "  }",
311
 
    // cross
312
 
    "  DEF soqt->crossswitch Switch {",
313
 
    "    whichChild -1",
314
 
    "    DEF soqt->crossposition Translation {",
315
 
    "      translation 0 0 0",
316
 
    "    }",
317
 
    "    DEF soqt->crossscale Scale {",
318
 
    "      scaleFactor 1 1 1",
319
 
    "    }",
320
 
    "    BaseColor {",
321
 
    "      rgb 1 0 0",
322
 
    "    }",
323
 
    "    Coordinate3 {",
324
 
    "      point [",
325
 
    "        0 -1  0,",
326
 
    "        0  1  0,",
327
 
    "       -1  0  0,",
328
 
    "        1  0  0",
329
 
    "      ]",
330
 
    "    }",
331
 
    "    IndexedLineSet {",
332
 
    "      coordIndex [",
333
 
    "        0, 1, -1,",
334
 
    "        2, 3, -1",
335
 
    "      ]",
336
 
    "    }",
337
 
    "  }",
338
 
    "}",
339
 
    NULL
340
 
  };
341
 
 
342
 
  int i, bufsize;
343
 
  for (i = bufsize = 0; superimposed[i]; i++)
344
 
    bufsize += strlen(superimposed[i]) + 1;
345
 
  char * buf = new char [bufsize + 1];
346
 
  for (i = bufsize = 0; superimposed[i]; i++) {
347
 
    strcpy(buf + bufsize, superimposed[i]);
348
 
    bufsize += strlen(superimposed[i]);
349
 
    buf[bufsize] = '\n';
350
 
    bufsize++;
351
 
  }
352
 
  SoInput * input = new SoInput;
353
 
  input->setBuffer(buf, bufsize);
354
 
  SbBool ok = SoDB::read(input, this->superimposition);
355
 
  assert(ok);
356
 
  delete input;
357
 
  delete [] buf;
358
 
  this->superimposition->ref();
359
 
 
360
 
 
361
 
  this->sscale = (SoScale *)
362
 
    this->getSuperimpositionNode("soqt->scale");
363
 
  this->stranslation = (SoTranslation *)
364
 
    this->getSuperimpositionNode("soqt->translation");
365
 
  this->sgeometry = (SoCoordinate3 *)
366
 
    this->getSuperimpositionNode("soqt->geometry");
367
 
  this->smaxspeedswitch = (SoSwitch *)
368
 
    this->getSuperimpositionNode("soqt->maxspeedswitch");
369
 
  this->scurrentspeedswitch = (SoSwitch *)
370
 
    this->getSuperimpositionNode("soqt->currentspeedswitch");
371
 
  this->crossswitch = (SoSwitch *)
372
 
    this->getSuperimpositionNode("soqt->crossswitch");
373
 
  this->crossposition = (SoTranslation *)
374
 
    this->getSuperimpositionNode("soqt->crossposition");
375
 
  this->crossscale = (SoScale *)
376
 
    this->getSuperimpositionNode("soqt->crossscale");
377
 
 
378
 
  SoCallback * cb = (SoCallback *)
379
 
    this->getSuperimpositionNode("soqt->callback");
380
 
  cb->setCallback(SoQtFlyViewerP::superimposition_cb, this);
381
 
 
382
 
  this->updateSpeedIndicator();
383
 
 
384
 
  PUBLIC(this)->addSuperimposition(this->superimposition);
385
 
  PUBLIC(this)->setSuperimpositionEnabled(this->superimposition,TRUE);
386
 
 
387
 
  if (build) {
388
 
    QWidget * viewer = PUBLIC(this)->buildWidget(PUBLIC(this)->getParentWidget());
389
 
    PUBLIC(this)->setBaseWidget(viewer);
390
 
  }
391
 
}
392
 
 
393
 
// This method dollies the camera back and forth in the scene.
394
 
void
395
 
SoQtFlyViewerP::dolly(const float delta) const
396
 
{
397
 
  SoCamera * const camera = PUBLIC(this)->getCamera();
398
 
  if (camera == NULL) { return; } // if there's no scenegraph, for instance
399
 
 
400
 
  SbPlane walkplane(PUBLIC(this)->getUpDirection(), 
401
 
                    camera->position.getValue());
402
 
 
403
 
  SbVec3f campos = camera->position.getValue();
404
 
  SbVec3f camvec;
405
 
  camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), camvec);
406
 
  SbLine cross(campos + camvec,
407
 
                campos + camvec + PUBLIC(this)->getUpDirection());
408
 
  SbVec3f intersect;
409
 
  walkplane.intersect(cross, intersect);
410
 
  SbVec3f dir = intersect - campos;
411
 
  dir.normalize();
412
 
 
413
 
  camera->position = campos - dir * delta;
414
 
}
415
 
 
416
 
// The viewer is a state machine, and all changes to the current state
417
 
// are made through this call.
418
 
void
419
 
SoQtFlyViewerP::setMode(ViewerMode newmode)
420
 
{
421
 
  this->viewermode = newmode;
422
 
  this->updateCursorRepresentation();
423
 
}
424
 
 
425
 
// This method locates a named node in the superimposed scene.
426
 
SoNode *
427
 
SoQtFlyViewerP::getSuperimpositionNode(const char * name)
428
 
{
429
 
  if (! this->searcher)
430
 
    this->searcher = new SoSearchAction;
431
 
  searcher->reset();
432
 
  searcher->setName(SbName(name));
433
 
  searcher->setInterest(SoSearchAction::FIRST);
434
 
  searcher->setSearchingAll(TRUE);
435
 
  searcher->apply(this->superimposition);
436
 
  assert(searcher->getPath());
437
 
  return searcher->getPath()->getTail();
438
 
}
439
 
 
440
 
SbBool
441
 
SoQtFlyViewerP::processKeyboardEvent( const SoKeyboardEvent * const ke )
442
 
{
443
 
  assert( ke != NULL );
444
 
  switch (ke->getState()) {
445
 
  case SoButtonEvent::UP:
446
 
    switch (ke->getKey()) {
447
 
    case SoKeyboardEvent::U:
448
 
      do {
449
 
        // either to switch to up-vector pick mode, or back to fly
450
 
        // mode if pick-mode already activated (ie cancel the
451
 
        // up-vector pick operation)
452
 
        SbBool uppickmode =
453
 
          this->getMode() == SoQtFlyViewerP::WAITING_FOR_UP_PICK;
454
 
        this->setMode(uppickmode ? SoQtFlyViewerP::FLYING :
455
 
                               SoQtFlyViewerP::WAITING_FOR_UP_PICK);
456
 
 
457
 
        this->stopMoving();
458
 
 
459
 
        this->updateSpeedIndicator();
460
 
        PUBLIC(this)->scheduleRedraw();
461
 
        return TRUE;
462
 
      } while (FALSE);
463
 
      break;
464
 
      
465
 
    case SoKeyboardEvent::S:
466
 
      this->stopMoving();
467
 
      this->updateSpeedIndicator();
468
 
      PUBLIC(this)->scheduleRedraw();
469
 
      return FALSE;
470
 
      
471
 
    case SoKeyboardEvent::LEFT_SHIFT:
472
 
      this->lshiftdown = FALSE;
473
 
      if (this->lshiftdown < 0) {
474
 
#if SOQT_DEBUG
475
 
        SoDebugError::post("SoQtFlyViewerP::processKeyboardEvent",
476
 
                           "left shift key count < 0");
477
 
#endif
478
 
        this->lshiftdown = 0;
479
 
      }
480
 
      break;
481
 
    case SoKeyboardEvent::RIGHT_SHIFT:
482
 
      this->rshiftdown = FALSE;
483
 
      if (this->rshiftdown < 0) {
484
 
#if SOQT_DEBUG
485
 
        SoDebugError::post("SoQtFlyViewerP::processKeyboardEvent",
486
 
                           "right shift key count < 0");
487
 
#endif
488
 
        this->rshiftdown = 0;
489
 
      }
490
 
      break;
491
 
    case SoKeyboardEvent::LEFT_CONTROL:
492
 
      this->lctrldown -= 1;
493
 
      if (this->lctrldown < 0) {
494
 
#if SOQT_DEBUG
495
 
        SoDebugError::post("SoQtFlyViewerP::processKyeboardEvent",
496
 
                           "left control key count < 0");
497
 
#endif
498
 
        this->lctrldown = 0;
499
 
      }
500
 
      break;
501
 
    case SoKeyboardEvent::RIGHT_CONTROL:
502
 
      this->rctrldown -= 1;
503
 
      if (this->rctrldown < 0) {
504
 
#if SOQT_DEBUG
505
 
        SoDebugError::post("SoQtFlyViewerP::processKyeboardEvent",
506
 
                           "right control key count < 0");
507
 
#endif
508
 
        this->rctrldown = 0;
509
 
      }
510
 
      break;
511
 
    default:
512
 
      break;
513
 
    }
514
 
    break;
515
 
  case SoButtonEvent::DOWN:
516
 
    switch (ke->getKey()) {
517
 
    case SoKeyboardEvent::LEFT_SHIFT:
518
 
      this->lshiftdown += 1;
519
 
      if (this->lshiftdown > 2) {
520
 
#if SOQT_DEBUG
521
 
        SoDebugError::post("SoQtFlyViewerP::processKeyboardEvent",
522
 
                           "left shift key count > 2");
523
 
#endif
524
 
        this->lshiftdown = 2;
525
 
      }
526
 
      break;
527
 
    case SoKeyboardEvent::RIGHT_SHIFT:
528
 
      this->rshiftdown += 1;
529
 
      if (this->rshiftdown > 2) {
530
 
#if SOQT_DEBUG
531
 
        SoDebugError::post("SoQtFlyViewerP::processKeyboardEvent",
532
 
                           "right shift key count > 2");
533
 
#endif
534
 
        this->rshiftdown = 2;
535
 
      }
536
 
      break;
537
 
    case SoKeyboardEvent::LEFT_CONTROL:
538
 
      this->lctrldown += 1;
539
 
      if (this->lctrldown > 2) {
540
 
#if SOQT_DEBUG
541
 
        SoDebugError::post("SoQtFlyViewerP::processKeyboardEvent",
542
 
                           "left control key count > 2");
543
 
#endif
544
 
        this->lctrldown = 2;
545
 
      }
546
 
      break;
547
 
    case SoKeyboardEvent::RIGHT_CONTROL:
548
 
      this->rctrldown += 1;
549
 
      if (this->rctrldown > 2) {
550
 
#if SOQT_DEBUG
551
 
        SoDebugError::post("SoQtFlyViewer::processSoEvent",
552
 
                           "right control key count > 2");
553
 
#endif
554
 
        this->rctrldown = 2;
555
 
      }
556
 
      break;
557
 
    default:
558
 
      break; 
559
 
    }
560
 
    break;
561
 
  default:
562
 
    break;
563
 
  }
564
 
 
565
 
  if ((this->getMode() == SoQtFlyViewerP::FLYING) &&
566
 
      (this->lctrldown || this->rctrldown)) {
567
 
    this->setMode(SoQtFlyViewerP::TILTING);
568
 
    
569
 
    this->tiltpos = this->mouseloc;
570
 
    this->lastpos = this->mouseloc;
571
 
 
572
 
    this->stopMoving();
573
 
    this->updateSpeedIndicator();
574
 
    this->crossswitch->whichChild.setValue(SO_SWITCH_ALL);
575
 
    PUBLIC(this)->scheduleRedraw();
576
 
    // NOTE; this could be optimized to only draw the superimposition in
577
 
    // question if speed is zero.
578
 
  } else if ((this->getMode() == SoQtFlyViewerP::TILTING) &&
579
 
             !this->lctrldown && !this->rctrldown) {
580
 
    this->setMode(SoQtFlyViewerP::FLYING);
581
 
    assert(this->crossswitch != NULL);
582
 
    this->crossswitch->whichChild.setValue(SO_SWITCH_NONE);
583
 
    PUBLIC(this)->scheduleRedraw();
584
 
  }
585
 
  return FALSE;
586
 
}
587
 
 
588
 
 
589
 
SbBool
590
 
SoQtFlyViewerP::processMouseButtonEvent( const SoMouseButtonEvent * const me )
591
 
{
592
 
  assert( me != NULL );
593
 
  
594
 
  // FIXME: only for fly mode
595
 
  switch (this->getMode()) {
596
 
  case SoQtFlyViewerP::WAITING_FOR_UP_PICK:
597
 
    if ((me->getButton() == SoMouseButtonEvent::BUTTON1) &&
598
 
        (me->getState() == SoButtonEvent::DOWN)) {
599
 
      PUBLIC(this)->findUpDirection(me->getPosition());
600
 
      this->setMode(SoQtFlyViewerP::FLYING);
601
 
      return TRUE;
602
 
    }
603
 
    break;
604
 
  case SoQtFlyViewerP::FLYING:
605
 
    switch (me->getButton()) {
606
 
    case SoMouseButtonEvent::BUTTON1:
607
 
 
608
 
      switch (me->getState()) {
609
 
        
610
 
      case SoButtonEvent::DOWN:
611
 
        // Incrementing speed.
612
 
        this->button1down = TRUE;
613
 
        if (this->button3down) {
614
 
          this->stopMoving();
615
 
        } 
616
 
        else {
617
 
          this->incrementMaxSpeed();
618
 
        }
619
 
        this->updateSpeedIndicator();
620
 
        PUBLIC(this)->scheduleRedraw();
621
 
        return TRUE;
622
 
      case SoButtonEvent::UP:
623
 
        this->button1down = FALSE;
624
 
        return TRUE;
625
 
      default:
626
 
        break;
627
 
      }
628
 
      break;
629
 
 
630
 
    case SoMouseButtonEvent::BUTTON3:
631
 
 
632
 
      switch (me->getState()) {
633
 
      case SoButtonEvent::DOWN:
634
 
        this->button3down = TRUE;
635
 
        
636
 
        if (this->button1down) {
637
 
          this->stopMoving();
638
 
        } 
639
 
        else
640
 
          this->decrementMaxSpeed();
641
 
     
642
 
        this->updateSpeedIndicator();
643
 
        PUBLIC(this)->scheduleRedraw();
644
 
        return TRUE;
645
 
      case SoButtonEvent::UP:
646
 
        this->button3down = FALSE;
647
 
        return TRUE;
648
 
      default:
649
 
        break;
650
 
      }
651
 
      break;
652
 
    default:
653
 
      break;
654
 
    }
655
 
  default:
656
 
    break;
657
 
  }
658
 
  return FALSE;
659
 
}
660
 
 
661
 
SbBool
662
 
SoQtFlyViewerP::processLocation2Event( const SoLocation2Event * const lev )
663
 
{  
664
 
  this->mouseloc = lev->getPosition();
665
 
 
666
 
  if (this->getMode() == SoQtFlyViewerP::TILTING) {
667
 
 
668
 
    float pan = (this->lastpos[0] - this->mouseloc[0])/100.0f;
669
 
    float tilt = (this->lastpos[1] - this->mouseloc[1])/100.0f;
670
 
    
671
 
    SoCamera * camera = PUBLIC(this)->getCamera();
672
 
    if (camera == NULL) 
673
 
      return TRUE; // probably sceneless
674
 
    
675
 
    this->updateCameraOrientation( camera, tilt, pan, 1.0f );
676
 
    this->lastpos = this->mouseloc;
677
 
  }
678
 
 
679
 
  // FIXME: The size of the glcanvas only changes when the viewer is
680
 
  // resized. The GLSize should be set from the FlyViewer, to remove
681
 
  // the dependency on the PUBLIC(this) class. 20021021 rolvs
682
 
  SbVec2s glsize( PUBLIC(this)->getGLSize() );
683
 
 
684
 
  // NOTE: The values are normalized, so that the FlyViewer behaves
685
 
  // the same way no matter the screen-size. The old way to do it made
686
 
  // the possible range of pan and tilt increment depend on the canvas
687
 
  // size. 20021022 rolvs.
688
 
  this->pan_increment = 0.5f - float(this->mouseloc[0])/glsize[0]; 
689
 
  this->tilt_increment = 0.5f - float(this->mouseloc[1])/glsize[1];
690
 
 
691
 
  return TRUE;
692
 
}
693
 
 
694
 
void
695
 
SoQtFlyViewerP::superimpositionevent(SoAction * action)
696
 
{
697
 
  if (!action->isOfType(SoGLRenderAction::getClassTypeId())) return;
698
 
  SbViewportRegion vpRegion =
699
 
    ((SoGLRenderAction *) action)->getViewportRegion();
700
 
  SbVec2s viewport = vpRegion.getViewportSizePixels();
701
 
  float aspect = float(viewport[0]) / float(viewport[1]);
702
 
  float factorx = 1.0f/float(viewport[1]) * 220.0f;
703
 
  float factory = factorx;
704
 
  if (aspect > 1.0f) {
705
 
    this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f, 0.0f));
706
 
  } else {
707
 
    this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f / aspect, 0.0f));
708
 
    factorx /= aspect;
709
 
    factory /= aspect;
710
 
  }
711
 
  if (viewport[0] > 500)
712
 
    factorx *= 500.0f / 400.0f;
713
 
  else
714
 
    factorx *= float(viewport[0]) / 400.0f;
715
 
  this->sscale->scaleFactor.setValue(SbVec3f(factorx, factory, 1.0f));
716
 
 
717
 
  if (this->getMode() == TILTING) {
718
 
    assert(this->crossposition != NULL);
719
 
    assert(this->crossscale != NULL);
720
 
    float tx = float(this->tiltpos[0]-float(viewport[0])/2.0f)/(float(viewport[0]));
721
 
    float ty = float(this->tiltpos[1]-float(viewport[1])/2.0f)/(float(viewport[1]));
722
 
    if (aspect > 1.0f) tx *= aspect;
723
 
    else ty /= aspect;
724
 
    this->crossposition->translation.setValue(SbVec3f(tx, ty, 0));
725
 
 
726
 
    float sx = (1.0f/float(viewport[0])) * 15.0f;
727
 
    float sy = (1.0f/float(viewport[1])) * 15.0f;
728
 
    if (aspect > 1.0f) sx *= aspect;
729
 
    else sy /= aspect;
730
 
    this->crossscale->scaleFactor.setValue(SbVec3f(sx, sy, 0));
731
 
  }
732
 
}
733
 
 
734
 
void
735
 
SoQtFlyViewerP::superimposition_cb(void * closure, SoAction * action)
736
 
{
737
 
  assert(closure != NULL);
738
 
  ((SoQtFlyViewerP *) closure)->superimpositionevent(action);
739
 
}
740
 
 
741
 
void
742
 
SoQtFlyViewerP::updateSpeedIndicator(void)
743
 
{
744
 
  assert(this->sgeometry != NULL);
745
 
 
746
 
  SbVec3f * points = this->sgeometry->point.startEditing();
747
 
 
748
 
  if (points[10][0] == 0.0f)
749
 
    this->smaxspeedswitch->whichChild.setValue(SO_SWITCH_ALL);
750
 
  if (points[14][0] == 0.0f)
751
 
    this->scurrentspeedswitch->whichChild.setValue(SO_SWITCH_ALL);
752
 
  points[10][0] = this->maxspeed / (SOQT_MAX_SPEED / 0.8f);
753
 
  points[11][0] = this->maxspeed / (SOQT_MAX_SPEED / 0.8f);
754
 
  points[14][0] = this->currentspeed / (SOQT_MAX_SPEED / 0.8f);
755
 
  points[15][0] = this->currentspeed / (SOQT_MAX_SPEED / 0.8f);
756
 
  this->sgeometry->point.finishEditing();
757
 
 
758
 
  if (this->maxspeed == 0.0f)
759
 
    this->smaxspeedswitch->whichChild.setValue(SO_SWITCH_NONE);
760
 
  if (this->currentspeed == 0.0f)
761
 
    this->scurrentspeedswitch->whichChild.setValue(SO_SWITCH_NONE);
762
 
}
763
 
 
764
 
float SoQtFlyViewerP::calculateChangeInTime()
765
 
{
766
 
  SbTime thisrender; 
767
 
  thisrender.setToTimeOfDay();
768
 
 
769
 
  float t = 0.0f;
770
 
 
771
 
  if (this->currentspeed == 0.0f)
772
 
    this->lastrender->setValue(thisrender.getValue() - 0.01);
773
 
 
774
 
  t = float(thisrender.getValue() - this->lastrender->getValue()) * 10.0f;
775
 
 
776
 
  if (t >= 1.0f) 
777
 
    t = 1.0f;
778
 
  return t; 
779
 
}
780
 
 
781
 
void SoQtFlyViewerP::updateCurrentSpeed( float dt )
782
 
{
783
 
  float curveSpeedReductionFactor = 
784
 
    1.0f - (this->pan_increment * this->pan_increment 
785
 
            + this->tilt_increment * this->tilt_increment);  
786
 
 
787
 
  // NOTE: I don't believe that this boundary condition could ever
788
 
  // happen. 20021022 rolvs
789
 
  if( curveSpeedReductionFactor < 0 )
790
 
    curveSpeedReductionFactor = 0;
791
 
 
792
 
  this->currentspeed +=
793
 
    (((this->currentspeed +
794
 
      this->maxspeed * curveSpeedReductionFactor) / 2.0f) - 
795
 
     this->currentspeed) * dt;
796
 
}
797
 
 
798
 
void SoQtFlyViewerP::updateCameraPosition( SoCamera * camera, 
799
 
                                              float current_speed,
800
 
                                              float dt )
801
 
{
802
 
  assert( camera != NULL );
803
 
 
804
 
  SbRotation orientation = camera->orientation.getValue();
805
 
  SbVec3f dir;
806
 
  camera->orientation.getValue().multVec( SbVec3f(0,0,-1), dir );
807
 
  dir.normalize();
808
 
  camera->position.setValue(camera->position.getValue() +
809
 
                            dir * (current_speed * dt ));
810
 
}
811
 
 
812
 
void SoQtFlyViewerP::updateCameraOrientation( SoCamera * camera, 
813
 
                                                 float d_tilt, 
814
 
                                                 float d_pan, 
815
 
                                                 float dt )
816
 
{
817
 
  assert( camera != NULL );
818
 
  // FIXME: Make sure that the angle between direction and up-vector
819
 
  // stays larger than zero, or else it gets 'locked' in an undefined
820
 
  // state and starts to act weird. This should probably be done in
821
 
  // parent class. 20021017 rolvs
822
 
  PUBLIC( this )->tiltCamera( d_tilt*dt );
823
 
 
824
 
  camera->orientation = camera->orientation.getValue() *
825
 
    SbRotation( PUBLIC(this)->getUpDirection(), d_pan*dt );
826
 
}
827
 
 
828
 
void
829
 
SoQtFlyViewerP::incrementMaxSpeed()
830
 
{
831
 
  this->max_speed_factor++;
832
 
  updateMaxSpeed();
833
 
}
834
 
 
835
 
 
836
 
void
837
 
SoQtFlyViewerP::decrementMaxSpeed()
838
 
{       
839
 
  this->max_speed_factor--;
840
 
  updateMaxSpeed();
841
 
}
842
 
 
843
 
 
844
 
void SoQtFlyViewerP::updateSpeedScalingFactor()
845
 
{
846
 
  SoNode *n = PUBLIC(this)->getSceneGraph();
847
 
  if( n == NULL )
848
 
    return; // Scenegraph not set yet?
849
 
 
850
 
  SoGetBoundingBoxAction bbact( PUBLIC(this)->getViewportRegion() );
851
 
  bbact.apply( n );  
852
 
  
853
 
  SbBox3f bbox = bbact.getBoundingBox();
854
 
  float bbox_diagonal = (bbox.getMax() - bbox.getMin()).length();
855
 
 
856
 
  // FIXME: It should be possible to create a simple scaling function,
857
 
  // based on some logaritmic evaluation. 20021017 rolvs.
858
 
  if( bbox_diagonal>100 )
859
 
    this->speed_scaling_factor = 1.0f; // log(bbox_diagonal);
860
 
  else if( bbox_diagonal>10 && bbox_diagonal < 100 )
861
 
    this->speed_scaling_factor = 0.4f; 
862
 
  else if( bbox_diagonal>1 && bbox_diagonal<10 )
863
 
    this->speed_scaling_factor = 0.3f; 
864
 
  else if( bbox_diagonal>0.1 && bbox_diagonal<1)
865
 
    this->speed_scaling_factor = 0.1f; 
866
 
  else
867
 
    this->speed_scaling_factor = 0.1f*bbox_diagonal;
868
 
}
869
 
 
870
 
void SoQtFlyViewerP::stopMoving()
871
 
{
872
 
  maxspeed = 0;
873
 
  currentspeed = 0; 
874
 
  max_speed_factor = 0;
875
 
}
876
 
 
877
 
void SoQtFlyViewerP::updateMaxSpeed()
878
 
{
879
 
  if( this->max_speed_factor == 0 ){
880
 
    this->stopMoving();
881
 
    return;
882
 
  }
883
 
 
884
 
  // FIXME: Move this methodcall so that it is called only
885
 
  // once. (e.g. when scene graph is set) 20021021 rolvs
886
 
  this->updateSpeedScalingFactor();
887
 
 
888
 
  this->maxspeed = 
889
 
    this->max_speed_factor 
890
 
    * float(pow( SOQT_INC_FACTOR, abs( this->max_speed_factor ) ))
891
 
    * this->speed_scaling_factor;
892
 
 
893
 
  if( this->maxspeed > SOQT_MAX_SPEED )
894
 
    this->maxspeed = SOQT_MAX_SPEED;
895
 
  else if( this->maxspeed < -1*SOQT_MAX_SPEED )
896
 
    this->maxspeed = -1*SOQT_MAX_SPEED;
897
 
}
898
 
 
899
 
 
900
 
 
901
 
// Set cursor graphics according to mode.
902
 
void
903
 
SoQtFlyViewerP::updateCursorRepresentation(void)
904
 
{
905
 
  if (!PUBLIC(this)->isCursorEnabled()) {
906
 
    PUBLIC(this)->setComponentCursor(SoQtCursor::getBlankCursor());
907
 
    return;
908
 
  }
909
 
 
910
 
  switch (this->viewermode) {
911
 
  case SoQtFlyViewerP::FLYING:
912
 
    PUBLIC(this)->setComponentCursor(SoQtCursor(SoQtCursor::DEFAULT));
913
 
    break;
914
 
 
915
 
  case SoQtFlyViewerP::WAITING_FOR_SEEK:
916
 
    PUBLIC(this)->setComponentCursor(SoQtCursor(SoQtCursor::CROSSHAIR));
917
 
    break;
918
 
 
919
 
  case SoQtFlyViewerP::WAITING_FOR_UP_PICK:
920
 
    PUBLIC(this)->setComponentCursor(SoQtCursor(SoQtCursor::UPARROW));
921
 
    break;
922
 
 
923
 
  case SoQtFlyViewerP::TILTING:
924
 
    PUBLIC(this)->setComponentCursor(SoQtCursor::getPanCursor());
925
 
    break;
926
 
 
927
 
  default:
928
 
    assert(0 && "unknown mode");
929
 
    break;
930
 
  }
931
 
}
932
 
 
933
 
#endif // DOXYGEN_SKIP_THIS
934
 
 
935
 
// ************************************************************************
936
 
 
937
 
SOQT_OBJECT_SOURCE(SoQtFlyViewer);
938
 
 
939
 
// ************************************************************************
940
 
 
941
 
/*!
942
 
  Public constructor.
943
 
*/
944
 
SoQtFlyViewer::SoQtFlyViewer(QWidget * parent,
945
 
                                   const char * name, 
946
 
                                   SbBool embed, 
947
 
                                   SoQtFullViewer::BuildFlag flag,
948
 
                                   SoQtViewer::Type type)
949
 
  : inherited(parent, name, embed, flag, type, FALSE)
950
 
{
951
 
  PRIVATE(this) = new SoQtFlyViewerP(this);
952
 
  PRIVATE(this)->constructor(TRUE);
953
 
}
954
 
 
955
 
// ************************************************************************
956
 
 
957
 
/*!
958
 
  Protected constructor, used by viewer components derived from the
959
 
  SoQtFlyViewer.
960
 
*/
961
 
SoQtFlyViewer::SoQtFlyViewer(QWidget * parent,
962
 
                                   const char * const name,
963
 
                                   SbBool embed, 
964
 
                                   SoQtFullViewer::BuildFlag flag, 
965
 
                                   SoQtViewer::Type type, 
966
 
                                   SbBool build)
967
 
  : inherited(parent, name, embed, flag, type, FALSE)
968
 
{
969
 
  PRIVATE(this) = new SoQtFlyViewerP(this);
970
 
  PRIVATE(this)->constructor(build);
971
 
}
972
 
 
973
 
// ************************************************************************
974
 
 
975
 
/*!
976
 
  Virtual constructor.
977
 
*/
978
 
SoQtFlyViewer::~SoQtFlyViewer()
979
 
{
980
 
  if (PRIVATE(this)->superimposition != NULL) {
981
 
    this->removeSuperimposition(PRIVATE(this)->superimposition);
982
 
    PRIVATE(this)->superimposition->unref();
983
 
    PRIVATE(this)->superimposition = NULL;
984
 
  }
985
 
  delete PRIVATE(this);
986
 
}
987
 
 
988
 
// ************************************************************************
989
 
 
990
 
// doc in super
991
 
void
992
 
SoQtFlyViewer::setViewing(SbBool enable)
993
 
{
994
 
  if (enable != this->isViewing())
995
 
    PRIVATE(this)->stopMoving();
996
 
 
997
 
  inherited::setViewing(enable);
998
 
  this->setSuperimpositionEnabled(PRIVATE(this)->superimposition, enable);
999
 
  this->scheduleRedraw();
1000
 
}
1001
 
 
1002
 
// ************************************************************************
1003
 
 
1004
 
// doc in super
1005
 
void
1006
 
SoQtFlyViewer::resetToHomePosition(void)
1007
 
{
1008
 
  PRIVATE(this)->stopMoving();
1009
 
  inherited::resetToHomePosition();
1010
 
}
1011
 
 
1012
 
// ************************************************************************
1013
 
 
1014
 
// doc in super
1015
 
void
1016
 
SoQtFlyViewer::viewAll(void)
1017
 
{
1018
 
  PRIVATE(this)->stopMoving();
1019
 
  inherited::viewAll();
1020
 
}
1021
 
 
1022
 
// ************************************************************************
1023
 
 
1024
 
// doc in super
1025
 
void
1026
 
SoQtFlyViewer::setCamera(SoCamera * camera)
1027
 
{
1028
 
  PRIVATE(this)->stopMoving();
1029
 
 
1030
 
  inherited::setCamera(camera);
1031
 
  // FIXME: do something with up-direction? 
1032
 
}
1033
 
 
1034
 
// ************************************************************************
1035
 
 
1036
 
// doc in super
1037
 
void
1038
 
SoQtFlyViewer::setCursorEnabled(SbBool enable)
1039
 
{
1040
 
  inherited::setCursorEnabled(enable);
1041
 
  PRIVATE(this)->updateCursorRepresentation();
1042
 
}
1043
 
 
1044
 
// ************************************************************************
1045
 
 
1046
 
// doc in super
1047
 
void
1048
 
SoQtFlyViewer::setCameraType(SoType type)
1049
 
{
1050
 
  PRIVATE(this)->stopMoving();
1051
 
  inherited::setCameraType(type);
1052
 
  // FIXME: what else? 20010907 mortene.
1053
 
}
1054
 
 
1055
 
// ************************************************************************
1056
 
 
1057
 
// doc in super
1058
 
const char *
1059
 
SoQtFlyViewer::getDefaultWidgetName(void) const
1060
 
{
1061
 
  static const char defaultWidgetName[] = "SoQtFlyViewer";
1062
 
  return defaultWidgetName;
1063
 
}
1064
 
 
1065
 
// ************************************************************************
1066
 
 
1067
 
// doc in super
1068
 
const char *
1069
 
SoQtFlyViewer::getDefaultTitle(void) const
1070
 
{
1071
 
  static const char defaultTitle[] = "Fly Viewer";
1072
 
  return defaultTitle;
1073
 
}
1074
 
 
1075
 
// ************************************************************************
1076
 
 
1077
 
// doc in super
1078
 
const char *
1079
 
SoQtFlyViewer::getDefaultIconTitle(void) const
1080
 
{
1081
 
  static const char defaultIconTitle[] = "Fly Viewer";
1082
 
  return defaultIconTitle;
1083
 
}
1084
 
 
1085
 
// ************************************************************************
1086
 
 
1087
 
// Documented in superclass.
1088
 
SbBool
1089
 
SoQtFlyViewer::processSoEvent(const SoEvent * const event)
1090
 
{
1091
 
  // FIXME: Refactor the event-handling so that it uses the same
1092
 
  // strategy as in SoQtExaminerViewer, where the event-handler
1093
 
  // only checks the state and the mode from that. 20021016 rolvs.
1094
 
 
1095
 
  // Let the end-user toggle between camera-interaction mode
1096
 
  // ("viewing") and scenegraph-interaction mode with ALT key(s).
1097
 
  // FIXME: Allow this to be handled by processKeyboardEvent? 
1098
 
  // 20021016 rolvs.
1099
 
  if (event->getTypeId().isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
1100
 
    SoKeyboardEvent * ke = (SoKeyboardEvent *)event;
1101
 
    switch (ke->getKey()) {
1102
 
    case SoKeyboardEvent::LEFT_ALT:
1103
 
    case SoKeyboardEvent::RIGHT_ALT:
1104
 
      if (this->isViewing() && (ke->getState() == SoButtonEvent::DOWN)) {
1105
 
        this->setViewing(FALSE);
1106
 
        return TRUE;
1107
 
      }
1108
 
      else if (!this->isViewing() && (ke->getState() == SoButtonEvent::UP)) {
1109
 
        this->setViewing(TRUE);
1110
 
        return TRUE;
1111
 
      }
1112
 
    default:
1113
 
      break;
1114
 
    }
1115
 
  }
1116
 
 
1117
 
  // We're in "interact" mode (ie *not* the camera modification mode),
1118
 
  // so don't handle the event here. It should either be forwarded to
1119
 
  // the scenegraph, or caught by SoQtViewer::processSoEvent() if
1120
 
  // it's an ESC press (to switch modes).
1121
 
  if (!this->isViewing()) { return inherited::processSoEvent(event); }
1122
 
 
1123
 
  // Events when in "ready-to-seek" mode are ignored, except those
1124
 
  // which influence the seek mode itself -- these are handled further
1125
 
  // up the inheritance hierarchy.
1126
 
  if (this->isSeekMode()) { return inherited::processSoEvent(event); }
1127
 
  
1128
 
  // FIXME: There is more parts of the code in
1129
 
  // SoQt*FlyViewer::processEvent that should go in to the
1130
 
  // processKeyboardEvent function; to be fixed later. 
1131
 
  // 20021015 rolvs
1132
 
 
1133
 
  // Keyboard handling
1134
 
  if (event->isOfType(SoKeyboardEvent::getClassTypeId())) {
1135
 
    SbBool result =
1136
 
      PRIVATE(this)->processKeyboardEvent( (SoKeyboardEvent*)event );
1137
 
 
1138
 
    if( result ){
1139
 
      return TRUE;
1140
 
    }
1141
 
    // Else: Do nothing, and proceed as usual
1142
 
  }
1143
 
 
1144
 
  // Mousebutton handling
1145
 
  // See FIXME and comment for keyboardhandler.
1146
 
  else if (event->isOfType(SoMouseButtonEvent::getClassTypeId())) {
1147
 
    // FIXME: only for fly mode
1148
 
    const SoMouseButtonEvent * const me = 
1149
 
      (const SoMouseButtonEvent *const) event;
1150
 
    SbBool result = PRIVATE( this )->processMouseButtonEvent( me );
1151
 
    if( result ) 
1152
 
      return TRUE;
1153
 
  }
1154
 
 
1155
 
  else if (event->isOfType(SoLocation2Event::getClassTypeId())) {
1156
 
    const SoLocation2Event * const le = 
1157
 
      (const SoLocation2Event * const) event;
1158
 
    SbBool result = PRIVATE( this )->processLocation2Event( le );
1159
 
    if( result ) 
1160
 
      return TRUE;
1161
 
  }
1162
 
 
1163
 
  return inherited::processSoEvent(event);
1164
 
}
1165
 
 
1166
 
// ************************************************************************
1167
 
 
1168
 
// doc in super
1169
 
void
1170
 
SoQtFlyViewer::setSeekMode(SbBool enable)
1171
 
{
1172
 
  // Note: this method is almost identical to the setSeekMode() in the
1173
 
  // SoQtExaminerViewer, so migrate any changes.
1174
 
 
1175
 
#if SOQT_DEBUG
1176
 
  if (enable == this->isSeekMode()) {
1177
 
    SoDebugError::postWarning("SoQtFlyViewer::setSeekMode",
1178
 
                              "seek mode already %sset", enable ? "" : "un");
1179
 
    return;
1180
 
  }
1181
 
#endif // SOQT_DEBUG
1182
 
 
1183
 
  // FIXME: what if we're in the middle of a seek already? 20010910 mortene.
1184
 
  // larsa - either stop the seek (on false) or reset timer to two new secs
1185
 
 
1186
 
  inherited::setSeekMode(enable);
1187
 
  PRIVATE(this)->setMode(enable ? SoQtFlyViewerP::WAITING_FOR_SEEK :
1188
 
                            SoQtFlyViewerP::FLYING);
1189
 
}
1190
 
 
1191
 
// ************************************************************************
1192
 
 
1193
 
// doc in super
1194
 
void
1195
 
SoQtFlyViewer::actualRedraw(void)
1196
 
{
1197
 
  if (!this->isViewing()) {
1198
 
    inherited::actualRedraw();
1199
 
    return;
1200
 
  }
1201
 
 
1202
 
  switch (PRIVATE(this)->getMode()) {
1203
 
  case SoQtFlyViewerP::FLYING:
1204
 
    {
1205
 
      float dt = PRIVATE(this)->calculateChangeInTime();
1206
 
      PRIVATE(this)->updateCurrentSpeed( dt );
1207
 
 
1208
 
      PRIVATE(this)->updateSpeedIndicator();
1209
 
 
1210
 
      SbTime thisrender; 
1211
 
      thisrender.setToTimeOfDay();
1212
 
 
1213
 
      if (PRIVATE(this)->currentspeed != 0.0f) {
1214
 
        float t = float(thisrender.getValue() -
1215
 
                        PRIVATE(this)->lastrender->getValue()) * 2.0f;
1216
 
        if (t > 0.0f) {
1217
 
          SoCamera * camera = this->getCamera();
1218
 
 
1219
 
          if (camera){ // could be a sceneless viewer
1220
 
            PRIVATE(this)->updateCameraPosition
1221
 
              ( camera,
1222
 
                PRIVATE(this)->currentspeed*
1223
 
                PRIVATE(this)->speed_scaling_factor,
1224
 
                t );
1225
 
            PRIVATE(this)->updateCameraOrientation
1226
 
              ( camera, 
1227
 
                PRIVATE(this)->tilt_increment, 
1228
 
                PRIVATE(this)->pan_increment, 
1229
 
                t );
1230
 
          }
1231
 
        }
1232
 
      }
1233
 
      
1234
 
      inherited::actualRedraw();
1235
 
      
1236
 
      PRIVATE(this)->lastrender->setValue(thisrender.getValue());
1237
 
      
1238
 
      if (PRIVATE(this)->currentspeed != 0.0f ||
1239
 
          PRIVATE(this)->maxspeed != 0.0f)
1240
 
        this->scheduleRedraw();
1241
 
    }
1242
 
    break;
1243
 
  default:
1244
 
    inherited::actualRedraw();
1245
 
    break;
1246
 
  }
1247
 
}
1248
 
 
1249
 
// ************************************************************************
1250
 
 
1251
 
// doc in super
1252
 
void
1253
 
SoQtFlyViewer::rightWheelMotion(float value)
1254
 
{
1255
 
  PRIVATE(this)->dolly(value - this->getRightWheelValue());
1256
 
  inherited::rightWheelMotion(value);
1257
 
}
1258
 
 
1259
 
// ************************************************************************
1260
 
 
1261
 
// doc in super
1262
 
void
1263
 
SoQtFlyViewer::afterRealizeHook(void)
1264
 
{
1265
 
  PRIVATE(this)->updateCursorRepresentation();
1266
 
  inherited::afterRealizeHook();
1267
 
}
1268
 
 
1269
 
// ************************************************************************
1270
 
 
1271
 
#undef PRIVATE
1272
 
#undef PUBLIC
1273