1// @configure_input@ 2 3/**************************************************************************\ 4 * Copyright (c) Kongsberg Oil & Gas Technologies AS 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are 9 * met: 10 * 11 * Redistributions of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 14 * Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * Neither the name of the copyright holder nor the names of its 19 * contributors may be used to endorse or promote products derived from 20 * this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 26 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33\**************************************************************************/ 34 35// This file contains the generic, "templatize-able" parts of the 36// So*FullViewer sourcecode. 37 38/*! 39 \class So@Gui@FullViewer So@Gui@FullViewer.h Inventor/@Gui@/viewers/So@Gui@FullViewer.h 40 \brief The So@Gui@FullViewer class adds some user interface components to the viewer canvas. 41 42 \ingroup components viewers 43 44 The So@Gui@FullViewer is an abstract viewer class which extends it's 45 superclass (the basic So@Gui@Viewer class) with two major user 46 interface additions: 47 48 <ul> 49 50 <li>decorations around the render canvas, with buttons and 51 thumbwheels to control camera interaction and various other aspects 52 of model / scene viewing</li> 53 54 <li>a popup menu, invoked with the right mouse button, which 55 controls yet more aspects of the rendering and the viewer</li> 56 57 </ul> 58 59 The user interface features listed above are the common parts of the 60 user interfaces of the So@Gui@FullViewer's non-abstract subclasses. 61 62 For "real" application programs, the viewers / components from this 63 class onwards and further down in the inheritance hierarchy is 64 usually not all that interesting, as they enforces too much extra 65 user interface cruft not compatible with the look and feel of the 66 other parts of the application user interface. So most "real" 67 applications will use either the So@Gui@Viewer or the 68 So@Gui@RenderArea as their base-level component, and then inherit 69 one of these down into one's own "proper" viewer classes. 70 71 The non-abstract subclasses of the So@Gui@FullViewer class are 72 viewer components often used as a test-bed for prototyping / rapid 73 application development when doing quick testing of scenes, 74 stand-alone 3D-models, animation techniques, etc etc. 75 76 77 \sa So@Gui@ConstrainedViewer, So@Gui@ExaminerViewer, So@Gui@PlaneViewer 78*/ 79 80 81// ************************************************************************* 82 83#include <float.h> 84 85#include <Inventor/@Gui@/viewers/So@Gui@FullViewer.h> 86#include <Inventor/@Gui@/viewers/So@Gui@FullViewerP.h> 87#include <Inventor/@Gui@/widgets/So@Gui@PopupMenu.h> 88#include <so@gui@defs.h> 89 90#include <Inventor/events/SoMouseButtonEvent.h> 91#include <Inventor/events/SoKeyboardEvent.h> 92#include <Inventor/errors/SoDebugError.h> 93#include <Inventor/nodes/SoOrthographicCamera.h> 94#include <Inventor/nodes/SoPerspectiveCamera.h> 95 96#ifdef HAVE_CONFIG_H 97#include <config.h> 98#endif // HAVE_CONFIG_H 99 100// ************************************************************************ 101 102#define PRIVATE(o) (o->pimpl) 103#define PUBLIC(o) (o->pub) 104 105// ************************************************************************ 106 107// Note: the following function documentation block will also be used 108// for all the miscellaneous viewer subclasses, so keep it general. 109/*! 110 \fn void So@Gui@FullViewer::createViewerButtons(@WIDGET@ parent, SbPList * buttonlist) 111 112 Set up the viewer buttons with pixmaps and event connections. 113 114 115 One important note if you want to override this method to add your 116 own buttons to the list (in the explanation below, it is assumed 117 that you know how virtual function table pointers are handled by 118 C++): 119 120 createViewerButtons() is called (indirectly) from the constructors 121 of the viewer classes. This means that you need to delay it's 122 invocation until your own subclass's constructor is run, because 123 otherwise your re-implementation won't have been added to the 124 internal virtual function table yet. 125 126 Delaying a superclass viewer from building it's decorations is done 127 by passing build==FALSE as the last argument of the protected 128 constructors. You will then have to explicitly trigger the building 129 in your own constructor. 130 131 Here's a minimal example that shows the steps needed to be able to 132 override createViewerButtons() from So@Gui@ExaminerViewer: 133 134 \code 135 class MyExaminerViewer : public So@Gui@ExaminerViewer { 136 137 public: 138 MyExaminerViewer(@WIDGET@ parent); 139 140 protected: 141 virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist); 142 }; 143 144 MyExaminerViewer::MyExaminerViewer(@WIDGET@ parent) 145 : So@Gui@ExaminerViewer(parent, NULL, TRUE, 146 So@Gui@FullViewer::BUILD_ALL, So@Gui@FullViewer::BROWSER, 147 // build == FALSE, to delay creation of decorations 148 FALSE) 149 { 150 // Explicitly trigger the construction of viewer decorations. 151 @WIDGET@ widget = this->buildWidget(this->getParentWidget()); 152 this->setBaseWidget(widget); 153 } 154 155 void 156 MyExaminerViewer::createViewerButtons(@WIDGET@ parent, SbPList * buttonlist) 157 { 158 So@Gui@ExaminerViewer::createViewerButtons(parent, buttonlist); 159 // [now add your own button(s) to the buttonlist] 160 } 161 \endcode 162*/ 163 164/*! 165 \enum So@Gui@FullViewer::BuildFlag 166 167 Valid values for the constructor argument that decides how much of 168 the user interface features to set up. The enum values are bitflags 169 that can be OR'ed together. 170*/ 171/*! 172 \var So@Gui@FullViewer::BuildFlag So@Gui@FullViewer::BUILD_NONE 173 174 Do not add any of the user interface components. 175*/ 176/*! 177 \var So@Gui@FullViewer::BuildFlag So@Gui@FullViewer::BUILD_DECORATION 178 179 Only build and set up the decorations around the OpenGL canvas. 180*/ 181/*! 182 \var So@Gui@FullViewer::BuildFlag So@Gui@FullViewer::BUILD_POPUP 183 184 Only build the popup menu. (Activated with the right mousebutton.) 185*/ 186/*! 187 \var So@Gui@FullViewer::BuildFlag So@Gui@FullViewer::BUILD_ALL 188 189 Build all user interface components of the So@Gui@FullViewer. 190*/ 191 192/*! 193 \var @WIDGET@ So@Gui@FullViewer::leftDecoration 194 The root widget for the left-side decorations. 195*/ 196 197/*! 198 \var @WIDGET@ So@Gui@FullViewer::leftWheel 199 The widget representing the thumbwheel left of the render canvas. 200*/ 201 202/*! 203 \var @WIDGET@ So@Gui@FullViewer::leftWheelLabel 204 Label widget of left wheel. 205*/ 206 207/*! 208 \var char * So@Gui@FullViewer::leftWheelStr 209 Text of left thumbwheel's label. 210*/ 211 212/*! 213 \var float So@Gui@FullViewer::leftWheelVal 214 Current value of the left thumbwheel. 215*/ 216 217/*! 218 \var @WIDGET@ So@Gui@FullViewer::bottomDecoration 219 The root widget for the bottom decorations. 220*/ 221 222/*! 223 \var @WIDGET@ So@Gui@FullViewer::bottomWheel 224 The widget representing the thumbwheel below the render canvas. 225*/ 226 227/*! 228 \var @WIDGET@ So@Gui@FullViewer::bottomWheelLabel 229 Label widget of bottom wheel. 230*/ 231 232/*! 233 \var char * So@Gui@FullViewer::bottomWheelStr 234 Text of bottom thumbwheel's label. 235*/ 236 237/*! 238 \var float So@Gui@FullViewer::bottomWheelVal 239 Current value of the bottom thumbwheel. 240*/ 241 242/*! 243 \var @WIDGET@ So@Gui@FullViewer::rightDecoration 244 The root widget for the right-side decorations. 245*/ 246 247/*! 248 \var @WIDGET@ So@Gui@FullViewer::rightWheel 249 The widget representing the thumbwheel on the right side of the render canvas. 250*/ 251 252/*! 253 \var @WIDGET@ So@Gui@FullViewer::rightWheelLabel 254 Label widget of right wheel. 255*/ 256 257/*! 258 \var char * So@Gui@FullViewer::rightWheelStr 259 Text of right thumbwheel's label. 260*/ 261 262/*! 263 \var float So@Gui@FullViewer::rightWheelVal 264 Current value of the right-side thumbwheel. 265*/ 266 267/*! 268 \var So@Gui@PopupMenu * So@Gui@FullViewer::prefmenu 269 Pointer to the popup menu instance. 270*/ 271 272/*! 273 \fn So@Gui@FullViewer::So@Gui@FullViewer(@WIDGET@ parent, const char * name, SbBool embed, So@Gui@FullViewer::BuildFlag buildFlag, So@Gui@Viewer::Type type, SbBool build) 274 275 Constructor. See parent class for explanation of arguments. 276 277 Subclasses will probably usually call with the \a buildNow flag set 278 to \c FALSE to be able to do delayed building of the OpenGL canvas 279 after other setup tasks has been performed. 280*/ 281 282/*! 283 \fn So@Gui@FullViewer::~So@Gui@FullViewer() 284 285 Destructor. 286*/ 287 288/*! 289 \fn void So@Gui@FullViewer::setDecoration(const SbBool enable) 290 291 Turn the viewer decorations on or off. 292 293 \sa isDecoration() 294*/ 295 296/*! 297 \fn SbBool So@Gui@FullViewer::isDecoration(void) const 298 299 Return \c TRUE if the viewer decorations are on, otherwise \c FALSE. 300 301 \sa setDecoration() 302*/ 303 304/*! 305 \fn void So@Gui@FullViewer::setPopupMenuEnabled(const SbBool enable) 306 307 Decide whether or not if clicking with the right mouse button on 308 the OpenGL canvas should reveal a preferences popup menu when in 309 viewing mode. 310 311 \sa isPopupMenuEnabled() 312*/ 313 314/*! 315 \fn SbBool So@Gui@FullViewer::isPopupMenuEnabled(void) const 316 317 Return \c TRUE if the popup preferences menu is enabled, 318 otherwise \c FALSE. 319 320 \sa setPopupMenuEnabled() 321*/ 322 323/*! 324 \fn @WIDGET@ So@Gui@FullViewer::getAppPushButtonParent(void) const 325 326 Returns the widget which is used as the parent of application 327 specified buttons. The row of application buttons (if any) will be 328 placed in the upper left corner. 329 330 \sa addAppPushButton(), insertAppPushButton(), removeAppPushButton() 331*/ 332 333/*! 334 \fn void So@Gui@FullViewer::addAppPushButton(@WIDGET@ newButton) 335 336 Add an application specific push button to the viewer decorations. 337 Application buttons will be laid out in a vertical row from the 338 upper left corner. 339 340 The button will be added bottom-most. 341 342 \sa insertAppPushButton(), removeAppPushButton(), getAppPushButtonParent() 343*/ 344 345/*! 346 \fn void So@Gui@FullViewer::insertAppPushButton(@WIDGET@ newButton, int index) 347 348 Insert an application specific push button to the viewer decorations 349 at the given \c index. 350 351 \sa addAppPushButton(), removeAppPushButton(), getAppPushButtonParent() 352*/ 353 354/*! 355 \fn void So@Gui@FullViewer::removeAppPushButton(@WIDGET@ oldButton) 356 357 Remove one of the application specific buttons. 358 359 \sa addAppPushButton(), insertAppPushButton() 360*/ 361 362/*! 363 \fn int So@Gui@FullViewer::findAppPushButton(@WIDGET@ oldButton) const 364 365 Return the index of a particular button that has been specified by 366 the application, or -1 of the button has not been added. 367 368 \sa addAppPushButton() 369*/ 370 371/*! 372 \fn int So@Gui@FullViewer::lengthAppPushButton(void) const 373 374 Return number of application specific buttons added. 375 376 \sa addAppPushButton(), insertAddAppPushButton() 377*/ 378 379/*! 380 \fn @WIDGET@ So@Gui@FullViewer::getRenderAreaWidget(void) const 381 382 Returns the render area OpenGL canvas widget. 383*/ 384 385/*! 386 \fn void So@Gui@FullViewer::buildDecoration(@WIDGET@ parent) 387 388 Build viewer decorations. 389*/ 390 391/*! 392 \fn @WIDGET@ So@Gui@FullViewer::buildLeftTrim(@WIDGET@ parent) 393 394 Build decorations on the left of the render canvas. Override this 395 method in subclasses if you want your own decorations on the viewer 396 window. 397 398 The decoration will be 30 pixels wide. 399*/ 400 401/*! 402 \fn @WIDGET@ So@Gui@FullViewer::buildBottomTrim(@WIDGET@ parent) 403 404 Build decorations on the bottom of the render canvas. Override this 405 method in subclasses if you want your own decorations on the viewer window. 406*/ 407 408/*! 409 \fn @WIDGET@ So@Gui@FullViewer::buildRightTrim(@WIDGET@ parent) 410 411 Build decorations on the right side of the render canvas. Override this 412 method in subclasses if you want your own decorations on the viewer window. 413*/ 414 415/*! 416 \fn @WIDGET@ So@Gui@FullViewer::buildAppButtons(@WIDGET@ parent) 417 418 Build the application specified button row (if any buttons were 419 set up). 420*/ 421 422/*! 423 \fn @WIDGET@ So@Gui@FullViewer::buildViewerButtons(@WIDGET@ parent) 424 425 Build and layout viewer specified button row. 426*/ 427 428/*! 429 \fn void So@Gui@FullViewer::buildPopupMenu(void) 430 431 Make a popup menu with preferences settings. 432 433 One important note as for when you want to override this function in 434 a subclass: be aware that it will usually be invoked (indirectly) 435 from this class's constructor. That is \e before the table of 436 virtual function pointers has been set up for the subclass, and 437 because of this, the function will not be called in the subclass 438 even though it is virtual. 439 440 To make the overriding actually be in effect, you need to delay 441 building the widgets of this class. For information on how to do 442 that, see the documentation of 443 So@Gui@FullViewer::createViewerButtons(). 444*/ 445 446/*! 447 \fn void So@Gui@FullViewer::openPopupMenu(const SbVec2s position) 448 449 NOTE: This method is not part of the original InventorXt API. 450*/ 451 452/*! 453 \fn void So@Gui@FullViewer::setLeftWheelString(const char * const string) 454 455 Set label of the left thumbwheel. 456*/ 457 458/*! 459 \fn void So@Gui@FullViewer::setBottomWheelString(const char * const string) 460 461 Set label of the bottom thumbwheel. 462*/ 463 464/*! 465 \fn void So@Gui@FullViewer::setRightWheelString(const char * const string) 466 467 Set label of the right thumbwheel. 468*/ 469 470// ************************************************************************ 471 472// Note: the following function documentation blocks for thumbwheel 473// handling will also be used for all the miscellaneous viewer 474// subclasses, so keep'em general. 475 476/*! 477 Called when the user start to drag the thumbwheel in the left 478 frame. Override this method in subclassed viewers to provide your 479 own functionality on the thumbwheel. 480 481 \sa leftWheelMotion(), leftWheelFinish() 482 \sa bottomWheelStart(), rightWheelStart() 483*/ 484void 485So@Gui@FullViewer::leftWheelStart(void) 486{ 487 this->interactiveCountInc(); 488} 489 490/*! 491 Called repeatedly as the user drags the thumbwheel in the left 492 frame. Override this method in subclassed viewers to provide your 493 own functionality on the thumbwheel. 494 495 \sa leftWheelStart(), leftWheelFinish() 496 \sa bottomWheelStart(), rightWheelStart() 497*/ 498void 499So@Gui@FullViewer::leftWheelMotion(float value) 500{ 501 this->leftWheelVal = value; 502} 503 504/*! 505 Called as the user let go of the thumbwheel in the left frame 506 after a drag operation. Override this method in subclassed viewers 507 to provide your own functionality on the thumbwheel. 508 509 \sa leftWheelStart(), leftWheelMotion() 510 \sa bottomWheelStart(), rightWheelStart() 511*/ 512void 513So@Gui@FullViewer::leftWheelFinish(void) 514{ 515 this->interactiveCountDec(); 516} 517 518/*! 519 Set a new value for the left thumbwheel. 520*/ 521void 522So@Gui@FullViewer::setLeftWheelValue(const float value) 523{ 524 this->leftWheelVal = value; 525 // Wheel may not be constructed yet, but we need to be robust, as 526 // set*WheelValue() is used from subclasses. 527 if (this->leftWheel) { 528 So@Gui@FullViewerP::setThumbWheelValue(this->leftWheel, value); 529 } 530} 531 532/*! 533 Get current value of the left thumbwheel. 534 535 \sa leftWheelMotion() 536*/ 537float 538So@Gui@FullViewer::getLeftWheelValue(void) const 539{ 540 return this->leftWheelVal; 541} 542 543/*! 544 Called when the user start to drag the thumbwheel in the bottom 545 frame. Override this method in subclassed viewers to provide your 546 own functionality on the thumbwheel. 547 548 \sa bottomWheelMotion(), bottomWheelFinish() 549 \sa leftWheelStart(), rightWheelStart() 550*/ 551void 552So@Gui@FullViewer::bottomWheelStart(void) 553{ 554 this->interactiveCountInc(); 555} 556 557/*! 558 Called repeatedly as the user drags the thumbwheel in the bottom 559 frame. Override this method in subclassed viewers to provide your 560 own functionality on the thumbwheel. 561 562 \sa bottomWheelStart(), bottomWheelFinish() 563 \sa leftWheelStart(), rightWheelStart() 564*/ 565void 566So@Gui@FullViewer::bottomWheelMotion(float value) 567{ 568 this->bottomWheelVal = value; 569} 570 571/*! 572 Called as the user let go of the thumbwheel in the bottom frame 573 after a drag operation. Override this method in subclassed viewers 574 to provide your own functionality on the thumbwheel. 575 576 \sa bottomWheelStart(), bottomWheelMotion() 577 \sa leftWheelStart(), rightWheelStart() 578*/ 579void 580So@Gui@FullViewer::bottomWheelFinish(void) 581{ 582 this->interactiveCountDec(); 583} 584 585/*! 586 Set a new value for the bottom thumbwheel. 587*/ 588void 589So@Gui@FullViewer::setBottomWheelValue(const float value) 590{ 591 this->bottomWheelVal = value; 592 // Wheel may not be constructed yet, but we need to be robust, as 593 // set*WheelValue() is used from subclasses. 594 if (this->bottomWheel) { 595 So@Gui@FullViewerP::setThumbWheelValue(this->bottomWheel, value); 596 } 597} 598 599/*! 600 Get current value of the bottom thumbwheel. 601 602 \sa bottomWheelMotion() 603*/ 604float 605So@Gui@FullViewer::getBottomWheelValue(void) const 606{ 607 return this->bottomWheelVal; 608} 609 610/*! 611 Called when the user start to drag the thumbwheel in the right 612 frame. Override this method in subclassed viewers to provide your 613 own functionality on the thumbwheel. 614 615 \sa rightWheelMotion(), rightWheelFinish() 616 \sa leftWheelStart(), bottomWheelStart() 617*/ 618void 619So@Gui@FullViewer::rightWheelStart(void) 620{ 621 this->interactiveCountInc(); 622} 623 624/*! 625 Called repeatedly as the user drags the thumbwheel in the right 626 frame. Override this method in subclassed viewers to provide your 627 own functionality on the thumbwheel. 628 629 \sa rightWheelStart(), rightWheelFinish() 630 \sa leftWheelStart(), bottomWheelStart() 631*/ 632void 633So@Gui@FullViewer::rightWheelMotion(float value) 634{ 635 this->rightWheelVal = value; 636} 637 638/*! 639 Called as the user let go of the thumbwheel in the right frame 640 after a drag operation. Override this method in subclassed viewers 641 to provide your own functionality on the thumbwheel. 642 643 \sa rightWheelStart(), rightWheelMotion() 644 \sa leftWheelStart(), bottomWheelStart() 645*/ 646void 647So@Gui@FullViewer::rightWheelFinish(void) 648{ 649 this->interactiveCountDec(); 650} 651 652/*! 653 Set a new value for the right thumbwheel. 654*/ 655void 656So@Gui@FullViewer::setRightWheelValue(const float value) 657{ 658 this->rightWheelVal = value; 659 // Wheel may not be constructed yet, but we need to be robust, as 660 // set*WheelValue() is used from subclasses. 661 if (this->rightWheel) { 662 So@Gui@FullViewerP::setThumbWheelValue(this->rightWheel, value); 663 } 664} 665 666/*! 667 Get current value of the right thumbwheel. 668 669 \sa rightWheelMotion() 670*/ 671float 672So@Gui@FullViewer::getRightWheelValue(void) const 673{ 674 return this->rightWheelVal; 675} 676 677// ************************************************************************* 678 679/*! 680 This method returns the native widget for the label below the left 681 thumb wheel. 682*/ 683 684@WIDGET@ 685So@Gui@FullViewer::getLeftWheelLabelWidget(void) const 686{ 687 return this->leftWheelLabel; 688} 689 690/*! 691 This method returns the native widget for the label below the right thumb 692 wheel. 693*/ 694@WIDGET@ 695So@Gui@FullViewer::getRightWheelLabelWidget(void) const 696{ 697 return this->rightWheelLabel; 698} 699 700/*! 701 This method returns the native widget for the label beside the 702 bottom thumb wheel. 703*/ 704@WIDGET@ 705So@Gui@FullViewer::getBottomWheelLabelWidget(void) const 706{ 707 return this->bottomWheelLabel; 708} 709 710// ************************************************************************ 711 712/*! 713 Set title of popup menu. 714*/ 715void 716So@Gui@FullViewer::setPopupMenuString(const char * name) 717{ 718 PRIVATE(this)->popupmenutitle = name; 719 if (this->prefmenu) { this->prefmenu->setMenuTitle(SoGuiFullViewerP::ROOT_MENU, name); } 720} 721 722 723// Documented in superclass. 724SbBool 725So@Gui@FullViewer::processSoEvent(const SoEvent * const ev) 726{ 727 // We're in "interact" mode (ie *not* the camera modification mode), 728 // so don't handle the event here. It should either be forwarded to 729 // the scenegraph, or caught by So@Gui@Viewer::processSoEvent() if 730 // it's an ESC press (to switch modes). 731 if (!this->isViewing()) { return inherited::processSoEvent(ev); } 732 733 // Note: with the original SGI InventorXt, the popup menu is also 734 // activated by RMB clicks in non-viewing mode. We want to allow RMB 735 // clicks to pass through to the scenegraph in non-viewing mode, so 736 // we don't copy that behavior. 737 738 if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) { 739 SoMouseButtonEvent * const e = (SoMouseButtonEvent *) ev; 740 if ((e->getButton() == SoMouseButtonEvent::BUTTON2)) { 741 if (this->isPopupMenuEnabled()) { 742 if (e->getState() == SoButtonEvent::DOWN) { 743 this->openPopupMenu(e->getPosition()); 744 } 745 // Steal all RMB-events if the viewer uses the popup-menu. 746 return TRUE; 747 } 748 } 749 } 750 751 return inherited::processSoEvent(ev); 752} 753 754// ************************************************************************* 755 756// FIXME: get rid of this hack and make this file truly 757// "generic". 20020109 mortene. 758#ifndef __COIN_SOWIN__ 759 760// ************************************************************************* 761 762// Doc in superclass. 763void 764So@Gui@FullViewer::setComponentCursor(const So@Gui@Cursor & cursor) 765{ 766 // Overridden to apply the new cursor only for the rendering canvas 767 // widget. Otherwise, the default So@Gui@Component 768 // setComponentCursor() method will set the cursor for the top-most 769 // parent widget, which makes it affect all sub-widgets, like the 770 // decorations stuff. 771 772 So@Gui@Component::setWidgetCursor(this->getGLWidget(), cursor); 773} 774 775// ************************************************************************* 776 777#endif // ! __COIN_SOWIN__ 778 779// ************************************************************************ 780 781#ifndef DOXYGEN_SKIP_THIS 782 783SoGuiFullViewerP::SoGuiFullViewerP(So@Gui@FullViewer * owner) 784{ 785 this->pub = owner; 786} 787 788SoGuiFullViewerP::~SoGuiFullViewerP() 789{ 790} 791 792So@Gui@PopupMenu * 793SoGuiFullViewerP::setupStandardPopupMenu(void) 794{ 795 So@Gui@PopupMenu * menu = So@Gui@PopupMenu::createInstance(); 796 797 menu->newMenu("rootmenu", ROOT_MENU); 798 // FIXME: none of the So*-toolkits so far uses the rootmenu title to 799 // set up a title string at the top of the root popupmenu. 20010810 mortene. 800 menu->setMenuTitle(ROOT_MENU, this->popupmenutitle.getString()); 801 802#if 0 // OBSOLETED: this looks ugly and confusing for the user. 20010810 mortene. 803 // Simple hack for a common / generic way of setting up a title for 804 // the popupmenu. 805 menu->newMenuItem("rootmenutitle", ROOT_MENU_TITLE); 806 menu->setMenuItemTitle(ROOT_MENU_TITLE, this->popupmenutitle.getString()); 807 menu->addMenuItem(ROOT_MENU, ROOT_MENU_TITLE); 808 menu->setMenuItemEnabled(ROOT_MENU_TITLE, FALSE); 809 menu->addSeparator(ROOT_MENU); 810#endif // OBSOLETED 811 812 menu->newMenu("functionsmenu", FUNCTIONS_MENU); 813 menu->setMenuTitle(FUNCTIONS_MENU, _("Functions")); 814 menu->newMenu("drawstylesmenu", DRAWSTYLES_MENU); 815 menu->setMenuTitle(DRAWSTYLES_MENU, _("Draw Styles")); 816 menu->newMenu("stereomenu", STEREO_MENU); 817 menu->setMenuTitle(STEREO_MENU, _("Stereo Viewing")); 818 menu->newMenuItem("examining", EXAMINING_ITEM); 819 menu->setMenuItemTitle(EXAMINING_ITEM, _("Viewing")); 820 menu->newMenuItem("decoration", DECORATION_ITEM); 821 menu->setMenuItemTitle(DECORATION_ITEM, _("Decorations")); 822 menu->newMenuItem("headlight", HEADLIGHT_ITEM); 823 menu->setMenuItemTitle(HEADLIGHT_ITEM, _("Headlight")); 824 menu->newMenuItem("fullscreen", FULLSCREEN_ITEM); 825 menu->setMenuItemTitle(FULLSCREEN_ITEM, _("Fullscreen")); 826 827 menu->addMenu(ROOT_MENU, FUNCTIONS_MENU); 828 menu->addMenu(ROOT_MENU, DRAWSTYLES_MENU); 829 menu->addMenu(ROOT_MENU, STEREO_MENU); 830 menu->addMenuItem(ROOT_MENU, EXAMINING_ITEM); 831 menu->addMenuItem(ROOT_MENU, DECORATION_ITEM); 832 menu->addMenuItem(ROOT_MENU, HEADLIGHT_ITEM); 833 menu->addMenuItem(ROOT_MENU, FULLSCREEN_ITEM); 834 835 menu->newMenuItem("home", HOME_ITEM); 836 menu->setMenuItemTitle(HOME_ITEM, _("Home")); 837 menu->newMenuItem("set_home", SET_HOME_ITEM); 838 menu->setMenuItemTitle(SET_HOME_ITEM, _("Set Home")); 839 menu->newMenuItem("view_all", VIEW_ALL_ITEM); 840 menu->setMenuItemTitle(VIEW_ALL_ITEM, _("View All")); 841 menu->newMenuItem("seek", SEEK_ITEM); 842 menu->setMenuItemTitle(SEEK_ITEM, _("Seek")); 843 844 menu->addMenuItem(FUNCTIONS_MENU, HOME_ITEM); 845 menu->addMenuItem(FUNCTIONS_MENU, SET_HOME_ITEM); 846 menu->addMenuItem(FUNCTIONS_MENU, VIEW_ALL_ITEM); 847 menu->addMenuItem(FUNCTIONS_MENU, SEEK_ITEM); 848 849 menu->newMenu("drawstylesstill", DRAWSTYLES_STILL_MENU); 850 menu->setMenuTitle(DRAWSTYLES_STILL_MENU, _("Still Drawstyle")); 851 852 menu->newMenuItem("as_is", AS_IS_ITEM); 853 menu->setMenuItemTitle(AS_IS_ITEM, _("as is")); 854 menu->newMenuItem("hidden_line", HIDDEN_LINE_ITEM); 855 menu->setMenuItemTitle(HIDDEN_LINE_ITEM, _("hidden line")); 856 menu->newMenuItem("wireframe_overlay", WIREFRAME_OVERLAY_ITEM); 857 menu->setMenuItemTitle(WIREFRAME_OVERLAY_ITEM, _("wireframe overlay")); 858 menu->newMenuItem("no_textures", NO_TEXTURE_ITEM); 859 menu->setMenuItemTitle(NO_TEXTURE_ITEM, _("no texture")); 860 menu->newMenuItem("low_resolution", LOW_RESOLUTION_ITEM); 861 menu->setMenuItemTitle(LOW_RESOLUTION_ITEM, _("low resolution")); 862 menu->newMenuItem("wireframe", WIREFRAME_ITEM); 863 menu->setMenuItemTitle(WIREFRAME_ITEM, _("wireframe")); 864 menu->newMenuItem("points", POINTS_ITEM); 865 menu->setMenuItemTitle(POINTS_ITEM, _("points")); 866 menu->newMenuItem("bounding_box", BOUNDING_BOX_ITEM); 867 menu->setMenuItemTitle(BOUNDING_BOX_ITEM, _("bounding box (no depth)")); 868 869 menu->newRadioGroup(STILL_GROUP); 870 menu->addRadioGroupItem(STILL_GROUP, AS_IS_ITEM); 871 menu->addRadioGroupItem(STILL_GROUP, HIDDEN_LINE_ITEM); 872 menu->addRadioGroupItem(STILL_GROUP, WIREFRAME_OVERLAY_ITEM); 873 menu->addRadioGroupItem(STILL_GROUP, NO_TEXTURE_ITEM); 874 menu->addRadioGroupItem(STILL_GROUP, LOW_RESOLUTION_ITEM); 875 menu->addRadioGroupItem(STILL_GROUP, WIREFRAME_ITEM); 876 menu->addRadioGroupItem(STILL_GROUP, POINTS_ITEM); 877 menu->addRadioGroupItem(STILL_GROUP, BOUNDING_BOX_ITEM); 878 879 menu->addMenuItem(DRAWSTYLES_STILL_MENU, AS_IS_ITEM); 880 menu->addMenuItem(DRAWSTYLES_STILL_MENU, HIDDEN_LINE_ITEM); 881 menu->addMenuItem(DRAWSTYLES_STILL_MENU, WIREFRAME_OVERLAY_ITEM); 882 menu->addMenuItem(DRAWSTYLES_STILL_MENU, NO_TEXTURE_ITEM); 883 menu->addMenuItem(DRAWSTYLES_STILL_MENU, LOW_RESOLUTION_ITEM); 884 menu->addMenuItem(DRAWSTYLES_STILL_MENU, WIREFRAME_ITEM); 885 menu->addMenuItem(DRAWSTYLES_STILL_MENU, POINTS_ITEM); 886 menu->addMenuItem(DRAWSTYLES_STILL_MENU, BOUNDING_BOX_ITEM); 887 888 menu->newMenu("drawstylesanimation", DRAWSTYLES_ANIMATING_MENU); 889 menu->setMenuTitle(DRAWSTYLES_ANIMATING_MENU, _("Animating Drawstyle")); 890 891 menu->newMenuItem("move_same_as_still", MOVE_SAME_AS_STILL_ITEM); 892 menu->setMenuItemTitle(MOVE_SAME_AS_STILL_ITEM, _("same as still")); 893 menu->newMenuItem("move_no_texture", MOVE_NO_TEXTURE_ITEM); 894 menu->setMenuItemTitle(MOVE_NO_TEXTURE_ITEM, _("no texture")); 895 menu->newMenuItem("move_low_res", MOVE_LOW_RES_ITEM); 896 menu->setMenuItemTitle(MOVE_LOW_RES_ITEM, _("low resolution")); 897 menu->newMenuItem("move_wireframe", MOVE_WIREFRAME_ITEM); 898 menu->setMenuItemTitle(MOVE_WIREFRAME_ITEM, _("wireframe")); 899 menu->newMenuItem("move_low_res_wireframe", MOVE_LOW_RES_WIREFRAME_ITEM); 900 menu->setMenuItemTitle(MOVE_LOW_RES_WIREFRAME_ITEM, 901 _("low res wireframe (no depth)")); 902 menu->newMenuItem("move_points", MOVE_POINTS_ITEM); 903 menu->setMenuItemTitle(MOVE_POINTS_ITEM, _("points")); 904 menu->newMenuItem("move_low_res_points", MOVE_LOW_RES_POINTS_ITEM); 905 menu->setMenuItemTitle(MOVE_LOW_RES_POINTS_ITEM, 906 _("low res points (no depth)")); 907 menu->newMenuItem("move_bounding_box", MOVE_BOUNDING_BOX_ITEM); 908 menu->setMenuItemTitle(MOVE_BOUNDING_BOX_ITEM, _("bounding box (no depth)")); 909 910 menu->newRadioGroup(MOVE_GROUP); 911 menu->addRadioGroupItem(MOVE_GROUP, MOVE_SAME_AS_STILL_ITEM); 912 menu->addRadioGroupItem(MOVE_GROUP, MOVE_NO_TEXTURE_ITEM); 913 menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_ITEM); 914 menu->addRadioGroupItem(MOVE_GROUP, MOVE_WIREFRAME_ITEM); 915 menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_WIREFRAME_ITEM); 916 menu->addRadioGroupItem(MOVE_GROUP, MOVE_POINTS_ITEM); 917 menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_POINTS_ITEM); 918 menu->addRadioGroupItem(MOVE_GROUP, MOVE_BOUNDING_BOX_ITEM); 919 920 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_SAME_AS_STILL_ITEM); 921 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_NO_TEXTURE_ITEM); 922 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_ITEM); 923 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_WIREFRAME_ITEM); 924 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_WIREFRAME_ITEM); 925 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_POINTS_ITEM); 926 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_POINTS_ITEM); 927 menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_BOUNDING_BOX_ITEM); 928 929 menu->newMenu("transparencytype", TRANSPARENCY_TYPE_MENU); 930 menu->setMenuTitle(TRANSPARENCY_TYPE_MENU, _("Transparency Type")); 931 menu->newRadioGroup(TRANSPARENCY_GROUP); 932 933 { // Fill in menu items in radiomenu with transparency selections. 934 935 struct menutransparencyitem { 936 const char * name, * title; 937 int id; 938 }; 939 940 struct menutransparencyitem items[] = { 941#ifdef __COIN__ 942 { "none", _("none"), NONE_TRANSPARENCY_ITEM }, 943#endif // __COIN__ 944 { "screen_door", _("screen door"), SCREEN_DOOR_TRANSPARENCY_ITEM }, 945 { "add", _("add"), ADD_TRANSPARENCY_ITEM }, 946 { "delayed_add", _("delayed add"), DELAYED_ADD_TRANSPARENCY_ITEM }, 947 { "sorted_object_add", _("sorted object add"), SORTED_OBJECT_ADD_TRANSPARENCY_ITEM }, 948 { "blend", _("blend"), BLEND_TRANSPARENCY_ITEM }, 949 { "delayed_blend", _("delayed blend"), DELAYED_BLEND_TRANSPARENCY_ITEM }, 950 { "sorted_object_blend", _("sorted object blend"), SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM } 951#ifdef __COIN__ // Coin extensions 952 , 953 { "sorted_object_sorted_triangle_add", _("sorted object sorted triangle add"), SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM }, 954 { "sorted_object_sorted_triangle_blend", _("sorted object sorted triangle blend"), SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM } 955#endif // __COIN__ 956#ifdef HAVE_SORTED_LAYERS_BLEND 957 , { "sorted_layers_blend", _("sorted layers blend"), SORTED_LAYERS_BLEND_ITEM } 958#endif // HAVE_SORTED_LAYERS_BLEND 959 }; 960 961 int nritems = sizeof(items) / sizeof(struct menutransparencyitem); 962 for (int i = 0; i < nritems; i++) { 963 menu->newMenuItem(items[i].name, items[i].id); 964 menu->setMenuItemTitle(items[i].id, items[i].title); 965 menu->addRadioGroupItem(TRANSPARENCY_GROUP, items[i].id); 966 menu->addMenuItem(TRANSPARENCY_TYPE_MENU, items[i].id); 967 } 968 } 969 970 menu->newMenuItem("stereooff", STEREO_OFF_ITEM); 971 menu->newMenuItem("stereoredcyan", STEREO_ANAGLYPH_ITEM); 972 menu->newMenuItem("stereoquadbuffer", STEREO_QUADBUFFER_ITEM); 973 menu->setMenuItemTitle(STEREO_OFF_ITEM, _("Off")); 974 menu->setMenuItemTitle(STEREO_ANAGLYPH_ITEM, _("Red/Cyan Anaglyph")); 975 menu->setMenuItemTitle(STEREO_QUADBUFFER_ITEM, _("Quad buffer")); 976 977 menu->newMenuItem("stereointerleavedrows", STEREO_INTERLEAVED_ROWS_ITEM); 978 menu->setMenuItemTitle(STEREO_INTERLEAVED_ROWS_ITEM, _("Interleaved Rows")); 979 menu->newMenuItem("stereointerleavedcolumns", STEREO_INTERLEAVED_COLUMNS_ITEM); 980 menu->setMenuItemTitle(STEREO_INTERLEAVED_COLUMNS_ITEM, _("Interleaved Columns")); 981 982 menu->newRadioGroup(STEREO_GROUP); 983 menu->addRadioGroupItem(STEREO_GROUP, STEREO_OFF_ITEM); 984 menu->addRadioGroupItem(STEREO_GROUP, STEREO_ANAGLYPH_ITEM); 985 menu->addRadioGroupItem(STEREO_GROUP, STEREO_QUADBUFFER_ITEM); 986 menu->addRadioGroupItem(STEREO_GROUP, STEREO_INTERLEAVED_ROWS_ITEM); 987 menu->addRadioGroupItem(STEREO_GROUP, STEREO_INTERLEAVED_COLUMNS_ITEM); 988 989 menu->addMenuItem(STEREO_MENU, STEREO_OFF_ITEM); 990 menu->addMenuItem(STEREO_MENU, STEREO_ANAGLYPH_ITEM); 991 menu->addMenuItem(STEREO_MENU, STEREO_QUADBUFFER_ITEM); 992 menu->addMenuItem(STEREO_MENU, STEREO_INTERLEAVED_ROWS_ITEM); 993 menu->addMenuItem(STEREO_MENU, STEREO_INTERLEAVED_COLUMNS_ITEM); 994 995 menu->newMenu("renderbuffertype", RENDER_BUFFER_TYPE_MENU); 996 menu->setMenuTitle(RENDER_BUFFER_TYPE_MENU, _("Render Buffer Type")); 997 998 menu->newMenuItem("single_buffer", SINGLE_BUFFER_ITEM); 999 menu->setMenuItemTitle(SINGLE_BUFFER_ITEM, _("single")); 1000 menu->newMenuItem("double_buffer", DOUBLE_BUFFER_ITEM); 1001 menu->setMenuItemTitle(DOUBLE_BUFFER_ITEM, _("double")); 1002 menu->newMenuItem("interactive_buffer", INTERACTIVE_BUFFER_ITEM); 1003 menu->setMenuItemTitle(INTERACTIVE_BUFFER_ITEM, _("interactive")); 1004 1005 menu->newRadioGroup(BUFFER_GROUP); 1006 menu->addRadioGroupItem(BUFFER_GROUP, SINGLE_BUFFER_ITEM); 1007 menu->addRadioGroupItem(BUFFER_GROUP, DOUBLE_BUFFER_ITEM); 1008 menu->addRadioGroupItem(BUFFER_GROUP, INTERACTIVE_BUFFER_ITEM); 1009 1010 menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, SINGLE_BUFFER_ITEM); 1011 menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, DOUBLE_BUFFER_ITEM); 1012 menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, INTERACTIVE_BUFFER_ITEM); 1013 1014 menu->addMenu(DRAWSTYLES_MENU, DRAWSTYLES_STILL_MENU); 1015 menu->addMenu(DRAWSTYLES_MENU, DRAWSTYLES_ANIMATING_MENU); 1016 menu->addMenu(DRAWSTYLES_MENU, TRANSPARENCY_TYPE_MENU); 1017 menu->addMenu(DRAWSTYLES_MENU, RENDER_BUFFER_TYPE_MENU); 1018 1019 int toggle; 1020 toggle = menu->newRadioGroup(); 1021 menu->addRadioGroupItem(toggle, EXAMINING_ITEM); 1022 toggle = menu->newRadioGroup(); 1023 menu->addRadioGroupItem(toggle, DECORATION_ITEM); 1024 toggle = menu->newRadioGroup(); 1025 menu->addRadioGroupItem(toggle, HEADLIGHT_ITEM); 1026 toggle = menu->newRadioGroup(); 1027 menu->addRadioGroupItem(toggle, FULLSCREEN_ITEM); 1028 1029 menu->addMenuSelectionCallback(SoGuiFullViewerP::menuSelectionCallback, 1030 (void *) this); 1031 1032 // this instance is freed in the native viewer component 1033 PUBLIC(this)->prefmenu = menu; 1034 return menu; 1035} 1036 1037// ************************************************************************ 1038 1039void 1040SoGuiFullViewerP::prepareMenu(So@Gui@PopupMenu * menu) 1041{ 1042 //// Misc. ////////////////////////////////////////////////////////// 1043 menu->setMenuItemMarked(DECORATION_ITEM, PUBLIC(this)->isDecoration()); 1044 menu->setMenuItemMarked(EXAMINING_ITEM, PUBLIC(this)->isViewing()); 1045 menu->setMenuItemMarked(HEADLIGHT_ITEM, PUBLIC(this)->isHeadlight()); 1046 menu->setMenuItemMarked(FULLSCREEN_ITEM, PUBLIC(this)->isFullScreen()); 1047 1048 //// Basic drawstyles. ////////////////////////////////////////////// 1049 this->setDrawStyleMenuActivation(So@Gui@FullViewer::STILL, 1050 PUBLIC(this)->getDrawStyle(So@Gui@FullViewer::STILL)); 1051 this->setDrawStyleMenuActivation(So@Gui@FullViewer::INTERACTIVE, 1052 PUBLIC(this)->getDrawStyle(So@Gui@FullViewer::INTERACTIVE)); 1053 1054 //// Transparency setting. ////////////////////////////////////////// 1055 switch (PUBLIC(this)->getTransparencyType()) { 1056 case SoGLRenderAction::SCREEN_DOOR: 1057 menu->setMenuItemMarked(SCREEN_DOOR_TRANSPARENCY_ITEM, TRUE); 1058 break; 1059 case SoGLRenderAction::ADD: 1060 menu->setMenuItemMarked(ADD_TRANSPARENCY_ITEM, TRUE); 1061 break; 1062 case SoGLRenderAction::DELAYED_ADD: 1063 menu->setMenuItemMarked(DELAYED_ADD_TRANSPARENCY_ITEM, TRUE); 1064 break; 1065 case SoGLRenderAction::SORTED_OBJECT_ADD: 1066 menu->setMenuItemMarked(SORTED_OBJECT_ADD_TRANSPARENCY_ITEM, TRUE); 1067 break; 1068 case SoGLRenderAction::BLEND: 1069 menu->setMenuItemMarked(BLEND_TRANSPARENCY_ITEM, TRUE); 1070 break; 1071 case SoGLRenderAction::DELAYED_BLEND: 1072 menu->setMenuItemMarked(DELAYED_BLEND_TRANSPARENCY_ITEM, TRUE); 1073 break; 1074 case SoGLRenderAction::SORTED_OBJECT_BLEND: 1075 menu->setMenuItemMarked(SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM, TRUE); 1076 break; 1077#ifdef __COIN__ // Coin extensions 1078 case SoGLRenderAction::NONE: 1079 menu->setMenuItemMarked(NONE_TRANSPARENCY_ITEM, TRUE); 1080 break; 1081 case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD: 1082 menu->setMenuItemMarked(SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM, TRUE); 1083 break; 1084 case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND: 1085 menu->setMenuItemMarked(SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM, TRUE); 1086 break; 1087#endif // __COIN__ 1088#ifdef HAVE_SORTED_LAYERS_BLEND 1089 case SoGLRenderAction::SORTED_LAYERS_BLEND: 1090 menu->setMenuItemMarked(SORTED_LAYERS_BLEND_ITEM, TRUE); 1091 break; 1092#endif // HAVE_SORTED_LAYERS_BLEND 1093 default: 1094#if SO@GUI@_DEBUG 1095 SoDebugError::postInfo("SoGuiFullViewerP::prepareMenu", 1096 "Unknown transparency type"); 1097#endif // SO@GUI@_DEBUG 1098 break; 1099 } 1100 1101 //// Stereo viewing. //////////////////////////////////////////////// 1102 1103 const So@Gui@Viewer::StereoType type = PUBLIC(this)->getStereoType(); 1104 switch (type) { 1105 case So@Gui@Viewer::STEREO_NONE: 1106 menu->setMenuItemMarked(STEREO_OFF_ITEM, TRUE); 1107 break; 1108 case So@Gui@Viewer::STEREO_ANAGLYPH: 1109 menu->setMenuItemMarked(STEREO_ANAGLYPH_ITEM, TRUE); 1110 break; 1111 case So@Gui@Viewer::STEREO_QUADBUFFER: 1112 menu->setMenuItemMarked(STEREO_QUADBUFFER_ITEM, TRUE); 1113 break; 1114 case So@Gui@Viewer::STEREO_INTERLEAVED_ROWS: 1115 menu->setMenuItemMarked(STEREO_INTERLEAVED_ROWS_ITEM, TRUE); 1116 break; 1117 case So@Gui@Viewer::STEREO_INTERLEAVED_COLUMNS: 1118 menu->setMenuItemMarked(STEREO_INTERLEAVED_COLUMNS_ITEM, TRUE); 1119 break; 1120 default: 1121 assert(FALSE); break; 1122 } 1123 1124 //// GL canvas settings. //////////////////////////////////////////// 1125 switch (PUBLIC(this)->getBufferingType()) { 1126 case So@Gui@Viewer::BUFFER_SINGLE: 1127 menu->setMenuItemMarked(SINGLE_BUFFER_ITEM, TRUE); 1128 break; 1129 case So@Gui@Viewer::BUFFER_DOUBLE: 1130 menu->setMenuItemMarked(DOUBLE_BUFFER_ITEM, TRUE); 1131 break; 1132 case So@Gui@Viewer::BUFFER_INTERACTIVE: 1133 menu->setMenuItemMarked(INTERACTIVE_BUFFER_ITEM, TRUE); 1134 break; 1135 default: 1136#if SO@GUI@_DEBUG 1137 SoDebugError::postInfo("SoGuiFullViewerP::prepareMenu", 1138 "Unknown buffer type"); 1139#endif // SO@GUI@_DEBUG 1140 break; 1141 } 1142} 1143 1144// ************************************************************************ 1145 1146void 1147SoGuiFullViewerP::menuSelection(int menuitemid) 1148{ 1149 SbBool ok; 1150 1151 switch (menuitemid) { 1152 case -1: 1153 // means no item was selected 1154#if SO@GUI@_DEBUG 1155 SoDebugError::postInfo("SoGuiFullViewerP::menuSelection", 1156 "-1 not appropriate on callback usage"); 1157#endif // SO@GUI@_DEBUG 1158 break; 1159 1160 case EXAMINING_ITEM: 1161 PUBLIC(this)->setViewing(PUBLIC(this)->isViewing() ? FALSE : TRUE); 1162 break; 1163 case DECORATION_ITEM: 1164 PUBLIC(this)->setDecoration(PUBLIC(this)->isDecoration() ? FALSE : TRUE); 1165 break; 1166 case HEADLIGHT_ITEM: 1167 PUBLIC(this)->setHeadlight(PUBLIC(this)->isHeadlight() ? FALSE : TRUE); 1168 break; 1169 case FULLSCREEN_ITEM: 1170 (void)PUBLIC(this)->setFullScreen(PUBLIC(this)->isFullScreen() ? FALSE : TRUE); 1171 break; 1172 1173 case HOME_ITEM: 1174 PUBLIC(this)->resetToHomePosition(); 1175 break; 1176 case SET_HOME_ITEM: 1177 PUBLIC(this)->saveHomePosition(); 1178 break; 1179 case VIEW_ALL_ITEM: 1180 PUBLIC(this)->viewAll(); 1181 break; 1182 case SEEK_ITEM: 1183 ((So@Gui@FullViewerP *)this)->seekbuttonClicked(); 1184 break; 1185 1186 case AS_IS_ITEM: 1187 case HIDDEN_LINE_ITEM: 1188 case WIREFRAME_OVERLAY_ITEM: 1189 case NO_TEXTURE_ITEM: 1190 case LOW_RESOLUTION_ITEM: 1191 case WIREFRAME_ITEM: 1192 case POINTS_ITEM: 1193 case BOUNDING_BOX_ITEM: 1194 this->drawstyleActivated(menuitemid); 1195 break; 1196 1197 case MOVE_SAME_AS_STILL_ITEM: 1198 case MOVE_NO_TEXTURE_ITEM: 1199 case MOVE_LOW_RES_ITEM: 1200 case MOVE_WIREFRAME_ITEM: 1201 case MOVE_LOW_RES_WIREFRAME_ITEM: 1202 case MOVE_POINTS_ITEM: 1203 case MOVE_LOW_RES_POINTS_ITEM: 1204 case MOVE_BOUNDING_BOX_ITEM: 1205 this->drawstyleActivated(menuitemid); 1206 break; 1207 1208 case SCREEN_DOOR_TRANSPARENCY_ITEM: 1209 case ADD_TRANSPARENCY_ITEM: 1210 case DELAYED_ADD_TRANSPARENCY_ITEM: 1211 case SORTED_OBJECT_ADD_TRANSPARENCY_ITEM: 1212 case BLEND_TRANSPARENCY_ITEM: 1213 case DELAYED_BLEND_TRANSPARENCY_ITEM: 1214 case SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM: 1215 case SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM: 1216 case SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM: 1217 case NONE_TRANSPARENCY_ITEM: 1218 case SORTED_LAYERS_BLEND_ITEM: // define test is not needed. This enum is always defined 1219 this->drawstyleActivated(menuitemid); 1220 PUBLIC(this)->scheduleRedraw(); 1221 break; 1222 1223 case SINGLE_BUFFER_ITEM: 1224 case DOUBLE_BUFFER_ITEM: 1225 case INTERACTIVE_BUFFER_ITEM: 1226 this->drawstyleActivated(menuitemid); 1227 break; 1228 1229 case STEREO_OFF_ITEM: 1230 ok = PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_NONE); 1231 assert(ok); 1232 break; 1233 case STEREO_ANAGLYPH_ITEM: 1234 ok = PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_ANAGLYPH); 1235 assert(ok && "anaglyph stereo should always be possible"); 1236 break; 1237 case STEREO_QUADBUFFER_ITEM: 1238 ok = PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_QUADBUFFER); 1239 if (!ok) { PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_NONE); } 1240 break; 1241 case STEREO_INTERLEAVED_ROWS_ITEM: 1242 ok = PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_INTERLEAVED_ROWS); 1243 if (!ok) { PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_NONE); } 1244 break; 1245 case STEREO_INTERLEAVED_COLUMNS_ITEM: 1246 ok = PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_INTERLEAVED_COLUMNS); 1247 if (!ok) { PUBLIC(this)->setStereoType(So@Gui@Viewer::STEREO_NONE); } 1248 break; 1249 1250 default: 1251 SoDebugError::postInfo("SoGuiFullViewerP::menuSelection", 1252 "popup menu handling for item %d is not implemented", 1253 menuitemid); 1254 break; 1255 } 1256} 1257 1258 1259// ************************************************************************ 1260 1261void 1262SoGuiFullViewerP::menuSelectionCallback(int menuitemid, 1263 void * userdata) 1264{ 1265 SoGuiFullViewerP * viewer = (SoGuiFullViewerP *) userdata; 1266 viewer->menuSelection(menuitemid); 1267} 1268 1269// ************************************************************************ 1270 1271void 1272SoGuiFullViewerP::setDrawStyleMenuActivation(So@Gui@Viewer::DrawType type, 1273 So@Gui@Viewer::DrawStyle value) 1274{ 1275 assert(PUBLIC(this)->prefmenu != NULL); 1276 1277 switch (type) { 1278 case So@Gui@Viewer::STILL: 1279 switch (value) { 1280 case So@Gui@Viewer::VIEW_AS_IS: 1281 PUBLIC(this)->prefmenu->setMenuItemMarked(AS_IS_ITEM, TRUE); 1282 break; 1283 case So@Gui@Viewer::VIEW_HIDDEN_LINE: 1284 PUBLIC(this)->prefmenu->setMenuItemMarked(HIDDEN_LINE_ITEM, TRUE); 1285 break; 1286 case So@Gui@Viewer::VIEW_WIREFRAME_OVERLAY: 1287 PUBLIC(this)->prefmenu->setMenuItemMarked(WIREFRAME_OVERLAY_ITEM, TRUE); 1288 break; 1289 case So@Gui@Viewer::VIEW_NO_TEXTURE: 1290 PUBLIC(this)->prefmenu->setMenuItemMarked(NO_TEXTURE_ITEM, TRUE); 1291 break; 1292 case So@Gui@Viewer::VIEW_LOW_COMPLEXITY: 1293 PUBLIC(this)->prefmenu->setMenuItemMarked(LOW_RESOLUTION_ITEM, TRUE); 1294 break; 1295 case So@Gui@Viewer::VIEW_LOW_RES_LINE: 1296#if SO@GUI@_DEBUG 1297 SoDebugError::postWarning("So@Gui@FullViewer::setDrawStyleMenuActivation", 1298 "Use VIEW_LINE, not VIEW_LOW_RES_LINE for the STILL drawstyle."); 1299#endif // debug 1300 case So@Gui@Viewer::VIEW_LINE: 1301 PUBLIC(this)->prefmenu->setMenuItemMarked(WIREFRAME_ITEM, TRUE); 1302 break; 1303 case So@Gui@Viewer::VIEW_LOW_RES_POINT: 1304#if SO@GUI@_DEBUG 1305 SoDebugError::postWarning("So@Gui@FullViewer::setDrawStyleMenuActivation", 1306 "Use VIEW_POINT, not VIEW_LOW_RES_POINT for the STILL drawstyle."); 1307#endif // debug 1308 case So@Gui@Viewer::VIEW_POINT: 1309 PUBLIC(this)->prefmenu->setMenuItemMarked(POINTS_ITEM, TRUE); 1310 break; 1311 case So@Gui@Viewer::VIEW_BBOX: 1312 PUBLIC(this)->prefmenu->setMenuItemMarked(BOUNDING_BOX_ITEM, TRUE); 1313 break; 1314 default: 1315#if SO@GUI@_DEBUG 1316 SoDebugError::postWarning("So@Gui@FullViewer::setDrawStyleMenuActivation", 1317 "Unsupporter still-drawstyle"); 1318#endif // debug 1319 break; 1320 } 1321 break; 1322 1323 case So@Gui@Viewer::INTERACTIVE: 1324 switch (value) { 1325 case So@Gui@Viewer::VIEW_SAME_AS_STILL: 1326 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_SAME_AS_STILL_ITEM, TRUE); 1327 break; 1328 case So@Gui@Viewer::VIEW_NO_TEXTURE: 1329 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_NO_TEXTURE_ITEM, TRUE); 1330 break; 1331 case So@Gui@Viewer::VIEW_LOW_COMPLEXITY: 1332 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_ITEM, TRUE); 1333 break; 1334 case So@Gui@Viewer::VIEW_LINE: 1335 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_WIREFRAME_ITEM, TRUE); 1336 break; 1337 case So@Gui@Viewer::VIEW_LOW_RES_LINE: 1338 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_WIREFRAME_ITEM, TRUE); 1339 break; 1340 case So@Gui@Viewer::VIEW_POINT: 1341 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_POINTS_ITEM, TRUE); 1342 break; 1343 case So@Gui@Viewer::VIEW_LOW_RES_POINT: 1344 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_POINTS_ITEM, TRUE); 1345 break; 1346 case So@Gui@Viewer::VIEW_BBOX: 1347 PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_BOUNDING_BOX_ITEM, TRUE); 1348 break; 1349 default: 1350#if SO@GUI@_DEBUG 1351 SoDebugError::postWarning("So@Gui@FullViewer::setDrawStyleMenuActivation", 1352 "Unsupporter interactive drawstyle"); 1353#endif // debug 1354 break; 1355 } 1356 break; 1357 1358 default: 1359#if SO@GUI@_DEBUG 1360 SoDebugError::postWarning("So@Gui@FullViewer::setDrawStyleMenuActivation", 1361 "Unsupporter drawstyle type"); 1362#endif // debug 1363 break; 1364 } 1365} 1366 1367// ************************************************************************ 1368 1369void 1370SoGuiFullViewerP::drawstyleActivated(int menuitemid) 1371{ 1372 switch (menuitemid) { 1373 case SINGLE_BUFFER_ITEM: 1374 PUBLIC(this)->setBufferingType(So@Gui@Viewer::BUFFER_SINGLE); 1375 return; 1376 case DOUBLE_BUFFER_ITEM: 1377 PUBLIC(this)->setBufferingType(So@Gui@Viewer::BUFFER_DOUBLE); 1378 return; 1379 case INTERACTIVE_BUFFER_ITEM: 1380 PUBLIC(this)->setBufferingType(So@Gui@Viewer::BUFFER_INTERACTIVE); 1381 return; 1382 default: 1383 break; 1384 } 1385 1386 // FIXME: should perhaps override transparency type to be screendoor 1387 // if we detect that the OpenGL canvas has 0 alpha bits available? 1388 // 20030626 mortene. 1389 switch (menuitemid) { 1390 case SCREEN_DOOR_TRANSPARENCY_ITEM: 1391 PUBLIC(this)->setTransparencyType(SoGLRenderAction::SCREEN_DOOR); 1392 return; 1393 case ADD_TRANSPARENCY_ITEM: 1394 PUBLIC(this)->setTransparencyType(SoGLRenderAction::ADD); 1395 return; 1396 case DELAYED_ADD_TRANSPARENCY_ITEM: 1397 PUBLIC(this)->setTransparencyType(SoGLRenderAction::DELAYED_ADD); 1398 return; 1399 case SORTED_OBJECT_ADD_TRANSPARENCY_ITEM: 1400 PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_ADD); 1401 return; 1402 case BLEND_TRANSPARENCY_ITEM: 1403 PUBLIC(this)->setTransparencyType(SoGLRenderAction::BLEND); 1404 return; 1405 case DELAYED_BLEND_TRANSPARENCY_ITEM: 1406 PUBLIC(this)->setTransparencyType(SoGLRenderAction::DELAYED_BLEND); 1407 return; 1408 case SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM: 1409 PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND); 1410 return; 1411#ifdef __COIN__ // Coin extensions 1412 case NONE_TRANSPARENCY_ITEM: 1413 PUBLIC(this)->setTransparencyType(SoGLRenderAction::NONE); 1414 return; 1415 case SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM: 1416 PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD); 1417 return; 1418 case SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM: 1419 PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND); 1420 return; 1421#endif // __COIN__ 1422#ifdef HAVE_SORTED_LAYERS_BLEND 1423 case SORTED_LAYERS_BLEND_ITEM: 1424 PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_LAYERS_BLEND); 1425 return; 1426#endif // HAVE_SORTED_LAYERS_BLEND 1427 default: 1428 // some other menu item, just continue 1429 break; 1430 } 1431 1432 So@Gui@Viewer::DrawStyle val = So@Gui@Viewer::VIEW_AS_IS; 1433 switch (menuitemid) { 1434 case AS_IS_ITEM: 1435 val = So@Gui@Viewer::VIEW_AS_IS; 1436 break; 1437 case HIDDEN_LINE_ITEM: 1438 val = So@Gui@Viewer::VIEW_HIDDEN_LINE; 1439 break; 1440 case WIREFRAME_OVERLAY_ITEM: 1441 val = So@Gui@Viewer::VIEW_WIREFRAME_OVERLAY; 1442 break; 1443 case NO_TEXTURE_ITEM: 1444 val = So@Gui@Viewer::VIEW_NO_TEXTURE; 1445 break; 1446 case LOW_RESOLUTION_ITEM: 1447 val = So@Gui@Viewer::VIEW_LOW_COMPLEXITY; 1448 break; 1449 case WIREFRAME_ITEM: 1450 val = So@Gui@Viewer::VIEW_LINE; 1451 break; 1452 case POINTS_ITEM: 1453 val = So@Gui@Viewer::VIEW_POINT; 1454 break; 1455 case BOUNDING_BOX_ITEM: 1456 val = So@Gui@Viewer::VIEW_BBOX; 1457 break; 1458 1459 case MOVE_SAME_AS_STILL_ITEM: 1460 val = So@Gui@Viewer::VIEW_SAME_AS_STILL; 1461 break; 1462 case MOVE_NO_TEXTURE_ITEM: 1463 val = So@Gui@Viewer::VIEW_NO_TEXTURE; 1464 break; 1465 case MOVE_LOW_RES_ITEM: 1466 val = So@Gui@Viewer::VIEW_LOW_COMPLEXITY; 1467 break; 1468 case MOVE_WIREFRAME_ITEM: 1469 val = So@Gui@Viewer::VIEW_LINE; 1470 break; 1471 case MOVE_LOW_RES_WIREFRAME_ITEM: 1472 val = So@Gui@Viewer::VIEW_LOW_RES_LINE; 1473 break; 1474 case MOVE_POINTS_ITEM: 1475 val = So@Gui@Viewer::VIEW_POINT; 1476 break; 1477 case MOVE_LOW_RES_POINTS_ITEM: 1478 val = So@Gui@Viewer::VIEW_LOW_RES_POINT; 1479 break; 1480 case MOVE_BOUNDING_BOX_ITEM: 1481 val = So@Gui@Viewer::VIEW_BBOX; 1482 break; 1483 1484 default: 1485 assert(0); 1486 break; 1487 } 1488 1489 So@Gui@Viewer::DrawType type = So@Gui@Viewer::STILL; 1490 1491 switch (menuitemid) { 1492 case AS_IS_ITEM: 1493 case HIDDEN_LINE_ITEM: 1494 case WIREFRAME_OVERLAY_ITEM: 1495 case NO_TEXTURE_ITEM: 1496 case LOW_RESOLUTION_ITEM: 1497 case WIREFRAME_ITEM: 1498 case POINTS_ITEM: 1499 case BOUNDING_BOX_ITEM: 1500 type = So@Gui@Viewer::STILL; 1501 break; 1502 1503 case MOVE_SAME_AS_STILL_ITEM: 1504 case MOVE_NO_TEXTURE_ITEM: 1505 case MOVE_LOW_RES_ITEM: 1506 case MOVE_WIREFRAME_ITEM: 1507 case MOVE_LOW_RES_WIREFRAME_ITEM: 1508 case MOVE_POINTS_ITEM: 1509 case MOVE_LOW_RES_POINTS_ITEM: 1510 case MOVE_BOUNDING_BOX_ITEM: 1511 type = So@Gui@Viewer::INTERACTIVE; 1512 break; 1513 1514 default: 1515 assert(0); 1516 break; 1517 } 1518 1519 PUBLIC(this)->setDrawStyle(type, val); 1520} 1521 1522// ************************************************************************ 1523 1524// Move camera parallel with the plane orthogonal to the camera 1525// direction vector. 1526// 1527// Used from both SoGuiPlaneViewer and SoGuiExaminerViewer. 1528// Implemented in the SoGuiFullViewer private class to collect common 1529// code. 1530void 1531SoGuiFullViewerP::pan(SoCamera * cam, 1532 float aspectratio, const SbPlane & panningplane, 1533 const SbVec2f & currpos, const SbVec2f & prevpos) 1534{ 1535 if (cam == NULL) return; // can happen for empty scenegraph 1536 if (currpos == prevpos) return; // useless invocation 1537 1538#if SO@GUI@_DEBUG && 0 1539 SoDebugError::postInfo("SoGuiFullViewerP::pan", 1540 "was(%.3g, %.3g) -> now(%.3g, %.3g)", 1541 prevpos[0], prevpos[1], currpos[0], currpos[1]); 1542#endif // SO@GUI@_DEBUG 1543 1544 // Find projection points for the last and current mouse coordinates. 1545 SbViewVolume vv = cam->getViewVolume(aspectratio); 1546 SbLine line; 1547 vv.projectPointToLine(currpos, line); 1548 SbVec3f current_planept; 1549 panningplane.intersect(line, current_planept); 1550 vv.projectPointToLine(prevpos, line); 1551 SbVec3f old_planept; 1552 panningplane.intersect(line, old_planept); 1553 1554 // Reposition camera according to the vector difference between the 1555 // projected points. 1556 cam->position = cam->position.getValue() - (current_planept - old_planept); 1557} 1558 1559// ************************************************************************* 1560 1561// Dependent on the camera type this will either shrink or expand the 1562// height of the viewport (orthogonal camera) or move the camera 1563// closer or further away from the focal point in the scene. 1564// 1565// Used from both SoGuiPlaneViewer and SoGuiExaminerViewer. 1566// Implemented in the SoGuiFullViewer private class to collect common 1567// code. 1568void 1569SoGuiFullViewerP::zoom(SoCamera * cam, const float diffvalue) 1570{ 1571 if (cam == NULL) return; // can happen for empty scenegraph 1572 SoType t = cam->getTypeId(); 1573 SbName tname = t.getName(); 1574 1575 // This will be in the range of <0, ->>. 1576 float multiplicator = float(exp(diffvalue)); 1577 1578 if (t.isDerivedFrom(SoOrthographicCamera::getClassTypeId())) { 1579 1580 // Since there's no perspective, "zooming" in the original sense 1581 // of the word won't have any visible effect. So we just increase 1582 // or decrease the field-of-view values of the camera instead, to 1583 // "shrink" the projection size of the model / scene. 1584 SoOrthographicCamera * oc = (SoOrthographicCamera *)cam; 1585 oc->height = oc->height.getValue() * multiplicator; 1586 1587 } 1588 else { 1589 // FrustumCamera can be found in the SmallChange CVS module (it's 1590 // a camera that lets you specify (for instance) an off-center 1591 // frustum (similar to glFrustum()) 1592 if (!t.isDerivedFrom(SoPerspectiveCamera::getClassTypeId()) && 1593 tname != "FrustumCamera") { 1594 static SbBool first = TRUE; 1595 if (first) { 1596 SoDebugError::postWarning("SoGuiFullViewerP::zoom", 1597 "Unknown camera type, " 1598 "will zoom by moving position, but this might not be correct."); 1599 first = FALSE; 1600 } 1601 } 1602 1603 const float oldfocaldist = cam->focalDistance.getValue(); 1604 const float newfocaldist = oldfocaldist * multiplicator; 1605 1606 SbVec3f direction; 1607 cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction); 1608 1609 const SbVec3f oldpos = cam->position.getValue(); 1610 const SbVec3f newpos = oldpos + (newfocaldist - oldfocaldist) * -direction; 1611 1612 // This catches a rather common user interface "buglet": if the 1613 // user zooms the camera out to a distance from origo larger than 1614 // what we still can safely do floating point calculations on 1615 // (i.e. without getting NaN or Inf values), the faulty floating 1616 // point values will propagate until we start to get debug error 1617 // messages and eventually an assert failure from core Coin code. 1618 // 1619 // With the below bounds check, this problem is avoided. 1620 // 1621 // (But note that we depend on the input argument ''diffvalue'' to 1622 // be small enough that zooming happens gradually. Ideally, we 1623 // should also check distorigo with isinf() and isnan() (or 1624 // inversely; isinfite()), but those only became standardized with 1625 // C99.) 1626 const float distorigo = newpos.length(); 1627 // sqrt(FLT_MAX) == ~ 1e+19, which should be both safe for further 1628 // calculations and ok for the end-user and app-programmer. 1629 if (distorigo > float(sqrt(FLT_MAX))) { 1630#if SO@GUI@_DEBUG && 0 // debug 1631 SoDebugError::postWarning("SoGuiFullViewerP::zoom", 1632 "zoomed too far (distance to origo==%f (%e))", 1633 distorigo, distorigo); 1634#endif // debug 1635 } 1636 else { 1637 cam->position = newpos; 1638 cam->focalDistance = newfocaldist; 1639 } 1640 } 1641} 1642 1643// ************************************************************************ 1644 1645#endif // DOXYGEN_SKIP_THIS 1646 1647#undef PRIVATE 1648#undef PUBLIC 1649 1650