00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "domUtils.h"
00024 #include "qglviewer.h"
00025 #include "camera.h"
00026 #include "keyFrameInterpolator.h"
00027
00028 #if QT_VERSION >= 0x040000
00029 # include <QtAlgorithms>
00030 # include <QTextEdit>
00031 # include <QApplication>
00032 # include <QFileInfo>
00033 # include <QDateTime>
00034 # include <QMessageBox>
00035 # include <QPushButton>
00036 # include <QTabWidget>
00037 # include <QTextStream>
00038 # include <QMouseEvent>
00039 # include <QTimer>
00040 # include <QImage>
00041 # include <QDir>
00042 # include <QUrl>
00043 #else
00044 # include <qapplication.h>
00045 # include <qfileinfo.h>
00046 # include <qdatetime.h>
00047 # include <qmessagebox.h>
00048 # include <qpushbutton.h>
00049 # include <qtabwidget.h>
00050 # include <qtextstream.h>
00051 # include <qtimer.h>
00052 # include <qimage.h>
00053 # include <qtextedit.h>
00054 # include <qkeysequence.h>
00055 # include <qdir.h>
00056
00057 # define KeyboardModifierMask KeyButtonMask
00058
00059 # define value data
00060 #endif
00061
00062 using namespace std;
00063 using namespace qglviewer;
00064
00065
00066 #if QT_VERSION >= 0x040000
00067 QList<QGLViewer*> QGLViewer::QGLViewerPool_;
00068 #else
00069 QPtrList<QGLViewer> QGLViewer::QGLViewerPool_;
00070 #endif
00071
00072
00090 void QGLViewer::defaultConstructor()
00091 {
00092
00093
00094
00095
00096
00097 updateGLOK_ = false;
00098
00099
00100
00101
00102
00103 #if QT_VERSION >= 0x040000
00104 int poolIndex = QGLViewer::QGLViewerPool_.indexOf(NULL);
00105 setFocusPolicy(Qt::StrongFocus);
00106 #else
00107 int poolIndex = QGLViewer::QGLViewerPool_.findRef(NULL);
00108 setFocusPolicy(QWidget::StrongFocus);
00109 #endif
00110
00111 if (poolIndex >= 0)
00112 QGLViewer::QGLViewerPool_.replace(poolIndex, this);
00113 else
00114 QGLViewer::QGLViewerPool_.append(this);
00115
00116 camera_ = new Camera();
00117 setCamera(camera());
00118
00119 setDefaultShortcuts();
00120 setDefaultMouseBindings();
00121
00122 setSnapshotFileName(tr("snapshot", "Default snapshot file name"));
00123 initializeSnapshotFormats();
00124 setSnapshotCounter(0);
00125 setSnapshotQuality(95);
00126
00127 fpsTime_.start();
00128 fpsCounter_ = 0;
00129 f_p_s_ = 0.0;
00130 fpsString_ = tr("%1Hz", "Frames per seconds, in Hertz").arg("?");
00131 visualHint_ = 0;
00132 previousPathId_ = 0;
00133
00134
00135
00136 manipulatedFrame_ = NULL;
00137 manipulatedFrameIsACamera_ = false;
00138 mouseGrabberIsAManipulatedFrame_ = false;
00139 mouseGrabberIsAManipulatedCameraFrame_ = false;
00140 displayMessage_ = false;
00141 connect(&messageTimer_, SIGNAL(timeout()), SLOT(hideMessage()));
00142 #if QT_VERSION >= 0x040000
00143 messageTimer_.setSingleShot(true);
00144 #endif
00145 helpWidget_ = NULL;
00146 setMouseGrabber(NULL);
00147
00148 setSceneRadius(1.0);
00149 showEntireScene();
00150 setStateFileName(".qglviewer.xml");
00151
00152
00153 setAxisIsDrawn(false);
00154 setGridIsDrawn(false);
00155 setFPSIsDisplayed(false);
00156 setCameraIsEdited(false);
00157 setTextIsEnabled(true);
00158 setStereoDisplay(false);
00159 setFullScreen(false);
00160
00161 animationTimerId_ = 0;
00162 stopAnimation();
00163 setAnimationPeriod(40);
00164
00165 selectBuffer_ = NULL;
00166 setSelectBufferSize(4*1000);
00167 setSelectRegionWidth(3);
00168 setSelectRegionHeight(3);
00169 setSelectedName(-1);
00170
00171 bufferTextureId_ = 0;
00172 bufferTextureMaxU_ = 0.0;
00173 bufferTextureMaxV_ = 0.0;
00174 bufferTextureWidth_ = 0;
00175 bufferTextureHeight_ = 0;
00176 previousBufferTextureFormat_ = 0;
00177 previousBufferTextureInternalFormat_ = 0;
00178
00179 #if QT_VERSION >= 0x040000
00180 setAttribute(Qt::WA_NoSystemBackground);
00181 #endif
00182
00183 tileRegion_ = NULL;
00184 }
00185
00186 #if QT_VERSION >= 0x040000 && !defined QT3_SUPPORT
00187
00194 QGLViewer::QGLViewer(QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags flags)
00195 : QGLWidget(parent, shareWidget, flags)
00196 { defaultConstructor(); }
00197
00203 QGLViewer::QGLViewer(QGLContext *context, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags flags)
00204 : QGLWidget(context, parent, shareWidget, flags)
00205 { defaultConstructor(); }
00206
00211 QGLViewer::QGLViewer(const QGLFormat& format, QWidget* parent, const QGLWidget* shareWidget, Qt::WindowFlags flags)
00212 : QGLWidget(format, parent, shareWidget, flags)
00213 { defaultConstructor(); }
00214 #endif
00215
00220 QGLViewer::~QGLViewer()
00221 {
00222
00223
00224
00225
00226
00227 #if QT_VERSION >= 0x040000
00228 QGLViewer::QGLViewerPool_.replace(QGLViewer::QGLViewerPool_.indexOf(this), NULL);
00229 #else
00230 QGLViewer::QGLViewerPool_.replace(QGLViewer::QGLViewerPool_.findRef(this), NULL);
00231 #endif
00232
00233 delete camera();
00234 delete[] selectBuffer_;
00235 if (helpWidget())
00236 {
00237
00238 helpWidget()->close();
00239 delete helpWidget_;
00240 }
00241 }
00242
00243
00244 static QString QGLViewerVersionString()
00245 {
00246 return QString::number((QGLVIEWER_VERSION & 0xff0000) >> 16) + "." +
00247 QString::number((QGLVIEWER_VERSION & 0x00ff00) >> 8) + "." +
00248 QString::number(QGLVIEWER_VERSION & 0x0000ff);
00249 }
00250
00251 static int convertToKeyboardModifiers(int state)
00252 {
00253 #if QT_VERSION < 0x040000
00254
00255
00256 if (state & Qt::MODIFIER_MASK)
00257 {
00258 if (state & Qt::CTRL) { state &= ~Qt::CTRL; state |= Qt::ControlButton; }
00259 if (state & Qt::SHIFT) { state &= ~Qt::SHIFT; state |= Qt::ShiftButton; }
00260 if (state & Qt::ALT) { state &= ~Qt::ALT; state |= Qt::AltButton; }
00261 # if QT_VERSION >= 0x030100
00262 if (state & Qt::META) { state &= ~Qt::META; state |= Qt::MetaButton; }
00263 # endif
00264 }
00265 #endif
00266 return state;
00267 }
00268
00269 static Qt::KeyboardModifiers convertKeyboardModifiers(Qt::KeyboardModifiers modifiers)
00270 {
00271 #if QT_VERSION < 0x040000
00272 return Qt::KeyboardModifiers(convertToKeyboardModifiers(modifiers));
00273 #else
00274 return modifiers;
00275 #endif
00276 }
00277
00278 static int convertToShortModifier(int state)
00279 {
00280
00281
00282 #if QT_VERSION < 0x040000
00283 if (state & Qt::KeyButtonMask)
00284 {
00285 if (state & Qt::ControlButton) { state &= ~Qt::ControlButton; state |= Qt::CTRL; }
00286 if (state & Qt::ShiftButton) { state &= ~Qt::ShiftButton; state |= Qt::SHIFT; }
00287 if (state & Qt::AltButton) { state &= ~Qt::AltButton; state |= Qt::ALT; }
00288 # if QT_VERSION >= 0x030100
00289 if (state & Qt::MetaButton) { state &= ~Qt::MetaButton; state |= Qt::META; }
00290 # endif
00291 }
00292 #endif
00293 return state;
00294 }
00295
00314 void QGLViewer::initializeGL()
00315 {
00316 if (updateGLOK_)
00317 qWarning("Internal debug: initializeGL() is called in QGLViewer constructor.");
00318
00319 glEnable(GL_LIGHT0);
00320 glEnable(GL_LIGHTING);
00321 glEnable(GL_DEPTH_TEST);
00322 glEnable(GL_COLOR_MATERIAL);
00323
00324
00325 setForegroundColor(QColor(180, 180, 180));
00326 setBackgroundColor(QColor(51, 51, 51));
00327
00328
00329 if (format().stereo())
00330 {
00331 glDrawBuffer(GL_BACK_RIGHT);
00332 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00333 glDrawBuffer(GL_BACK_LEFT);
00334 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00335 }
00336 else
00337 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00338
00339
00340 init();
00341
00342
00343 if (isFullScreen())
00344 QTimer::singleShot( 100, this, SLOT(delayedFullScreen()) );
00345
00346 updateGLOK_ = true;
00347 }
00348
00355 void QGLViewer::paintGL()
00356 {
00357 updateGLOK_ = false;
00358 if (displaysInStereo())
00359 {
00360 for (int view=1; view>=0; --view)
00361 {
00362
00363 preDrawStereo(view);
00364
00365 if (camera()->frame()->isManipulated())
00366 fastDraw();
00367 else
00368 draw();
00369 postDraw();
00370 }
00371 }
00372 else
00373 {
00374
00375 preDraw();
00376
00377 if (camera()->frame()->isManipulated())
00378 fastDraw();
00379 else
00380 draw();
00381
00382 postDraw();
00383 }
00384 updateGLOK_ = true;
00385 Q_EMIT drawFinished(true);
00386 }
00387
00399 void QGLViewer::preDraw()
00400 {
00401 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00402
00403
00404 camera()->loadProjectionMatrix();
00405
00406 camera()->loadModelViewMatrix();
00407
00408 Q_EMIT drawNeeded();
00409 }
00410
00421 void QGLViewer::postDraw()
00422 {
00423
00424 glMatrixMode(GL_MODELVIEW);
00425 glPushMatrix();
00426 camera()->loadModelViewMatrix();
00427
00428
00429
00430 glPushAttrib(GL_ALL_ATTRIB_BITS);
00431
00432
00433 glDisable(GL_TEXTURE_1D);
00434 glDisable(GL_TEXTURE_2D);
00435 #ifdef GL_TEXTURE_3D // OpenGL 1.2 Only...
00436 glDisable(GL_TEXTURE_3D);
00437 #endif
00438
00439 glDisable(GL_TEXTURE_GEN_Q);
00440 glDisable(GL_TEXTURE_GEN_R);
00441 glDisable(GL_TEXTURE_GEN_S);
00442 glDisable(GL_TEXTURE_GEN_T);
00443
00444 #ifdef GL_RESCALE_NORMAL // OpenGL 1.2 Only...
00445 glEnable(GL_RESCALE_NORMAL);
00446 #endif
00447
00448 glDisable(GL_COLOR_MATERIAL);
00449 qglColor(foregroundColor());
00450
00451 if (cameraIsEdited())
00452 camera()->drawAllPaths();
00453
00454
00455 drawVisualHints();
00456
00457 if (gridIsDrawn()) { glLineWidth(1.0); drawGrid(camera()->sceneRadius()); }
00458 if (axisIsDrawn()) { glLineWidth(2.0); drawAxis(camera()->sceneRadius()); }
00459
00460
00461 const unsigned int maxCounter = 20;
00462 if (++fpsCounter_ == maxCounter)
00463 {
00464 f_p_s_ = 1000.0 * maxCounter / fpsTime_.restart();
00465 fpsString_ = tr("%1Hz", "Frames per seconds, in Hertz").arg(f_p_s_, 0, 'f', ((f_p_s_ < 10.0)?1:0));
00466 fpsCounter_ = 0;
00467 }
00468
00469
00470 float color[4];
00471 color[0] = foregroundColor().red() / 255.0;
00472 color[1] = foregroundColor().green() / 255.0;
00473 color[2] = foregroundColor().blue() / 255.0;
00474 color[3] = 1.0;
00475 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
00476 glDisable(GL_LIGHTING);
00477 glDisable(GL_DEPTH_TEST);
00478
00479 if (FPSIsDisplayed()) displayFPS();
00480 if (displayMessage_) drawText(10, height()-10, message_);
00481
00482
00483 glPopAttrib();
00484 glPopMatrix();
00485 }
00486
00492 void QGLViewer::preDrawStereo(bool leftBuffer)
00493 {
00494
00495
00496
00497 if (!leftBuffer)
00498 glDrawBuffer(GL_BACK_LEFT);
00499 else
00500 glDrawBuffer(GL_BACK_RIGHT);
00501
00502
00503 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
00504
00505 camera()->loadProjectionMatrixStereo(leftBuffer);
00506
00507 camera()->loadModelViewMatrixStereo(leftBuffer);
00508
00509 Q_EMIT drawNeeded();
00510 }
00511
00519 void QGLViewer::fastDraw()
00520 {
00521 draw();
00522 }
00523
00531 void QGLViewer::setCameraIsEdited(bool edit)
00532 {
00533 cameraIsEdited_ = edit;
00534 if (edit)
00535 {
00536 previousCameraZClippingCoefficient_ = camera()->zClippingCoefficient();
00537
00538 camera()->setZClippingCoefficient(5.0);
00539 }
00540 else
00541 camera()->setZClippingCoefficient(previousCameraZClippingCoefficient_);
00542
00543 Q_EMIT cameraIsEditedChanged(edit);
00544
00545 if (updateGLOK_)
00546 updateGL();
00547 }
00548
00549
00550 void QGLViewer::setDefaultShortcuts()
00551 {
00552
00553 setShortcut(DRAW_AXIS, Qt::Key_A);
00554 setShortcut(DRAW_GRID, Qt::Key_G);
00555 setShortcut(DISPLAY_FPS, Qt::Key_F);
00556 setShortcut(ENABLE_TEXT, Qt::SHIFT+Qt::Key_Question);
00557 setShortcut(EXIT_VIEWER, Qt::Key_Escape);
00558 setShortcut(SAVE_SCREENSHOT, Qt::CTRL+Qt::Key_S);
00559 setShortcut(CAMERA_MODE, Qt::Key_Space);
00560 setShortcut(FULL_SCREEN, Qt::ALT+Qt::Key_Return);
00561 setShortcut(STEREO, Qt::Key_S);
00562 setShortcut(ANIMATION, Qt::Key_Return);
00563 setShortcut(HELP, Qt::Key_H);
00564 setShortcut(EDIT_CAMERA, Qt::Key_C);
00565 setShortcut(MOVE_CAMERA_LEFT, Qt::Key_Left);
00566 setShortcut(MOVE_CAMERA_RIGHT,Qt::Key_Right);
00567 setShortcut(MOVE_CAMERA_UP, Qt::Key_Up);
00568 setShortcut(MOVE_CAMERA_DOWN, Qt::Key_Down);
00569 setShortcut(INCREASE_FLYSPEED,Qt::Key_Plus);
00570 setShortcut(DECREASE_FLYSPEED,Qt::Key_Minus);
00571 setShortcut(SNAPSHOT_TO_CLIPBOARD,Qt::CTRL+Qt::Key_C);
00572
00573 keyboardActionDescription_[DISPLAY_FPS] = tr("Toggles the display of the FPS", "DISPLAY_FPS action description");
00574 keyboardActionDescription_[SAVE_SCREENSHOT] = tr("Saves a screenshot", "SAVE_SCREENSHOT action description");
00575 keyboardActionDescription_[FULL_SCREEN] = tr("Toggles full screen display", "FULL_SCREEN action description");
00576 keyboardActionDescription_[DRAW_AXIS] = tr("Toggles the display of the world axis", "DRAW_AXIS action description");
00577 keyboardActionDescription_[DRAW_GRID] = tr("Toggles the display of the XY grid", "DRAW_GRID action description");
00578 keyboardActionDescription_[CAMERA_MODE] = tr("Changes camera mode (revolve or fly)", "CAMERA_MODE action description");
00579 keyboardActionDescription_[STEREO] = tr("Toggles stereo display", "STEREO action description");
00580 keyboardActionDescription_[HELP] = tr("Opens this help window", "HELP action description");
00581 keyboardActionDescription_[ANIMATION] = tr("Starts/stops the animation", "ANIMATION action description");
00582 keyboardActionDescription_[EDIT_CAMERA] = tr("Toggles camera paths display", "EDIT_CAMERA action description");
00583 keyboardActionDescription_[ENABLE_TEXT] = tr("Toggles the display of the text", "ENABLE_TEXT action description");
00584 keyboardActionDescription_[EXIT_VIEWER] = tr("Exits program", "EXIT_VIEWER action description");
00585 keyboardActionDescription_[MOVE_CAMERA_LEFT] = tr("Moves camera left", "MOVE_CAMERA_LEFT action description");
00586 keyboardActionDescription_[MOVE_CAMERA_RIGHT] = tr("Moves camera right", "MOVE_CAMERA_RIGHT action description");
00587 keyboardActionDescription_[MOVE_CAMERA_UP] = tr("Moves camera up", "MOVE_CAMERA_UP action description");
00588 keyboardActionDescription_[MOVE_CAMERA_DOWN] = tr("Moves camera down", "MOVE_CAMERA_DOWN action description");
00589 keyboardActionDescription_[INCREASE_FLYSPEED] = tr("Increases fly speed", "INCREASE_FLYSPEED action description");
00590 keyboardActionDescription_[DECREASE_FLYSPEED] = tr("Decreases fly speed", "DECREASE_FLYSPEED action description");
00591 keyboardActionDescription_[SNAPSHOT_TO_CLIPBOARD] = tr("Copies a snapshot to clipboard", "SNAPSHOT_TO_CLIPBOARD action description");
00592
00593
00594 setPathKey(Qt::Key_F1, 1);
00595 setPathKey(Qt::Key_F2, 2);
00596 setPathKey(Qt::Key_F3, 3);
00597 setPathKey(Qt::Key_F4, 4);
00598 setPathKey(Qt::Key_F5, 5);
00599 setPathKey(Qt::Key_F6, 6);
00600 setPathKey(Qt::Key_F7, 7);
00601 setPathKey(Qt::Key_F8, 8);
00602 setPathKey(Qt::Key_F9, 9);
00603 setPathKey(Qt::Key_F10, 10);
00604 setPathKey(Qt::Key_F11, 11);
00605 setPathKey(Qt::Key_F12, 12);
00606
00607 #if QT_VERSION >= 0x040000
00608 setAddKeyFrameKeyboardModifiers(Qt::AltModifier);
00609 setPlayPathKeyboardModifiers(Qt::NoModifier);
00610 #else
00611 setAddKeyFrameKeyboardModifiers(Qt::AltButton);
00612 setPlayPathKeyboardModifiers(Qt::NoButton);
00613 #endif
00614 }
00615
00616
00617 void QGLViewer::setDefaultMouseBindings()
00618 {
00619 #if QT_VERSION >= 0x040000
00620 const Qt::KeyboardModifiers cameraKeyboardModifiers = Qt::NoModifier;
00621 const Qt::KeyboardModifiers frameKeyboardModifiers = Qt::ControlModifier;
00622 #else
00623 const Qt::KeyboardModifiers cameraKeyboardModifiers = Qt::NoButton;
00624 const Qt::KeyboardModifiers frameKeyboardModifiers = Qt::ControlButton;
00625 #endif
00626
00627 for (int handler=0; handler<2; ++handler)
00628 {
00629 MouseHandler mh = (MouseHandler)(handler);
00630 Qt::KeyboardModifiers modifiers = (mh == FRAME) ? frameKeyboardModifiers : cameraKeyboardModifiers;
00631
00632 setMouseBinding(modifiers | Qt::LeftButton, mh, ROTATE);
00633 setMouseBinding(modifiers | Qt::MidButton, mh, ZOOM);
00634 setMouseBinding(modifiers | Qt::RightButton, mh, TRANSLATE);
00635
00636 setMouseBinding(modifiers | Qt::LeftButton | Qt::MidButton, mh, SCREEN_ROTATE);
00637
00638
00639 setWheelBinding(modifiers, mh, ZOOM);
00640 }
00641
00642 #if QT_VERSION >= 0x040000
00643
00644 setMouseBinding(Qt::SHIFT + Qt::MidButton, CAMERA, ZOOM_ON_REGION);
00645
00646 setMouseBinding(Qt::SHIFT + Qt::LeftButton, SELECT);
00647 #else
00648 setMouseBinding(Qt::SHIFT + Qt::MidButton, CAMERA, ZOOM_ON_REGION);
00649 setMouseBinding(Qt::SHIFT + Qt::LeftButton, SELECT);
00650 #endif
00651
00652
00653 setMouseBinding(Qt::LeftButton, ALIGN_CAMERA, true);
00654 setMouseBinding(Qt::MidButton, SHOW_ENTIRE_SCENE, true);
00655 setMouseBinding(Qt::RightButton, CENTER_SCENE, true);
00656
00657 setMouseBinding(frameKeyboardModifiers | Qt::LeftButton, ALIGN_FRAME, true);
00658 setMouseBinding(frameKeyboardModifiers | Qt::RightButton, CENTER_FRAME, true);
00659
00660
00661 setMouseBinding(Qt::LeftButton, RAP_FROM_PIXEL, true, Qt::RightButton);
00662 setMouseBinding(Qt::RightButton, RAP_IS_CENTER, true, Qt::LeftButton);
00663 setMouseBinding(Qt::LeftButton, ZOOM_ON_PIXEL, true, Qt::MidButton);
00664 setMouseBinding(Qt::RightButton, ZOOM_TO_FIT, true, Qt::MidButton);
00665
00666 #ifdef Q_OS_MAC
00667
00668
00669
00670 # if QT_VERSION >= 0x040000
00671 const Qt::KeyboardModifiers macKeyboardModifiers = Qt::AltModifier;
00672 # else
00673 const Qt::KeyboardModifiers macKeyboardModifiers = Qt::AltButton;
00674 # endif
00675
00676 setMouseBinding(macKeyboardModifiers | Qt::LeftButton, CAMERA, TRANSLATE);
00677 setMouseBinding(macKeyboardModifiers | Qt::LeftButton, CENTER_SCENE, true);
00678 setMouseBinding(frameKeyboardModifiers | macKeyboardModifiers | Qt::LeftButton, CENTER_FRAME, true);
00679 setMouseBinding(frameKeyboardModifiers | macKeyboardModifiers | Qt::LeftButton, FRAME, TRANSLATE);
00680
00681
00682
00683 setMouseBinding(Qt::META + Qt::RightButton, RAP_FROM_PIXEL, true, Qt::LeftButton);
00684 setMouseBinding(Qt::SHIFT + Qt::META + Qt::RightButton, RAP_IS_CENTER, true, Qt::LeftButton);
00685
00686 setMouseBinding(Qt::META + Qt::RightButton, ZOOM_ON_PIXEL, false);
00687 setMouseBinding(Qt::SHIFT + Qt::MetaModifier | Qt::RightButton, ZOOM_TO_FIT, false);
00688 #endif
00689 }
00690
00707 void QGLViewer::setCamera(Camera* const camera)
00708 {
00709 if (!camera)
00710 return;
00711
00712 camera->setSceneRadius(sceneRadius());
00713 camera->setSceneCenter(sceneCenter());
00714 camera->setScreenWidthAndHeight(width(),height());
00715
00716
00717 disconnect(this->camera()->frame(), SIGNAL(manipulated()), this, SLOT(updateGL()));
00718 disconnect(this->camera()->frame(), SIGNAL(spun()), this, SLOT(updateGL()));
00719
00720
00721 connect(camera->frame(), SIGNAL(manipulated()), SLOT(updateGL()));
00722 connect(camera->frame(), SIGNAL(spun()), SLOT(updateGL()));
00723
00724 connectAllCameraKFIInterpolatedSignals(false);
00725 camera_ = camera;
00726 connectAllCameraKFIInterpolatedSignals();
00727
00728 previousCameraZClippingCoefficient_ = this->camera()->zClippingCoefficient();
00729 }
00730
00731 void QGLViewer::connectAllCameraKFIInterpolatedSignals(bool connection)
00732 {
00733 for (QMap<int, KeyFrameInterpolator*>::ConstIterator it = camera()->kfi_.begin(), end=camera()->kfi_.end(); it != end; ++it)
00734 {
00735 if (connection)
00736 connect(camera()->keyFrameInterpolator(it.key()), SIGNAL(interpolated()), SLOT(updateGL()));
00737 else
00738 disconnect(camera()->keyFrameInterpolator(it.key()), SIGNAL(interpolated()), this, SLOT(updateGL()));
00739 }
00740
00741 if (connection)
00742 connect(camera()->interpolationKfi_, SIGNAL(interpolated()), SLOT(updateGL()));
00743 else
00744 disconnect(camera()->interpolationKfi_, SIGNAL(interpolated()), this, SLOT(updateGL()));
00745 }
00746
00763 void QGLViewer::drawLight(GLenum light, float scale) const
00764 {
00765 static GLUquadric* quadric = gluNewQuadric();
00766
00767 const float length = sceneRadius() / 5.0 * scale;
00768
00769 GLboolean lightIsOn;
00770 glGetBooleanv(light, &lightIsOn);
00771
00772 if (lightIsOn)
00773 {
00774
00775 glPushMatrix();
00776 glLoadIdentity();
00777
00778 float color[4];
00779 glGetLightfv(light, GL_DIFFUSE, color);
00780 glColor4fv(color);
00781
00782 float pos[4];
00783 glGetLightfv(light, GL_POSITION, pos);
00784
00785 if (pos[3] != 0.0)
00786 {
00787 glTranslatef(pos[0]/pos[3], pos[1]/pos[3], pos[2]/pos[3]);
00788
00789 GLfloat cutOff;
00790 glGetLightfv(light, GL_SPOT_CUTOFF, &cutOff);
00791 if (cutOff != 180.0)
00792 {
00793 GLfloat dir[4];
00794 glGetLightfv(light, GL_SPOT_DIRECTION, dir);
00795 glMultMatrixd(Quaternion(Vec(0,0,1), Vec(dir)).matrix());
00796 QGLViewer::drawArrow(length);
00797 gluCylinder(quadric, 0.0, 0.7 * length * sin(cutOff * M_PI / 180.0), 0.7 * length * cos(cutOff * M_PI / 180.0), 12, 1);
00798 }
00799 else
00800 gluSphere(quadric, 0.2*length, 10, 10);
00801 }
00802 else
00803 {
00804
00805 Vec dir(pos[0], pos[1], pos[2]);
00806 dir.normalize();
00807 Frame fr=Frame(camera()->cameraCoordinatesOf(4.0 * length * camera()->frame()->inverseTransformOf(dir)),
00808 Quaternion(Vec(0,0,-1), dir));
00809 glMultMatrixd(fr.matrix());
00810 drawArrow(length);
00811 }
00812
00813 glPopMatrix();
00814 }
00815 }
00816
00817
00860 void QGLViewer::drawText(int x, int y, const QString& text, const QFont& fnt)
00861 {
00862 if (!textIsEnabled())
00863 return;
00864
00865 #if QT_VERSION < QGLVIEWER_QT_VERSION_WITHOUT_GLUT
00866 const GLfloat font_scale = 119.05f - 33.33f;
00867
00868 startScreenCoordinatesSystem();
00869
00870
00871 glPushAttrib(GL_ALL_ATTRIB_BITS);
00872 glDisable(GL_LIGHTING);
00873 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00874 glEnable(GL_BLEND);
00875 glDisable(GL_DEPTH_TEST);
00876 glEnable(GL_LINE_SMOOTH);
00877 glLineWidth(1.0);
00878
00879 glTranslatef((GLfloat)x, (GLfloat)y, 0.0);
00880 const GLfloat scale = ((fnt.pixelSize()>0)?fnt.pixelSize():fnt.pointSize()) / font_scale;
00881 glScalef(scale, -scale, scale);
00882
00883 for (uint i=0; i<text.length(); ++i)
00884 glutStrokeCharacter(GLUT_STROKE_ROMAN, text.at(i));
00885
00886 glPopAttrib();
00887
00888 stopScreenCoordinatesSystem();
00889 #else
00890
00891 # if QT_VERSION < 0x030300 && defined Q_OS_UNIX
00892
00893 QFont newFont(fnt);
00894 newFont.setFamily("fixed");
00895 newFont.setRawMode(true);
00896 newFont.setPixelSize(10);
00897 newFont.setFixedPitch(true);
00898 # if QT_VERSION >= 0x030200
00899 newFont.setStyleStrategy(QFont::OpenGLCompatible);
00900 # endif
00901 newFont.setStyleHint(QFont::AnyStyle, QFont::PreferBitmap);
00902 renderText(x, y, text, newFont);
00903 # else
00904 if (tileRegion_ != NULL) {
00905 renderText((x-tileRegion_->xMin) * width() / (tileRegion_->xMax - tileRegion_->xMin),
00906 (y-tileRegion_->yMin) * height() / (tileRegion_->yMax - tileRegion_->yMin), text, scaledFont(fnt));
00907 } else
00908 renderText(x, y, text, fnt);
00909 # endif
00910
00911 #endif
00912 }
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00992 void QGLViewer::displayMessage(const QString& message, int delay)
00993 {
00994 message_ = message;
00995 displayMessage_ = true;
00996 #if QT_VERSION >= 0x040000
00997
00998 messageTimer_.start(delay);
00999 #else
01000 if (messageTimer_.isActive())
01001 messageTimer_.changeInterval(delay);
01002 else
01003 messageTimer_.start(delay, true);
01004 #endif
01005 if (textIsEnabled() && updateGLOK_)
01006 updateGL();
01007 }
01008
01009 void QGLViewer::hideMessage()
01010 {
01011 displayMessage_ = false;
01012 if (textIsEnabled())
01013 updateGL();
01014 }
01015
01016
01026 void QGLViewer::displayFPS()
01027 {
01028 drawText(10, int(1.5*((QApplication::font().pixelSize()>0)?QApplication::font().pixelSize():QApplication::font().pointSize())), fpsString_);
01029 }
01030
01062 void QGLViewer::startScreenCoordinatesSystem(bool upward) const
01063 {
01064 glMatrixMode(GL_PROJECTION);
01065 glPushMatrix();
01066 glLoadIdentity();
01067 if (tileRegion_ != NULL)
01068 if (upward)
01069 glOrtho(tileRegion_->xMin, tileRegion_->xMax, tileRegion_->yMin, tileRegion_->yMax, 0.0, -1.0);
01070 else
01071 glOrtho(tileRegion_->xMin, tileRegion_->xMax, tileRegion_->yMax, tileRegion_->yMin, 0.0, -1.0);
01072 else
01073 if (upward)
01074 glOrtho(0, width(), 0, height(), 0.0, -1.0);
01075 else
01076 glOrtho(0, width(), height(), 0, 0.0, -1.0);
01077
01078 glMatrixMode(GL_MODELVIEW);
01079 glPushMatrix();
01080 glLoadIdentity();
01081 }
01082
01087 void QGLViewer::stopScreenCoordinatesSystem() const
01088 {
01089 glMatrixMode(GL_PROJECTION);
01090 glPopMatrix();
01091
01092 glMatrixMode(GL_MODELVIEW);
01093 glPopMatrix();
01094 }
01095
01099 void QGLViewer::timerEvent(QTimerEvent *)
01100 {
01101 if (animationIsStarted())
01102 {
01103 animate();
01104 updateGL();
01105 }
01106 }
01107
01109 void QGLViewer::startAnimation()
01110 {
01111 animationTimerId_ = startTimer(animationPeriod());
01112 animationStarted_ = true;
01113 }
01114
01116 void QGLViewer::stopAnimation()
01117 {
01118 animationStarted_ = false;
01119 if (animationTimerId_ != 0)
01120 killTimer(animationTimerId_);
01121 }
01122
01126 void QGLViewer::closeEvent(QCloseEvent *e)
01127 {
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01144
01145
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156
01157
01158 saveStateToFile();
01159 QGLWidget::closeEvent(e);
01160 }
01161
01171 void QGLViewer::select(const QMouseEvent* event)
01172 {
01173
01174 Q_EMIT pointSelected(event);
01175 select(event->pos());
01176 }
01177
01228 void QGLViewer::select(const QPoint& point)
01229 {
01230 beginSelection(point);
01231 drawWithNames();
01232 endSelection(point);
01233 postSelection(point);
01234 }
01235
01247 void QGLViewer::beginSelection(const QPoint& point)
01248 {
01249
01250 makeCurrent();
01251
01252
01253 glSelectBuffer(selectBufferSize(), selectBuffer());
01254 glRenderMode(GL_SELECT);
01255 glInitNames();
01256
01257
01258 glMatrixMode(GL_PROJECTION);
01259 glLoadIdentity();
01260 static GLint viewport[4];
01261 camera()->getViewport(viewport);
01262 gluPickMatrix(point.x(), point.y(), selectRegionWidth(), selectRegionHeight(), viewport);
01263
01264
01265
01266 camera()->loadProjectionMatrix(false);
01267
01268 camera()->loadModelViewMatrix();
01269 }
01270
01307 void QGLViewer::endSelection(const QPoint& point)
01308 {
01309 Q_UNUSED(point);
01310
01311
01312 glFlush();
01313
01314
01315 GLint nbHits = glRenderMode(GL_RENDER);
01316
01317 if (nbHits <= 0)
01318 setSelectedName(-1);
01319 else
01320 {
01321
01322
01323
01324
01325 GLuint zMin = (selectBuffer())[1];
01326 setSelectedName((selectBuffer())[3]);
01327 for (int i=1; i<nbHits; ++i)
01328 if ((selectBuffer())[4*i+1] < zMin)
01329 {
01330 zMin = (selectBuffer())[4*i+1];
01331 setSelectedName((selectBuffer())[4*i+3]);
01332 }
01333 }
01334 }
01335
01339 void QGLViewer::setSelectBufferSize(int size)
01340 {
01341 if (selectBuffer_)
01342 delete[] selectBuffer_;
01343 selectBufferSize_ = size;
01344 selectBuffer_ = new GLuint[selectBufferSize()];
01345 }
01346
01347 void QGLViewer::performClickAction(ClickAction ca, const QMouseEvent* const e)
01348 {
01349
01350 switch (ca)
01351 {
01352
01353
01354 case NO_CLICK_ACTION :
01355 break;
01356 case ZOOM_ON_PIXEL :
01357 camera()->interpolateToZoomOnPixel(e->pos());
01358 break;
01359 case ZOOM_TO_FIT :
01360 camera()->interpolateToFitScene();
01361 break;
01362 case SELECT :
01363 select(e);
01364 updateGL();
01365 break;
01366 case RAP_FROM_PIXEL :
01367 if (camera()->setRevolveAroundPointFromPixel(e->pos()))
01368 {
01369 setVisualHintsMask(1);
01370 updateGL();
01371 }
01372 break;
01373 case RAP_IS_CENTER :
01374 camera()->setRevolveAroundPoint(sceneCenter());
01375 setVisualHintsMask(1);
01376 updateGL();
01377 break;
01378 case CENTER_FRAME :
01379 if (manipulatedFrame())
01380 manipulatedFrame()->projectOnLine(camera()->position(), camera()->viewDirection());
01381 break;
01382 case CENTER_SCENE :
01383 camera()->centerScene();
01384 break;
01385 case SHOW_ENTIRE_SCENE :
01386 camera()->showEntireScene();
01387 break;
01388 case ALIGN_FRAME :
01389 if (manipulatedFrame())
01390 manipulatedFrame()->alignWithFrame(camera()->frame());
01391 break;
01392 case ALIGN_CAMERA :
01393 camera()->frame()->alignWithFrame(NULL, true);
01394 break;
01395 }
01396 }
01397
01414 void QGLViewer::mousePressEvent(QMouseEvent* e)
01415 {
01416
01417
01418 ClickActionPrivate cap;
01419 cap.doubleClick = false;
01420 #if QT_VERSION >= 0x040000
01421 cap.modifiers = e->modifiers();
01422 cap.button = e->button();
01423 cap.buttonsBefore = (Qt::MouseButtons)(e->buttons() & ~(e->button()));
01424 #else
01425 cap.modifiers = (Qt::KeyboardModifiers)(e->state() & Qt::KeyboardModifierMask);
01426 cap.button = (Qt::MouseButtons)((e->stateAfter() & Qt::MouseButtonMask) & (~(e->state() & Qt::MouseButtonMask)));
01427 cap.buttonsBefore = (Qt::MouseButtons)(e->state() & Qt::MouseButtonMask);
01428 #endif
01429
01430 if (clickBinding_.contains(cap))
01431 performClickAction(clickBinding_[cap], e);
01432 else
01433 if (mouseGrabber())
01434 {
01435 if (mouseGrabberIsAManipulatedFrame_)
01436 {
01437 for (QMap<int, MouseActionPrivate>::ConstIterator it=mouseBinding_.begin(), end=mouseBinding_.end(); it!=end; ++it)
01438 #if QT_VERSION >= 0x040000
01439 if ((it.value().handler == FRAME) && ((it.key() & Qt::MouseButtonMask) == e->buttons()))
01440 #else
01441 if ((it.data().handler == FRAME) && ((it.key() & Qt::MouseButtonMask) == (e->stateAfter() & Qt::MouseButtonMask)))
01442 #endif
01443 {
01444 ManipulatedFrame* mf = dynamic_cast<ManipulatedFrame*>(mouseGrabber());
01445 if (mouseGrabberIsAManipulatedCameraFrame_)
01446 {
01447 mf->ManipulatedFrame::startAction(it.value().action, it.value().withConstraint);
01448 mf->ManipulatedFrame::mousePressEvent(e, camera());
01449 }
01450 else
01451 {
01452 mf->startAction(it.value().action, it.value().withConstraint);
01453 mf->mousePressEvent(e, camera());
01454 }
01455 break;
01456 }
01457 }
01458 else
01459 mouseGrabber()->mousePressEvent(e, camera());
01460 updateGL();
01461 }
01462 else
01463 {
01464
01465 #if QT_VERSION >= 0x040000
01466 const int state = e->modifiers() | e->buttons();
01467 #else
01468 const int state = e->stateAfter();
01469 #endif
01470
01471 if (mouseBinding_.contains(state))
01472 {
01473 MouseActionPrivate map = mouseBinding_[state];
01474 switch (map.handler)
01475 {
01476 case CAMERA :
01477 camera()->frame()->startAction(map.action, map.withConstraint);
01478 camera()->frame()->mousePressEvent(e, camera());
01479 break;
01480 case FRAME :
01481 if (manipulatedFrame())
01482 {
01483 if (manipulatedFrameIsACamera_)
01484 {
01485 manipulatedFrame()->ManipulatedFrame::startAction(map.action, map.withConstraint);
01486 manipulatedFrame()->ManipulatedFrame::mousePressEvent(e, camera());
01487 }
01488 else
01489 {
01490 manipulatedFrame()->startAction(map.action, map.withConstraint);
01491 manipulatedFrame()->mousePressEvent(e, camera());
01492 }
01493 }
01494 break;
01495 }
01496 if (map.action == SCREEN_ROTATE)
01497
01498 updateGL();
01499 }
01500 #if QT_VERSION >= 0x030000
01501 else
01502 e->ignore();
01503 #endif
01504 }
01505 }
01506
01546 void QGLViewer::mouseMoveEvent(QMouseEvent* e)
01547 {
01548 if (mouseGrabber())
01549 {
01550 mouseGrabber()->checkIfGrabsMouse(e->x(), e->y(), camera());
01551 if (mouseGrabber()->grabsMouse())
01552 if (mouseGrabberIsAManipulatedCameraFrame_)
01553 (dynamic_cast<ManipulatedFrame*>(mouseGrabber()))->ManipulatedFrame::mouseMoveEvent(e, camera());
01554 else
01555 mouseGrabber()->mouseMoveEvent(e, camera());
01556 else
01557 setMouseGrabber(NULL);
01558 updateGL();
01559 }
01560
01561 if (!mouseGrabber())
01562 {
01563
01564 if (camera()->frame()->isManipulated())
01565 {
01566 camera()->frame()->mouseMoveEvent(e, camera());
01567
01568 if (camera()->frame()->action_ == ZOOM_ON_REGION)
01569 updateGL();
01570 }
01571 else
01572 if ((manipulatedFrame()) && (manipulatedFrame()->isManipulated()))
01573 if (manipulatedFrameIsACamera_)
01574 manipulatedFrame()->ManipulatedFrame::mouseMoveEvent(e, camera());
01575 else
01576 manipulatedFrame()->mouseMoveEvent(e, camera());
01577 else
01578 if (hasMouseTracking())
01579 {
01580 #if QT_VERSION >= 0x040000
01581 Q_FOREACH (MouseGrabber* mg, MouseGrabber::MouseGrabberPool())
01582 {
01583 #else
01584 QPtrListIterator<MouseGrabber> it(MouseGrabber::MouseGrabberPool());
01585 for (MouseGrabber* mg; (mg = it.current()); ++it)
01586 {
01587 #endif
01588 mg->checkIfGrabsMouse(e->x(), e->y(), camera());
01589 if (mg->grabsMouse())
01590 {
01591 setMouseGrabber(mg);
01592
01593 if (mouseGrabber() == mg)
01594 {
01595 updateGL();
01596 break;
01597 }
01598 }
01599 }
01600 }
01601 }
01602 }
01603
01609 void QGLViewer::mouseReleaseEvent(QMouseEvent* e)
01610 {
01611 if (mouseGrabber())
01612 {
01613 if (mouseGrabberIsAManipulatedCameraFrame_)
01614 (dynamic_cast<ManipulatedFrame*>(mouseGrabber()))->ManipulatedFrame::mouseReleaseEvent(e, camera());
01615 else
01616 mouseGrabber()->mouseReleaseEvent(e, camera());
01617 mouseGrabber()->checkIfGrabsMouse(e->x(), e->y(), camera());
01618 if (!(mouseGrabber()->grabsMouse()))
01619 setMouseGrabber(NULL);
01620
01621 }
01622 else
01623
01624 if (camera()->frame()->isManipulated())
01625 {
01626
01627
01628 camera()->frame()->mouseReleaseEvent(e, camera());
01629
01630
01631
01632 }
01633 else
01634 if ((manipulatedFrame()) && (manipulatedFrame()->isManipulated()))
01635 {
01636
01637 if (manipulatedFrameIsACamera_)
01638 manipulatedFrame()->ManipulatedFrame::mouseReleaseEvent(e, camera());
01639 else
01640 manipulatedFrame()->mouseReleaseEvent(e, camera());
01641
01642
01643 }
01644 #if QT_VERSION >= 0x030000
01645 else
01646 e->ignore();
01647 #endif
01648
01649
01650
01651 updateGL();
01652 }
01653
01658 void QGLViewer::wheelEvent(QWheelEvent* e)
01659 {
01660 if (mouseGrabber())
01661 {
01662 if (mouseGrabberIsAManipulatedFrame_)
01663 {
01664 for (QMap<Qt::KeyboardModifiers, MouseActionPrivate>::ConstIterator it=wheelBinding_.begin(), end=wheelBinding_.end(); it!=end; ++it)
01665 if (it.value().handler == FRAME)
01666 {
01667 ManipulatedFrame* mf = dynamic_cast<ManipulatedFrame*>(mouseGrabber());
01668 if (mouseGrabberIsAManipulatedCameraFrame_)
01669 {
01670 mf->ManipulatedFrame::startAction(it.value().action, it.value().withConstraint);
01671 mf->ManipulatedFrame::wheelEvent(e, camera());
01672 }
01673 else
01674 {
01675 mf->startAction(it.value().action, it.value().withConstraint);
01676 mf->wheelEvent(e, camera());
01677 }
01678 break;
01679 }
01680 }
01681 else
01682 mouseGrabber()->wheelEvent(e, camera());
01683 updateGL();
01684 }
01685 else
01686 {
01687
01688 #if QT_VERSION >= 0x040000
01689 const Qt::KeyboardModifiers modifiers = e->modifiers();
01690 #else
01691 const Qt::KeyboardModifiers modifiers = e->state();
01692 #endif
01693 if (wheelBinding_.contains(modifiers))
01694 {
01695 MouseActionPrivate map = wheelBinding_[modifiers];
01696 switch (map.handler)
01697 {
01698 case CAMERA :
01699 camera()->frame()->startAction(map.action, map.withConstraint);
01700 camera()->frame()->wheelEvent(e, camera());
01701 break;
01702 case FRAME :
01703 if (manipulatedFrame()) {
01704 if (manipulatedFrameIsACamera_)
01705 {
01706 manipulatedFrame()->ManipulatedFrame::startAction(map.action, map.withConstraint);
01707 manipulatedFrame()->ManipulatedFrame::wheelEvent(e, camera());
01708 }
01709 else
01710 {
01711 manipulatedFrame()->startAction(map.action, map.withConstraint);
01712 manipulatedFrame()->wheelEvent(e, camera());
01713 }
01714 }
01715 break;
01716 }
01717 }
01718 #if QT_VERSION >= 0x030000
01719 else
01720 e->ignore();
01721 #endif
01722 }
01723 }
01724
01729 void QGLViewer::mouseDoubleClickEvent(QMouseEvent* e)
01730 {
01731
01732 ClickActionPrivate cap;
01733 cap.doubleClick = true;
01734 #if QT_VERSION >= 0x040000
01735 cap.modifiers = e->modifiers();
01736 cap.button = e->button();
01737 cap.buttonsBefore = (Qt::MouseButtons)(e->buttons() & ~(e->button()));
01738 #else
01739 cap.modifiers = (Qt::KeyboardModifiers)(e->state() & Qt::KeyboardModifierMask);
01740 cap.button = (Qt::MouseButtons)((e->stateAfter() & Qt::MouseButtonMask) & (~(e->state() & Qt::MouseButtonMask)));
01741 cap.buttonsBefore = (Qt::MouseButtons)(e->state() & Qt::MouseButtonMask);
01742 #endif
01743 if (clickBinding_.contains(cap))
01744 performClickAction(clickBinding_[cap], e);
01745 else
01746 if (mouseGrabber())
01747 mouseGrabber()->mouseDoubleClickEvent(e, camera());
01748 #if QT_VERSION >= 0x030000
01749 else
01750 e->ignore();
01751 #endif
01752 }
01753
01758 void QGLViewer::setStereoDisplay(bool stereo)
01759 {
01760 if (format().stereo())
01761 {
01762 stereo_ = stereo;
01763 if (!displaysInStereo())
01764 {
01765 glDrawBuffer(GL_BACK_LEFT);
01766 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01767 glDrawBuffer(GL_BACK_RIGHT);
01768 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
01769 }
01770
01771 Q_EMIT stereoChanged(stereo_);
01772
01773 if (updateGLOK_)
01774 updateGL();
01775 }
01776 else
01777 if (stereo)
01778 QMessageBox::warning(this, tr("Stereo not supported", "Message box window title"), tr("Stereo is not supported on this display."));
01779 else
01780 stereo_ = false;
01781 }
01782
01787 void QGLViewer::setFullScreen(bool fullScreen)
01788 {
01789 fullScreen_ = fullScreen;
01790
01791
01792 if (!updateGLOK_)
01793 return;
01794
01795 QWidget* tlw = topLevelWidget();
01796
01797 if (isFullScreen())
01798 {
01799 prevPos_ = topLevelWidget()->pos();
01800 tlw->showFullScreen();
01801 tlw->move(0,0);
01802 }
01803 else
01804 {
01805 tlw->showNormal();
01806 tlw->move(prevPos_);
01807 }
01808 }
01809
01816 void QGLViewer::setMouseGrabber(MouseGrabber* mouseGrabber)
01817 {
01818 if (!mouseGrabberIsEnabled(mouseGrabber))
01819 return;
01820
01821 mouseGrabber_ = mouseGrabber;
01822
01823 mouseGrabberIsAManipulatedFrame_ = (dynamic_cast<ManipulatedFrame*>(mouseGrabber) != NULL);
01824 mouseGrabberIsAManipulatedCameraFrame_ = ((dynamic_cast<ManipulatedCameraFrame*>(mouseGrabber) != NULL) &&
01825 (mouseGrabber != camera()->frame()));
01826 Q_EMIT mouseGrabberChanged(mouseGrabber);
01827 }
01828
01830 void QGLViewer::setMouseGrabberIsEnabled(const qglviewer::MouseGrabber* const mouseGrabber, bool enabled)
01831 {
01832 if (enabled)
01833 disabledMouseGrabbers_.remove(reinterpret_cast<size_t>(mouseGrabber));
01834 else
01835 disabledMouseGrabbers_[reinterpret_cast<size_t>(mouseGrabber)];
01836 }
01837
01838 static QString keyboardModifiersString(Qt::KeyboardModifiers m, bool noButton=false)
01839 {
01840 #if QT_VERSION >= 0x040000
01841 if (noButton && (m==Qt::NoModifier))
01842 #else
01843 if (noButton && (m==Qt::NoButton))
01844 #endif
01845 return QGLViewer::tr("(no button)");
01846
01847 QString keySequence = "";
01848
01849 #if QT_VERSION >= 0x040000
01850 if (m & Qt::ControlModifier) keySequence += "Ctrl+";
01851 if (m & Qt::AltModifier) keySequence += "Alt+";
01852 if (m & Qt::ShiftModifier) keySequence += "Shift+";
01853 if (m & Qt::MetaModifier) keySequence += "Meta+";
01854 #else
01855 if (m & Qt::ControlButton) keySequence += "Ctrl+";
01856 if (m & Qt::AltButton) keySequence += "Alt+";
01857 if (m & Qt::ShiftButton) keySequence += "Shift+";
01858 # if QT_VERSION >= 0x030000
01859 if (m & Qt::MetaButton) keySequence += "Meta+";
01860 # endif
01861 #endif
01862
01863 if (keySequence.length() > 0)
01864 #if QT_VERSION >= 0x040000
01865 return QKeySequence(keySequence+"X").toString(QKeySequence::NativeText).replace("X", "");
01866 #else
01867 return QString(QKeySequence(keySequence+"X")).replace("X", "");
01868 #endif
01869 else
01870 return QString();
01871 }
01872
01873 static QString mouseButtonsString(Qt::MouseButtons b)
01874 {
01875 QString result("");
01876 bool addAmpersand = false;
01877 if (b & Qt::LeftButton) { result += QGLViewer::tr("Left", "left mouse button"); addAmpersand=true; }
01878 if (b & Qt::MidButton) { if (addAmpersand) result += " & "; result += QGLViewer::tr("Middle", "middle mouse button"); addAmpersand=true; }
01879 if (b & Qt::RightButton) { if (addAmpersand) result += " & "; result += QGLViewer::tr("Right", "right mouse button"); }
01880 return result;
01881 }
01882
01883 QString QGLViewer::mouseActionString(QGLViewer::MouseAction ma)
01884 {
01885 switch (ma)
01886 {
01887 case QGLViewer::NO_MOUSE_ACTION : return QString::null;
01888 case QGLViewer::ROTATE : return QGLViewer::tr("Rotates", "ROTATE mouse action");
01889 case QGLViewer::ZOOM : return QGLViewer::tr("Zooms", "ZOOM mouse action");
01890 case QGLViewer::TRANSLATE : return QGLViewer::tr("Translates", "TRANSLATE mouse action");
01891 case QGLViewer::MOVE_FORWARD : return QGLViewer::tr("Moves forward", "MOVE_FORWARD mouse action");
01892 case QGLViewer::LOOK_AROUND : return QGLViewer::tr("Looks around", "LOOK_AROUND mouse action");
01893 case QGLViewer::MOVE_BACKWARD : return QGLViewer::tr("Moves backward", "MOVE_BACKWARD mouse action");
01894 case QGLViewer::SCREEN_ROTATE : return QGLViewer::tr("Rotates in screen plane", "SCREEN_ROTATE mouse action");
01895 case QGLViewer::ROLL : return QGLViewer::tr("Rolls", "ROLL mouse action");
01896 case QGLViewer::DRIVE : return QGLViewer::tr("Drives", "DRIVE mouse action");
01897 case QGLViewer::SCREEN_TRANSLATE : return QGLViewer::tr("Horizontally/Vertically translates", "SCREEN_TRANSLATE mouse action");
01898 case QGLViewer::ZOOM_ON_REGION : return QGLViewer::tr("Zooms on region for", "ZOOM_ON_REGION mouse action");
01899 }
01900 return QString::null;
01901 }
01902
01903 QString QGLViewer::clickActionString(QGLViewer::ClickAction ca)
01904 {
01905 switch (ca)
01906 {
01907 case QGLViewer::NO_CLICK_ACTION : return QString::null;
01908 case QGLViewer::ZOOM_ON_PIXEL : return QGLViewer::tr("Zooms on pixel", "ZOOM_ON_PIXEL click action");
01909 case QGLViewer::ZOOM_TO_FIT : return QGLViewer::tr("Zooms to fit scene", "ZOOM_TO_FIT click action");
01910 case QGLViewer::SELECT : return QGLViewer::tr("Selects", "SELECT click action");
01911 case QGLViewer::RAP_FROM_PIXEL : return QGLViewer::tr("Sets revolve around point", "RAP_FROM_PIXEL click action");
01912 case QGLViewer::RAP_IS_CENTER : return QGLViewer::tr("Resets revolve around point", "RAP_IS_CENTER click action");
01913 case QGLViewer::CENTER_FRAME : return QGLViewer::tr("Centers frame", "CENTER_FRAME click action");
01914 case QGLViewer::CENTER_SCENE : return QGLViewer::tr("Centers scene", "CENTER_SCENE click action");
01915 case QGLViewer::SHOW_ENTIRE_SCENE : return QGLViewer::tr("Shows entire scene", "SHOW_ENTIRE_SCENE click action");
01916 case QGLViewer::ALIGN_FRAME : return QGLViewer::tr("Aligns frame", "ALIGN_FRAME click action");
01917 case QGLViewer::ALIGN_CAMERA : return QGLViewer::tr("Aligns camera", "ALIGN_CAMERA click action");
01918 }
01919 return QString::null;
01920 }
01921
01922 QString QGLViewer::formatClickActionPrivate(ClickActionPrivate cap)
01923 {
01924 bool buttonsBefore = cap.buttonsBefore != Qt::NoButton;
01925 return tr("%1%2%3%4%5%6", "Modifier / button or wheel / double click / with / button / pressed")
01926 .arg(keyboardModifiersString(cap.modifiers))
01927 .arg(mouseButtonsString(cap.button)+(cap.button == Qt::NoButton ? tr("Wheel", "Mouse wheel") : ""))
01928 .arg(cap.doubleClick ? tr(" double click", "Suffix after mouse button") : "")
01929 .arg(buttonsBefore ? tr(" with ", "As in : Left button with Ctrl pressed") : "")
01930 .arg(buttonsBefore ? mouseButtonsString(cap.buttonsBefore) : "")
01931 .arg(buttonsBefore ? tr(" pressed", "As in : Left button with Ctrl pressed") : "");
01932 }
01933
01968 void QGLViewer::setMouseBindingDescription(int state, QString description, bool doubleClick, Qt::MouseButtons buttonsBefore)
01969 {
01970 ClickActionPrivate cap;
01971 cap.modifiers = Qt::KeyboardModifiers(convertToKeyboardModifiers(state) & Qt::KeyboardModifierMask);
01972 cap.button = Qt::MouseButtons(state & Qt::MouseButtonMask);
01973 cap.doubleClick = doubleClick;
01974 cap.buttonsBefore = buttonsBefore;
01975
01976 if (description.isEmpty())
01977 mouseDescription_.remove(cap);
01978 else
01979 mouseDescription_[cap] = description;
01980 }
01981
01982 static QString tableLine(const QString& left, const QString& right)
01983 {
01984 static bool even = false;
01985 const QString tdtd("</b></td><td>");
01986 const QString tdtr("</td></tr>\n");
01987
01988 QString res("<tr bgcolor=\"");
01989
01990 if (even)
01991 res += "#eeeeff\">";
01992 else
01993 res += "#ffffff\">";
01994 res += "<td><b>" + left + tdtd + right + tdtr;
01995 even = !even;
01996
01997 return res;
01998 }
01999
02009 QString QGLViewer::mouseString() const
02010 {
02011 QString text("<center><table border=\"1\" cellspacing=\"0\" cellpadding=\"4\">\n");
02012 const QString trtd("<tr><td>");
02013 const QString tdtr("</td></tr>\n");
02014 const QString tdtd("</td><td>");
02015
02016 text += QString("<tr bgcolor=\"#aaaacc\"><th align=\"center\">%1</th><th align=\"center\">%2</th></tr>\n").
02017 arg(tr("Button(s)", "Buttons column header in help window mouse tab")).arg(tr("Description", "Description column header in help window mouse tab"));
02018
02019 QMap<ClickActionPrivate, QString> mouseBinding;
02020
02021
02022 for (QMap<ClickActionPrivate, QString>::ConstIterator itm=mouseDescription_.begin(), endm=mouseDescription_.end(); itm!=endm; ++itm)
02023 mouseBinding[itm.key()] = itm.value();
02024
02025 for (QMap<ClickActionPrivate, QString>::ConstIterator it=mouseBinding.begin(), end=mouseBinding.end(); it != end; ++it)
02026 {
02027
02028 if (it.value().isNull())
02029 continue;
02030
02031 text += tableLine(formatClickActionPrivate(it.key()), it.value());
02032 }
02033
02034
02035 if (!mouseBinding.isEmpty())
02036 {
02037 mouseBinding.clear();
02038 text += QString("<tr bgcolor=\"#aaaacc\"><td colspan=2>%1</td></tr>\n").arg(tr("Standard mouse bindings", "In help window mouse tab"));
02039 }
02040
02041
02042
02043
02044 for (QMap<Qt::KeyboardModifiers, MouseActionPrivate>::ConstIterator itw=wheelBinding_.begin(), endw=wheelBinding_.end(); itw != endw; ++itw)
02045 {
02046 ClickActionPrivate cap;
02047 cap.doubleClick = false;
02048 cap.modifiers = itw.key();
02049 cap.button = Qt::NoButton;
02050 cap.buttonsBefore = Qt::NoButton;
02051
02052 QString text = mouseActionString(itw.value().action);
02053
02054 if (!text.isNull())
02055 {
02056 switch (itw.value().handler)
02057 {
02058 case CAMERA: text += " " + tr("camera", "Suffix after action"); break;
02059 case FRAME: text += " " + tr("manipulated frame", "Suffix after action"); break;
02060 }
02061 if (!(itw.value().withConstraint))
02062 text += "*";
02063 }
02064
02065 mouseBinding[cap] = text;
02066 }
02067
02068 for (QMap<int, MouseActionPrivate>::ConstIterator itmb=mouseBinding_.begin(), endmb=mouseBinding_.end();
02069 itmb != endmb; ++itmb)
02070 {
02071 ClickActionPrivate cap;
02072 cap.doubleClick = false;
02073 cap.modifiers = Qt::KeyboardModifiers(itmb.key() & Qt::KeyboardModifierMask);
02074 cap.button = Qt::MouseButtons(itmb.key() & Qt::MouseButtonMask);
02075 cap.buttonsBefore = Qt::NoButton;
02076
02077 QString text = mouseActionString(itmb.value().action);
02078
02079 if (!text.isNull())
02080 {
02081 switch (itmb.value().handler)
02082 {
02083 case CAMERA: text += " " + tr("camera", "Suffix after action"); break;
02084 case FRAME: text += " " + tr("manipulated frame", "Suffix after action"); break;
02085 }
02086 if (!(itmb.value().withConstraint))
02087 text += "*";
02088 }
02089 mouseBinding[cap] = text;
02090 }
02091
02092 for (QMap<ClickActionPrivate, ClickAction>::ConstIterator itcb=clickBinding_.begin(), endcb=clickBinding_.end(); itcb!=endcb; ++itcb)
02093 mouseBinding[itcb.key()] = clickActionString(itcb.value());
02094
02095 for (QMap<ClickActionPrivate, QString>::ConstIterator it2=mouseBinding.begin(), end2=mouseBinding.end(); it2 != end2; ++it2)
02096 {
02097 if (it2.value().isNull())
02098 continue;
02099
02100 text += tableLine(formatClickActionPrivate(it2.key()), it2.value());
02101 }
02102
02103 text += "</table></center>";
02104
02105 return text;
02106 }
02107
02122 void QGLViewer::setKeyDescription(int key, QString description)
02123 {
02124 #if QT_VERSION >= 0x030000
02125
02126 key = convertToKeyboardModifiers(key);
02127 #endif
02128 if (description.isEmpty())
02129 keyDescription_.remove(key);
02130 else
02131 keyDescription_[key] = description;
02132 }
02133
02134 static QString keyString(int key)
02135 {
02136 #if QT_VERSION >= 0x030000
02137 # if QT_VERSION >= 0x040100
02138 return QKeySequence(convertToShortModifier(key)).toString();
02139 # else
02140 return QString(QKeySequence(convertToShortModifier(key)));
02141 # endif
02142 #else
02143
02144 return QString(QKeySequence(key));
02145 #endif
02146 }
02147
02148 QString QGLViewer::cameraPathKeysString() const
02149 {
02150 if (pathIndex_.isEmpty())
02151 return QString::null;
02152
02153 #if QT_VERSION >= 0x040000 || QT_VERSION < 0x030000
02154 QVector<int> keys;
02155 #else
02156 QValueVector<int> keys;
02157 #endif
02158 keys.reserve(pathIndex_.count());
02159 for (QMap<Qt::Key, int>::ConstIterator i = pathIndex_.begin(), endi=pathIndex_.end(); i != endi; ++i)
02160 keys.push_back(i.key());
02161 #if QT_VERSION >= 0x040000
02162 qSort(keys);
02163 #else
02164 # if QT_VERSION >= 0x030000
02165 qHeapSort(keys);
02166 # else
02167 sort(keys.begin(), keys.end());
02168 # endif
02169 #endif
02170
02171 #if QT_VERSION >= 0x040000 || QT_VERSION < 0x030000
02172 QVector<int>::const_iterator it = keys.begin(), end = keys.end();
02173 #else
02174 QValueVector<int>::const_iterator it = keys.begin(), end = keys.end();
02175 #endif
02176 QString res = keyString(*it);
02177
02178 const int maxDisplayedKeys = 6;
02179 int nbDisplayedKeys = 0;
02180 int previousKey = (*it);
02181 int state = 0;
02182 ++it;
02183 while ((it != end) && (nbDisplayedKeys < maxDisplayedKeys-1))
02184 {
02185 switch (state)
02186 {
02187 case 0 :
02188 if ((*it) == previousKey + 1)
02189 state++;
02190 else
02191 {
02192 res += ", " + keyString(*it);
02193 nbDisplayedKeys++;
02194 }
02195 break;
02196 case 1 :
02197 if ((*it) == previousKey + 1)
02198 state++;
02199 else
02200 {
02201 res += ", " + keyString(previousKey);
02202 res += ", " + keyString(*it);
02203 nbDisplayedKeys += 2;
02204 state = 0;
02205 }
02206 break;
02207 default :
02208 if ((*it) != previousKey + 1)
02209 {
02210 res += ".." + keyString(previousKey);
02211 res += ", " + keyString(*it);
02212 nbDisplayedKeys += 2;
02213 state = 0;
02214 }
02215 break;
02216 }
02217 previousKey = *it;
02218 ++it;
02219 }
02220
02221 if (state == 1)
02222 res += ", " + keyString(previousKey);
02223 if (state == 2)
02224 res += ".." + keyString(previousKey);
02225 if (it != end)
02226 res += "...";
02227
02228 return res;
02229 }
02230
02239 QString QGLViewer::keyboardString() const
02240 {
02241 QString text("<center><table border=\"1\" cellspacing=\"0\" cellpadding=\"4\">\n");
02242 text += QString("<tr bgcolor=\"#aaaacc\"><th align=\"center\">%1</th><th align=\"center\">%2</th></tr>\n").
02243 arg(QGLViewer::tr("Key(s)", "Keys column header in help window mouse tab")).arg(QGLViewer::tr("Description", "Description column header in help window mouse tab"));
02244
02245 QMap<int, QString> keyDescription;
02246
02247
02248 for (QMap<int, QString>::ConstIterator kd=keyDescription_.begin(), kdend=keyDescription_.end(); kd!=kdend; ++kd)
02249 keyDescription[kd.key()] = kd.value();
02250
02251
02252 for (QMap<int, QString>::ConstIterator kb=keyDescription.begin(), endb=keyDescription.end(); kb!=endb; ++kb)
02253 text += tableLine(keyString(kb.key()), kb.value());
02254
02255
02256
02257 if (!keyDescription.isEmpty())
02258 {
02259 keyDescription.clear();
02260 text += QString("<tr bgcolor=\"#aaaacc\"><td colspan=2>%1</td></tr>\n").arg(QGLViewer::tr("Standard viewer keys", "In help window keys tab"));
02261 }
02262
02263
02264
02265 for (QMap<KeyboardAction, unsigned int>::ConstIterator it=keyboardBinding_.begin(), end=keyboardBinding_.end(); it != end; ++it)
02266 if ((it.value() != 0) && ((!cameraIsInRevolveMode()) || ((it.key() != INCREASE_FLYSPEED) && (it.key() != DECREASE_FLYSPEED))))
02267 keyDescription[it.value()] = keyboardActionDescription_[it.key()];
02268
02269
02270 for (QMap<int, QString>::ConstIterator kb2=keyDescription.begin(), endb2=keyDescription.end(); kb2!=endb2; ++kb2)
02271 text += tableLine(keyString(kb2.key()), kb2.value());
02272
02273
02274
02275 const QString cpks = cameraPathKeysString();
02276 if (!cpks.isNull())
02277 {
02278 text += "<tr bgcolor=\"#ccccff\"><td colspan=2>\n";
02279 text += QGLViewer::tr("Camera paths are controlled using %1 (noted <i>Fx</i> below):", "Help window key tab camera keys").arg(cpks) + "</td></tr>\n";
02280 text += tableLine(keyboardModifiersString(playPathKeyboardModifiers()) + "<i>" + QGLViewer::tr("Fx", "Generic function key (F1..F12)") + "</i>",
02281 QGLViewer::tr("Plays path (or resets saved position)"));
02282 text += tableLine(keyboardModifiersString(addKeyFrameKeyboardModifiers()) + "<i>" + QGLViewer::tr("Fx", "Generic function key (F1..F12)") + "</i>",
02283 QGLViewer::tr("Adds a key frame to path (or defines a position)"));
02284 text += tableLine(keyboardModifiersString(addKeyFrameKeyboardModifiers()) + "<i>" + QGLViewer::tr("Fx", "Generic function key (F1..F12)") + "</i>+<i>" + QGLViewer::tr("Fx", "Generic function key (F1..F12)") + "</i>",
02285 QGLViewer::tr("Deletes path (or saved position)"));
02286 }
02287 text += "</table></center>";
02288
02289 return text;
02290 }
02291
02293 void QGLViewer::aboutQGLViewer() {
02294 help();
02295 #if QT_VERSION >= 0x040000
02296 helpWidget()->setCurrentIndex(3);
02297 #else
02298 helpWidget()->setCurrentPage(3);
02299 #endif
02300 }
02301
02302
02312 void QGLViewer::help()
02313 {
02314 Q_EMIT helpRequired();
02315
02316 bool resize = false;
02317 int width=600;
02318 int height=400;
02319
02320 static QString label[] = {tr("&Help", "Help window tab title"), tr("&Keyboard", "Help window tab title"), tr("&Mouse", "Help window tab title"), tr("&About", "Help window about title")};
02321
02322 if (!helpWidget())
02323 {
02324
02325 helpWidget_ = new QTabWidget(NULL);
02326 #if QT_VERSION >= 0x040000
02327 helpWidget()->setWindowTitle(tr("Help", "Help window title"));
02328 #else
02329 helpWidget()->setCaption(tr("Help", "Help window title"));
02330 #endif
02331
02332 resize = true;
02333 for (int i=0; i<4; ++i)
02334 {
02335 QTextEdit* tab = new QTextEdit(NULL);
02336 #if QT_VERSION >= 0x030000
02337 tab->setReadOnly(true);
02338 #endif
02339
02340 #if QT_VERSION >= 0x040000
02341 helpWidget()->insertTab(i, tab, label[i]);
02342 if (i==3) {
02343 # include "qglviewer-icon.xpm"
02344 QPixmap pixmap(qglviewer_icon);
02345 tab->document()->addResource(QTextDocument::ImageResource,
02346 QUrl("mydata://qglviewer-icon.xpm"), QVariant(pixmap));
02347 }
02348 #else
02349 tab->setTextFormat(Qt::RichText);
02350 helpWidget()->insertTab(tab, label[i]);
02351 #endif
02352 }
02353 }
02354
02355
02356 #if QT_VERSION < 0x030000
02357 const int currentPageIndex = helpWidget()->currentPageIndex();
02358 #endif
02359
02360 for (int i=0; i<4; ++i)
02361 {
02362 QString text;
02363 switch (i)
02364 {
02365 case 0 : text = helpString(); break;
02366 case 1 : text = keyboardString(); break;
02367 case 2 : text = mouseString(); break;
02368 case 3 : text = QString("<center><br><img src=\"mydata://qglviewer-icon.xpm\">") + tr(
02369 "<h1>libQGLViewer</h1>"
02370 "<h3>Version %1</h3><br>"
02371 "A versatile 3D viewer based on OpenGL and Qt<br>"
02372 "Copyright 2002-%2 Gilles Debunne<br>"
02373 "<code>%3</code>").arg(QGLViewerVersionString()).arg("2012").arg("http://www.libqglviewer.com") +
02374 QString("</center>");
02375 break;
02376 default : break;
02377 }
02378
02379 #if QT_VERSION >= 0x040000
02380 QTextEdit* textEdit = (QTextEdit*)(helpWidget()->widget(i));
02381 textEdit->setHtml(text);
02382 #else
02383 # if QT_VERSION < 0x030000
02384 helpWidget()->setCurrentPage(i);
02385 QTextEdit* textEdit = (QTextEdit*)(helpWidget()->currentPage());
02386 # else
02387 QTextEdit* textEdit = (QTextEdit*)(helpWidget()->page(i));
02388 # endif
02389 textEdit->setText(text);
02390 #endif
02391
02392 #if QT_VERSION < 0x040000
02393 if (resize && (textEdit->heightForWidth(width) > height))
02394 height = textEdit->heightForWidth(width);
02395 #else
02396 if (resize && (textEdit->height() > height))
02397 height = textEdit->height();
02398 #endif
02399 }
02400
02401 #if QT_VERSION < 0x030000
02402 helpWidget()->setCurrentPage(currentPageIndex);
02403 #endif
02404
02405 if (resize)
02406 helpWidget()->resize(width, height+40);
02407 helpWidget()->show();
02408 helpWidget()->raise();
02409 }
02410
02437 void QGLViewer::keyPressEvent(QKeyEvent *e)
02438 {
02439 if (e->key() == 0)
02440 {
02441 e->ignore();
02442 return;
02443 }
02444
02445 const Qt::Key key = Qt::Key(e->key());
02446 #if QT_VERSION >= 0x040000
02447 const Qt::KeyboardModifiers modifiers = e->modifiers();
02448 #else
02449 const Qt::KeyboardModifiers modifiers = (Qt::KeyboardModifiers)(e->state() & Qt::KeyboardModifierMask);
02450 #endif
02451
02452 QMap<KeyboardAction, unsigned int>::ConstIterator it=keyboardBinding_.begin(), end=keyboardBinding_.end();
02453 const unsigned int target = key | modifiers;
02454 while ((it != end) && (it.value() != target))
02455 ++it;
02456
02457 if (it != end)
02458 handleKeyboardAction(it.key());
02459 else
02460 if (pathIndex_.contains(Qt::Key(key)))
02461 {
02462
02463 int index = pathIndex_[Qt::Key(key)];
02464
02465 static QTime doublePress;
02466
02467 if (modifiers == playPathKeyboardModifiers())
02468 {
02469 int elapsed = doublePress.restart();
02470 if ((elapsed < 250) && (index==previousPathId_))
02471 camera()->resetPath(index);
02472 else
02473 {
02474
02475 if (index != previousPathId_)
02476 {
02477 KeyFrameInterpolator* previous = camera()->keyFrameInterpolator(previousPathId_);
02478 if ((previous) && (previous->interpolationIsStarted()))
02479 previous->resetInterpolation();
02480 }
02481 camera()->playPath(index);
02482 }
02483 previousPathId_ = index;
02484 }
02485 else if (modifiers == addKeyFrameKeyboardModifiers())
02486 {
02487 int elapsed = doublePress.restart();
02488 if ((elapsed < 250) && (index==previousPathId_))
02489 {
02490 if (camera()->keyFrameInterpolator(index))
02491 {
02492 disconnect(camera()->keyFrameInterpolator(index), SIGNAL(interpolated()), this, SLOT(updateGL()));
02493 if (camera()->keyFrameInterpolator(index)->numberOfKeyFrames() > 1)
02494 displayMessage(tr("Path %1 deleted", "Feedback message").arg(index));
02495 else
02496 displayMessage(tr("Position %1 deleted", "Feedback message").arg(index));
02497 camera()->deletePath(index);
02498 }
02499 }
02500 else
02501 {
02502 bool nullBefore = (camera()->keyFrameInterpolator(index) == NULL);
02503 camera()->addKeyFrameToPath(index);
02504 if (nullBefore)
02505 connect(camera()->keyFrameInterpolator(index), SIGNAL(interpolated()), SLOT(updateGL()));
02506 int nbKF = camera()->keyFrameInterpolator(index)->numberOfKeyFrames();
02507 if (nbKF > 1)
02508 displayMessage(tr("Path %1, position %2 added", "Feedback message").arg(index).arg(nbKF));
02509 else
02510 displayMessage(tr("Position %1 saved", "Feedback message").arg(index));
02511 }
02512 previousPathId_ = index;
02513 }
02514 updateGL();
02515 }
02516 else
02517 e->ignore();
02518 }
02519
02520 void QGLViewer::handleKeyboardAction(KeyboardAction id)
02521 {
02522 switch (id)
02523 {
02524 case DRAW_AXIS : toggleAxisIsDrawn(); break;
02525 case DRAW_GRID : toggleGridIsDrawn(); break;
02526 case DISPLAY_FPS : toggleFPSIsDisplayed(); break;
02527 case ENABLE_TEXT : toggleTextIsEnabled(); break;
02528 case EXIT_VIEWER : saveStateToFileForAllViewers(); qApp->closeAllWindows(); break;
02529 case SAVE_SCREENSHOT : saveSnapshot(false, false); break;
02530 case FULL_SCREEN : toggleFullScreen(); break;
02531 case STEREO : toggleStereoDisplay(); break;
02532 case ANIMATION : toggleAnimation(); break;
02533 case HELP : help(); break;
02534 case EDIT_CAMERA : toggleCameraIsEdited(); break;
02535 case SNAPSHOT_TO_CLIPBOARD : snapshotToClipboard(); break;
02536 case CAMERA_MODE :
02537 toggleCameraMode();
02538 displayMessage(cameraIsInRevolveMode()?tr("Camera in revolve around mode", "Feedback message"):tr("Camera in fly mode", "Feedback message"));
02539 break;
02540
02541 case MOVE_CAMERA_LEFT :
02542 camera()->frame()->translate(camera()->frame()->inverseTransformOf(Vec(-10.0*camera()->flySpeed(), 0.0, 0.0)));
02543 updateGL();
02544 break;
02545 case MOVE_CAMERA_RIGHT :
02546 camera()->frame()->translate(camera()->frame()->inverseTransformOf(Vec( 10.0*camera()->flySpeed(), 0.0, 0.0)));
02547 updateGL();
02548 break;
02549 case MOVE_CAMERA_UP :
02550 camera()->frame()->translate(camera()->frame()->inverseTransformOf(Vec(0.0, 10.0*camera()->flySpeed(), 0.0)));
02551 updateGL();
02552 break;
02553 case MOVE_CAMERA_DOWN :
02554 camera()->frame()->translate(camera()->frame()->inverseTransformOf(Vec(0.0, -10.0*camera()->flySpeed(), 0.0)));
02555 updateGL();
02556 break;
02557
02558 case INCREASE_FLYSPEED : camera()->setFlySpeed(camera()->flySpeed() * 1.5); break;
02559 case DECREASE_FLYSPEED : camera()->setFlySpeed(camera()->flySpeed() / 1.5); break;
02560 }
02561 }
02562
02567 void QGLViewer::resizeGL(int width, int height)
02568 {
02569 QGLWidget::resizeGL(width, height);
02570 glViewport( 0, 0, GLint(width), GLint(height) );
02571 camera()->setScreenWidthAndHeight(this->width(), this->height());
02572 }
02573
02575
02577
02595 void QGLViewer::setShortcut(KeyboardAction action, unsigned int key)
02596 {
02597 keyboardBinding_[action] = convertToKeyboardModifiers(key);
02598 }
02599
02615 unsigned int QGLViewer::shortcut(KeyboardAction action) const
02616 {
02617 if (keyboardBinding_.contains(action))
02618 return convertToShortModifier(keyboardBinding_[action]);
02619 else
02620 return 0;
02621 }
02622
02623 #ifndef DOXYGEN
02624 void QGLViewer::setKeyboardAccelerator(KeyboardAction action, int key)
02625 {
02626 qWarning("setKeyboardAccelerator is deprecated. Use setShortcut instead.");
02627 setShortcut(action, key);
02628 }
02629
02630 int QGLViewer::keyboardAccelerator(KeyboardAction action) const
02631 {
02632 qWarning("keyboardAccelerator is deprecated. Use shortcut instead.");
02633 return shortcut(action);
02634 }
02635 #endif
02636
02638
02654 Qt::Key QGLViewer::pathKey(int index) const
02655 {
02656 for (QMap<Qt::Key, int>::ConstIterator it = pathIndex_.begin(), end=pathIndex_.end(); it != end; ++it)
02657 if (it.value() == index)
02658 return it.key();
02659 return Qt::Key(0);
02660 }
02661
02673 void QGLViewer::setPathKey(int key, int index)
02674 {
02675 if (key < 0)
02676 pathIndex_.remove(Qt::Key(-key));
02677 else
02678 pathIndex_[Qt::Key(key)] = index;
02679 }
02680
02682 void QGLViewer::setPlayPathKeyboardModifiers(Qt::KeyboardModifiers modifiers)
02683 {
02684 playPathKeyboardModifiers_ = convertKeyboardModifiers(modifiers);
02685 }
02686
02688 void QGLViewer::setAddKeyFrameKeyboardModifiers(Qt::KeyboardModifiers modifiers)
02689 {
02690 addKeyFrameKeyboardModifiers_ = convertKeyboardModifiers(modifiers);
02691 }
02692
02706 Qt::KeyboardModifiers QGLViewer::addKeyFrameKeyboardModifiers() const
02707 {
02708 return addKeyFrameKeyboardModifiers_;
02709 }
02710
02723 Qt::KeyboardModifiers QGLViewer::playPathKeyboardModifiers() const
02724 {
02725 return playPathKeyboardModifiers_;
02726 }
02727
02728 #ifndef DOXYGEN
02729
02730 Qt::KeyboardModifiers QGLViewer::addKeyFrameStateKey() const
02731 {
02732 qWarning("addKeyFrameStateKey has been renamed addKeyFrameKeyboardModifiers");
02733 return addKeyFrameKeyboardModifiers(); }
02734
02735 Qt::KeyboardModifiers QGLViewer::playPathStateKey() const
02736 {
02737 qWarning("playPathStateKey has been renamed playPathKeyboardModifiers");
02738 return playPathKeyboardModifiers();
02739 }
02740
02741 void QGLViewer::setAddKeyFrameStateKey(int buttonState)
02742 {
02743 qWarning("setAddKeyFrameStateKey has been renamed setAddKeyFrameKeyboardModifiers");
02744 setAddKeyFrameKeyboardModifiers(Qt::KeyboardModifiers(buttonState & Qt::KeyboardModifierMask));
02745 }
02746
02747 void QGLViewer::setPlayPathStateKey(int buttonState)
02748 {
02749 qWarning("setPlayPathStateKey has been renamed setPlayPathKeyboardModifiers");
02750 setPlayPathKeyboardModifiers(Qt::KeyboardModifiers(buttonState & Qt::KeyboardModifierMask));
02751 }
02752
02753 Qt::Key QGLViewer::keyFrameKey(int index) const
02754 {
02755 qWarning("keyFrameKey has been renamed pathKey.");
02756 return pathKey(index);
02757 }
02758
02759 Qt::KeyboardModifiers QGLViewer::playKeyFramePathStateKey() const
02760 {
02761 qWarning("playKeyFramePathStateKey has been renamed playPathKeyboardModifiers.");
02762 return playPathKeyboardModifiers();
02763 }
02764
02765 void QGLViewer::setKeyFrameKey(int index, int key)
02766 {
02767 qWarning("setKeyFrameKey is deprecated, use setPathKey instead, with swapped parameters.");
02768 setPathKey(key, index);
02769 }
02770
02771 void QGLViewer::setPlayKeyFramePathStateKey(int buttonState)
02772 {
02773 qWarning("setPlayKeyFramePathStateKey has been renamed setPlayPathKeyboardModifiers.");
02774 setPlayPathKeyboardModifiers(Qt::KeyboardModifiers(buttonState & Qt::KeyboardModifierMask));
02775 }
02776 #endif
02777
02779
02781
02822 void QGLViewer::setHandlerKeyboardModifiers(MouseHandler handler, Qt::KeyboardModifiers modifiers)
02823 {
02824 QMap<int, MouseActionPrivate> newMouseBinding;
02825 QMap<Qt::KeyboardModifiers, MouseActionPrivate> newWheelBinding;
02826 QMap<ClickActionPrivate, ClickAction> newClickBinding_;
02827
02828 QMap<int, MouseActionPrivate>::Iterator mit;
02829 QMap<Qt::KeyboardModifiers, MouseActionPrivate>::Iterator wit;
02830
02831
02832 for (mit = mouseBinding_.begin(); mit != mouseBinding_.end(); ++mit)
02833 if ((mit.value().handler != handler) || (mit.value().action == ZOOM_ON_REGION))
02834 newMouseBinding[mit.key()] = mit.value();
02835
02836 for (wit = wheelBinding_.begin(); wit != wheelBinding_.end(); ++wit)
02837 if (wit.value().handler != handler)
02838 newWheelBinding[wit.key()] = wit.value();
02839
02840
02841 modifiers = convertKeyboardModifiers(modifiers);
02842 for (mit = mouseBinding_.begin(); mit != mouseBinding_.end(); ++mit)
02843 if ((mit.value().handler == handler) && (mit.value().action != ZOOM_ON_REGION))
02844 {
02845 int newState = modifiers | (mit.key() & Qt::MouseButtonMask);
02846 newMouseBinding[newState] = mit.value();
02847 }
02848
02849 for (wit = wheelBinding_.begin(); wit != wheelBinding_.end(); ++wit)
02850 if (wit.value().handler == handler)
02851 {
02852 Qt::KeyboardModifiers newState = modifiers;
02853 newWheelBinding[newState] = wit.value();
02854 }
02855
02856
02857 for (QMap<ClickActionPrivate, ClickAction>::ConstIterator cb=clickBinding_.begin(), end=clickBinding_.end(); cb != end; ++cb)
02858 if (((handler==CAMERA) && ((cb.value() == CENTER_SCENE) || (cb.value() == ALIGN_CAMERA))) ||
02859 ((handler==FRAME) && ((cb.value() == CENTER_FRAME) || (cb.value() == ALIGN_FRAME))))
02860 {
02861 ClickActionPrivate cap;
02862 cap.modifiers = modifiers;
02863 cap.button = cb.key().button;
02864 cap.doubleClick = cb.key().doubleClick;
02865 cap.buttonsBefore = cb.key().buttonsBefore;
02866 newClickBinding_[cap] = cb.value();
02867 }
02868 else
02869 newClickBinding_[cb.key()] = cb.value();
02870
02871 mouseBinding_ = newMouseBinding;
02872 wheelBinding_ = newWheelBinding;
02873 clickBinding_ = newClickBinding_;
02874 }
02875
02876
02877 #ifndef DOXYGEN
02878 void QGLViewer::setHandlerStateKey(MouseHandler handler, int buttonState)
02879 {
02880 qWarning("setHandlerStateKey has been renamed setHandlerKeyboardModifiers");
02881 setHandlerKeyboardModifiers(handler, Qt::KeyboardModifiers(buttonState & Qt::KeyboardModifierMask));
02882 }
02883
02884 void QGLViewer::setMouseStateKey(MouseHandler handler, int buttonState)
02885 {
02886 qWarning("setMouseStateKey has been renamed setHandlerKeyboardModifiers.");
02887 setHandlerKeyboardModifiers(handler, Qt::KeyboardModifiers(buttonState & Qt::KeyboardModifierMask));
02888 }
02889 #endif
02890
02922 void QGLViewer::setMouseBinding(int state, MouseHandler handler, MouseAction action, bool withConstraint)
02923 {
02924 if ((handler == FRAME) && ((action == MOVE_FORWARD) || (action == MOVE_BACKWARD) ||
02925 (action == ROLL) || (action == LOOK_AROUND) ||
02926 (action == ZOOM_ON_REGION)))
02927 {
02928 #if QT_VERSION >= 0x040000
02929 qWarning("Cannot bind %s to FRAME", mouseActionString(action).toLatin1().constData());
02930 #else
02931 qWarning("Cannot bind %s to FRAME", mouseActionString(action).latin1());
02932 #endif
02933 }
02934 else
02935 if ((state & Qt::MouseButtonMask) == 0)
02936 qWarning("No mouse button specified in setMouseBinding");
02937 else
02938 {
02939 MouseActionPrivate map;
02940 map.handler = handler;
02941 map.action = action;
02942 map.withConstraint = withConstraint;
02943 state = convertToKeyboardModifiers(state);
02944
02945 mouseBinding_.remove(state);
02946
02947 if (action != NO_MOUSE_ACTION)
02948 mouseBinding_.insert(state, map);
02949
02950 ClickActionPrivate cap;
02951 cap.modifiers = Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask);
02952 cap.button = Qt::MouseButtons(state & Qt::MouseButtonMask);
02953 cap.doubleClick = false;
02954 cap.buttonsBefore = Qt::NoButton;
02955 clickBinding_.remove(cap);
02956 }
02957 }
02958
02959
02984 void QGLViewer::setMouseBinding(int state, ClickAction action, bool doubleClick, Qt::MouseButtons buttonsBefore)
02985 {
02986 if ((buttonsBefore != Qt::NoButton) && !doubleClick)
02987 qWarning("Buttons before is only meaningful when doubleClick is true in setMouseBinding().");
02988 else
02989 if ((state & Qt::MouseButtonMask) == 0)
02990 qWarning("No mouse button specified in setMouseBinding");
02991 else
02992 {
02993 ClickActionPrivate cap;
02994 state = convertToKeyboardModifiers(state);
02995 cap.modifiers = Qt::KeyboardModifiers(state & Qt::KeyboardModifierMask);
02996 cap.button = Qt::MouseButtons(state & Qt::MouseButtonMask);
02997 cap.doubleClick = doubleClick;
02998 cap.buttonsBefore = buttonsBefore;
02999 clickBinding_.remove(cap);
03000
03001
03002 if (action != NO_CLICK_ACTION)
03003 clickBinding_.insert(cap, action);
03004
03005 if ((!doubleClick) && (buttonsBefore == Qt::NoButton))
03006 mouseBinding_.remove(state);
03007 }
03008 }
03009
03020 void QGLViewer::setWheelBinding(Qt::KeyboardModifiers modifiers, MouseHandler handler, MouseAction action, bool withConstraint)
03021 {
03022
03023 if ((action != ZOOM) && (action != MOVE_FORWARD) && (action != MOVE_BACKWARD) && (action != NO_MOUSE_ACTION))
03024 #if QT_VERSION >= 0x040000
03025 qWarning("Cannot bind %s to wheel", mouseActionString(action).toLatin1().constData());
03026 #else
03027 qWarning("Cannot bind %s to wheel", + mouseActionString(action).latin1());
03028 #endif
03029 else
03030 if ((handler == FRAME) && (action != ZOOM) && (action != NO_MOUSE_ACTION))
03031 #if QT_VERSION >= 0x040000
03032 qWarning("Cannot bind %s to FRAME wheel", mouseActionString(action).toLatin1().constData());
03033 #else
03034 qWarning("Cannot bind %s to FRAME wheel", mouseActionString(action).latin1());
03035 #endif
03036 else
03037 {
03038 MouseActionPrivate map;
03039 map.handler = handler;
03040 map.action = action;
03041 map.withConstraint = withConstraint;
03042 modifiers = convertKeyboardModifiers(modifiers);
03043 wheelBinding_.remove(modifiers);
03044
03045 if (action != NO_MOUSE_ACTION)
03046 wheelBinding_.insert(modifiers, map);
03047 }
03048 }
03049
03061 QGLViewer::MouseAction QGLViewer::mouseAction(int state) const
03062 {
03063 state = convertToKeyboardModifiers(state);
03064 if (mouseBinding_.contains(state))
03065 return mouseBinding_[state].action;
03066 else
03067 return NO_MOUSE_ACTION;
03068 }
03069
03080 int QGLViewer::mouseHandler(int state) const
03081 {
03082 state = convertToKeyboardModifiers(state);
03083 if (mouseBinding_.contains(state))
03084 return mouseBinding_[state].handler;
03085 else
03086 return -1;
03087 }
03088
03106 int QGLViewer::mouseButtonState(MouseHandler handler, MouseAction action, bool withConstraint) const
03107 {
03108 for (QMap<int, MouseActionPrivate>::ConstIterator it=mouseBinding_.begin(), end=mouseBinding_.end(); it != end; ++it)
03109 if ( (it.value().handler == handler) && (it.value().action == action) && (it.value().withConstraint == withConstraint) )
03110 return it.key();
03111
03112 return Qt::NoButton;
03113 }
03114
03120 QGLViewer::MouseAction QGLViewer::wheelAction(Qt::KeyboardModifiers modifiers) const
03121 {
03122 modifiers = convertKeyboardModifiers(modifiers);
03123 if (wheelBinding_.contains(modifiers))
03124 return wheelBinding_[modifiers].action;
03125 else
03126 return NO_MOUSE_ACTION;
03127 }
03128
03130 int QGLViewer::wheelHandler(Qt::KeyboardModifiers modifiers) const
03131 {
03132 modifiers = convertKeyboardModifiers(modifiers);
03133 if (wheelBinding_.contains(modifiers))
03134 return wheelBinding_[modifiers].handler;
03135 else
03136 return -1;
03137 }
03138
03143 int QGLViewer::wheelButtonState(MouseHandler handler, MouseAction action, bool withConstraint) const
03144 {
03145 for (QMap<Qt::KeyboardModifiers, MouseActionPrivate>::ConstIterator it=wheelBinding_.begin(), end=wheelBinding_.end(); it!=end; ++it)
03146 if ( (it.value().handler == handler) && (it.value().action == action) && (it.value().withConstraint == withConstraint) )
03147 return it.key();
03148
03149 return -1;
03150 }
03151
03153 QGLViewer::ClickAction QGLViewer::clickAction(int state, bool doubleClick, Qt::MouseButtons buttonsBefore) const
03154 {
03155 ClickActionPrivate cap;
03156 cap.modifiers = Qt::KeyboardModifiers(convertToKeyboardModifiers(state) & Qt::KeyboardModifierMask);
03157 cap.button = Qt::MouseButtons(state & Qt::MouseButtonMask);
03158 cap.doubleClick = doubleClick;
03159 cap.buttonsBefore = buttonsBefore;
03160 if (clickBinding_.contains(cap))
03161 return clickBinding_[cap];
03162 else
03163 return NO_CLICK_ACTION;
03164 }
03165
03171 void QGLViewer::getClickButtonState(ClickAction ca, int& state, bool& doubleClick, Qt::MouseButtons& buttonsBefore) const
03172 {
03173 for (QMap<ClickActionPrivate, ClickAction>::ConstIterator it=clickBinding_.begin(), end=clickBinding_.end(); it != end; ++it)
03174 if (it.value() == ca)
03175 {
03176 state = it.key().modifiers | it.key().button;
03177 doubleClick = it.key().doubleClick;
03178 buttonsBefore = it.key().buttonsBefore;
03179 return;
03180 }
03181
03182 state = Qt::NoButton;
03183 }
03184
03188 bool QGLViewer::cameraIsInRevolveMode() const
03189 {
03190
03191 return mouseButtonState(CAMERA, ROTATE) != Qt::NoButton;
03192 }
03193
03207 void QGLViewer::toggleCameraMode()
03208 {
03209 bool revolveMode = cameraIsInRevolveMode();
03210 int bs;
03211 if (revolveMode)
03212 bs = mouseButtonState(CAMERA, ROTATE);
03213 else
03214 bs = mouseButtonState(CAMERA, MOVE_FORWARD);
03215 Qt::KeyboardModifiers modifiers = Qt::KeyboardModifiers(bs & Qt::KeyboardModifierMask);
03216
03217
03218 if (revolveMode)
03219 {
03220 camera()->frame()->updateFlyUpVector();
03221 camera()->frame()->stopSpinning();
03222
03223 setMouseBinding(modifiers | Qt::LeftButton, CAMERA, MOVE_FORWARD);
03224 setMouseBinding(modifiers | Qt::MidButton, CAMERA, LOOK_AROUND);
03225 setMouseBinding(modifiers | Qt::RightButton, CAMERA, MOVE_BACKWARD);
03226
03227 setMouseBinding(modifiers | Qt::LeftButton | Qt::MidButton, CAMERA, ROLL);
03228
03229
03230 setMouseBinding(Qt::LeftButton, NO_CLICK_ACTION, true);
03231 setMouseBinding(Qt::MidButton, NO_CLICK_ACTION, true);
03232 setMouseBinding(Qt::RightButton, NO_CLICK_ACTION, true);
03233
03234 setWheelBinding(modifiers, CAMERA, MOVE_FORWARD);
03235 }
03236 else
03237 {
03238
03239 setMouseBinding(modifiers | Qt::LeftButton, CAMERA, ROTATE);
03240 setMouseBinding(modifiers | Qt::MidButton, CAMERA, ZOOM);
03241 setMouseBinding(modifiers | Qt::RightButton, CAMERA, TRANSLATE);
03242
03243 setMouseBinding(modifiers | Qt::LeftButton | Qt::MidButton, CAMERA, SCREEN_ROTATE);
03244
03245
03246 setMouseBinding(Qt::LeftButton, ALIGN_CAMERA, true);
03247 setMouseBinding(Qt::MidButton, SHOW_ENTIRE_SCENE, true);
03248 setMouseBinding(Qt::RightButton, CENTER_SCENE, true);
03249
03250 setWheelBinding(modifiers, CAMERA, ZOOM);
03251 }
03252 }
03253
03255
03257
03269 void QGLViewer::setManipulatedFrame(ManipulatedFrame* frame)
03270 {
03271 if (manipulatedFrame())
03272 {
03273 manipulatedFrame()->stopSpinning();
03274
03275 if (manipulatedFrame() != camera()->frame())
03276 {
03277 disconnect(manipulatedFrame(), SIGNAL(manipulated()), this, SLOT(updateGL()));
03278 disconnect(manipulatedFrame(), SIGNAL(spun()), this, SLOT(updateGL()));
03279 }
03280 }
03281
03282 manipulatedFrame_ = frame;
03283
03284 manipulatedFrameIsACamera_ = ((manipulatedFrame() != camera()->frame()) &&
03285 (dynamic_cast<ManipulatedCameraFrame*>(manipulatedFrame()) != NULL));
03286
03287 if (manipulatedFrame())
03288 {
03289
03290 if (manipulatedFrame() != camera()->frame())
03291 {
03292 connect(manipulatedFrame(), SIGNAL(manipulated()), SLOT(updateGL()));
03293 connect(manipulatedFrame(), SIGNAL(spun()), SLOT(updateGL()));
03294 }
03295 }
03296 }
03297
03298 #ifndef DOXYGEN
03299
03300
03302
03317 void QGLViewer::drawVisualHints()
03318 {
03319
03320 if (visualHint_ & 1)
03321 {
03322 const float size = 15.0;
03323 Vec proj = camera()->projectedCoordinatesOf(camera()->revolveAroundPoint());
03324 startScreenCoordinatesSystem();
03325 glDisable(GL_LIGHTING);
03326 glDisable(GL_DEPTH_TEST);
03327 glLineWidth(3.0);
03328 glBegin(GL_LINES);
03329 glVertex2f(proj.x - size, proj.y);
03330 glVertex2f(proj.x + size, proj.y);
03331 glVertex2f(proj.x, proj.y - size);
03332 glVertex2f(proj.x, proj.y + size);
03333 glEnd();
03334 glEnable(GL_DEPTH_TEST);
03335 stopScreenCoordinatesSystem();
03336 }
03337
03338
03339
03340
03341
03342 ManipulatedFrame* mf = NULL;
03343 Vec pnt;
03344 if (camera()->frame()->action_ == SCREEN_ROTATE)
03345 {
03346 mf = camera()->frame();
03347 pnt = camera()->revolveAroundPoint();
03348 }
03349 if (manipulatedFrame() && (manipulatedFrame()->action_ == SCREEN_ROTATE))
03350 {
03351 mf = manipulatedFrame();
03352
03353
03354 pnt = manipulatedFrame()->position();
03355 }
03356
03357 if (mf)
03358 {
03359 pnt = camera()->projectedCoordinatesOf(pnt);
03360 startScreenCoordinatesSystem();
03361 glDisable(GL_LIGHTING);
03362 glDisable(GL_DEPTH_TEST);
03363 glLineWidth(3.0);
03364 glBegin(GL_LINES);
03365 glVertex2f(pnt.x, pnt.y);
03366 glVertex2f(mf->prevPos_.x(), mf->prevPos_.y());
03367 glEnd();
03368 glEnable(GL_DEPTH_TEST);
03369 stopScreenCoordinatesSystem();
03370 }
03371
03372
03373 if (camera()->frame()->action_ == ZOOM_ON_REGION)
03374 {
03375 startScreenCoordinatesSystem();
03376 glDisable(GL_LIGHTING);
03377 glDisable(GL_DEPTH_TEST);
03378 glLineWidth(2.0);
03379 glBegin(GL_LINE_LOOP);
03380 glVertex2i(camera()->frame()->pressPos_.x(), camera()->frame()->pressPos_.y());
03381 glVertex2i(camera()->frame()->prevPos_.x(), camera()->frame()->pressPos_.y());
03382 glVertex2i(camera()->frame()->prevPos_.x(), camera()->frame()->prevPos_.y());
03383 glVertex2i(camera()->frame()->pressPos_.x(), camera()->frame()->prevPos_.y());
03384 glEnd();
03385 glEnable(GL_DEPTH_TEST);
03386 stopScreenCoordinatesSystem();
03387 }
03388 }
03389
03393 void QGLViewer::setVisualHintsMask(int mask, int delay)
03394 {
03395 visualHint_ = visualHint_ | mask;
03396 QTimer::singleShot(delay, this, SLOT(resetVisualHints()));
03397 }
03398
03400 void QGLViewer::resetVisualHints()
03401 {
03402 visualHint_ = 0;
03403 }
03404 #endif
03405
03407
03409
03419 void QGLViewer::drawArrow(float length, float radius, int nbSubdivisions)
03420 {
03421 static GLUquadric* quadric = gluNewQuadric();
03422
03423 if (radius < 0.0)
03424 radius = 0.05 * length;
03425
03426 const float head = 2.5*(radius / length) + 0.1;
03427 const float coneRadiusCoef = 4.0 - 5.0 * head;
03428
03429 gluCylinder(quadric, radius, radius, length * (1.0 - head/coneRadiusCoef), nbSubdivisions, 1);
03430 glTranslatef(0.0, 0.0, length * (1.0 - head));
03431 gluCylinder(quadric, coneRadiusCoef * radius, 0.0, head * length, nbSubdivisions, 1);
03432 glTranslatef(0.0, 0.0, -length * (1.0 - head));
03433 }
03434
03439 void QGLViewer::drawArrow(const Vec& from, const Vec& to, float radius, int nbSubdivisions)
03440 {
03441 glPushMatrix();
03442 glTranslatef(from[0],from[1],from[2]);
03443 const Vec dir = to-from;
03444 glMultMatrixd(Quaternion(Vec(0,0,1), dir).matrix());
03445 QGLViewer::drawArrow(dir.norm(), radius, nbSubdivisions);
03446 glPopMatrix();
03447 }
03448
03467 void QGLViewer::drawAxis(float length)
03468 {
03469 const float charWidth = length / 40.0;
03470 const float charHeight = length / 30.0;
03471 const float charShift = 1.04 * length;
03472
03473 GLboolean lighting, colorMaterial;
03474 glGetBooleanv(GL_LIGHTING, &lighting);
03475 glGetBooleanv(GL_COLOR_MATERIAL, &colorMaterial);
03476
03477 glDisable(GL_LIGHTING);
03478
03479 glBegin(GL_LINES);
03480
03481 glVertex3f(charShift, charWidth, -charHeight);
03482 glVertex3f(charShift, -charWidth, charHeight);
03483 glVertex3f(charShift, -charWidth, -charHeight);
03484 glVertex3f(charShift, charWidth, charHeight);
03485
03486 glVertex3f( charWidth, charShift, charHeight);
03487 glVertex3f(0.0, charShift, 0.0);
03488 glVertex3f(-charWidth, charShift, charHeight);
03489 glVertex3f(0.0, charShift, 0.0);
03490 glVertex3f(0.0, charShift, 0.0);
03491 glVertex3f(0.0, charShift, -charHeight);
03492
03493 glVertex3f(-charWidth, charHeight, charShift);
03494 glVertex3f( charWidth, charHeight, charShift);
03495 glVertex3f( charWidth, charHeight, charShift);
03496 glVertex3f(-charWidth, -charHeight, charShift);
03497 glVertex3f(-charWidth, -charHeight, charShift);
03498 glVertex3f( charWidth, -charHeight, charShift);
03499 glEnd();
03500
03501 glEnable(GL_LIGHTING);
03502 glDisable(GL_COLOR_MATERIAL);
03503
03504 float color[4];
03505 color[0] = 0.7f; color[1] = 0.7f; color[2] = 1.0f; color[3] = 1.0f;
03506 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
03507 QGLViewer::drawArrow(length, 0.01*length);
03508
03509 color[0] = 1.0f; color[1] = 0.7f; color[2] = 0.7f; color[3] = 1.0f;
03510 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
03511 glPushMatrix();
03512 glRotatef(90.0, 0.0, 1.0, 0.0);
03513 QGLViewer::drawArrow(length, 0.01*length);
03514 glPopMatrix();
03515
03516 color[0] = 0.7f; color[1] = 1.0f; color[2] = 0.7f; color[3] = 1.0f;
03517 glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, color);
03518 glPushMatrix();
03519 glRotatef(-90.0, 1.0, 0.0, 0.0);
03520 QGLViewer::drawArrow(length, 0.01*length);
03521 glPopMatrix();
03522
03523 if (colorMaterial)
03524 glEnable(GL_COLOR_MATERIAL);
03525 if (!lighting)
03526 glDisable(GL_LIGHTING);
03527 }
03528
03535 void QGLViewer::drawGrid(float size, int nbSubdivisions)
03536 {
03537 GLboolean lighting;
03538 glGetBooleanv(GL_LIGHTING, &lighting);
03539
03540 glDisable(GL_LIGHTING);
03541
03542 glBegin(GL_LINES);
03543 for (int i=0; i<=nbSubdivisions; ++i)
03544 {
03545 const float pos = size*(2.0*i/nbSubdivisions-1.0);
03546 glVertex2f(pos, -size);
03547 glVertex2f(pos, +size);
03548 glVertex2f(-size, pos);
03549 glVertex2f( size, pos);
03550 }
03551 glEnd();
03552
03553 if (lighting)
03554 glEnable(GL_LIGHTING);
03555 }
03556
03558
03560
03562 void QGLViewer::saveStateToFileForAllViewers()
03563 {
03564 #if QT_VERSION >= 0x040000
03565 Q_FOREACH (QGLViewer* viewer, QGLViewer::QGLViewerPool())
03566 {
03567 #else
03568 QPtrListIterator<QGLViewer> it(QGLViewer::QGLViewerPool());
03569 for (QGLViewer* viewer; (viewer = it.current()) != 0; ++it)
03570 {
03571 #endif
03572 if (viewer)
03573 viewer->saveStateToFile();
03574 }
03575 }
03576
03578
03580
03594 QString QGLViewer::stateFileName() const
03595 {
03596 QString name = stateFileName_;
03597
03598 if (!name.isEmpty() && QGLViewer::QGLViewerIndex(this) > 0)
03599 {
03600 QFileInfo fi(name);
03601 #if QT_VERSION >= 0x040000
03602 if (fi.suffix().isEmpty())
03603 #else
03604 if (fi.extension(false).isEmpty())
03605 #endif
03606 name += QString::number(QGLViewer::QGLViewerIndex(this));
03607 else
03608 #if QT_VERSION >= 0x040000
03609 name = fi.absolutePath() + '/' + fi.completeBaseName() + QString::number(QGLViewer::QGLViewerIndex(this)) + "." + fi.suffix();
03610 #else
03611 # if QT_VERSION >= 0x030000
03612 name = fi.dirPath() + '/' + fi.baseName(true) + QString::number(QGLViewer::QGLViewerIndex(this)) + "." + fi.extension(false);
03613 # else
03614 name = fi.dirPath() + '/' + fi.baseName() + QString::number(QGLViewer::QGLViewerIndex(this)) + "." + fi.extension();
03615 # endif
03616 #endif
03617 }
03618
03619 return name;
03620 }
03621
03629 void QGLViewer::saveStateToFile()
03630 {
03631 QString name = stateFileName();
03632
03633 if (name.isEmpty())
03634 return;
03635
03636 QFileInfo fileInfo(name);
03637
03638 if (fileInfo.isDir())
03639 {
03640 QMessageBox::warning(this, tr("Save to file error", "Message box window title"), tr("State file name (%1) references a directory instead of a file.").arg(name));
03641 return;
03642 }
03643
03644 #if QT_VERSION >= 0x040000
03645 const QString dirName = fileInfo.absolutePath();
03646 #else
03647 const QString dirName = fileInfo.dirPath();
03648 #endif
03649 if (!QFileInfo(dirName).exists())
03650 {
03651 QDir dir;
03652 #if QT_VERSION >= 0x040000
03653 if (!(dir.mkdir(dirName)))
03654 #else
03655 if (!(dir.mkdir(dirName, true)))
03656 #endif
03657 {
03658 QMessageBox::warning(this, tr("Save to file error", "Message box window title"), tr("Unable to create directory %1").arg(dirName));
03659 return;
03660 }
03661 }
03662
03663
03664 QFile f(name);
03665 #if QT_VERSION >= 0x040000
03666 if (f.open(QIODevice::WriteOnly))
03667 #else
03668 if (f.open(IO_WriteOnly))
03669 #endif
03670 {
03671 QTextStream out(&f);
03672 QDomDocument doc("QGLVIEWER");
03673 doc.appendChild(domElement("QGLViewer", doc));
03674 doc.save(out, 2);
03675 f.flush();
03676 f.close();
03677 }
03678 else
03679 #if QT_VERSION < 0x030200
03680 QMessageBox::warning(this, tr("Save to file error", "Message box window title"), tr("Unable to save to file %1").arg(name));
03681 #else
03682 QMessageBox::warning(this, tr("Save to file error", "Message box window title"), tr("Unable to save to file %1").arg(name) + ":\n" + f.errorString());
03683 #endif
03684 }
03685
03706 bool QGLViewer::restoreStateFromFile()
03707 {
03708 QString name = stateFileName();
03709
03710 if (name.isEmpty())
03711 return false;
03712
03713 QFileInfo fileInfo(name);
03714
03715 if (!fileInfo.isFile())
03716
03717 return false;
03718
03719 if (!fileInfo.isReadable())
03720 {
03721 QMessageBox::warning(this, tr("Problem in state restoration", "Message box window title"), tr("File %1 is not readable.").arg(name));
03722 return false;
03723 }
03724
03725
03726 QFile f(name);
03727 #if QT_VERSION >= 0x040000
03728 if (f.open(QIODevice::ReadOnly) == true)
03729 #else
03730 if (f.open(IO_ReadOnly) == true)
03731 #endif
03732 {
03733 QDomDocument doc;
03734 doc.setContent(&f);
03735 f.close();
03736 QDomElement main = doc.documentElement();
03737 initFromDOMElement(main);
03738 }
03739 else
03740 {
03741 #if QT_VERSION < 0x030200
03742 QMessageBox::warning(this, tr("Open file error", "Message box window title"), tr("Unable to open file %1").arg(name));
03743 #else
03744 QMessageBox::warning(this, tr("Open file error", "Message box window title"), tr("Unable to open file %1").arg(name) + ":\n" + f.errorString());
03745 #endif
03746 return false;
03747 }
03748
03749 return true;
03750 }
03751
03784 QDomElement QGLViewer::domElement(const QString& name, QDomDocument& document) const
03785 {
03786 QDomElement de = document.createElement(name);
03787 de.setAttribute("version", QGLViewerVersionString());
03788
03789 QDomElement stateNode = document.createElement("State");
03790
03791 stateNode.appendChild(DomUtils::QColorDomElement(foregroundColor(), "foregroundColor", document));
03792 stateNode.appendChild(DomUtils::QColorDomElement(backgroundColor(), "backgroundColor", document));
03793 stateNode.setAttribute("stereo", (displaysInStereo()?"true":"false"));
03794 stateNode.setAttribute("cameraMode", (cameraIsInRevolveMode()?"revolve":"fly"));
03795 de.appendChild(stateNode);
03796
03797 QDomElement displayNode = document.createElement("Display");
03798 displayNode.setAttribute("axisIsDrawn", (axisIsDrawn()?"true":"false"));
03799 displayNode.setAttribute("gridIsDrawn", (gridIsDrawn()?"true":"false"));
03800 displayNode.setAttribute("FPSIsDisplayed", (FPSIsDisplayed()?"true":"false"));
03801 displayNode.setAttribute("cameraIsEdited", (cameraIsEdited()?"true":"false"));
03802
03803 de.appendChild(displayNode);
03804
03805 QDomElement geometryNode = document.createElement("Geometry");
03806 geometryNode.setAttribute("fullScreen", (isFullScreen()?"true":"false"));
03807 if (isFullScreen())
03808 {
03809 geometryNode.setAttribute("prevPosX", QString::number(prevPos_.x()));
03810 geometryNode.setAttribute("prevPosY", QString::number(prevPos_.y()));
03811 }
03812 else
03813 {
03814 QWidget* tlw = topLevelWidget();
03815 geometryNode.setAttribute("width", QString::number(tlw->width()));
03816 geometryNode.setAttribute("height", QString::number(tlw->height()));
03817 geometryNode.setAttribute("posX", QString::number(tlw->pos().x()));
03818 geometryNode.setAttribute("posY", QString::number(tlw->pos().y()));
03819 }
03820 de.appendChild(geometryNode);
03821
03822
03823 if (cameraIsEdited())
03824 camera()->setZClippingCoefficient(previousCameraZClippingCoefficient_);
03825 de.appendChild(camera()->domElement("Camera", document));
03826 if (cameraIsEdited())
03827
03828 camera()->setZClippingCoefficient(5.0);
03829
03830 if (manipulatedFrame())
03831 de.appendChild(manipulatedFrame()->domElement("ManipulatedFrame", document));
03832
03833 return de;
03834 }
03835
03870 void QGLViewer::initFromDOMElement(const QDomElement& element)
03871 {
03872 const QString version = element.attribute("version");
03873
03874 if (version[0] != '2')
03875
03876 #if QT_VERSION >= 0x040000
03877 qWarning("State file created using QGLViewer version %s may not be correctly read.", version.toLatin1().constData());
03878 #else
03879 qWarning("State file created using QGLViewer version %s may not be correctly read.", version.latin1());
03880 #endif
03881
03882 QDomElement child=element.firstChild().toElement();
03883 bool tmpCameraIsEdited = cameraIsEdited();
03884 while (!child.isNull())
03885 {
03886 if (child.tagName() == "State")
03887 {
03888
03889
03890 setStereoDisplay(DomUtils::boolFromDom(child, "stereo", false));
03891 if ((child.attribute("cameraMode", "revolve") == "fly") && (cameraIsInRevolveMode()))
03892 toggleCameraMode();
03893
03894 QDomElement ch=child.firstChild().toElement();
03895 while (!ch.isNull())
03896 {
03897 if (ch.tagName() == "foregroundColor")
03898 setForegroundColor(DomUtils::QColorFromDom(ch));
03899 if (ch.tagName() == "backgroundColor")
03900 setBackgroundColor(DomUtils::QColorFromDom(ch));
03901 ch = ch.nextSibling().toElement();
03902 }
03903 }
03904
03905 if (child.tagName() == "Display")
03906 {
03907
03908 setAxisIsDrawn(DomUtils::boolFromDom(child, "axisIsDrawn", false));
03909 setGridIsDrawn(DomUtils::boolFromDom(child, "gridIsDrawn", false));
03910 setFPSIsDisplayed(DomUtils::boolFromDom(child, "FPSIsDisplayed", false));
03911
03912 tmpCameraIsEdited = DomUtils::boolFromDom(child, "cameraIsEdited", false);
03913
03914 }
03915
03916 if (child.tagName() == "Geometry")
03917 {
03918 setFullScreen(DomUtils::boolFromDom(child, "fullScreen", false));
03919
03920 if (isFullScreen())
03921 {
03922 prevPos_.setX(DomUtils::intFromDom(child, "prevPosX", 0));
03923 prevPos_.setY(DomUtils::intFromDom(child, "prevPosY", 0));
03924 }
03925 else
03926 {
03927 int width = DomUtils::intFromDom(child, "width", 600);
03928 int height = DomUtils::intFromDom(child, "height", 400);
03929 topLevelWidget()->resize(width, height);
03930 camera()->setScreenWidthAndHeight(this->width(), this->height());
03931
03932 QPoint pos;
03933 pos.setX(DomUtils::intFromDom(child, "posX", 0));
03934 pos.setY(DomUtils::intFromDom(child, "posY", 0));
03935 topLevelWidget()->move(pos);
03936 }
03937 }
03938
03939 if (child.tagName() == "Camera")
03940 {
03941 connectAllCameraKFIInterpolatedSignals(false);
03942 camera()->initFromDOMElement(child);
03943 connectAllCameraKFIInterpolatedSignals();
03944 }
03945
03946 if ((child.tagName() == "ManipulatedFrame") && (manipulatedFrame()))
03947 manipulatedFrame()->initFromDOMElement(child);
03948
03949 child = child.nextSibling().toElement();
03950 }
03951
03952
03953
03954
03955
03956 cameraIsEdited_ = tmpCameraIsEdited;
03957 if (cameraIsEdited_)
03958 {
03959 previousCameraZClippingCoefficient_ = camera()->zClippingCoefficient();
03960
03961 camera()->setZClippingCoefficient(5.0);
03962 }
03963 }
03964
03965 #ifndef DOXYGEN
03966
03968 void QGLViewer::saveToFile(const QString& fileName)
03969 {
03970 if (!fileName.isEmpty())
03971 setStateFileName(fileName);
03972
03973 qWarning("saveToFile() is deprecated, use saveStateToFile() instead.");
03974 saveStateToFile();
03975 }
03976
03979 bool QGLViewer::restoreFromFile(const QString& fileName)
03980 {
03981 if (!fileName.isEmpty())
03982 setStateFileName(fileName);
03983
03984 qWarning("restoreFromFile() is deprecated, use restoreStateFromFile() instead.");
03985 return restoreStateFromFile();
03986 }
03987 #endif
03988
04042 void QGLViewer::copyBufferToTexture(GLint internalFormat, GLenum format)
04043 {
04044 int h = 16;
04045 int w = 16;
04046
04047 while (w < width())
04048 w <<= 1;
04049 while (h < height())
04050 h <<= 1;
04051
04052 bool init = false;
04053
04054 if ((w != bufferTextureWidth_) || (h != bufferTextureHeight_))
04055 {
04056 bufferTextureWidth_ = w;
04057 bufferTextureHeight_ = h;
04058 bufferTextureMaxU_ = width() / float(bufferTextureWidth_);
04059 bufferTextureMaxV_ = height() / float(bufferTextureHeight_);
04060 init = true;
04061 }
04062
04063 if (bufferTextureId() == 0)
04064 {
04065 glGenTextures(1, &bufferTextureId_);
04066 glBindTexture(GL_TEXTURE_2D, bufferTextureId_);
04067 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
04068 glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
04069 init = true;
04070 }
04071 else
04072 glBindTexture(GL_TEXTURE_2D, bufferTextureId_);
04073
04074 if ((format != previousBufferTextureFormat_) ||
04075 (internalFormat != previousBufferTextureInternalFormat_))
04076 {
04077 previousBufferTextureFormat_ = format;
04078 previousBufferTextureInternalFormat_ = internalFormat;
04079 init = true;
04080 }
04081
04082 if (init)
04083 {
04084 if (format == GL_NONE)
04085 format = internalFormat;
04086
04087 glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, bufferTextureWidth_, bufferTextureHeight_, 0, format, GL_UNSIGNED_BYTE, NULL);
04088 }
04089
04090 glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, width(), height());
04091 }
04092
04099 GLuint QGLViewer::bufferTextureId() const
04100 {
04101 if (glIsTexture(bufferTextureId_))
04102 return bufferTextureId_;
04103 else
04104 return 0;
04105 }