[soqt] 04/09: Add files from SoGui as a patch. Need for build.
Anton Gladky
gladk at alioth.debian.org
Tue Sep 17 19:21:56 UTC 2013
This is an automated email from the git hooks/post-receive script.
gladk pushed a commit to branch master
in repository soqt.
commit 8b79572b925294e78fd2760633b22f572f057f35
Author: Anton Gladky <gladky.anton at gmail.com>
Date: Tue Sep 17 21:00:08 2013 +0200
Add files from SoGui as a patch. Need for build.
---
debian/patches/add_sogui.patch |41764 ++++++++++++++++++++++++++++++++++++++++
debian/patches/series | 1 +
2 files changed, 41765 insertions(+)
diff --git a/debian/patches/add_sogui.patch b/debian/patches/add_sogui.patch
new file mode 100644
index 0000000..77f5332
--- /dev/null
+++ b/debian/patches/add_sogui.patch
@@ -0,0 +1,41764 @@
+Description: add SoGui into the soqt.
+ The latest VCS-version of SoQT does not build without SoGui-files.
+ The source is added here as a patch.
+ https://bitbucket.org/Coin3D/sogui/src
+Author: Anton Gladky <gladk at debian.org>
+Last-Update: 2013-09-17
+
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/.hg_archival.txt
+@@ -0,0 +1,5 @@
++repo: 14ca99190cb55f414982b9a037817ced369b28a3
++node: 229ba2f86292cd8b89bbd7381c2cf22e138cdc84
++branch: default
++latesttag: soqt-1_4_0
++latesttagdistance: 63
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/BUGS.txt
+@@ -0,0 +1,161 @@
++=====================================================================
++NOTE: see also So at Gui@/BUGS.txt.
++=====================================================================
++
++000 SoText2 won't show with drawstyle == hidden line. Bug reported by
++ Jean Davy. Reproduce with this minimal, stand-alone example:
++
++ ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++ #include <Inventor/Qt/SoQt.h>
++ #include <Inventor/Qt/viewers/SoQtExaminerViewer.h>
++ #include <Inventor/nodes/SoCone.h>
++ #include <Inventor/nodes/SoSeparator.h>
++ #include <Inventor/nodes/SoText2.h>
++
++ int
++ main(int argc, char* argv[])
++ {
++ QWidget * mainwin = SoQt::init(argv[0]);
++ SoSeparator * root = new SoSeparator;
++
++ root->addChild(new SoCone);
++ SoText2 * text2d = new SoText2;
++ root->addChild(text2d);
++ text2d->string = "tjo-bing";
++
++ SoQtExaminerViewer * viewer = new SoQtExaminerViewer(mainwin);
++ viewer->setSceneGraph(root);
++ viewer->setDrawStyle(SoQtExaminerViewer::STILL,
++ SoQtExaminerViewer::VIEW_HIDDEN_LINE);
++
++ SoQt::show(mainwin);
++ SoQt::mainLoop();
++
++ return 0;
++ }
++ ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++
++ This is the cause of the bug, according to <pederb at sim.no>:
++
++ We use GL polygon offset to do hidden line rendering, and this
++ caused problems since the SoText2 characters are rendered twice
++ (for the first pass we just draw everything black, with an
++ z-buffer offset). SoText2 characters are drawn as bitmaps, which
++ are not affected by polygon offset.
++
++ Consider this a fairly low priority bug.
++
++ <mortene at sim.no> 20020521.
++
++=====================================================================
++
++002 Should search for and pick up VRML97 Viewpoint and other bindable
++ nodes.
++
++ As of now, the SoGuiViewer only scans a newly set scene graph for
++ SoCamera nodes. (If found, it will "attach" the viewer controls to
++ the first one.) If none is found, the viewer sets up it's own in
++ it's private "control graph".
++
++ This doesn't work with VRML97 scene graphs, obviously, so
++ SoGuiViewer should also scan for Viewpoint nodes to be set up as
++ the viewer's camera.
++
++ Note that matters are complicated a bit by the fact that we can't
++ be sure that an implementation of any VRML97 nodes is actually
++ present in the Coin / Inventor library (it could be SGI Inventor,
++ or it could be Coin configured to exclude VRML97 support). So we
++ need to search for them by using the SoType::fromName("Viewpoint")
++ type (check that this is != SoType::badType() to see whether
++ VRML97 is supported), and connect up it's position, orientation
++ and fieldOfViewer fields by using the introspection features of
++ SoFieldContainer.
++
++ In addition to the Viewpoint nodes, other bindable nodes should
++ also be handled (Fog and Background).
++
++ 20030107 mortene.
++
++=====================================================================
++
++003 View volume settings becomes incorrect for "point scene".
++
++ If the scene graph just contains a single point in 3D space, the
++ view volume setup will cause heaps of error messages when running
++ on top of debug-mode Coin.
++
++ Can be reproduced by loading this into an examinerviewer and
++ interacting with the camera:
++
++ ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++ #Inventor V2.1 ascii
++
++ Coordinate3 { point 42 4242 424242 }
++ PointSet { }
++ ----8<--- [snip] ---------8<--- [snip] ---------8<--- [snip] ---
++
++ A suggestion for a solution: should most likely handle this
++ problem by detecting when the scene bounding sphere is below a
++ certain radius, and then "artificially" expand it to a minimum
++ value.
++
++ 20030916 mortene.
++
++=====================================================================
++
++004 Switching back and forth between camera types causes bugs in
++ height / heightAngle fields.
++
++ To reproduce, load a simple scene into the SoGuiExaminerViewer,
++ then switch camera modes, zoom back and forth, switch, zoom,
++ etc. Eventually, the field-of-view for the SoPerspectiveCamera
++ will go bonkers.
++
++ 20040726 mortene.
++
++=====================================================================
++
++005 Switching back and forth between camera types causes weird
++ behavior with "view all".
++
++ To reproduce buggy behavior: load an iv-file just containing an
++ SoSphere node into an SoGuiExaminerViewer. Go to ortho camera,
++ click "view all", switch to perspective camera, click "view
++ all". The camera will now be a great deal further away from the
++ sphere than when in ortho camera mode.
++
++ This bug may be related to the generally buggy re-calculation of
++ height / heightAngle when switching back and forth between ortho
++ and perspective camera, as described in bug #004.
++
++ 20040726 mortene.
++
++=====================================================================
++
++006 Static building of the So* libraries under Windows linking with a
++ staticly built Coin causes Coin to be included within the So*
++ lib-file.
++
++ This will typically cause multiple Coin instances in the final
++ executable, as the user is likely to link with Coin again for the
++ app code. The same problem also probably manifests itself with
++ e.g. SIM Voleon, SIM Aruba, and our other libraries dependent on
++ Coin.
++
++ 20041021 mortene.
++
++ Update 20041103 larsa: Fixed, but not for SIM Voleon and
++ SmallChange. WIll fix for those and remove this item RSN.
++
++=====================================================================
++
++007 Catch GL errors in a proper manner.
++
++ glGetError() should always be called in a loop, i.e. as we do in
++ Coin with the coin_catch_gl_errors() call in src/glue/gl.c.
++
++ Audit and fix all code in the So* libraries in this regard.
++
++ 20051115 mortene.
++
++=====================================================================
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/HACKING
+@@ -0,0 +1,35 @@
++This file describes some hacking techniques and tips & tricks that are
++common for the GUI interface toolkits.
++
++Be sure to check Coin/HACKING for Coin-specific tricks and more
++generic information, plus the file HACKING (if present) on the
++sourcecode root of the "parent" toolkit CVS module.
++
++
++0 Finding Component Information
++===============================
++
++ We have added some easter eggs to the debug versions of the
++ GUI toolkit libraries that can be used to find information
++ about which components are in use.
++
++ Typing 'glinfo' in a viewer will probe into all kinds of information
++ from the GL driver and open a window displaying it.
++
++ Typing 'ivinfo' in a viewer will probe about the underlying Open
++ Inventor implementation and display it in a new window.
++
++ Typing 'soinfo' in a viewer will open a window with some basic
++ information about the toolkit library and possibly the native
++ toolkit it has been built on.
++
++
++1 Performance profiling / debugging
++===================================
++
++ If you are doing work related to rendering performance, you will
++ probably want to see frames-per-second statistics when spinning
++ models, etc. If you set the environment variable
++ COIN_SHOW_FPS_COUNTER to "1", a fps counter should show up in the
++ bottom left corner of the GL canvas when you do animation (spinning,
++ zooming, etc) in the viewer components.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/Makefile.common
+@@ -0,0 +1,785 @@
++############################################################################
++# src/Inventor/@Gui@/common/Makefile.common
++#
++# This file takes care of all the common code generation that is happening
++# across all the Coin3D GUI toolkit libraries.
++#
++
++SoGui_BuiltFiles = \
++ $(top_builddir)/sogui.doxygen \
++ $(top_builddir)/so at gui@-config \
++ $(top_builddir)/so at gui@- at CONFIG@.cfg
++
++SoGui_src_BuiltFiles = \
++ $(top_builddir)/src/so at gui@defs.h
++##$(top_builddir)/src/config.h
++
++SoGui_build_BuiltFiles =
++
++SoGui_src_Inventor_BuiltFiles =
++
++SoGui_src_Inventor_Gui_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/SoAny.h \
++ $(top_builddir)/src/Inventor/@Gui@/SoAny.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@Basic.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@.h \
++ $(top_builddir)/src/Inventor/@Gui@/SoGuiP.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@Common.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@Component.h \
++ $(top_builddir)/src/Inventor/@Gui@/SoGuiComponentP.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidget.h \
++ $(top_builddir)/src/Inventor/@Gui@/SoGuiGLWidgetP.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@ColorEditor.h \
++ $(top_builddir)/src/Inventor/@Gui@/So at Gui@MaterialEditor.h \
++ $(SoGui_src_Inventor_Gui_common_BuiltFiles)
++
++SoGui_src_Inventor_Gui_common_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/common/gl.h
++
++SoGui_src_Inventor_Gui_devices_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/devices/spwinput.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/spwinput_x11.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.c \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiDeviceP.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Device.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocusCommon.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocus.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiInputFocusP.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Keyboard.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiKeyboardP.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Mouse.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@SpacenavDevice.h \
++ $(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@SpacenavDevice.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/devices/SoGuiMouseP.h
++
++SoGui_src_Inventor_Gui_editors_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.h \
++ $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.h \
++ $(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.cpp
++
++SoGui_src_Inventor_Gui_nodes_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiNodes.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Nodes.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSceneTexture2.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SceneTexture2.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewportFix.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/ViewportFix.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/ViewpointWrapper.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPane.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Pane.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPosition.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Position.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiTranslation.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Translation.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiFrame.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Frame.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiImage.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Image.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiLabel.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Label.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiToggleButton.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/ToggleButton.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiRadioButton.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/RadioButton.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiClickCounter.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/ClickCounter.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider1.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Slider1.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider2.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/Slider2.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiColorEditor.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/ColorEditor.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiMaterialEditor.h \
++ $(top_builddir)/src/Inventor/@Gui@/nodes/MaterialEditor.cpp
++
++SoGui_src_Inventor_Gui_engines_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/engines/SoGuiEngines.h \
++ $(top_builddir)/src/Inventor/@Gui@/engines/Engines.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/engines/SoGuiRadioGroup.h \
++ $(top_builddir)/src/Inventor/@Gui@/engines/RadioGroup.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/engines/SoGuiFormat.h \
++ $(top_builddir)/src/Inventor/@Gui@/engines/Format.cpp
++
++SoGui_src_Inventor_Gui_viewers_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiViewerP.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiFullViewerP.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiExaminerViewerP.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiPlaneViewerP.h \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp
++
++SoGui_src_Inventor_Gui_widgets_BuiltFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.h \
++ $(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.cpp \
++ $(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.h \
++ $(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.cpp
++
++SoGui_man_man1_BuiltFiles = \
++ $(top_builddir)/man/man1/so at gui@-config.1
++
++SoGuiBuiltFiles = \
++ $(SoGui_BuiltFiles) \
++ $(SoGui_build_BuiltFiles) \
++ $(SoGui_src_BuiltFiles) \
++ $(SoGui_src_Inventor_BuiltFiles) \
++ $(SoGui_src_Inventor_Gui_BuiltFiles) \
++ $(SoGui_src_Inventor_Gui_devices_BuiltFiles) \
++ $(SoGui_src_Inventor_Gui_editors_BuiltFiles) \
++ $(SoGui_src_Inventor_Gui_engines_BuiltFiles) \
++ $(SoGui_src_Inventor_Gui_nodes_BuiltFiles) \
++ $(SoGui_src_Inventor_Gui_viewers_BuiltFiles) \
++ $(SoGui_src_Inventor_Gui_widgets_BuiltFiles) \
++ $(SoGui_man_man1_BuiltFiles)
++
++if BUILD_METAFILES
++
++SoGui_BuiltMetaFiles =
++SoGui_src_BuiltMetaFiles =
++SoGui_src_Inventor_BuiltMetaFiles =
++
++SoGui_src_Inventor_Gui_BuiltMetaFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc \
++ $(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc \
++ $(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc
++
++if HAVE_JOYSTICK_LINUX
++SoGui_src_Inventor_Gui_devices_LinuxJoystickMetaFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc
++else
++SoGui_src_Inventor_Gui_devices_LinuxJoystickMetaFiles =
++endif
++
++SoGui_src_Inventor_Gui_devices_BuiltMetaFiles = \
++ $(SoGui_src_Inventor_Gui_devices_LinuxJoystickMetaFiles)
++
++SoGui_src_Inventor_Gui_viewers_BuiltMetaFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc \
++ $(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc
++
++SoGui_src_Inventor_Gui_widgets_BuiltMetaFiles = \
++ $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc \
++ $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc \
++ $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc
++
++else
++
++SoGui_src_Inventor_Gui_BuiltMetaFiles =
++SoGui_src_Inventor_Gui_devices_BuiltMetaFiles =
++SoGui_src_Inventor_Gui_viewers_BuiltMetaFiles =
++SoGui_src_Inventor_Gui_widgets_BuiltMetaFiles =
++
++endif
++
++SoGuiBuiltMetaFiles = \
++ $(SoGui_BuiltMetaFiles) \
++ $(SoGui_src_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_Gui_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_Gui_devices_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_Gui_editors_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_Gui_engines_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_Gui_nodes_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_Gui_viewers_BuiltMetaFiles) \
++ $(SoGui_src_Inventor_Gui_widgets_BuiltMetaFiles)
++
++SoGuiAllBuiltFiles = \
++ $(SoGuiBuiltFiles) \
++ $(SoGuiBuiltMetaFiles)
++
++SoGuiCommonWinFiles = \
++ cfg/errors.txt \
++ cfg/doxy4win.pl \
++ cfg/gendsp.pl \
++ cfg/wrapmsvc.exe
++
++SoGuiCommonDistFiles = \
++ BUGS.txt \
++ src/Inventor/@Gui@/common/BUGS.txt \
++ \
++ src/Inventor/@Gui@/common/Makefile.common \
++ src/Inventor/@Gui@/common/sogui-config.in \
++ src/Inventor/@Gui@/common/sogui.doxygen.in \
++ src/Inventor/@Gui@/common/sogui-config.1.in \
++ src/Inventor/@Gui@/common/sogui.cfg.in \
++ src/Inventor/@Gui@/common/SoGuiBasic.h.in \
++ src/Inventor/@Gui@/common/SoGuiCursor.h.in \
++ src/Inventor/@Gui@/common/SoGuiCursor.cpp.in \
++ src/Inventor/@Gui@/common/SoGuiObject.h.in \
++ src/Inventor/@Gui@/common/SoGuiObject.cpp.in \
++ src/Inventor/@Gui@/common/SoGui.h.in \
++ src/Inventor/@Gui@/common/SoGuiP.h.in \
++ src/Inventor/@Gui@/common/SoGuiCommon.cpp.in \
++ src/Inventor/@Gui@/common/SoGuiComponentCommon.cpp.in \
++ src/Inventor/@Gui@/common/SoGuiComponent.h.in \
++ src/Inventor/@Gui@/common/SoGuiComponentP.h.in \
++ src/Inventor/@Gui@/common/SoGuiGLWidget.h.in \
++ src/Inventor/@Gui@/common/SoGuiGLWidgetP.h.in \
++ src/Inventor/@Gui@/common/SoGuiGLWidgetCommon.cpp.in \
++ src/Inventor/@Gui@/common/SoGuiRenderArea.h.in \
++ src/Inventor/@Gui@/common/SoGuiRenderArea.cpp.in \
++ src/Inventor/@Gui@/common/SoGuiColorEditor.h.in \
++ src/Inventor/@Gui@/common/SoGuiMaterialEditor.h.in \
++ src/Inventor/@Gui@/common/SbGuiList.h \
++ src/Inventor/@Gui@/common/SoAny.h.in \
++ src/Inventor/@Gui@/common/SoAny.cpp.in \
++ src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.h.in \
++ src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.cpp.in \
++ src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.h.in \
++ src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.cpp.in \
++ src/Inventor/@Gui@/common/gl.h.in \
++ src/Inventor/@Gui@/common/soguidefs.h.in \
++ src/Inventor/@Gui@/common/spwinput.h.in \
++ src/Inventor/@Gui@/common/spwinput_win32.h.in \
++ src/Inventor/@Gui@/common/spwinput_x11.cpp.in \
++ src/Inventor/@Gui@/common/spwinput_win32.c.in \
++ src/Inventor/@Gui@/common/devices/SoGuiDevice.cpp.in \
++ src/Inventor/@Gui@/common/devices/SoGuiDeviceP.h.in \
++ src/Inventor/@Gui@/common/devices/SoGuiDevice.h.in \
++ src/Inventor/@Gui@/common/devices/SoGuiInputFocus.cpp.in \
++ src/Inventor/@Gui@/common/devices/SoGuiInputFocus.h.in \
++ src/Inventor/@Gui@/common/devices/SoGuiInputFocusP.h.in \
++ src/Inventor/@Gui@/common/devices/SoGuiKeyboard.cpp.in \
++ src/Inventor/@Gui@/common/devices/SoGuiKeyboard.h.in \
++ src/Inventor/@Gui@/common/devices/SoGuiKeyboardP.h.in \
++ src/Inventor/@Gui@/common/devices/SoGuiMouse.cpp.in \
++ src/Inventor/@Gui@/common/devices/SoGuiMouse.h.in \
++ src/Inventor/@Gui@/common/devices/SoGuiMouseP.h.in \
++ src/Inventor/@Gui@/common/docs/doxygen/header.html \
++ src/Inventor/@Gui@/common/docs/doxygen/footer.html \
++ src/Inventor/@Gui@/common/docs/doxygen/stylesheet.css \
++ src/Inventor/@Gui@/common/docs/doxygen/Coin_logo.png \
++ src/Inventor/@Gui@/common/editors/SoGuiColorEditor.h.in \
++ src/Inventor/@Gui@/common/editors/SoGuiColorEditor.cpp.in \
++ src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.h.in \
++ src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.cpp.in \
++ src/Inventor/@Gui@/common/engines/Engines.h.in \
++ src/Inventor/@Gui@/common/engines/Engines.cpp.in \
++ src/Inventor/@Gui@/common/engines/RadioGroup.h.in \
++ src/Inventor/@Gui@/common/engines/RadioGroup.cpp.in \
++ src/Inventor/@Gui@/common/engines/Format.h.in \
++ src/Inventor/@Gui@/common/engines/Format.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Nodes.h.in \
++ src/Inventor/@Gui@/common/nodes/Nodes.cpp.in \
++ src/Inventor/@Gui@/common/nodes/SceneTexture2.h.in \
++ src/Inventor/@Gui@/common/nodes/SceneTexture2.cpp.in \
++ src/Inventor/@Gui@/common/nodes/ViewportFix.h.in \
++ src/Inventor/@Gui@/common/nodes/ViewportFix.cpp.in \
++ src/Inventor/@Gui@/common/nodes/ViewpointWrapper.h.in \
++ src/Inventor/@Gui@/common/nodes/ViewpointWrapper.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Pane.h.in \
++ src/Inventor/@Gui@/common/nodes/Pane.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Position.h.in \
++ src/Inventor/@Gui@/common/nodes/Position.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Translation.h.in \
++ src/Inventor/@Gui@/common/nodes/Translation.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Frame.h.in \
++ src/Inventor/@Gui@/common/nodes/Frame.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Image.h.in \
++ src/Inventor/@Gui@/common/nodes/Image.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Label.h.in \
++ src/Inventor/@Gui@/common/nodes/Label.cpp.in \
++ src/Inventor/@Gui@/common/nodes/ToggleButton.h.in \
++ src/Inventor/@Gui@/common/nodes/ToggleButton.cpp.in \
++ src/Inventor/@Gui@/common/nodes/RadioButton.h.in \
++ src/Inventor/@Gui@/common/nodes/RadioButton.cpp.in \
++ src/Inventor/@Gui@/common/nodes/ClickCounter.h.in \
++ src/Inventor/@Gui@/common/nodes/ClickCounter.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Slider1.h.in \
++ src/Inventor/@Gui@/common/nodes/Slider1.cpp.in \
++ src/Inventor/@Gui@/common/nodes/Slider2.h.in \
++ src/Inventor/@Gui@/common/nodes/Slider2.cpp.in \
++ src/Inventor/@Gui@/common/nodes/ColorEditor.h.in \
++ src/Inventor/@Gui@/common/nodes/ColorEditor.cpp.in \
++ src/Inventor/@Gui@/common/nodes/MaterialEditor.h.in \
++ src/Inventor/@Gui@/common/nodes/MaterialEditor.cpp.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.cpp.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.cpp.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.cpp.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiFullViewerP.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.cpp.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewerP.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.cpp.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewerP.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiViewer.cpp.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiViewer.h.in \
++ src/Inventor/@Gui@/common/viewers/SoGuiViewerP.h.in \
++ src/Inventor/@Gui@/common/pixmaps/home.xpm \
++ src/Inventor/@Gui@/common/pixmaps/ortho.xpm \
++ src/Inventor/@Gui@/common/pixmaps/perspective.xpm \
++ src/Inventor/@Gui@/common/pixmaps/pick.xpm \
++ src/Inventor/@Gui@/common/pixmaps/seek.xpm \
++ src/Inventor/@Gui@/common/pixmaps/set_home.xpm \
++ src/Inventor/@Gui@/common/pixmaps/view.xpm \
++ src/Inventor/@Gui@/common/pixmaps/view_all.xpm \
++ src/Inventor/@Gui@/common/pixmaps/x.xpm \
++ src/Inventor/@Gui@/common/pixmaps/y.xpm \
++ src/Inventor/@Gui@/common/pixmaps/z.xpm
++
++############################################################################
++## the toolkit-specific anomalies
++
++SoQt_ExtraBuiltMetaFiles = \
++ $(top_builddir)/src/Inventor/Qt/widgets/moc_SoQtGLArea.cpp
++
++############################################################################
++## the actual gory rules for generating the sources, invokable from *any*
++## dir in So at Gui@
++
++$(top_builddir)/sogui.doxygen: $(top_srcdir)/src/Inventor/@Gui@/common/sogui.doxygen.in $(top_builddir)/config.status
++ @cd $(top_builddir); \
++ $(SHELL) config.status --file=sogui.doxygen:src/Inventor/@Gui@/common/sogui.doxygen.in; \
++ $(top_srcdir)/cfg/doxy4win.pl sogui.doxygen; \
++ rm -f sogui.doxygen.bak;
++
++$(top_builddir)/so at gui@-config: $(top_srcdir)/src/Inventor/@Gui@/common/sogui-config.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=so at gui@-config:src/Inventor/@Gui@/common/sogui-config.in && chmod +x so at gui@-config )
++
++$(top_builddir)/so at gui@- at CONFIG@.cfg: $(top_srcdir)/src/Inventor/@Gui@/common/sogui.cfg.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=so at gui@- at CONFIG@.cfg:src/Inventor/@Gui@/common/sogui.cfg.in )
++
++############################################################################
++
++## src/
++
++$(top_builddir)/src/config.h: $(top_srcdir)/src/config.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status src/config.h )
++
++$(top_builddir)/src/so at gui@defs.h: $(top_srcdir)/src/Inventor/@Gui@/common/soguidefs.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/so at gui@defs.h:src/Inventor/@Gui@/common/soguidefs.h.in )
++
++## src/Inventor/@Gui@/
++
++$(top_builddir)/src/Inventor/@Gui@/SoAny.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoAny.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoAny.h:src/Inventor/@Gui@/common/SoAny.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoAny.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoAny.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoAny.cpp:src/Inventor/@Gui@/common/SoAny.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Basic.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiBasic.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=-:src/Inventor/@Gui@/common/SoGuiBasic.h.in | $(SHELL) config.status --header=src/Inventor/@Gui@/So at Gui@Basic.h:- )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiObject.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Object.h:src/Inventor/@Gui@/common/SoGuiObject.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Object.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiObject.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Object.cpp:src/Inventor/@Gui@/common/SoGuiObject.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiCursor.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Cursor.h:src/Inventor/@Gui@/common/SoGuiCursor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Cursor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiCursor.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Cursor.cpp:src/Inventor/@Gui@/common/SoGuiCursor.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGui.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@.h:src/Inventor/@Gui@/common/SoGui.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoGuiP.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoGuiP.h:src/Inventor/@Gui@/common/SoGuiP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Common.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiCommon.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Common.cpp:src/Inventor/@Gui@/common/SoGuiCommon.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiComponentCommon.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp:src/Inventor/@Gui@/common/SoGuiComponentCommon.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@Component.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiComponent.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@Component.h:src/Inventor/@Gui@/common/SoGuiComponent.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoGuiComponentP.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiComponentP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoGuiComponentP.h:src/Inventor/@Gui@/common/SoGuiComponentP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidget.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiGLWidget.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@GLWidget.h:src/Inventor/@Gui@/common/SoGuiGLWidget.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/SoGuiGLWidgetP.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiGLWidgetP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/SoGuiGLWidgetP.h:src/Inventor/@Gui@/common/SoGuiGLWidgetP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiGLWidgetCommon.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp:src/Inventor/@Gui@/common/SoGuiGLWidgetCommon.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiRenderArea.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@RenderArea.h:src/Inventor/@Gui@/common/SoGuiRenderArea.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@RenderArea.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiRenderArea.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@RenderArea.cpp:src/Inventor/@Gui@/common/SoGuiRenderArea.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@ColorEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiColorEditor.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@ColorEditor.h:src/Inventor/@Gui@/common/SoGuiColorEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/So at Gui@MaterialEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/SoGuiMaterialEditor.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/So at Gui@MaterialEditor.h:src/Inventor/@Gui@/common/SoGuiMaterialEditor.h.in )
++
++## src/Inventor/@Gui@/common/
++
++$(top_builddir)/src/Inventor/@Gui@/common/gl.h: $(top_srcdir)/src/Inventor/@Gui@/common/gl.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ if test -d src/Inventor/@Gui@/common; then :; else \
++ echo "mkdir src/Inventor/@Gui@/common"; \
++ mkdir src/Inventor/@Gui@/common; \
++ fi; \
++ $(SHELL) config.status --file=src/Inventor/@Gui@/common/gl.h:src/Inventor/@Gui@/common/gl.h.in )
++
++## src/Inventor/@Gui@/devices/
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiDevice.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiDevice.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Device.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiDevice.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@Device.h:src/Inventor/@Gui@/common/devices/SoGuiDevice.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiDeviceP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiDeviceP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiDeviceP.h:src/Inventor/@Gui@/common/devices/SoGuiDeviceP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocusCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiInputFocus.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@InputFocusCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiInputFocus.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@InputFocus.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiInputFocus.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@InputFocus.h:src/Inventor/@Gui@/common/devices/SoGuiInputFocus.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiInputFocusP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiInputFocusP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiInputFocusP.h:src/Inventor/@Gui@/common/devices/SoGuiInputFocusP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiKeyboard.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiKeyboard.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Keyboard.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiKeyboard.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@Keyboard.h:src/Inventor/@Gui@/common/devices/SoGuiKeyboard.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiKeyboardP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiKeyboardP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiKeyboardP.h:src/Inventor/@Gui@/common/devices/SoGuiKeyboardP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiMouse.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp:src/Inventor/@Gui@/common/devices/SoGuiMouse.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/So at Gui@Mouse.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiMouse.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/So at Gui@Mouse.h:src/Inventor/@Gui@/common/devices/SoGuiMouse.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiMouseP.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiMouseP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiMouseP.h:src/Inventor/@Gui@/common/devices/SoGuiMouseP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.h: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.h:src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/SoGuiSpacenavDevice.cpp:src/Inventor/@Gui@/common/devices/SoGuiSpacenavDevice.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput.h: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput.h:src/Inventor/@Gui@/common/spwinput.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.h: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput_win32.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput_win32.h:src/Inventor/@Gui@/common/spwinput_win32.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput_x11.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput_x11.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput_x11.cpp:src/Inventor/@Gui@/common/spwinput_x11.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/devices/spwinput_win32.c: $(top_srcdir)/src/Inventor/@Gui@/common/spwinput_win32.c.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/devices/spwinput_win32.c:src/Inventor/@Gui@/common/spwinput_win32.c.in )
++
++## src/Inventor/@Gui@/editors/
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiColorEditor.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@ColorEditor.h:src/Inventor/@Gui@/common/editors/SoGuiColorEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@ColorEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiColorEditor.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@ColorEditor.cpp:src/Inventor/@Gui@/common/editors/SoGuiColorEditor.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.h:src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/editors/So at Gui@MaterialEditor.cpp:src/Inventor/@Gui@/common/editors/SoGuiMaterialEditor.cpp.in )
++
++## src/Inventor/@Gui@/engines/
++
++$(top_builddir)/src/Inventor/@Gui@/engines/SoGuiEngines.h: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Engines.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/SoGuiEngines.h:src/Inventor/@Gui@/common/engines/Engines.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/Engines.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Engines.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/Engines.cpp:src/Inventor/@Gui@/common/engines/Engines.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/SoGuiRadioGroup.h: $(top_srcdir)/src/Inventor/@Gui@/common/engines/RadioGroup.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/SoGuiRadioGroup.h:src/Inventor/@Gui@/common/engines/RadioGroup.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/RadioGroup.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/engines/RadioGroup.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/RadioGroup.cpp:src/Inventor/@Gui@/common/engines/RadioGroup.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/SoGuiFormat.h: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Format.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/SoGuiFormat.h:src/Inventor/@Gui@/common/engines/Format.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/engines/Format.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/engines/Format.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/engines/Format.cpp:src/Inventor/@Gui@/common/engines/Format.cpp.in )
++
++## src/Inventor/@Gui@/nodes/
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiNodes.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Nodes.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiNodes.h:src/Inventor/@Gui@/common/nodes/Nodes.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Nodes.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Nodes.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Nodes.cpp:src/Inventor/@Gui@/common/nodes/Nodes.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSceneTexture2.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/SceneTexture2.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiSceneTexture2.h:src/Inventor/@Gui@/common/nodes/SceneTexture2.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SceneTexture2.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/SceneTexture2.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SceneTexture2.cpp:src/Inventor/@Gui@/common/nodes/SceneTexture2.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewportFix.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewportFix.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiViewportFix.h:src/Inventor/@Gui@/common/nodes/ViewportFix.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ViewportFix.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewportFix.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ViewportFix.cpp:src/Inventor/@Gui@/common/nodes/ViewportFix.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewpointWrapper.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h:src/Inventor/@Gui@/common/nodes/ViewpointWrapper.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ViewpointWrapper.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ViewpointWrapper.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ViewpointWrapper.cpp:src/Inventor/@Gui@/common/nodes/ViewpointWrapper.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPane.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Pane.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiPane.h:src/Inventor/@Gui@/common/nodes/Pane.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Pane.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Pane.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Pane.cpp:src/Inventor/@Gui@/common/nodes/Pane.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiPosition.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Position.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiPosition.h:src/Inventor/@Gui@/common/nodes/Position.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Position.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Position.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Position.cpp:src/Inventor/@Gui@/common/nodes/Position.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiTranslation.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Translation.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiTranslation.h:src/Inventor/@Gui@/common/nodes/Translation.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Translation.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Translation.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Translation.cpp:src/Inventor/@Gui@/common/nodes/Translation.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiFrame.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Frame.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiFrame.h:src/Inventor/@Gui@/common/nodes/Frame.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Frame.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Frame.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Frame.cpp:src/Inventor/@Gui@/common/nodes/Frame.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiImage.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Image.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiImage.h:src/Inventor/@Gui@/common/nodes/Image.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Image.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Image.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Image.cpp:src/Inventor/@Gui@/common/nodes/Image.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiLabel.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Label.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiLabel.h:src/Inventor/@Gui@/common/nodes/Label.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Label.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Label.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Label.cpp:src/Inventor/@Gui@/common/nodes/Label.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiToggleButton.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ToggleButton.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiToggleButton.h:src/Inventor/@Gui@/common/nodes/ToggleButton.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ToggleButton.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ToggleButton.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ToggleButton.cpp:src/Inventor/@Gui@/common/nodes/ToggleButton.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiRadioButton.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/RadioButton.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiRadioButton.h:src/Inventor/@Gui@/common/nodes/RadioButton.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/RadioButton.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/RadioButton.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/RadioButton.cpp:src/Inventor/@Gui@/common/nodes/RadioButton.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiClickCounter.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ClickCounter.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiClickCounter.h:src/Inventor/@Gui@/common/nodes/ClickCounter.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ClickCounter.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ClickCounter.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ClickCounter.cpp:src/Inventor/@Gui@/common/nodes/ClickCounter.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider1.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider1.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiSlider1.h:src/Inventor/@Gui@/common/nodes/Slider1.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Slider1.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider1.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Slider1.cpp:src/Inventor/@Gui@/common/nodes/Slider1.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiSlider2.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider2.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiSlider2.h:src/Inventor/@Gui@/common/nodes/Slider2.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/Slider2.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/Slider2.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/Slider2.cpp:src/Inventor/@Gui@/common/nodes/Slider2.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiColorEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ColorEditor.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiColorEditor.h:src/Inventor/@Gui@/common/nodes/ColorEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/ColorEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/ColorEditor.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/ColorEditor.cpp:src/Inventor/@Gui@/common/nodes/ColorEditor.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/SoGuiMaterialEditor.h: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/MaterialEditor.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/SoGuiMaterialEditor.h:src/Inventor/@Gui@/common/nodes/MaterialEditor.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/nodes/MaterialEditor.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/nodes/MaterialEditor.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/nodes/MaterialEditor.cpp:src/Inventor/@Gui@/common/nodes/MaterialEditor.cpp.in )
++
++## src/Inventor/@Gui@/viewers/
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiViewer.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@Viewer.h:src/Inventor/@Gui@/common/viewers/SoGuiViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiViewerP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiViewer.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiConstrainedViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiFlyViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiFullViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFullViewerP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiFullViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiFullViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiFullViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiExaminerViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewerP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiExaminerViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiExaminerViewer.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h:src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/SoGuiPlaneViewerP.h: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewerP.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/SoGuiPlaneViewerP.h:src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewerP.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp:src/Inventor/@Gui@/common/viewers/SoGuiPlaneViewer.cpp.in )
++
++## src/Inventor/@Gui@/widgets/
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.h: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/SoAnyThumbWheel.h:src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/SoAnyThumbWheel.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/SoAnyThumbWheel.cpp:src/Inventor/@Gui@/common/widgets/SoAnyThumbWheel.cpp.in )
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.h: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.h.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.h:src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.h.in )
++
++$(top_builddir)/src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.cpp: $(top_srcdir)/src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.cpp.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=src/Inventor/@Gui@/widgets/So at Gui@PopupMenu.cpp:src/Inventor/@Gui@/common/widgets/SoGuiPopupMenu.cpp.in )
++
++## build/
++
++## ..nothing at the moment..
++
++## man/man1/
++
++$(top_builddir)/man/man1/so at gui@-config.1: $(top_srcdir)/src/Inventor/@Gui@/common/sogui-config.1.in $(top_builddir)/config.status
++ @( cd $(top_builddir); $(SHELL) config.status --file=man/man1/so at gui@-config.1:src/Inventor/@Gui@/common/sogui-config.1.in )
++
++# **************************************************************************
++# auto-generated Qt moc files.
++
++if BUILD_METAFILES
++
++## src/Inventor/@Gui@/
++
++$(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc: $(top_srcdir)/src/Inventor/@Gui@/So at Gui@P.h $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ echo " $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc $(top_srcdir)/src/Inventor/@Gui@/So at Gui@P.h"; \
++ $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at P.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/So at Gui@P.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc: $(top_srcdir)/src/Inventor/@Gui@/So at Gui@ComponentP.h $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ echo " $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc src/Inventor/@Gui@/So at Gui@ComponentP.h"; \
++ $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at ComponentP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/So at Gui@ComponentP.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc: $(top_srcdir)/src/Inventor/@Gui@/So at Gui@GLWidgetP.h $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ echo " $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc src/Inventor/@Gui@/So at Gui@GLWidgetP.h"; \
++ $(MOC) -i -o src/Inventor/@Gui@/@meta_prefix at So@Gui at GLWidgetP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/So at Gui@GLWidgetP.h` )
++
++## src/Inventor/@Gui@/devices/
++
++$(top_builddir)/src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc: $(top_srcdir)/src/Inventor/@Gui@/devices/So at Gui@LinuxJoystickP.h $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ echo " $(MOC) -i -o src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/devices/So at Gui@LinuxJoystickP.h`"; \
++ $(MOC) -i -o src/Inventor/@Gui@/devices/@meta_prefix at So@Gui at LinuxJoystickP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/devices/So at Gui@LinuxJoystickP.h` )
++
++## src/Inventor/@Gui@/viewers/
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc: $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewerP.h $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ echo " $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewerP.h`"; \
++ $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at FullViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@FullViewerP.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc: $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ echo " $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h`"; \
++ $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at ExaminerViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h` )
++
++$(top_builddir)/src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc: $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h $(top_builddir)/config.status
++ @( cd $(top_builddir); \
++ echo " $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h`"; \
++ $(MOC) -i -o src/Inventor/@Gui@/viewers/@meta_prefix at So@Gui at PlaneViewerP.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h` )
++
++## src/Inventor/@Gui@/widgets/
++
++# $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc: $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@ThumbWheel.h $(top_builddir)/config.status
++# @( cd $(top_builddir); \
++# echo " $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@ThumbWheel.h`"; \
++# $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at ThumbWheel.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@ThumbWheel.h` )
++#
++# $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc: $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@GLArea.h $(top_builddir)/config.status
++# @( cd $(top_builddir); \
++# echo " $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@GLArea.h`"; \
++# $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix at So@Gui at GLArea.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/So at Gui@GLArea.h` )
++#
++# $(top_builddir)/src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc: $(top_srcdir)/src/Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h $(top_builddir)/config.status
++# @( cd $(top_builddir); \
++# echo " $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h`"; \
++# $(MOC) -i -o src/Inventor/@Gui@/widgets/@meta_prefix@@Gui at NativePopupMenu.icc `$(UNIX2WINPATH) $(top_srcdir)/src/Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h` )
++
++endif
++
++## src/Inventor/@Gui@/common/Makefile.common EOF
++############################################################################
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/NEWS
+@@ -0,0 +1,2 @@
++NEWS
++====
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/README
+@@ -0,0 +1,8 @@
++README
++======
++
++This directory is a distinct Subversion repository, named SoGUI. The
++purpose of this repository is to collect code that is common for all
++Coin GUI component sets, so it can be shared and reused (and to round
++up all the bugs in one place :).
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SbGuiList.h
+@@ -0,0 +1,226 @@
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SOGUI_SBGUILIST_H
++#define SOGUI_SBGUILIST_H
++
++/**************************************************************************/
++
++// IMPORTANT NOTES:
++//
++// * This file is a duplicate of Coin's lists/SbList.h file, and any
++// important fixes/improvements here should be migrated.
++//
++// * This file contains definitions which should only be used during
++// library build for now. It is not yet installed for use by the
++// application programmer.
++
++/**************************************************************************/
++
++#include <Inventor/SbBasic.h>
++#include <assert.h>
++#include <stddef.h> // NULL definition
++
++// We usually implement inline functions below the class definition,
++// since we think that makes the file more readable. However, this is
++// not done for this class, since Visual C++ is not too happy about
++// having functions declared as inline for a template class.
++// pederb, 2001-10-12
++
++template <class Type>
++class SbGuiList {
++ // Older compilers aren't too happy about const declarations in the
++ // class definitions, so use the enum trick described by Scott
++ // Meyers in "Effective C++".
++ enum { DEFAULTSIZE = 4 };
++
++public:
++
++ SbGuiList(const int sizehint = DEFAULTSIZE)
++ : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
++ if (sizehint > DEFAULTSIZE) this->grow(sizehint);
++ }
++
++ SbGuiList(const SbGuiList<Type> & l)
++ : itembuffersize(DEFAULTSIZE), numitems(0), itembuffer(builtinbuffer) {
++ this->copy(l);
++ }
++
++ ~SbGuiList() {
++ if (this->itembuffer != builtinbuffer) delete[] this->itembuffer;
++ }
++
++ void copy(const SbGuiList<Type> & l) {
++ if (this == &l) return;
++ const int n = l.numitems;
++ this->expand(n);
++ for (int i = 0; i < n; i++) this->itembuffer[i] = l.itembuffer[i];
++ }
++
++ SbGuiList <Type> & operator=(const SbGuiList<Type> & l) {
++ this->copy(l);
++ return *this;
++ }
++
++ void fit(void) {
++ const int items = this->numitems;
++
++ if (items < this->itembuffersize) {
++ Type * newitembuffer = this->builtinbuffer;
++ if (items > DEFAULTSIZE) newitembuffer = new Type[items];
++
++ if (newitembuffer != this->itembuffer) {
++ for (int i = 0; i < items; i++) newitembuffer[i] = this->itembuffer[i];
++ }
++
++ if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
++ this->itembuffer = newitembuffer;
++ this->itembuffersize = items > DEFAULTSIZE ? items : DEFAULTSIZE;
++ }
++ }
++
++ void append(const Type item) {
++ if (this->numitems == this->itembuffersize) this->grow();
++ this->itembuffer[this->numitems++] = item;
++ }
++
++ int find(const Type item) const {
++ for (int i = 0; i < this->numitems; i++)
++ if (this->itembuffer[i] == item) return i;
++ return -1;
++ }
++
++ void insert(const Type item, const int insertbefore) {
++ assert(insertbefore >= 0 && insertbefore <= this->numitems);
++ if (this->numitems == this->itembuffersize) this->grow();
++
++ for (int i = this->numitems; i > insertbefore; i--)
++ this->itembuffer[i] = this->itembuffer[i-1];
++ this->itembuffer[insertbefore] = item;
++ this->numitems++;
++ }
++
++ void removeItem(const Type item) {
++ int idx = this->find(item);
++ assert(idx != -1);
++ this->remove(idx);
++ }
++
++ void remove(const int index) {
++ assert(index >= 0 && index < this->numitems);
++ this->numitems--;
++ for (int i = index; i < this->numitems; i++)
++ this->itembuffer[i] = this->itembuffer[i + 1];
++ }
++
++ void removeFast(const int index) {
++ assert(index >= 0 && index < this->numitems);
++ this->itembuffer[index] = this->itembuffer[--this->numitems];
++ }
++
++ int getLength(void) const {
++ return this->numitems;
++ }
++
++ void truncate(const int length, const int fit = 0) {
++ assert(length <= this->numitems);
++ this->numitems = length;
++ if (fit) this->fit();
++ }
++
++ void push(const Type item) {
++ this->append(item);
++ }
++
++ Type pop(void) {
++ assert(this->numitems > 0);
++ return this->itembuffer[--this->numitems];
++ }
++
++ const Type * getArrayPtr(const int start = 0) const {
++ return &this->itembuffer[start];
++ }
++
++ Type operator[](const int index) const {
++ assert(index >= 0 && index < this->numitems);
++ return this->itembuffer[index];
++ }
++
++ Type & operator[](const int index) {
++ assert(index >= 0 && index < this->numitems);
++ return this->itembuffer[index];
++ }
++
++ int operator==(const SbGuiList<Type> & l) const {
++ if (this == &l) return TRUE;
++ if (this->numitems != l.numitems) return FALSE;
++ for (int i = 0; i < this->numitems; i++)
++ if (this->itembuffer[i] != l.itembuffer[i]) return FALSE;
++ return TRUE;
++ }
++
++ int operator!=(const SbGuiList<Type> & l) const {
++ return !(*this == l);
++ }
++
++protected:
++
++ void expand(const int size) {
++ this->grow(size);
++ this->numitems = size;
++ }
++
++ int getArraySize(void) const {
++ return this->itembuffersize;
++ }
++
++private:
++ void grow(const int size = -1) {
++ // Default behavior is to double array size.
++ if (size == -1) this->itembuffersize <<= 1;
++ else if (size <= this->itembuffersize) return;
++ else { this->itembuffersize = size; }
++
++ Type * newbuffer = new Type[this->itembuffersize];
++ const int n = this->numitems;
++ for (int i = 0; i < n; i++) newbuffer[i] = this->itembuffer[i];
++ if (this->itembuffer != this->builtinbuffer) delete[] this->itembuffer;
++ this->itembuffer = newbuffer;
++ }
++
++ int itembuffersize;
++ int numitems;
++ Type * itembuffer;
++ Type builtinbuffer[DEFAULTSIZE];
++};
++
++#endif // !SOGUI_SBGUILIST_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAny.cpp.in
+@@ -0,0 +1,690 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class SoAny SoAny.h
++ \brief The SoAny class is a collection of common toolkit methods.
++
++ SoAny contains internal (ie not accessible to the application
++ programmer) functionality which needs to be "globally" visible to
++ all parts of the toolkit.
++*/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#ifdef HAVE_WINDOWS_H
++#include <windows.h> /* GetEnvironmentVariable() */
++#endif /* HAVE_WINDOWS_H */
++
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/elements/SoGLCacheContextElement.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/SoInput.h>
++#include <Inventor/SoDB.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++#include <Inventor/@Gui@/nodes/SoGuiNodes.h>
++#include <Inventor/@Gui@/engines/SoGuiEngines.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++
++static SoAny * single_instance = NULL;
++
++SoSearchAction * SoAny::finder = NULL;
++
++// Following block explains OpenGL cache context handling in some
++// depth. Copied from an email write-up by pederb:
++//
++// The SoGui toolkits use the SoAny class to handle cache context ids
++// and cache context id sharing (cache context ids can be shared on
++// Windows and on Unix if the display and screen are equal).
++//
++// E.g. in SoQt, when a new GL-widget is created, it is registered
++// using SoAny::registerGLContext (from SoQtGLWidget.cpp). When the
++// GL-widget is destructed, SoAny::unregisterGLContext() must be
++// called. Then, in SoGuiRenderArea::initGraphic(),
++// SoAny::getSharedCacheContextId() is called to find a valid cache
++// context id for SoGLRenderAction.
++//
++// What one needs to do is to detect when the GL-context is
++// destructed, and then call SoAny::unregisterGLContext(). Then
++// SoAny::registerGLContext() to register the new context, and then
++// set the new cache context id in the SoGLRenderAction. This can
++// probably be done just by calling SoGuiRenderArea::initGraphic().
++
++class soany_cache_context {
++public:
++ soany_cache_context(void * display, void * screen)
++ : display(display), screen(screen), cacheid(-1) { }
++ ~soany_cache_context() { }
++
++ SbBool isSameCacheContext(void * displayarg, void * screenarg) const {
++ return (this->display == displayarg && this->screen == screenarg);
++ }
++ SbBool findContext(void * context) const {
++ for (int i = 0; i < this->contextlist.getLength(); i++) {
++ if (this->contextlist[i] == context) return TRUE;
++ }
++ return FALSE;
++ }
++ void * getFirstContext(void) const {
++ assert(this->contextlist.getLength());
++ return this->contextlist[0];
++ }
++ void addContext(void * context) {
++ assert(!this->findContext(context));
++ this->contextlist.append(context);
++ }
++
++ SbBool tryRemoveContext(void * context) {
++ for (int i = 0; i < this->contextlist.getLength(); i++) {
++ if (this->contextlist[i] == context) {
++ this->contextlist.remove(i);
++ return TRUE;
++ }
++ }
++ return FALSE;
++ }
++ SbBool isEmpty(void) const {
++ return this->contextlist.getLength() == 0;
++ }
++ int getCacheContextId(void) {
++ if (this->cacheid < 0) {
++#ifdef __COIN__
++ // Coin has a method for generating an unique cache context id.
++ // Unfortunately, this method does not exists for SGI/TGS Inventor.
++ this->cacheid = (int) SoGLCacheContextElement::getUniqueCacheContext();
++#else // ! __COIN__
++ this->cacheid = soany_cache_context::oiv_counter++;
++#endif // ! __COIN__
++ }
++ return this->cacheid;
++ }
++
++private:
++ void * display;
++ void * screen;
++ int cacheid;
++ SbPList contextlist;
++ static int oiv_counter;
++};
++
++#if 0 // FIXME: not sure if this is ok, check with pederb. 20010806 mortene.
++// A semi-random magic number -- we want to avoid crashing with any
++// cache context id values internally used in SGI / TGS OIV as magic
++// numbers.
++int soany_cache_context::oiv_counter = 4242;
++#else
++int soany_cache_context::oiv_counter = 0;
++#endif
++
++// *************************************************************************
++
++static void soany_atexit_cleanup(void);
++
++void
++SoAny::init()
++{
++ So at Gui@Object::init();
++ So at Gui@Cursor::initClass();
++ SoGuiNodes::initClasses();
++ SoGuiEngines::initClasses();
++ SoAny::atexit((SoAny::atexit_f*)soany_atexit_cleanup, 0);
++ SoAny::atexit((SoAny::atexit_f*)SoAny::cleanup_si, 0);
++}
++
++// private constructor
++SoAny::SoAny(void)
++ : fatalcb(NULL)
++{
++}
++
++// private destructor
++SoAny::~SoAny()
++{
++ for (int i = 0; i < this->cclist.getLength(); i++) {
++ delete (soany_cache_context*) this->cclist[i];
++ }
++}
++
++/*!
++ Returns pointer to the single instance of this class (implemented
++ according to the singleton design pattern).
++*/
++SoAny *
++SoAny::si(void)
++{
++ if (single_instance == NULL) single_instance = new SoAny;
++ return single_instance;
++}
++
++// Free memory/resources used by the singleton object. Will be called
++// automatically on exit.
++void
++SoAny::cleanup_si(void)
++{
++ delete single_instance;
++ single_instance = NULL;
++ if (SoAny::finder) {
++ delete SoAny::finder;
++ SoAny::finder = NULL;
++ }
++}
++
++/*!
++ Returns a pointer to any previous context with which GL sharing
++ is possible, or \e NULL if none found.
++*/
++void *
++SoAny::getSharedGLContext(void * display, void * screen)
++{
++ for (int i = 0; i < this->cclist.getLength(); i++) {
++ soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++ if (cc->isSameCacheContext(display, screen)) {
++ return cc->getFirstContext();
++ }
++ }
++ return NULL;
++}
++
++/*!
++ Adds GL context information. Might be platform dependent what the \a
++ display and \a screen will be. Call this method once when the
++ context is created. In the Coin GUI toolkits, \a context will be a
++ pointer to a So at Gui@GLWidget.
++*/
++void
++SoAny::registerGLContext(void * context, void * display, void * screen)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("SoAny::registerGLContext",
++ "context==%p, display==%p, screen==%p",
++ context, display, screen);
++#endif // debug
++
++ int i, n = this->cclist.getLength();
++ for (i = 0; i < n; i++) {
++ soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++ if (cc->isSameCacheContext(display, screen)) break;
++ }
++ if (i == n) this->cclist.append(new soany_cache_context(display, screen));
++ soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++ cc->addContext(context);
++}
++
++/*!
++ Removes a GL context from the list of contexts. Should be called
++ when the context/widget is destructed.
++*/
++void
++SoAny::unregisterGLContext(void * context)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("SoAny::unregisterGLContext", "context==%p", context);
++#endif // debug
++
++ for (int i = 0; i < this->cclist.getLength(); i++) {
++ soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++ if (cc->tryRemoveContext(context)) {
++ if (cc->isEmpty()) {
++ delete cc;
++ this->cclist.remove(i);
++ }
++ return;
++ }
++ }
++ assert(FALSE && "couldn't find context in internal list");
++}
++
++/*!
++ Returns a shared cache context id, to be used as argument
++ in SoGLRenderAction::setCacheContext().
++*/
++int
++SoAny::getSharedCacheContextId(void * context)
++{
++ for (int i = 0; i < this->cclist.getLength(); i++) {
++ soany_cache_context * cc = (soany_cache_context*) this->cclist[i];
++ if (cc->findContext(context)) return cc->getCacheContextId();
++ }
++#if SO at GUI@_DEBUG
++ SoDebugError::post("SoAny::getSharedCacheContextId",
++ "could not find shared cache context for context %p "
++ "(shared context handling not implemented for this "
++ "toolkit?)", context);
++#endif // SO at GUI@_DEBUG
++ return 0;
++}
++
++/*!
++ Set up a fatal error handler in case of "impossible" errors. Calls
++ to this function are calls forwarded from
++ So at Gui@::setFatalErrorHandler().
++
++ Returns previous fatal error handler callback, or \c NULL if none.
++
++ \sa So at Gui@::setFatalErrorHandler()
++ */
++So at Gui@::FatalErrorCB *
++SoAny::setFatalErrorHandler(So at Gui@::FatalErrorCB * cb, void * userdataarg)
++{
++ So at Gui@::FatalErrorCB * oldcb = this->fatalcb;
++ this->fatalcb = cb;
++ this->userdata = userdataarg;
++ return oldcb;
++}
++
++/*!
++ In the case of a fatal error condition in the library, this method
++ should be used to invoke the application fatal error handler.
++
++ Returns \c TRUE if an error handler was set up, or \c FALSE if none.
++
++ If no handler was set up, a dialog box with the error string will be
++ shown and then the application will exit.
++
++ A very important issue to be aware of for "client code" around in
++ the So*-libraries is that this function will not return if the
++ application programmer has set up a fatal error handler which throws
++ an exception. Because of this, the "as good as possible" clean-up
++ code around the points of fatal error failures needs to be executed
++ \e before calling this function.
++
++ \sa SoAny::setFatalErrorHandler()
++ */
++SbBool
++SoAny::invokeFatalErrorHandler(SbString errmsg, So at Gui@::FatalErrors errcode)
++{
++ // First trigger the internal clean-up routines.
++ int internals = this->internalfehandlers.getLength();
++ for (int idx = 0; idx < internals; idx++) {
++ SoAny::InternalFatalErrorCB * cb =
++ (SoAny::InternalFatalErrorCB *)this->internalfehandlers[idx];
++ (*cb)(this->internalfedata[idx]);
++ }
++
++ // If no app-programmer registered callback, throw up our own
++ // message dialog.
++ if (this->fatalcb == NULL) {
++ So at Gui@::createSimpleErrorDialog(NULL,
++ "Fatal application error",
++ errmsg.getString(),
++ "Application will exit.");
++ return FALSE;
++ }
++
++ fatalcb(errmsg, errcode, this->userdata);
++ return TRUE;
++}
++
++
++/*!
++ Lets us register an internal callback to run when a fatal error is
++ detected.
++
++ Internal clean-up functions is sometimes necessary because we set up
++ external references to internal resources which may not be valid
++ after a fatal error hits.
++*/
++void
++SoAny::addInternalFatalErrorHandler(SoAny::InternalFatalErrorCB * cb,
++ void * userdataarg)
++{
++ this->internalfehandlers.append((void *)cb);
++ this->internalfedata.append(userdataarg);
++}
++
++
++/**************************************************************************/
++
++/*** Singlelinked list for the environment variables. *********************/
++
++/*
++ FIXME: should implement a generic (macro-based) singlelinked list
++ abstraction in C (the following code could be a good starting
++ point). Then axe this code. Then move the various listhandling stuff
++ in the Coin library from the SbList<> template to the C-based one to
++ aid any future transition to pure C. 20010821 mortene.
++
++ UPDATE: SbList isn't really a linked list, but in fact a growable
++ array -- so the code below can not be used as a replacement. Still,
++ we should have a generic linked list class. 20011220 mortene.
++*/
++
++static struct envvar_data * envlist_head = NULL;
++static struct envvar_data * envlist_tail = NULL;
++
++struct envvar_data {
++ char * name;
++ char * val;
++ struct envvar_data * next;
++};
++
++static void
++envlist_append(struct envvar_data * item)
++{
++ item->next = NULL;
++ if (envlist_head == NULL) {
++ envlist_head = item;
++ envlist_tail = item;
++ }
++ else {
++ envlist_tail->next = item;
++ envlist_tail = item;
++ }
++}
++
++/**************************************************************************/
++
++/*
++ When working with MSWindows applications using the library as a DLL,
++ setenv() / getenv() will not work as expected, as the application
++ and the DLL has different instances of the C library with different
++ datastructures on different heaps. That's why we need this
++ abstraction around the C-libs getenv() vs the Win32 API
++ GetEnvironmentVariable() function.
++
++ Note: do not deallocate the returned string -- they are supposed to
++ be permanently available to all callers. Deallocating the resources
++ is the responsibility of the application exit cleanup code.
++*/
++
++const char *
++SoAny::getenv(const char * envname)
++{
++ /* Important note: this code is dulplicated in Coin, Coin-1,
++ So at Gui@/.../common/SoAny.cpp.in (and possibly stable forks of the
++ toolkits). If you do bugfixes or whatever, keep them in sync! */
++#ifdef HAVE_GETENVIRONMENTVARIABLE
++ int neededsize;
++ neededsize = GetEnvironmentVariable(envname, NULL, 0);
++ /* neededsize includes the \0-terminating character */
++ if ( neededsize >= 1 ) {
++ int resultsize;
++ struct envvar_data * envptr;
++ char * valbuf = (char *) malloc(neededsize);
++ if ( valbuf == NULL ) {
++ /* Augh. Could we handle this any better? */
++ /* If we already bookkeep a buffer for this variable, we /could/ try
++ to reuse it (much work for a non-100% solution). 20030205 larsa */
++ return NULL;
++ }
++ resultsize = GetEnvironmentVariable(envname, valbuf, neededsize);
++ if ( resultsize != (neededsize - 1) ) {
++ /* Augh. Could we handle this any better? */
++ /* How about looping to top and trying again (in case the reason is mt
++ and envval being changed in the background, or maybe just asserting?
++ 20030205 larsa */
++ free(valbuf);
++ return NULL;
++ }
++
++ /*
++ The GetEnvironmentVariable() signature forces us to allocate the space
++ for the value string on the outside of the call, as opposed to the UNIX
++ getenv() function. We therefore have to do bookkeeping and maintain
++ this linked list of allocated buffers that should be cleaned up on exit
++ (atexit()). We don't keep it for lookup of values - we actually can't
++ use the valus as value caches in case they have been changed from other
++ parts of the application. We only keep them so we can free them later.
++ */
++
++ /* Try to find bookkeeped envvar buffer among those registered earlier. */
++ envptr = envlist_head;
++ while ( (envptr != NULL) && (strcmp(envptr->name, envname) != 0) )
++ envptr = envptr->next;
++
++ /* We can avoid this if-else by always freeing the envvar_data for the
++ variable upfront, but it's a tad less efficient. */
++ if ( envptr != NULL ) {
++ /* We are already bookkeeping a buffer for this variable.
++ * => free previous value buffer and bookkeep the new one instead */
++ free(envptr->val);
++ envptr->val = valbuf;
++ } else {
++ /* We aren't bookkeeping a buffer for this one yet. */
++ envptr = (struct envvar_data *) malloc(sizeof(struct envvar_data));
++ if ( envptr == NULL ) {
++ /* Augh. Could we handle this any better? */
++ /* We can alternatively ignore the bookkeeping and leak the buffer
++ - 20030205 larsa */
++ free(valbuf);
++ return NULL;
++ }
++ envptr->name = strdup(envname);
++ if ( envptr->name == NULL ) {
++ /* Augh. Could we handle this any better? */
++ /* We can alternatively ignore the bookkeeping and leak the buffer
++ - 20030205 larsa */
++ free(envptr);
++ free(valbuf);
++ return NULL;
++ }
++ envptr->val = valbuf;
++ envlist_append(envptr);
++ }
++ return envptr->val;
++ }
++ return NULL;
++#else /* !HAVE_GETENVIRONMENTVARIABLE */
++ return ::getenv(envname);
++#endif /* !HAVE_GETENVIRONMENTVARIABLE */
++}
++
++/**************************************************************************/
++
++#if defined(HAVE_WIN32_LOADLIBRARY) && defined(HAVE_TLHELP32_H)
++
++#include <tlhelp32.h>
++
++
++typedef HANDLE (WINAPI * CreateToolhelp32Snapshot_t)(DWORD, DWORD);
++typedef BOOL (WINAPI * Module32First_t)(HANDLE, LPMODULEENTRY32);
++typedef BOOL (WINAPI * Module32Next_t)(HANDLE, LPMODULEENTRY32);
++
++static CreateToolhelp32Snapshot_t funCreateToolhelp32Snapshot = NULL;
++static Module32First_t funModule32First = NULL;
++static Module32Next_t funModule32Next = NULL;
++
++
++void
++SoAny::listWin32ProcessModules(void)
++{
++ BOOL ok;
++
++ HINSTANCE kernel32dll = LoadLibrary("kernel32.dll");
++ assert(kernel32dll && "LoadLibrary(''kernel32.dll'') failed");
++
++ funCreateToolhelp32Snapshot = (CreateToolhelp32Snapshot_t)
++ GetProcAddress(kernel32dll, "CreateToolhelp32Snapshot");
++ funModule32First = (Module32First_t)
++ GetProcAddress(kernel32dll, "Module32First");
++ funModule32Next = (Module32Next_t)
++ GetProcAddress(kernel32dll, "Module32Next");
++
++
++ do {
++ if (!funCreateToolhelp32Snapshot || !funModule32First || !funModule32Next) {
++ SoDebugError::postWarning("SoAny::listWin32ProcessModules",
++ "Tool Help Library not available (NT4?)");
++ break; // goto end of do-while loop
++ }
++
++ HANDLE tool32snap = funCreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
++ assert((tool32snap != (void *)-1) && "CreateToolhelp32Snapshot() failed");
++
++ MODULEENTRY32 moduleentry;
++ moduleentry.dwSize = sizeof(MODULEENTRY32);
++ ok = funModule32First(tool32snap, &moduleentry);
++ assert(ok && "Module32First() failed");
++
++ SoDebugError::postInfo("SoAny::listWin32ProcessModules",
++ "MODULEENTRY32.szModule=='%s', .szExePath=='%s'",
++ moduleentry.szModule, moduleentry.szExePath);
++
++ while (funModule32Next(tool32snap, &moduleentry)) {
++ SoDebugError::postInfo("SoAny::listWin32ProcessModules",
++ "MODULEENTRY32.szModule=='%s', .szExePath=='%s'",
++ moduleentry.szModule, moduleentry.szExePath);
++ }
++
++ assert(GetLastError()==ERROR_NO_MORE_FILES && "Module32Next() failed");
++
++ ok = CloseHandle(tool32snap);
++ assert(ok && "CloseHandle() failed");
++ } while (0);
++
++ ok = FreeLibrary(kernel32dll);
++ assert(ok && "FreeLibrary() failed");
++}
++
++
++#else // !HAVE_WIN32_LOADLIBRARY || !HAVE_TLHELP32_H
++
++void
++SoAny::listWin32ProcessModules(void)
++{
++ SoDebugError::postWarning("SoAny::listWin32ProcessModules",
++ "Tool Help Library not available "
++ "(non-win32 platform?)");
++}
++
++#endif // !HAVE_WIN32_LOADLIBRARY || !HAVE_TLHELP32_H
++
++/**************************************************************************/
++
++char *
++SoAny::strconcat(const char ** stringlist, const char * glue, SbBool glueend) // static
++{
++ int i, gluelen, buflen;
++ char * buffer, * ptr;
++ assert(stringlist);
++ gluelen = 0;
++ buflen = 1; // The Terminator (1982)
++ if ( glue ) gluelen = strlen(glue);
++ for ( i = 0; stringlist[i] != NULL; i++ )
++ buflen += strlen(stringlist[i]) + gluelen;
++ if ( !glueend ) buflen -= gluelen;
++ buffer = new char [buflen];
++ assert(buffer);
++ ptr = buffer;
++ for ( i = 0; stringlist[i] != NULL; i++ ) {
++ int len;
++ len = strlen(stringlist[i]);
++ memcpy(ptr, stringlist[i], len);
++ ptr += len;
++ if ( gluelen && ((stringlist[i+1] != NULL) || glueend) ) {
++ memcpy(ptr, glue, gluelen);
++ ptr += gluelen;
++ }
++ }
++ *ptr = '\0';
++ return buffer;
++}
++
++SoNode *
++SoAny::loadSceneGraph(const char ** stringlist) // static
++{
++ char * buffer = SoAny::strconcat(stringlist, "\n");
++ SoNode * root = SoAny::loadSceneGraph(buffer);
++ delete [] buffer;
++ return root;
++}
++
++SoNode *
++SoAny::loadSceneGraph(char * buffer, unsigned int bufsize) // static
++{
++ SoSeparator * root;
++ SoInput in;
++ in.setBuffer(buffer, bufsize ? bufsize : strlen(buffer));
++ root = SoDB::readAll(&in);
++ return root;
++}
++
++SoNode *
++SoAny::scanSceneForName(SoNode * scene, const char * name, SbBool searchAll)
++{
++ assert(scene->getRefCount() > 0);
++ SoPath * path;
++ if ( SoAny::finder == NULL )
++ SoAny::finder = new SoSearchAction;
++ SoAny::finder->reset();
++ SoAny::finder->setName(SbName(name));
++ SoAny::finder->setInterest(SoSearchAction::FIRST);
++ if ( searchAll ) SoAny::finder->setSearchingAll(TRUE);
++ SoAny::finder->apply(scene);
++ path = SoAny::finder->getPath();
++ return path ? path->getTail() : NULL;
++}
++
++// FIXME: Dummy implementation of sogui_atexit(). Replace with real
++// implementation. kintel 20060209
++void
++SoAny::atexit(SoAny::atexit_f * fp, int priority)
++{
++ // disabled this, as it is not safe to clean up So at Gui@ after Coin
++ // has been cleaned up. -mortene
++ //
++ // atexit(fp);
++}
++
++static void
++soany_atexit_cleanup(void)
++{
++ struct envvar_data * ptr = envlist_head;
++ while (ptr != NULL) {
++ struct envvar_data * tmp = ptr;
++ free(ptr->name);
++ free(ptr->val);
++ ptr = ptr->next;
++ free(tmp);
++ }
++ envlist_head = NULL;
++ envlist_tail = NULL;
++
++#if defined(HAVE_WIN32_LOADLIBRARY) && defined(HAVE_TLHELP32_H)
++ funCreateToolhelp32Snapshot = NULL;
++ funModule32First = NULL;
++ funModule32Next = NULL;
++#endif
++}
++
++/**************************************************************************/
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAny.h.in
+@@ -0,0 +1,106 @@
++#ifndef SOANY_H
++#define SOANY_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains definitions which should _only_ be used during
++// library build. It is not installed for use by the application
++// programmer.
++#ifndef SO at GUI@_INTERNAL
++#error Only for internal use during library build.
++#endif /* !SO at GUI@_INTERNAL */
++
++// ************************************************************************
++
++#include <Inventor/SbPList.h>
++
++#include <Inventor/@Gui@/So at Gui@.h>
++
++class SoNode;
++class SoSearchAction;
++
++// ************************************************************************
++
++class SoAny {
++public:
++ static void init();
++
++ // use the singleton design pattern for access
++ static SoAny * si(void);
++
++ static const char * getenv(const char * e);
++
++ void * getSharedGLContext(void * display, void * screen);
++ void registerGLContext(void * context, void * display, void * screen);
++ void unregisterGLContext(void * context);
++ int getSharedCacheContextId(void * context);
++
++ static void listWin32ProcessModules(void);
++
++ So at Gui@::FatalErrorCB * setFatalErrorHandler(So at Gui@::FatalErrorCB * cb, void * userdata);
++ SbBool invokeFatalErrorHandler(SbString errmsg, So at Gui@::FatalErrors errcode);
++ typedef void InternalFatalErrorCB(void * userdata);
++ void addInternalFatalErrorHandler(SoAny::InternalFatalErrorCB * cb,
++ void * ud);
++
++ static char * strconcat(const char ** stringlist, const char * glue = NULL, SbBool glueend = TRUE);
++ static SoNode * loadSceneGraph(const char ** stringlist);
++ static SoNode * loadSceneGraph(char * buffer, unsigned int bufsize = 0);
++ static SoNode * scanSceneForName(SoNode * scene, const char * name, SbBool searchAll = FALSE);
++
++ // FIXME: Dummy sogui_atexit(). Replace with real
++ // implementation. kintel 20060209
++ typedef void atexit_f(void);
++ static void atexit(atexit_f * fp, int priority);
++
++private:
++ SoAny(void);
++ ~SoAny();
++ static void cleanup_si(void);
++
++ // (use SbPList instances to be able to compile properly on SGI /
++ // TGS Inventor aswell as Coin)
++ SbPList cclist;
++ SbPList internalfehandlers, internalfedata;
++
++ So at Gui@::FatalErrorCB * fatalcb;
++ void * userdata;
++
++ static SoSearchAction * finder;
++}; // class SoAny
++
++// ************************************************************************
++
++#endif // ! SOANY_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialList.cpp.in
+@@ -0,0 +1,457 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <assert.h>
++#include <string.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#ifdef HAVE_DIRENT_H
++#include <dirent.h>
++#endif
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif
++#include <stdlib.h>
++
++#include <Inventor/SbPList.h>
++#include <Inventor/errors/SoDebugError.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/SoAnyMaterialList.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++struct So at Gui@MaterialListCallbackInfo {
++ So at Gui@MaterialListCB * callback;
++ void * closure;
++};
++
++/*!
++ \class SoAnyMaterialList Inventor/@Gui@/SoAnyMaterialList.h
++ \brief The SoAnyMaterialList class is the common code for the MaterialList
++ component classes.
++*/
++
++// *************************************************************************
++
++/*!
++*/
++
++SoAnyMaterialList::SoAnyMaterialList(
++ const char * const dir)
++{
++ this->callbacks = NULL;
++ this->dirpath = NULL;
++ this->directory = NULL;
++ if (dir != NULL)
++ this->dirpath = strcpy(new char [strlen(dir)+1], dir);
++}
++
++/*!
++*/
++
++SoAnyMaterialList::~SoAnyMaterialList(
++ void)
++{
++ if (this->callbacks != NULL) {
++ const int num = this->callbacks->getLength();
++ for (int i = 0; i < num; i++)
++ delete (So at Gui@MaterialListCallbackInfo *) (*this->callbacks)[i];
++ delete this->callbacks;
++ }
++ if (this->dirpath)
++ delete [] this->dirpath;
++ if (this->directory != NULL)
++ this->freeMaterialDirectory();
++}
++
++// *************************************************************************
++
++/*!
++*/
++
++void
++SoAnyMaterialList::addCallback(
++ So at Gui@MaterialListCB * const callback,
++ void * const closure)
++{
++ if (this->callbacks == NULL)
++ this->callbacks = new SbPList;
++ So at Gui@MaterialListCallbackInfo * info =
++ new So at Gui@MaterialListCallbackInfo;
++ info->callback = callback;
++ info->closure = closure;
++ this->callbacks->append(info);
++} // addCallback()
++
++/*!
++*/
++
++void
++SoAnyMaterialList::removeCallback(
++ So at Gui@MaterialListCB * const callback,
++ void * const closure)
++{
++ if (! this->callbacks) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("SoAnyMaterialList::removeCallback",
++ "component has zero callbacks set.");
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++
++ const int numcallbacks = this->callbacks->getLength();
++ for (int i = 0; i < numcallbacks; i++) {
++ So at Gui@MaterialListCallbackInfo * info =
++ (So at Gui@MaterialListCallbackInfo *) (*this->callbacks)[i];
++ if (info->callback == callback && info->closure == closure) {
++ this->callbacks->remove(i);
++ delete info;
++ return;
++ }
++ }
++
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("SoAnyMaterialList::removeCallback",
++ "callback was not set for component.");
++#endif // SO at GUI@_DEBUG
++} // removeCallback()
++
++/*!
++*/
++
++void
++SoAnyMaterialList::invokeCallbacks(
++ SoMaterial * material)
++{
++ if (this->callbacks) {
++ const int numCallbacks = this->callbacks->getLength();
++ for (int i = 0; i < numCallbacks; i++) {
++ So at Gui@MaterialListCallbackInfo * info =
++ (So at Gui@MaterialListCallbackInfo *) (*this->callbacks)[i];
++ info->callback(info->closure, (SoMaterial *) material);
++ }
++ }
++} // invokeCallbacks()
++
++// *************************************************************************
++
++/*!
++ \internal
++
++ This method frees up the memory used by the material-index data strucure.
++*/
++
++void
++SoAnyMaterialList::freeMaterialDirectory(
++ void)
++{
++ if (this->directory == NULL)
++ return;
++ int i, j;
++ if ((this->directory->flags & SO at GUI@_BUILTIN_MATERIALS) == 0) {
++ // all data is allocated
++ for (i = 0; i < this->directory->numGroups; i++) {
++ for (j = 0; j < this->directory->groups[i]->numMaterials; j++) {
++ delete [] (char *) this->directory->groups[i]->materials[j]->data;
++ delete [] (char *) this->directory->groups[i]->materials[j]->name;
++ delete this->directory->groups[i]->materials[j];
++ }
++ delete [] (char *) this->directory->groups[i]->name;
++ delete [] this->directory->groups[i]->materials;
++ delete this->directory->groups[i];
++ }
++ delete [] this->directory->groups;
++ } else {
++ // lots of data is static and should therefore not be freed
++ for (i = 0; i < this->directory->numGroups; i++) {
++ for (j = 0; j < this->directory->groups[i]->numMaterials; j++)
++ delete this->directory->groups[i]->materials[j];
++ delete [] this->directory->groups[i]->materials;
++ delete this->directory->groups[i];
++ }
++ delete [] this->directory->groups;
++ }
++ delete this->directory;
++ this->directory = NULL;
++} // freeMaterialDirectory()
++
++// *************************************************************************
++
++const char *
++SoAnyMaterialList::getMaterialDirectoryPath(
++ void) const
++{
++ return this->dirpath;
++} // getMaterialDirectoryPath()
++
++// *************************************************************************
++
++/*!
++ \internal
++*/
++
++static
++int
++containsFiles(
++ const char * const path)
++{
++#ifdef HAVE_DIRENT_H
++ DIR * directory = opendir(path);
++ struct dirent * entry;
++ struct stat entrystats;
++ if (directory != NULL) {
++ const int pathnamelen = strlen(path);
++ int foundfile = 0;
++ while (! foundfile && (entry = readdir(directory)) != NULL) {
++ if (entry->d_name[0] == '.') continue;
++ char * entrypath = new char [pathnamelen + strlen(entry->d_name) + 2];
++ sprintf(entrypath, "%s/%s", path, entry->d_name);
++ if (stat(entrypath, &entrystats) == 0 &&
++ S_ISREG(entrystats.st_mode)) {
++ delete [] entrypath;
++ closedir(directory);
++ return 1;
++ }
++ delete [] entrypath;
++ }
++ closedir(directory);
++ }
++#endif
++ return 0;
++} // containsFiles()
++
++/*!
++ \internal
++*/
++
++char **
++SoAnyMaterialList::getNonemptySubdirs(// static, private
++ const char * const path)
++{
++#ifdef HAVE_DIRENT_H
++ DIR * dir = opendir(path);
++ if (! dir) return NULL;
++
++ SbPList subdirs;
++ DIR * subdir;
++ const int pathlen = strlen(path) + 2;
++ struct dirent * entry, * subentry;
++ struct stat statbuf, substatbuf;
++ while ((entry = readdir(dir)) != NULL) {
++ if (entry->d_name[0] == '.') continue;
++ int pathnamelen = pathlen + strlen(entry->d_name);
++ char * pathname = new char [ pathnamelen ];
++ sprintf(pathname, "%s/%s", path, entry->d_name);
++ if ((stat(pathname, &statbuf) == 0) && S_ISDIR(statbuf.st_mode)) {
++ if ((subdir = opendir(pathname)) != NULL) {
++ int foundfile = 0;
++ while (! foundfile && (subentry = readdir(subdir)) != NULL) {
++ if (subentry->d_name[0] == '.') continue;
++ char * entrypathname =
++ new char [pathnamelen + strlen(subentry->d_name) + 1];
++ sprintf(entrypathname, "%s/%s", pathname, subentry->d_name);
++ if (stat(entrypathname, &substatbuf) == 0 &&
++ S_ISREG(substatbuf.st_mode)) {
++ foundfile = 1;
++ }
++ delete [] entrypathname;
++ }
++ if (foundfile)
++ subdirs.append(strcpy(new char [strlen(entry->d_name)+1],
++ entry->d_name));
++ closedir(subdir);
++ }
++ }
++ delete [] pathname;
++ }
++ closedir(dir);
++
++ const int num = subdirs.getLength();
++ char ** subdirarray = new char * [ num + 1 ];
++ for (int i = 0; i < num; i++)
++ subdirarray[i] = (char *) subdirs[i];
++ subdirarray[num] = NULL;
++ return subdirarray;
++#endif
++ return NULL;
++} // numNonemptySubdirs()
++
++
++/*!
++ \internal
++*/
++
++char **
++SoAnyMaterialList::getRegularFiles(// static, private
++ const char * const path)
++{
++#ifdef HAVE_DIRENT_H
++ DIR * dir = opendir(path);
++ if (! dir) return NULL;
++
++ const int pathlen = strlen(path);
++ SbPList files;
++ struct dirent * entry;
++ while ((entry = readdir(dir)) != NULL) {
++ if (entry->d_name[0] == '.') continue;
++ char * pathname = new char [pathlen + 2 + strlen(entry->d_name)];
++ sprintf(pathname, "%s/%s", path, entry->d_name);
++ struct stat statbuf;
++ if ((stat(pathname, &statbuf) == 0) && S_ISREG(statbuf.st_mode))
++ files.append(strcpy(new char [strlen(entry->d_name)+1],
++ entry->d_name));
++ delete [] pathname;
++ }
++ closedir(dir);
++
++ const int num = files.getLength();
++ char ** filearray = new char * [ num + 1 ];
++ for (int i = 0; i < num; i++)
++ filearray[i] = (char *) files[i];
++ filearray[num] = NULL;
++ return filearray;
++#endif
++ return NULL;
++} // getRegularFiles()
++
++/*!
++ \internal
++
++ Used for qsort().
++*/
++
++int
++SoAnyMaterialList::qsort_comparator(// static, private
++ const void * itemA,
++ const void * itemB)
++{
++ SO at GUI@_STUB();
++ return 0;
++} // qsort_comparator()
++
++/*!
++*/
++
++So at Gui@MaterialDirectory *
++SoAnyMaterialList::getMaterialDirectory(
++ void)
++{
++ if (this->directory != NULL) // already created
++ return this->directory;
++
++ // get the path to search for materials in
++ SbString path;
++ if (this->dirpath) { path = this->dirpath; }
++
++ const char * envvars[] = {
++ // FIXME: where the hell does the "WALLET" env-var come from?
++ // 20020109 mortene.
++ "SO_MATERIAL_DIR", "WALLET", "COIN_HOME"
++ };
++
++ for (unsigned int i=0; i < (sizeof(envvars) / sizeof(char *)); i++) {
++ if (path.getLength() == 0) {
++ const char * p = SoAny::si()->getenv(envvars[i]);
++ if (p) { path = p; }
++ }
++ }
++
++ if (path.getLength() > 0) { path += "/materials"; }
++ else {
++ const char * p = SoAny::si()->getenv("OIVHOME");
++ if (p) {
++ path = p;
++ // FIXME: use DIRSEP string? ????-??-?? larsa.
++ path += "/data/materials";
++ }
++ }
++
++ this->directory = new So at Gui@MaterialDirectory;
++ this->directory->flags = 0;
++ this->directory->current = 0;
++
++ SbBool founddiskmaterials = FALSE;
++
++ if (path.getLength() > 0) {
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("SoAnyMaterialList::getMaterialDirectory",
++ "scanning '%s'", path.getString());
++#endif // debug
++ char ** subdirs = SoAnyMaterialList::getNonemptySubdirs(path.getString());
++ if (subdirs) {
++ founddiskmaterials = TRUE;
++ int numsubdirs;
++ for (numsubdirs = 0; subdirs[numsubdirs] != NULL; numsubdirs++) { }
++ this->directory->numGroups = numsubdirs;
++ this->directory->groups = new So at Gui@MaterialGroup * [ numsubdirs ];
++ for (int subdir = 0; subdir < numsubdirs; subdir++) {
++ this->directory->groups[subdir] = new So at Gui@MaterialGroup;
++ this->directory->groups[subdir]->name = subdirs[subdir];
++ char * subdirname =
++ new char [strlen(path.getString()) + strlen(subdirs[subdir]) + 2];
++ sprintf(subdirname, "%s/%s", path.getString(), subdirs[subdir]);
++ char ** files = SoAnyMaterialList::getRegularFiles(subdirname);
++ assert(files != NULL);
++ int numfiles;
++ for (numfiles = 0; files[numfiles] != NULL; numfiles++) { }
++ this->directory->groups[subdir]->numMaterials = numfiles;
++ this->directory->groups[subdir]->materials =
++ new So at Gui@Material * [ numfiles ];
++ for (int file = 0; file < numfiles; file++) {
++ this->directory->groups[subdir]->materials[file] =
++ new So at Gui@Material;
++ this->directory->groups[subdir]->materials[file]->name =
++ files[file];
++ char * buf = new char [strlen(subdirname) + strlen(files[file]) + 2];
++ sprintf(buf, "%s/%s", subdirname, files[file]);
++ this->directory->groups[subdir]->materials[file]->data = buf;
++ }
++ delete [] files; // actual strings are transfered, don't delete them!
++ delete [] subdirname;
++ }
++ delete [] subdirs; // actual strings are transfered, don't delete them!
++ }
++ }
++
++ // fallback on builtins
++ if (!founddiskmaterials) { this->setupBuiltinMaterials(this->directory); }
++ return this->directory;
++} // getMaterialDirectory()
++
++// *************************************************************************
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialList.h.in
+@@ -0,0 +1,100 @@
++#ifndef SOANY_MATERIALLIST_H
++#define SOANY_MATERIALLIST_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/So at Gui@MaterialList.h>
++
++class SbPList;
++class SoMaterial;
++
++// *************************************************************************
++
++#define SO at GUI@_BUILTIN_MATERIALS 0x0001
++
++struct So at Gui@Material {
++ const char * name;
++ const char * data;
++};
++
++struct So at Gui@MaterialGroup {
++ const char * name;
++ short numMaterials;
++ So at Gui@Material ** materials;
++ @WIDGET@ menuitem;
++};
++
++struct So at Gui@MaterialDirectory {
++ short flags;
++ short numGroups;
++ So at Gui@MaterialGroup ** groups;
++ short current;
++};
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API SoAnyMaterialList {
++public:
++ SoAnyMaterialList(const char * const dir);
++ ~SoAnyMaterialList(void);
++
++ void addCallback(
++ So at Gui@MaterialListCB * const callback, void * const closure);
++ void removeCallback(
++ So at Gui@MaterialListCB * const callback, void * const closure);
++ void invokeCallbacks(SoMaterial * material);
++
++ const char * getMaterialDirectoryPath(void) const;
++ So at Gui@MaterialDirectory * getMaterialDirectory(void);
++
++private:
++ void setupBuiltinMaterials(So at Gui@MaterialDirectory * const index) const;
++ void freeMaterialDirectory(void);
++
++ static char ** getNonemptySubdirs(const char * const path);
++ static char ** getRegularFiles(const char * const path);
++
++ static int qsort_comparator(const void * itemA, const void * itemB);
++
++private:
++ SbPList * callbacks;
++ char * dirpath;
++ So at Gui@MaterialDirectory * directory;
++
++}; // class SoAnyMaterialList
++
++// *************************************************************************
++
++#endif // ! SOANY_MATERIALLIST_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialListBuiltins.cpp.in
+@@ -0,0 +1,1492 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/**************************************************************************
++ * IMPORTANT NOTICE
++ * Be aware that the file So at Gui@MaterialListBuiltins.cpp is generated from
++ * the file So at Gui@MaterialListBuiltins.cpp.m4, so changes has to be done in
++ * the source file with the m4 macros. The generation is done manually,
++ * since it is no point in making this project depend on the user having
++ * m4 installed.
++ **************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <string.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/SoAnyMaterialList.h>
++
++#ifdef WITH_STATIC_DEFAULTS
++#include <materials/materials.h>
++#endif // WITH_STATIC_DEFAULTS
++
++// *************************************************************************
++
++#ifdef WITH_STATIC_DEFAULTS
++static
++const char *
++builtin_material_names[] = {
++ "artdeco",
++ "artdeco.0",
++ "artdeco.1",
++ "artdeco.2",
++ "artdeco.3",
++ "artdeco.4",
++ "artdeco.5",
++ "artdeco.6",
++ "artdeco.7",
++ "artdeco.8",
++ "artdeco.9",
++ "artdeco.10",
++ "artdeco.11",
++ "artdeco.12",
++ "artdeco.13",
++ "artdeco.14",
++ "artdeco.15",
++ "artdeco.16",
++ "artdeco.17",
++ "artdeco.18",
++ "artdeco.19",
++ "artdeco.20",
++ "artdeco.21",
++ "artdeco.22",
++ "artdeco.23",
++ "artdeco.24",
++ "artdeco.25",
++ "artdeco.26",
++ "artdeco.27",
++ "artdeco.28",
++ "artdeco.29",
++ "artdeco.30",
++ "artdeco.31",
++ "artdeco.32",
++ "artdeco.33",
++ "artdeco.34",
++ "autumn",
++ "autumn.0",
++ "autumn.1",
++ "autumn.2",
++ "autumn.3",
++ "autumn.4",
++ "autumn.5",
++ "autumn.6",
++ "autumn.7",
++ "autumn.8",
++ "autumn.9",
++ "autumn.10",
++ "autumn.11",
++ "autumn.12",
++ "autumn.13",
++ "autumn.14",
++ "autumn.15",
++ "autumn.16",
++ "autumn.17",
++ "autumn.18",
++ "autumn.19",
++ "autumn.20",
++ "autumn.21",
++ "autumn.22",
++ "autumn.23",
++ "autumn.24",
++ "autumn.25",
++ "autumn.26",
++ "autumn.27",
++ "autumn.28",
++ "autumn.29",
++ "autumn.30",
++ "autumn.31",
++ "autumn.32",
++ "autumn.33",
++ "autumn.34",
++ "glass",
++ "glass.0",
++ "glass.1",
++ "glass.2",
++ "glass.3",
++ "glass.4",
++ "glass.5",
++ "glass.6",
++ "glass.7",
++ "glass.8",
++ "glass.9",
++ "glass.10",
++ "glass.11",
++ "glass.12",
++ "glass.13",
++ "glass.14",
++ "glass.15",
++ "glass.16",
++ "glass.17",
++ "glass.18",
++ "glass.19",
++ "glass.20",
++ "glass.21",
++ "glass.22",
++ "glass.23",
++ "glass.24",
++ "glass.25",
++ "glass.26",
++ "glass.27",
++ "glass.28",
++ "glass.29",
++ "glass.30",
++ "glass.31",
++ "glass.32",
++ "glass.33",
++ "glass.34",
++ "metal",
++ "metal.0",
++ "metal.1",
++ "metal.2",
++ "metal.3",
++ "metal.4",
++ "metal.5",
++ "metal.6",
++ "metal.7",
++ "metal.8",
++ "metal.9",
++ "metal.10",
++ "metal.11",
++ "metal.12",
++ "metal.13",
++ "metal.14",
++ "metal.15",
++ "metal.16",
++ "metal.17",
++ "metal.18",
++ "metal.19",
++ "metal.20",
++ "metal.21",
++ "metal.22",
++ "metal.23",
++ "metal.24",
++ "metal.25",
++ "metal.26",
++ "metal.27",
++ "metal.28",
++ "metal.29",
++ "metal.30",
++ "metal.31",
++ "metal.32",
++ "metal.33",
++ "metal.34",
++ "neon",
++ "neon.0",
++ "neon.1",
++ "neon.2",
++ "neon.3",
++ "neon.4",
++ "neon.5",
++ "neon.6",
++ "neon.7",
++ "neon.8",
++ "neon.9",
++ "neon.10",
++ "neon.11",
++ "neon.12",
++ "neon.13",
++ "neon.14",
++ "neon.15",
++ "neon.16",
++ "neon.17",
++ "neon.18",
++ "neon.19",
++ "neon.20",
++ "neon.21",
++ "neon.22",
++ "neon.23",
++ "neon.24",
++ "neon.25",
++ "neon.26",
++ "neon.27",
++ "neon.28",
++ "neon.29",
++ "neon.30",
++ "neon.31",
++ "neon.32",
++ "neon.33",
++ "neon.34",
++ "rococo",
++ "rococo.0",
++ "rococo.1",
++ "rococo.2",
++ "rococo.3",
++ "rococo.4",
++ "rococo.5",
++ "rococo.6",
++ "rococo.7",
++ "rococo.8",
++ "rococo.9",
++ "rococo.10",
++ "rococo.11",
++ "rococo.12",
++ "rococo.13",
++ "rococo.14",
++ "rococo.15",
++ "rococo.16",
++ "rococo.17",
++ "rococo.18",
++ "rococo.19",
++ "rococo.20",
++ "rococo.21",
++ "rococo.22",
++ "rococo.23",
++ "rococo.24",
++ "rococo.25",
++ "rococo.26",
++ "rococo.27",
++ "rococo.28",
++ "rococo.29",
++ "rococo.30",
++ "rococo.31",
++ "rococo.32",
++ "rococo.33",
++ "rococo.34",
++ "santafe",
++ "santafe.0",
++ "santafe.1",
++ "santafe.2",
++ "santafe.3",
++ "santafe.4",
++ "santafe.5",
++ "santafe.6",
++ "santafe.7",
++ "santafe.8",
++ "santafe.9",
++ "santafe.10",
++ "santafe.11",
++ "santafe.12",
++ "santafe.13",
++ "santafe.14",
++ "santafe.15",
++ "santafe.16",
++ "santafe.17",
++ "santafe.18",
++ "santafe.19",
++ "santafe.20",
++ "santafe.21",
++ "santafe.22",
++ "santafe.23",
++ "santafe.24",
++ "santafe.25",
++ "santafe.26",
++ "santafe.27",
++ "santafe.28",
++ "santafe.29",
++ "santafe.30",
++ "santafe.31",
++ "santafe.32",
++ "santafe.33",
++ "santafe.34",
++ "sheen",
++ "sheen.0",
++ "sheen.1",
++ "sheen.2",
++ "sheen.3",
++ "sheen.4",
++ "sheen.5",
++ "sheen.6",
++ "sheen.7",
++ "sheen.8",
++ "sheen.9",
++ "sheen.10",
++ "sheen.11",
++ "sheen.12",
++ "sheen.13",
++ "sheen.14",
++ "sheen.15",
++ "sheen.16",
++ "sheen.17",
++ "sheen.18",
++ "sheen.19",
++ "sheen.20",
++ "sheen.21",
++ "sheen.22",
++ "sheen.23",
++ "sheen.24",
++ "sheen.25",
++ "sheen.26",
++ "sheen.27",
++ "sheen.28",
++ "sheen.29",
++ "sheen.30",
++ "sheen.31",
++ "sheen.32",
++ "sheen.33",
++ "sheen.34",
++ "silky",
++ "silky.0",
++ "silky.1",
++ "silky.2",
++ "silky.3",
++ "silky.4",
++ "silky.5",
++ "silky.6",
++ "silky.7",
++ "silky.8",
++ "silky.9",
++ "silky.10",
++ "silky.11",
++ "silky.12",
++ "silky.13",
++ "silky.14",
++ "silky.15",
++ "silky.16",
++ "silky.17",
++ "silky.18",
++ "silky.19",
++ "silky.20",
++ "silky.21",
++ "silky.22",
++ "silky.23",
++ "silky.24",
++ "silky.25",
++ "silky.26",
++ "silky.27",
++ "silky.28",
++ "silky.29",
++ "silky.30",
++ "silky.31",
++ "silky.32",
++ "silky.33",
++ "silky.34",
++ "spring",
++ "spring.0",
++ "spring.1",
++ "spring.2",
++ "spring.3",
++ "spring.4",
++ "spring.5",
++ "spring.6",
++ "spring.7",
++ "spring.8",
++ "spring.9",
++ "spring.10",
++ "spring.11",
++ "spring.12",
++ "spring.13",
++ "spring.14",
++ "spring.15",
++ "spring.16",
++ "spring.17",
++ "spring.18",
++ "spring.19",
++ "spring.20",
++ "spring.21",
++ "spring.22",
++ "spring.23",
++ "spring.24",
++ "spring.25",
++ "spring.26",
++ "spring.27",
++ "spring.28",
++ "spring.29",
++ "spring.30",
++ "spring.31",
++ "spring.32",
++ "spring.33",
++ "spring.34",
++ "summer",
++ "summer.0",
++ "summer.1",
++ "summer.2",
++ "summer.3",
++ "summer.4",
++ "summer.5",
++ "summer.6",
++ "summer.7",
++ "summer.8",
++ "summer.9",
++ "summer.10",
++ "summer.11",
++ "summer.12",
++ "summer.13",
++ "summer.14",
++ "summer.15",
++ "summer.16",
++ "summer.17",
++ "summer.18",
++ "summer.19",
++ "summer.20",
++ "summer.21",
++ "summer.22",
++ "summer.23",
++ "summer.24",
++ "summer.25",
++ "summer.26",
++ "summer.27",
++ "summer.28",
++ "summer.29",
++ "summer.30",
++ "summer.31",
++ "summer.32",
++ "summer.33",
++ "summer.34",
++ "tropical",
++ "tropical.0",
++ "tropical.1",
++ "tropical.2",
++ "tropical.3",
++ "tropical.4",
++ "tropical.5",
++ "tropical.6",
++ "tropical.7",
++ "tropical.8",
++ "tropical.9",
++ "tropical.10",
++ "tropical.11",
++ "tropical.12",
++ "tropical.13",
++ "tropical.14",
++ "tropical.15",
++ "tropical.16",
++ "tropical.17",
++ "tropical.18",
++ "tropical.19",
++ "tropical.20",
++ "tropical.21",
++ "tropical.22",
++ "tropical.23",
++ "tropical.24",
++ "tropical.25",
++ "tropical.26",
++ "tropical.27",
++ "tropical.28",
++ "tropical.29",
++ "tropical.30",
++ "tropical.31",
++ "tropical.32",
++ "tropical.33",
++ "tropical.34",
++ "winter",
++ "winter.0",
++ "winter.1",
++ "winter.2",
++ "winter.3",
++ "winter.4",
++ "winter.5",
++ "winter.6",
++ "winter.7",
++ "winter.8",
++ "winter.9",
++ "winter.10",
++ "winter.11",
++ "winter.12",
++ "winter.13",
++ "winter.14",
++ "winter.15",
++ "winter.16",
++ "winter.17",
++ "winter.18",
++ "winter.19",
++ "winter.20",
++ "winter.21",
++ "winter.22",
++ "winter.23",
++ "winter.24",
++ "winter.25",
++ "winter.26",
++ "winter.27",
++ "winter.28",
++ "winter.29",
++ "winter.30",
++ "winter.31",
++ "winter.32",
++ "winter.33",
++ "winter.34",
++ NULL
++}; // builtin_material_names
++#endif // WITH_STATIC_DEFAULTS
++
++// *************************************************************************
++
++/*!
++ \internal
++
++ This method fills in the So at Gui@MaterialDirectory structure with the builtin
++ material data.
++*/
++
++void
++SoAnyMaterialList::setupBuiltinMaterials(// private
++ So at Gui@MaterialDirectory * const index) const
++{
++ assert(index != NULL);
++ index->numGroups = 0;
++ index->groups = NULL;
++#ifdef WITH_STATIC_DEFAULTS
++ index->flags |= SO at GUI@_BUILTIN_MATERIALS;
++ index->numGroups = 13;
++ index->groups = new So at Gui@MaterialGroup * [ 13 ];
++ for (int i = 0; i < index->numGroups; i++) {
++ index->groups[i] = new So at Gui@MaterialGroup;
++ index->groups[i]->numMaterials = 35;
++ index->groups[i]->materials = new So at Gui@Material * [ 35 ];
++ for (int j = 0; j < 35; j++) {
++ index->groups[i]->materials[j] = new So at Gui@Material;
++ }
++ }
++
++ index->groups[0]->name = builtin_material_names[0];
++ index->groups[0]->materials[0]->name = builtin_material_names[1];
++ index->groups[0]->materials[0]->data = artdeco0_iv;
++ index->groups[0]->materials[1]->name = builtin_material_names[2];
++ index->groups[0]->materials[1]->data = artdeco1_iv;
++ index->groups[0]->materials[2]->name = builtin_material_names[3];
++ index->groups[0]->materials[2]->data = artdeco2_iv;
++ index->groups[0]->materials[3]->name = builtin_material_names[4];
++ index->groups[0]->materials[3]->data = artdeco3_iv;
++ index->groups[0]->materials[4]->name = builtin_material_names[5];
++ index->groups[0]->materials[4]->data = artdeco4_iv;
++ index->groups[0]->materials[5]->name = builtin_material_names[6];
++ index->groups[0]->materials[5]->data = artdeco5_iv;
++ index->groups[0]->materials[6]->name = builtin_material_names[7];
++ index->groups[0]->materials[6]->data = artdeco6_iv;
++ index->groups[0]->materials[7]->name = builtin_material_names[8];
++ index->groups[0]->materials[7]->data = artdeco7_iv;
++ index->groups[0]->materials[8]->name = builtin_material_names[9];
++ index->groups[0]->materials[8]->data = artdeco8_iv;
++ index->groups[0]->materials[9]->name = builtin_material_names[10];
++ index->groups[0]->materials[9]->data = artdeco9_iv;
++ index->groups[0]->materials[10]->name = builtin_material_names[11];
++ index->groups[0]->materials[10]->data = artdeco10_iv;
++ index->groups[0]->materials[11]->name = builtin_material_names[12];
++ index->groups[0]->materials[11]->data = artdeco11_iv;
++ index->groups[0]->materials[12]->name = builtin_material_names[13];
++ index->groups[0]->materials[12]->data = artdeco12_iv;
++ index->groups[0]->materials[13]->name = builtin_material_names[14];
++ index->groups[0]->materials[13]->data = artdeco13_iv;
++ index->groups[0]->materials[14]->name = builtin_material_names[15];
++ index->groups[0]->materials[14]->data = artdeco14_iv;
++ index->groups[0]->materials[15]->name = builtin_material_names[16];
++ index->groups[0]->materials[15]->data = artdeco15_iv;
++ index->groups[0]->materials[16]->name = builtin_material_names[17];
++ index->groups[0]->materials[16]->data = artdeco16_iv;
++ index->groups[0]->materials[17]->name = builtin_material_names[18];
++ index->groups[0]->materials[17]->data = artdeco17_iv;
++ index->groups[0]->materials[18]->name = builtin_material_names[19];
++ index->groups[0]->materials[18]->data = artdeco18_iv;
++ index->groups[0]->materials[19]->name = builtin_material_names[20];
++ index->groups[0]->materials[19]->data = artdeco19_iv;
++ index->groups[0]->materials[20]->name = builtin_material_names[21];
++ index->groups[0]->materials[20]->data = artdeco20_iv;
++ index->groups[0]->materials[21]->name = builtin_material_names[22];
++ index->groups[0]->materials[21]->data = artdeco21_iv;
++ index->groups[0]->materials[22]->name = builtin_material_names[23];
++ index->groups[0]->materials[22]->data = artdeco22_iv;
++ index->groups[0]->materials[23]->name = builtin_material_names[24];
++ index->groups[0]->materials[23]->data = artdeco23_iv;
++ index->groups[0]->materials[24]->name = builtin_material_names[25];
++ index->groups[0]->materials[24]->data = artdeco24_iv;
++ index->groups[0]->materials[25]->name = builtin_material_names[26];
++ index->groups[0]->materials[25]->data = artdeco25_iv;
++ index->groups[0]->materials[26]->name = builtin_material_names[27];
++ index->groups[0]->materials[26]->data = artdeco26_iv;
++ index->groups[0]->materials[27]->name = builtin_material_names[28];
++ index->groups[0]->materials[27]->data = artdeco27_iv;
++ index->groups[0]->materials[28]->name = builtin_material_names[29];
++ index->groups[0]->materials[28]->data = artdeco28_iv;
++ index->groups[0]->materials[29]->name = builtin_material_names[30];
++ index->groups[0]->materials[29]->data = artdeco29_iv;
++ index->groups[0]->materials[30]->name = builtin_material_names[31];
++ index->groups[0]->materials[30]->data = artdeco30_iv;
++ index->groups[0]->materials[31]->name = builtin_material_names[32];
++ index->groups[0]->materials[31]->data = artdeco31_iv;
++ index->groups[0]->materials[32]->name = builtin_material_names[33];
++ index->groups[0]->materials[32]->data = artdeco32_iv;
++ index->groups[0]->materials[33]->name = builtin_material_names[34];
++ index->groups[0]->materials[33]->data = artdeco33_iv;
++ index->groups[0]->materials[34]->name = builtin_material_names[35];
++ index->groups[0]->materials[34]->data = artdeco34_iv;
++ index->groups[1]->name = builtin_material_names[36];
++ index->groups[1]->materials[0]->name = builtin_material_names[37];
++ index->groups[1]->materials[0]->data = autumn0_iv;
++ index->groups[1]->materials[1]->name = builtin_material_names[38];
++ index->groups[1]->materials[1]->data = autumn1_iv;
++ index->groups[1]->materials[2]->name = builtin_material_names[39];
++ index->groups[1]->materials[2]->data = autumn2_iv;
++ index->groups[1]->materials[3]->name = builtin_material_names[40];
++ index->groups[1]->materials[3]->data = autumn3_iv;
++ index->groups[1]->materials[4]->name = builtin_material_names[41];
++ index->groups[1]->materials[4]->data = autumn4_iv;
++ index->groups[1]->materials[5]->name = builtin_material_names[42];
++ index->groups[1]->materials[5]->data = autumn5_iv;
++ index->groups[1]->materials[6]->name = builtin_material_names[43];
++ index->groups[1]->materials[6]->data = autumn6_iv;
++ index->groups[1]->materials[7]->name = builtin_material_names[44];
++ index->groups[1]->materials[7]->data = autumn7_iv;
++ index->groups[1]->materials[8]->name = builtin_material_names[45];
++ index->groups[1]->materials[8]->data = autumn8_iv;
++ index->groups[1]->materials[9]->name = builtin_material_names[46];
++ index->groups[1]->materials[9]->data = autumn9_iv;
++ index->groups[1]->materials[10]->name = builtin_material_names[47];
++ index->groups[1]->materials[10]->data = autumn10_iv;
++ index->groups[1]->materials[11]->name = builtin_material_names[48];
++ index->groups[1]->materials[11]->data = autumn11_iv;
++ index->groups[1]->materials[12]->name = builtin_material_names[49];
++ index->groups[1]->materials[12]->data = autumn12_iv;
++ index->groups[1]->materials[13]->name = builtin_material_names[50];
++ index->groups[1]->materials[13]->data = autumn13_iv;
++ index->groups[1]->materials[14]->name = builtin_material_names[51];
++ index->groups[1]->materials[14]->data = autumn14_iv;
++ index->groups[1]->materials[15]->name = builtin_material_names[52];
++ index->groups[1]->materials[15]->data = autumn15_iv;
++ index->groups[1]->materials[16]->name = builtin_material_names[53];
++ index->groups[1]->materials[16]->data = autumn16_iv;
++ index->groups[1]->materials[17]->name = builtin_material_names[54];
++ index->groups[1]->materials[17]->data = autumn17_iv;
++ index->groups[1]->materials[18]->name = builtin_material_names[55];
++ index->groups[1]->materials[18]->data = autumn18_iv;
++ index->groups[1]->materials[19]->name = builtin_material_names[56];
++ index->groups[1]->materials[19]->data = autumn19_iv;
++ index->groups[1]->materials[20]->name = builtin_material_names[57];
++ index->groups[1]->materials[20]->data = autumn20_iv;
++ index->groups[1]->materials[21]->name = builtin_material_names[58];
++ index->groups[1]->materials[21]->data = autumn21_iv;
++ index->groups[1]->materials[22]->name = builtin_material_names[59];
++ index->groups[1]->materials[22]->data = autumn22_iv;
++ index->groups[1]->materials[23]->name = builtin_material_names[60];
++ index->groups[1]->materials[23]->data = autumn23_iv;
++ index->groups[1]->materials[24]->name = builtin_material_names[61];
++ index->groups[1]->materials[24]->data = autumn24_iv;
++ index->groups[1]->materials[25]->name = builtin_material_names[62];
++ index->groups[1]->materials[25]->data = autumn25_iv;
++ index->groups[1]->materials[26]->name = builtin_material_names[63];
++ index->groups[1]->materials[26]->data = autumn26_iv;
++ index->groups[1]->materials[27]->name = builtin_material_names[64];
++ index->groups[1]->materials[27]->data = autumn27_iv;
++ index->groups[1]->materials[28]->name = builtin_material_names[65];
++ index->groups[1]->materials[28]->data = autumn28_iv;
++ index->groups[1]->materials[29]->name = builtin_material_names[66];
++ index->groups[1]->materials[29]->data = autumn29_iv;
++ index->groups[1]->materials[30]->name = builtin_material_names[67];
++ index->groups[1]->materials[30]->data = autumn30_iv;
++ index->groups[1]->materials[31]->name = builtin_material_names[68];
++ index->groups[1]->materials[31]->data = autumn31_iv;
++ index->groups[1]->materials[32]->name = builtin_material_names[69];
++ index->groups[1]->materials[32]->data = autumn32_iv;
++ index->groups[1]->materials[33]->name = builtin_material_names[70];
++ index->groups[1]->materials[33]->data = autumn33_iv;
++ index->groups[1]->materials[34]->name = builtin_material_names[71];
++ index->groups[1]->materials[34]->data = autumn34_iv;
++ index->groups[2]->name = builtin_material_names[72];
++ index->groups[2]->materials[0]->name = builtin_material_names[73];
++ index->groups[2]->materials[0]->data = glass0_iv;
++ index->groups[2]->materials[1]->name = builtin_material_names[74];
++ index->groups[2]->materials[1]->data = glass1_iv;
++ index->groups[2]->materials[2]->name = builtin_material_names[75];
++ index->groups[2]->materials[2]->data = glass2_iv;
++ index->groups[2]->materials[3]->name = builtin_material_names[76];
++ index->groups[2]->materials[3]->data = glass3_iv;
++ index->groups[2]->materials[4]->name = builtin_material_names[77];
++ index->groups[2]->materials[4]->data = glass4_iv;
++ index->groups[2]->materials[5]->name = builtin_material_names[78];
++ index->groups[2]->materials[5]->data = glass5_iv;
++ index->groups[2]->materials[6]->name = builtin_material_names[79];
++ index->groups[2]->materials[6]->data = glass6_iv;
++ index->groups[2]->materials[7]->name = builtin_material_names[80];
++ index->groups[2]->materials[7]->data = glass7_iv;
++ index->groups[2]->materials[8]->name = builtin_material_names[81];
++ index->groups[2]->materials[8]->data = glass8_iv;
++ index->groups[2]->materials[9]->name = builtin_material_names[82];
++ index->groups[2]->materials[9]->data = glass9_iv;
++ index->groups[2]->materials[10]->name = builtin_material_names[83];
++ index->groups[2]->materials[10]->data = glass10_iv;
++ index->groups[2]->materials[11]->name = builtin_material_names[84];
++ index->groups[2]->materials[11]->data = glass11_iv;
++ index->groups[2]->materials[12]->name = builtin_material_names[85];
++ index->groups[2]->materials[12]->data = glass12_iv;
++ index->groups[2]->materials[13]->name = builtin_material_names[86];
++ index->groups[2]->materials[13]->data = glass13_iv;
++ index->groups[2]->materials[14]->name = builtin_material_names[87];
++ index->groups[2]->materials[14]->data = glass14_iv;
++ index->groups[2]->materials[15]->name = builtin_material_names[88];
++ index->groups[2]->materials[15]->data = glass15_iv;
++ index->groups[2]->materials[16]->name = builtin_material_names[89];
++ index->groups[2]->materials[16]->data = glass16_iv;
++ index->groups[2]->materials[17]->name = builtin_material_names[90];
++ index->groups[2]->materials[17]->data = glass17_iv;
++ index->groups[2]->materials[18]->name = builtin_material_names[91];
++ index->groups[2]->materials[18]->data = glass18_iv;
++ index->groups[2]->materials[19]->name = builtin_material_names[92];
++ index->groups[2]->materials[19]->data = glass19_iv;
++ index->groups[2]->materials[20]->name = builtin_material_names[93];
++ index->groups[2]->materials[20]->data = glass20_iv;
++ index->groups[2]->materials[21]->name = builtin_material_names[94];
++ index->groups[2]->materials[21]->data = glass21_iv;
++ index->groups[2]->materials[22]->name = builtin_material_names[95];
++ index->groups[2]->materials[22]->data = glass22_iv;
++ index->groups[2]->materials[23]->name = builtin_material_names[96];
++ index->groups[2]->materials[23]->data = glass23_iv;
++ index->groups[2]->materials[24]->name = builtin_material_names[97];
++ index->groups[2]->materials[24]->data = glass24_iv;
++ index->groups[2]->materials[25]->name = builtin_material_names[98];
++ index->groups[2]->materials[25]->data = glass25_iv;
++ index->groups[2]->materials[26]->name = builtin_material_names[99];
++ index->groups[2]->materials[26]->data = glass26_iv;
++ index->groups[2]->materials[27]->name = builtin_material_names[100];
++ index->groups[2]->materials[27]->data = glass27_iv;
++ index->groups[2]->materials[28]->name = builtin_material_names[101];
++ index->groups[2]->materials[28]->data = glass28_iv;
++ index->groups[2]->materials[29]->name = builtin_material_names[102];
++ index->groups[2]->materials[29]->data = glass29_iv;
++ index->groups[2]->materials[30]->name = builtin_material_names[103];
++ index->groups[2]->materials[30]->data = glass30_iv;
++ index->groups[2]->materials[31]->name = builtin_material_names[104];
++ index->groups[2]->materials[31]->data = glass31_iv;
++ index->groups[2]->materials[32]->name = builtin_material_names[105];
++ index->groups[2]->materials[32]->data = glass32_iv;
++ index->groups[2]->materials[33]->name = builtin_material_names[106];
++ index->groups[2]->materials[33]->data = glass33_iv;
++ index->groups[2]->materials[34]->name = builtin_material_names[107];
++ index->groups[2]->materials[34]->data = glass34_iv;
++ index->groups[3]->name = builtin_material_names[108];
++ index->groups[3]->materials[0]->name = builtin_material_names[109];
++ index->groups[3]->materials[0]->data = metal0_iv;
++ index->groups[3]->materials[1]->name = builtin_material_names[110];
++ index->groups[3]->materials[1]->data = metal1_iv;
++ index->groups[3]->materials[2]->name = builtin_material_names[111];
++ index->groups[3]->materials[2]->data = metal2_iv;
++ index->groups[3]->materials[3]->name = builtin_material_names[112];
++ index->groups[3]->materials[3]->data = metal3_iv;
++ index->groups[3]->materials[4]->name = builtin_material_names[113];
++ index->groups[3]->materials[4]->data = metal4_iv;
++ index->groups[3]->materials[5]->name = builtin_material_names[114];
++ index->groups[3]->materials[5]->data = metal5_iv;
++ index->groups[3]->materials[6]->name = builtin_material_names[115];
++ index->groups[3]->materials[6]->data = metal6_iv;
++ index->groups[3]->materials[7]->name = builtin_material_names[116];
++ index->groups[3]->materials[7]->data = metal7_iv;
++ index->groups[3]->materials[8]->name = builtin_material_names[117];
++ index->groups[3]->materials[8]->data = metal8_iv;
++ index->groups[3]->materials[9]->name = builtin_material_names[118];
++ index->groups[3]->materials[9]->data = metal9_iv;
++ index->groups[3]->materials[10]->name = builtin_material_names[119];
++ index->groups[3]->materials[10]->data = metal10_iv;
++ index->groups[3]->materials[11]->name = builtin_material_names[120];
++ index->groups[3]->materials[11]->data = metal11_iv;
++ index->groups[3]->materials[12]->name = builtin_material_names[121];
++ index->groups[3]->materials[12]->data = metal12_iv;
++ index->groups[3]->materials[13]->name = builtin_material_names[122];
++ index->groups[3]->materials[13]->data = metal13_iv;
++ index->groups[3]->materials[14]->name = builtin_material_names[123];
++ index->groups[3]->materials[14]->data = metal14_iv;
++ index->groups[3]->materials[15]->name = builtin_material_names[124];
++ index->groups[3]->materials[15]->data = metal15_iv;
++ index->groups[3]->materials[16]->name = builtin_material_names[125];
++ index->groups[3]->materials[16]->data = metal16_iv;
++ index->groups[3]->materials[17]->name = builtin_material_names[126];
++ index->groups[3]->materials[17]->data = metal17_iv;
++ index->groups[3]->materials[18]->name = builtin_material_names[127];
++ index->groups[3]->materials[18]->data = metal18_iv;
++ index->groups[3]->materials[19]->name = builtin_material_names[128];
++ index->groups[3]->materials[19]->data = metal19_iv;
++ index->groups[3]->materials[20]->name = builtin_material_names[129];
++ index->groups[3]->materials[20]->data = metal20_iv;
++ index->groups[3]->materials[21]->name = builtin_material_names[130];
++ index->groups[3]->materials[21]->data = metal21_iv;
++ index->groups[3]->materials[22]->name = builtin_material_names[131];
++ index->groups[3]->materials[22]->data = metal22_iv;
++ index->groups[3]->materials[23]->name = builtin_material_names[132];
++ index->groups[3]->materials[23]->data = metal23_iv;
++ index->groups[3]->materials[24]->name = builtin_material_names[133];
++ index->groups[3]->materials[24]->data = metal24_iv;
++ index->groups[3]->materials[25]->name = builtin_material_names[134];
++ index->groups[3]->materials[25]->data = metal25_iv;
++ index->groups[3]->materials[26]->name = builtin_material_names[135];
++ index->groups[3]->materials[26]->data = metal26_iv;
++ index->groups[3]->materials[27]->name = builtin_material_names[136];
++ index->groups[3]->materials[27]->data = metal27_iv;
++ index->groups[3]->materials[28]->name = builtin_material_names[137];
++ index->groups[3]->materials[28]->data = metal28_iv;
++ index->groups[3]->materials[29]->name = builtin_material_names[138];
++ index->groups[3]->materials[29]->data = metal29_iv;
++ index->groups[3]->materials[30]->name = builtin_material_names[139];
++ index->groups[3]->materials[30]->data = metal30_iv;
++ index->groups[3]->materials[31]->name = builtin_material_names[140];
++ index->groups[3]->materials[31]->data = metal31_iv;
++ index->groups[3]->materials[32]->name = builtin_material_names[141];
++ index->groups[3]->materials[32]->data = metal32_iv;
++ index->groups[3]->materials[33]->name = builtin_material_names[142];
++ index->groups[3]->materials[33]->data = metal33_iv;
++ index->groups[3]->materials[34]->name = builtin_material_names[143];
++ index->groups[3]->materials[34]->data = metal34_iv;
++ index->groups[4]->name = builtin_material_names[144];
++ index->groups[4]->materials[0]->name = builtin_material_names[145];
++ index->groups[4]->materials[0]->data = neon0_iv;
++ index->groups[4]->materials[1]->name = builtin_material_names[146];
++ index->groups[4]->materials[1]->data = neon1_iv;
++ index->groups[4]->materials[2]->name = builtin_material_names[147];
++ index->groups[4]->materials[2]->data = neon2_iv;
++ index->groups[4]->materials[3]->name = builtin_material_names[148];
++ index->groups[4]->materials[3]->data = neon3_iv;
++ index->groups[4]->materials[4]->name = builtin_material_names[149];
++ index->groups[4]->materials[4]->data = neon4_iv;
++ index->groups[4]->materials[5]->name = builtin_material_names[150];
++ index->groups[4]->materials[5]->data = neon5_iv;
++ index->groups[4]->materials[6]->name = builtin_material_names[151];
++ index->groups[4]->materials[6]->data = neon6_iv;
++ index->groups[4]->materials[7]->name = builtin_material_names[152];
++ index->groups[4]->materials[7]->data = neon7_iv;
++ index->groups[4]->materials[8]->name = builtin_material_names[153];
++ index->groups[4]->materials[8]->data = neon8_iv;
++ index->groups[4]->materials[9]->name = builtin_material_names[154];
++ index->groups[4]->materials[9]->data = neon9_iv;
++ index->groups[4]->materials[10]->name = builtin_material_names[155];
++ index->groups[4]->materials[10]->data = neon10_iv;
++ index->groups[4]->materials[11]->name = builtin_material_names[156];
++ index->groups[4]->materials[11]->data = neon11_iv;
++ index->groups[4]->materials[12]->name = builtin_material_names[157];
++ index->groups[4]->materials[12]->data = neon12_iv;
++ index->groups[4]->materials[13]->name = builtin_material_names[158];
++ index->groups[4]->materials[13]->data = neon13_iv;
++ index->groups[4]->materials[14]->name = builtin_material_names[159];
++ index->groups[4]->materials[14]->data = neon14_iv;
++ index->groups[4]->materials[15]->name = builtin_material_names[160];
++ index->groups[4]->materials[15]->data = neon15_iv;
++ index->groups[4]->materials[16]->name = builtin_material_names[161];
++ index->groups[4]->materials[16]->data = neon16_iv;
++ index->groups[4]->materials[17]->name = builtin_material_names[162];
++ index->groups[4]->materials[17]->data = neon17_iv;
++ index->groups[4]->materials[18]->name = builtin_material_names[163];
++ index->groups[4]->materials[18]->data = neon18_iv;
++ index->groups[4]->materials[19]->name = builtin_material_names[164];
++ index->groups[4]->materials[19]->data = neon19_iv;
++ index->groups[4]->materials[20]->name = builtin_material_names[165];
++ index->groups[4]->materials[20]->data = neon20_iv;
++ index->groups[4]->materials[21]->name = builtin_material_names[166];
++ index->groups[4]->materials[21]->data = neon21_iv;
++ index->groups[4]->materials[22]->name = builtin_material_names[167];
++ index->groups[4]->materials[22]->data = neon22_iv;
++ index->groups[4]->materials[23]->name = builtin_material_names[168];
++ index->groups[4]->materials[23]->data = neon23_iv;
++ index->groups[4]->materials[24]->name = builtin_material_names[169];
++ index->groups[4]->materials[24]->data = neon24_iv;
++ index->groups[4]->materials[25]->name = builtin_material_names[170];
++ index->groups[4]->materials[25]->data = neon25_iv;
++ index->groups[4]->materials[26]->name = builtin_material_names[171];
++ index->groups[4]->materials[26]->data = neon26_iv;
++ index->groups[4]->materials[27]->name = builtin_material_names[172];
++ index->groups[4]->materials[27]->data = neon27_iv;
++ index->groups[4]->materials[28]->name = builtin_material_names[173];
++ index->groups[4]->materials[28]->data = neon28_iv;
++ index->groups[4]->materials[29]->name = builtin_material_names[174];
++ index->groups[4]->materials[29]->data = neon29_iv;
++ index->groups[4]->materials[30]->name = builtin_material_names[175];
++ index->groups[4]->materials[30]->data = neon30_iv;
++ index->groups[4]->materials[31]->name = builtin_material_names[176];
++ index->groups[4]->materials[31]->data = neon31_iv;
++ index->groups[4]->materials[32]->name = builtin_material_names[177];
++ index->groups[4]->materials[32]->data = neon32_iv;
++ index->groups[4]->materials[33]->name = builtin_material_names[178];
++ index->groups[4]->materials[33]->data = neon33_iv;
++ index->groups[4]->materials[34]->name = builtin_material_names[179];
++ index->groups[4]->materials[34]->data = neon34_iv;
++ index->groups[5]->name = builtin_material_names[180];
++ index->groups[5]->materials[0]->name = builtin_material_names[181];
++ index->groups[5]->materials[0]->data = rococo0_iv;
++ index->groups[5]->materials[1]->name = builtin_material_names[182];
++ index->groups[5]->materials[1]->data = rococo1_iv;
++ index->groups[5]->materials[2]->name = builtin_material_names[183];
++ index->groups[5]->materials[2]->data = rococo2_iv;
++ index->groups[5]->materials[3]->name = builtin_material_names[184];
++ index->groups[5]->materials[3]->data = rococo3_iv;
++ index->groups[5]->materials[4]->name = builtin_material_names[185];
++ index->groups[5]->materials[4]->data = rococo4_iv;
++ index->groups[5]->materials[5]->name = builtin_material_names[186];
++ index->groups[5]->materials[5]->data = rococo5_iv;
++ index->groups[5]->materials[6]->name = builtin_material_names[187];
++ index->groups[5]->materials[6]->data = rococo6_iv;
++ index->groups[5]->materials[7]->name = builtin_material_names[188];
++ index->groups[5]->materials[7]->data = rococo7_iv;
++ index->groups[5]->materials[8]->name = builtin_material_names[189];
++ index->groups[5]->materials[8]->data = rococo8_iv;
++ index->groups[5]->materials[9]->name = builtin_material_names[190];
++ index->groups[5]->materials[9]->data = rococo9_iv;
++ index->groups[5]->materials[10]->name = builtin_material_names[191];
++ index->groups[5]->materials[10]->data = rococo10_iv;
++ index->groups[5]->materials[11]->name = builtin_material_names[192];
++ index->groups[5]->materials[11]->data = rococo11_iv;
++ index->groups[5]->materials[12]->name = builtin_material_names[193];
++ index->groups[5]->materials[12]->data = rococo12_iv;
++ index->groups[5]->materials[13]->name = builtin_material_names[194];
++ index->groups[5]->materials[13]->data = rococo13_iv;
++ index->groups[5]->materials[14]->name = builtin_material_names[195];
++ index->groups[5]->materials[14]->data = rococo14_iv;
++ index->groups[5]->materials[15]->name = builtin_material_names[196];
++ index->groups[5]->materials[15]->data = rococo15_iv;
++ index->groups[5]->materials[16]->name = builtin_material_names[197];
++ index->groups[5]->materials[16]->data = rococo16_iv;
++ index->groups[5]->materials[17]->name = builtin_material_names[198];
++ index->groups[5]->materials[17]->data = rococo17_iv;
++ index->groups[5]->materials[18]->name = builtin_material_names[199];
++ index->groups[5]->materials[18]->data = rococo18_iv;
++ index->groups[5]->materials[19]->name = builtin_material_names[200];
++ index->groups[5]->materials[19]->data = rococo19_iv;
++ index->groups[5]->materials[20]->name = builtin_material_names[201];
++ index->groups[5]->materials[20]->data = rococo20_iv;
++ index->groups[5]->materials[21]->name = builtin_material_names[202];
++ index->groups[5]->materials[21]->data = rococo21_iv;
++ index->groups[5]->materials[22]->name = builtin_material_names[203];
++ index->groups[5]->materials[22]->data = rococo22_iv;
++ index->groups[5]->materials[23]->name = builtin_material_names[204];
++ index->groups[5]->materials[23]->data = rococo23_iv;
++ index->groups[5]->materials[24]->name = builtin_material_names[205];
++ index->groups[5]->materials[24]->data = rococo24_iv;
++ index->groups[5]->materials[25]->name = builtin_material_names[206];
++ index->groups[5]->materials[25]->data = rococo25_iv;
++ index->groups[5]->materials[26]->name = builtin_material_names[207];
++ index->groups[5]->materials[26]->data = rococo26_iv;
++ index->groups[5]->materials[27]->name = builtin_material_names[208];
++ index->groups[5]->materials[27]->data = rococo27_iv;
++ index->groups[5]->materials[28]->name = builtin_material_names[209];
++ index->groups[5]->materials[28]->data = rococo28_iv;
++ index->groups[5]->materials[29]->name = builtin_material_names[210];
++ index->groups[5]->materials[29]->data = rococo29_iv;
++ index->groups[5]->materials[30]->name = builtin_material_names[211];
++ index->groups[5]->materials[30]->data = rococo30_iv;
++ index->groups[5]->materials[31]->name = builtin_material_names[212];
++ index->groups[5]->materials[31]->data = rococo31_iv;
++ index->groups[5]->materials[32]->name = builtin_material_names[213];
++ index->groups[5]->materials[32]->data = rococo32_iv;
++ index->groups[5]->materials[33]->name = builtin_material_names[214];
++ index->groups[5]->materials[33]->data = rococo33_iv;
++ index->groups[5]->materials[34]->name = builtin_material_names[215];
++ index->groups[5]->materials[34]->data = rococo34_iv;
++ index->groups[6]->name = builtin_material_names[216];
++ index->groups[6]->materials[0]->name = builtin_material_names[217];
++ index->groups[6]->materials[0]->data = santafe0_iv;
++ index->groups[6]->materials[1]->name = builtin_material_names[218];
++ index->groups[6]->materials[1]->data = santafe1_iv;
++ index->groups[6]->materials[2]->name = builtin_material_names[219];
++ index->groups[6]->materials[2]->data = santafe2_iv;
++ index->groups[6]->materials[3]->name = builtin_material_names[220];
++ index->groups[6]->materials[3]->data = santafe3_iv;
++ index->groups[6]->materials[4]->name = builtin_material_names[221];
++ index->groups[6]->materials[4]->data = santafe4_iv;
++ index->groups[6]->materials[5]->name = builtin_material_names[222];
++ index->groups[6]->materials[5]->data = santafe5_iv;
++ index->groups[6]->materials[6]->name = builtin_material_names[223];
++ index->groups[6]->materials[6]->data = santafe6_iv;
++ index->groups[6]->materials[7]->name = builtin_material_names[224];
++ index->groups[6]->materials[7]->data = santafe7_iv;
++ index->groups[6]->materials[8]->name = builtin_material_names[225];
++ index->groups[6]->materials[8]->data = santafe8_iv;
++ index->groups[6]->materials[9]->name = builtin_material_names[226];
++ index->groups[6]->materials[9]->data = santafe9_iv;
++ index->groups[6]->materials[10]->name = builtin_material_names[227];
++ index->groups[6]->materials[10]->data = santafe10_iv;
++ index->groups[6]->materials[11]->name = builtin_material_names[228];
++ index->groups[6]->materials[11]->data = santafe11_iv;
++ index->groups[6]->materials[12]->name = builtin_material_names[229];
++ index->groups[6]->materials[12]->data = santafe12_iv;
++ index->groups[6]->materials[13]->name = builtin_material_names[230];
++ index->groups[6]->materials[13]->data = santafe13_iv;
++ index->groups[6]->materials[14]->name = builtin_material_names[231];
++ index->groups[6]->materials[14]->data = santafe14_iv;
++ index->groups[6]->materials[15]->name = builtin_material_names[232];
++ index->groups[6]->materials[15]->data = santafe15_iv;
++ index->groups[6]->materials[16]->name = builtin_material_names[233];
++ index->groups[6]->materials[16]->data = santafe16_iv;
++ index->groups[6]->materials[17]->name = builtin_material_names[234];
++ index->groups[6]->materials[17]->data = santafe17_iv;
++ index->groups[6]->materials[18]->name = builtin_material_names[235];
++ index->groups[6]->materials[18]->data = santafe18_iv;
++ index->groups[6]->materials[19]->name = builtin_material_names[236];
++ index->groups[6]->materials[19]->data = santafe19_iv;
++ index->groups[6]->materials[20]->name = builtin_material_names[237];
++ index->groups[6]->materials[20]->data = santafe20_iv;
++ index->groups[6]->materials[21]->name = builtin_material_names[238];
++ index->groups[6]->materials[21]->data = santafe21_iv;
++ index->groups[6]->materials[22]->name = builtin_material_names[239];
++ index->groups[6]->materials[22]->data = santafe22_iv;
++ index->groups[6]->materials[23]->name = builtin_material_names[240];
++ index->groups[6]->materials[23]->data = santafe23_iv;
++ index->groups[6]->materials[24]->name = builtin_material_names[241];
++ index->groups[6]->materials[24]->data = santafe24_iv;
++ index->groups[6]->materials[25]->name = builtin_material_names[242];
++ index->groups[6]->materials[25]->data = santafe25_iv;
++ index->groups[6]->materials[26]->name = builtin_material_names[243];
++ index->groups[6]->materials[26]->data = santafe26_iv;
++ index->groups[6]->materials[27]->name = builtin_material_names[244];
++ index->groups[6]->materials[27]->data = santafe27_iv;
++ index->groups[6]->materials[28]->name = builtin_material_names[245];
++ index->groups[6]->materials[28]->data = santafe28_iv;
++ index->groups[6]->materials[29]->name = builtin_material_names[246];
++ index->groups[6]->materials[29]->data = santafe29_iv;
++ index->groups[6]->materials[30]->name = builtin_material_names[247];
++ index->groups[6]->materials[30]->data = santafe30_iv;
++ index->groups[6]->materials[31]->name = builtin_material_names[248];
++ index->groups[6]->materials[31]->data = santafe31_iv;
++ index->groups[6]->materials[32]->name = builtin_material_names[249];
++ index->groups[6]->materials[32]->data = santafe32_iv;
++ index->groups[6]->materials[33]->name = builtin_material_names[250];
++ index->groups[6]->materials[33]->data = santafe33_iv;
++ index->groups[6]->materials[34]->name = builtin_material_names[251];
++ index->groups[6]->materials[34]->data = santafe34_iv;
++ index->groups[7]->name = builtin_material_names[252];
++ index->groups[7]->materials[0]->name = builtin_material_names[253];
++ index->groups[7]->materials[0]->data = sheen0_iv;
++ index->groups[7]->materials[1]->name = builtin_material_names[254];
++ index->groups[7]->materials[1]->data = sheen1_iv;
++ index->groups[7]->materials[2]->name = builtin_material_names[255];
++ index->groups[7]->materials[2]->data = sheen2_iv;
++ index->groups[7]->materials[3]->name = builtin_material_names[256];
++ index->groups[7]->materials[3]->data = sheen3_iv;
++ index->groups[7]->materials[4]->name = builtin_material_names[257];
++ index->groups[7]->materials[4]->data = sheen4_iv;
++ index->groups[7]->materials[5]->name = builtin_material_names[258];
++ index->groups[7]->materials[5]->data = sheen5_iv;
++ index->groups[7]->materials[6]->name = builtin_material_names[259];
++ index->groups[7]->materials[6]->data = sheen6_iv;
++ index->groups[7]->materials[7]->name = builtin_material_names[260];
++ index->groups[7]->materials[7]->data = sheen7_iv;
++ index->groups[7]->materials[8]->name = builtin_material_names[261];
++ index->groups[7]->materials[8]->data = sheen8_iv;
++ index->groups[7]->materials[9]->name = builtin_material_names[262];
++ index->groups[7]->materials[9]->data = sheen9_iv;
++ index->groups[7]->materials[10]->name = builtin_material_names[263];
++ index->groups[7]->materials[10]->data = sheen10_iv;
++ index->groups[7]->materials[11]->name = builtin_material_names[264];
++ index->groups[7]->materials[11]->data = sheen11_iv;
++ index->groups[7]->materials[12]->name = builtin_material_names[265];
++ index->groups[7]->materials[12]->data = sheen12_iv;
++ index->groups[7]->materials[13]->name = builtin_material_names[266];
++ index->groups[7]->materials[13]->data = sheen13_iv;
++ index->groups[7]->materials[14]->name = builtin_material_names[267];
++ index->groups[7]->materials[14]->data = sheen14_iv;
++ index->groups[7]->materials[15]->name = builtin_material_names[268];
++ index->groups[7]->materials[15]->data = sheen15_iv;
++ index->groups[7]->materials[16]->name = builtin_material_names[269];
++ index->groups[7]->materials[16]->data = sheen16_iv;
++ index->groups[7]->materials[17]->name = builtin_material_names[270];
++ index->groups[7]->materials[17]->data = sheen17_iv;
++ index->groups[7]->materials[18]->name = builtin_material_names[271];
++ index->groups[7]->materials[18]->data = sheen18_iv;
++ index->groups[7]->materials[19]->name = builtin_material_names[272];
++ index->groups[7]->materials[19]->data = sheen19_iv;
++ index->groups[7]->materials[20]->name = builtin_material_names[273];
++ index->groups[7]->materials[20]->data = sheen20_iv;
++ index->groups[7]->materials[21]->name = builtin_material_names[274];
++ index->groups[7]->materials[21]->data = sheen21_iv;
++ index->groups[7]->materials[22]->name = builtin_material_names[275];
++ index->groups[7]->materials[22]->data = sheen22_iv;
++ index->groups[7]->materials[23]->name = builtin_material_names[276];
++ index->groups[7]->materials[23]->data = sheen23_iv;
++ index->groups[7]->materials[24]->name = builtin_material_names[277];
++ index->groups[7]->materials[24]->data = sheen24_iv;
++ index->groups[7]->materials[25]->name = builtin_material_names[278];
++ index->groups[7]->materials[25]->data = sheen25_iv;
++ index->groups[7]->materials[26]->name = builtin_material_names[279];
++ index->groups[7]->materials[26]->data = sheen26_iv;
++ index->groups[7]->materials[27]->name = builtin_material_names[280];
++ index->groups[7]->materials[27]->data = sheen27_iv;
++ index->groups[7]->materials[28]->name = builtin_material_names[281];
++ index->groups[7]->materials[28]->data = sheen28_iv;
++ index->groups[7]->materials[29]->name = builtin_material_names[282];
++ index->groups[7]->materials[29]->data = sheen29_iv;
++ index->groups[7]->materials[30]->name = builtin_material_names[283];
++ index->groups[7]->materials[30]->data = sheen30_iv;
++ index->groups[7]->materials[31]->name = builtin_material_names[284];
++ index->groups[7]->materials[31]->data = sheen31_iv;
++ index->groups[7]->materials[32]->name = builtin_material_names[285];
++ index->groups[7]->materials[32]->data = sheen32_iv;
++ index->groups[7]->materials[33]->name = builtin_material_names[286];
++ index->groups[7]->materials[33]->data = sheen33_iv;
++ index->groups[7]->materials[34]->name = builtin_material_names[287];
++ index->groups[7]->materials[34]->data = sheen34_iv;
++ index->groups[8]->name = builtin_material_names[288];
++ index->groups[8]->materials[0]->name = builtin_material_names[289];
++ index->groups[8]->materials[0]->data = silky0_iv;
++ index->groups[8]->materials[1]->name = builtin_material_names[290];
++ index->groups[8]->materials[1]->data = silky1_iv;
++ index->groups[8]->materials[2]->name = builtin_material_names[291];
++ index->groups[8]->materials[2]->data = silky2_iv;
++ index->groups[8]->materials[3]->name = builtin_material_names[292];
++ index->groups[8]->materials[3]->data = silky3_iv;
++ index->groups[8]->materials[4]->name = builtin_material_names[293];
++ index->groups[8]->materials[4]->data = silky4_iv;
++ index->groups[8]->materials[5]->name = builtin_material_names[294];
++ index->groups[8]->materials[5]->data = silky5_iv;
++ index->groups[8]->materials[6]->name = builtin_material_names[295];
++ index->groups[8]->materials[6]->data = silky6_iv;
++ index->groups[8]->materials[7]->name = builtin_material_names[296];
++ index->groups[8]->materials[7]->data = silky7_iv;
++ index->groups[8]->materials[8]->name = builtin_material_names[297];
++ index->groups[8]->materials[8]->data = silky8_iv;
++ index->groups[8]->materials[9]->name = builtin_material_names[298];
++ index->groups[8]->materials[9]->data = silky9_iv;
++ index->groups[8]->materials[10]->name = builtin_material_names[299];
++ index->groups[8]->materials[10]->data = silky10_iv;
++ index->groups[8]->materials[11]->name = builtin_material_names[300];
++ index->groups[8]->materials[11]->data = silky11_iv;
++ index->groups[8]->materials[12]->name = builtin_material_names[301];
++ index->groups[8]->materials[12]->data = silky12_iv;
++ index->groups[8]->materials[13]->name = builtin_material_names[302];
++ index->groups[8]->materials[13]->data = silky13_iv;
++ index->groups[8]->materials[14]->name = builtin_material_names[303];
++ index->groups[8]->materials[14]->data = silky14_iv;
++ index->groups[8]->materials[15]->name = builtin_material_names[304];
++ index->groups[8]->materials[15]->data = silky15_iv;
++ index->groups[8]->materials[16]->name = builtin_material_names[305];
++ index->groups[8]->materials[16]->data = silky16_iv;
++ index->groups[8]->materials[17]->name = builtin_material_names[306];
++ index->groups[8]->materials[17]->data = silky17_iv;
++ index->groups[8]->materials[18]->name = builtin_material_names[307];
++ index->groups[8]->materials[18]->data = silky18_iv;
++ index->groups[8]->materials[19]->name = builtin_material_names[308];
++ index->groups[8]->materials[19]->data = silky19_iv;
++ index->groups[8]->materials[20]->name = builtin_material_names[309];
++ index->groups[8]->materials[20]->data = silky20_iv;
++ index->groups[8]->materials[21]->name = builtin_material_names[310];
++ index->groups[8]->materials[21]->data = silky21_iv;
++ index->groups[8]->materials[22]->name = builtin_material_names[311];
++ index->groups[8]->materials[22]->data = silky22_iv;
++ index->groups[8]->materials[23]->name = builtin_material_names[312];
++ index->groups[8]->materials[23]->data = silky23_iv;
++ index->groups[8]->materials[24]->name = builtin_material_names[313];
++ index->groups[8]->materials[24]->data = silky24_iv;
++ index->groups[8]->materials[25]->name = builtin_material_names[314];
++ index->groups[8]->materials[25]->data = silky25_iv;
++ index->groups[8]->materials[26]->name = builtin_material_names[315];
++ index->groups[8]->materials[26]->data = silky26_iv;
++ index->groups[8]->materials[27]->name = builtin_material_names[316];
++ index->groups[8]->materials[27]->data = silky27_iv;
++ index->groups[8]->materials[28]->name = builtin_material_names[317];
++ index->groups[8]->materials[28]->data = silky28_iv;
++ index->groups[8]->materials[29]->name = builtin_material_names[318];
++ index->groups[8]->materials[29]->data = silky29_iv;
++ index->groups[8]->materials[30]->name = builtin_material_names[319];
++ index->groups[8]->materials[30]->data = silky30_iv;
++ index->groups[8]->materials[31]->name = builtin_material_names[320];
++ index->groups[8]->materials[31]->data = silky31_iv;
++ index->groups[8]->materials[32]->name = builtin_material_names[321];
++ index->groups[8]->materials[32]->data = silky32_iv;
++ index->groups[8]->materials[33]->name = builtin_material_names[322];
++ index->groups[8]->materials[33]->data = silky33_iv;
++ index->groups[8]->materials[34]->name = builtin_material_names[323];
++ index->groups[8]->materials[34]->data = silky34_iv;
++ index->groups[9]->name = builtin_material_names[324];
++ index->groups[9]->materials[0]->name = builtin_material_names[325];
++ index->groups[9]->materials[0]->data = spring0_iv;
++ index->groups[9]->materials[1]->name = builtin_material_names[326];
++ index->groups[9]->materials[1]->data = spring1_iv;
++ index->groups[9]->materials[2]->name = builtin_material_names[327];
++ index->groups[9]->materials[2]->data = spring2_iv;
++ index->groups[9]->materials[3]->name = builtin_material_names[328];
++ index->groups[9]->materials[3]->data = spring3_iv;
++ index->groups[9]->materials[4]->name = builtin_material_names[329];
++ index->groups[9]->materials[4]->data = spring4_iv;
++ index->groups[9]->materials[5]->name = builtin_material_names[330];
++ index->groups[9]->materials[5]->data = spring5_iv;
++ index->groups[9]->materials[6]->name = builtin_material_names[331];
++ index->groups[9]->materials[6]->data = spring6_iv;
++ index->groups[9]->materials[7]->name = builtin_material_names[332];
++ index->groups[9]->materials[7]->data = spring7_iv;
++ index->groups[9]->materials[8]->name = builtin_material_names[333];
++ index->groups[9]->materials[8]->data = spring8_iv;
++ index->groups[9]->materials[9]->name = builtin_material_names[334];
++ index->groups[9]->materials[9]->data = spring9_iv;
++ index->groups[9]->materials[10]->name = builtin_material_names[335];
++ index->groups[9]->materials[10]->data = spring10_iv;
++ index->groups[9]->materials[11]->name = builtin_material_names[336];
++ index->groups[9]->materials[11]->data = spring11_iv;
++ index->groups[9]->materials[12]->name = builtin_material_names[337];
++ index->groups[9]->materials[12]->data = spring12_iv;
++ index->groups[9]->materials[13]->name = builtin_material_names[338];
++ index->groups[9]->materials[13]->data = spring13_iv;
++ index->groups[9]->materials[14]->name = builtin_material_names[339];
++ index->groups[9]->materials[14]->data = spring14_iv;
++ index->groups[9]->materials[15]->name = builtin_material_names[340];
++ index->groups[9]->materials[15]->data = spring15_iv;
++ index->groups[9]->materials[16]->name = builtin_material_names[341];
++ index->groups[9]->materials[16]->data = spring16_iv;
++ index->groups[9]->materials[17]->name = builtin_material_names[342];
++ index->groups[9]->materials[17]->data = spring17_iv;
++ index->groups[9]->materials[18]->name = builtin_material_names[343];
++ index->groups[9]->materials[18]->data = spring18_iv;
++ index->groups[9]->materials[19]->name = builtin_material_names[344];
++ index->groups[9]->materials[19]->data = spring19_iv;
++ index->groups[9]->materials[20]->name = builtin_material_names[345];
++ index->groups[9]->materials[20]->data = spring20_iv;
++ index->groups[9]->materials[21]->name = builtin_material_names[346];
++ index->groups[9]->materials[21]->data = spring21_iv;
++ index->groups[9]->materials[22]->name = builtin_material_names[347];
++ index->groups[9]->materials[22]->data = spring22_iv;
++ index->groups[9]->materials[23]->name = builtin_material_names[348];
++ index->groups[9]->materials[23]->data = spring23_iv;
++ index->groups[9]->materials[24]->name = builtin_material_names[349];
++ index->groups[9]->materials[24]->data = spring24_iv;
++ index->groups[9]->materials[25]->name = builtin_material_names[350];
++ index->groups[9]->materials[25]->data = spring25_iv;
++ index->groups[9]->materials[26]->name = builtin_material_names[351];
++ index->groups[9]->materials[26]->data = spring26_iv;
++ index->groups[9]->materials[27]->name = builtin_material_names[352];
++ index->groups[9]->materials[27]->data = spring27_iv;
++ index->groups[9]->materials[28]->name = builtin_material_names[353];
++ index->groups[9]->materials[28]->data = spring28_iv;
++ index->groups[9]->materials[29]->name = builtin_material_names[354];
++ index->groups[9]->materials[29]->data = spring29_iv;
++ index->groups[9]->materials[30]->name = builtin_material_names[355];
++ index->groups[9]->materials[30]->data = spring30_iv;
++ index->groups[9]->materials[31]->name = builtin_material_names[356];
++ index->groups[9]->materials[31]->data = spring31_iv;
++ index->groups[9]->materials[32]->name = builtin_material_names[357];
++ index->groups[9]->materials[32]->data = spring32_iv;
++ index->groups[9]->materials[33]->name = builtin_material_names[358];
++ index->groups[9]->materials[33]->data = spring33_iv;
++ index->groups[9]->materials[34]->name = builtin_material_names[359];
++ index->groups[9]->materials[34]->data = spring34_iv;
++ index->groups[10]->name = builtin_material_names[360];
++ index->groups[10]->materials[0]->name = builtin_material_names[361];
++ index->groups[10]->materials[0]->data = summer0_iv;
++ index->groups[10]->materials[1]->name = builtin_material_names[362];
++ index->groups[10]->materials[1]->data = summer1_iv;
++ index->groups[10]->materials[2]->name = builtin_material_names[363];
++ index->groups[10]->materials[2]->data = summer2_iv;
++ index->groups[10]->materials[3]->name = builtin_material_names[364];
++ index->groups[10]->materials[3]->data = summer3_iv;
++ index->groups[10]->materials[4]->name = builtin_material_names[365];
++ index->groups[10]->materials[4]->data = summer4_iv;
++ index->groups[10]->materials[5]->name = builtin_material_names[366];
++ index->groups[10]->materials[5]->data = summer5_iv;
++ index->groups[10]->materials[6]->name = builtin_material_names[367];
++ index->groups[10]->materials[6]->data = summer6_iv;
++ index->groups[10]->materials[7]->name = builtin_material_names[368];
++ index->groups[10]->materials[7]->data = summer7_iv;
++ index->groups[10]->materials[8]->name = builtin_material_names[369];
++ index->groups[10]->materials[8]->data = summer8_iv;
++ index->groups[10]->materials[9]->name = builtin_material_names[370];
++ index->groups[10]->materials[9]->data = summer9_iv;
++ index->groups[10]->materials[10]->name = builtin_material_names[371];
++ index->groups[10]->materials[10]->data = summer10_iv;
++ index->groups[10]->materials[11]->name = builtin_material_names[372];
++ index->groups[10]->materials[11]->data = summer11_iv;
++ index->groups[10]->materials[12]->name = builtin_material_names[373];
++ index->groups[10]->materials[12]->data = summer12_iv;
++ index->groups[10]->materials[13]->name = builtin_material_names[374];
++ index->groups[10]->materials[13]->data = summer13_iv;
++ index->groups[10]->materials[14]->name = builtin_material_names[375];
++ index->groups[10]->materials[14]->data = summer14_iv;
++ index->groups[10]->materials[15]->name = builtin_material_names[376];
++ index->groups[10]->materials[15]->data = summer15_iv;
++ index->groups[10]->materials[16]->name = builtin_material_names[377];
++ index->groups[10]->materials[16]->data = summer16_iv;
++ index->groups[10]->materials[17]->name = builtin_material_names[378];
++ index->groups[10]->materials[17]->data = summer17_iv;
++ index->groups[10]->materials[18]->name = builtin_material_names[379];
++ index->groups[10]->materials[18]->data = summer18_iv;
++ index->groups[10]->materials[19]->name = builtin_material_names[380];
++ index->groups[10]->materials[19]->data = summer19_iv;
++ index->groups[10]->materials[20]->name = builtin_material_names[381];
++ index->groups[10]->materials[20]->data = summer20_iv;
++ index->groups[10]->materials[21]->name = builtin_material_names[382];
++ index->groups[10]->materials[21]->data = summer21_iv;
++ index->groups[10]->materials[22]->name = builtin_material_names[383];
++ index->groups[10]->materials[22]->data = summer22_iv;
++ index->groups[10]->materials[23]->name = builtin_material_names[384];
++ index->groups[10]->materials[23]->data = summer23_iv;
++ index->groups[10]->materials[24]->name = builtin_material_names[385];
++ index->groups[10]->materials[24]->data = summer24_iv;
++ index->groups[10]->materials[25]->name = builtin_material_names[386];
++ index->groups[10]->materials[25]->data = summer25_iv;
++ index->groups[10]->materials[26]->name = builtin_material_names[387];
++ index->groups[10]->materials[26]->data = summer26_iv;
++ index->groups[10]->materials[27]->name = builtin_material_names[388];
++ index->groups[10]->materials[27]->data = summer27_iv;
++ index->groups[10]->materials[28]->name = builtin_material_names[389];
++ index->groups[10]->materials[28]->data = summer28_iv;
++ index->groups[10]->materials[29]->name = builtin_material_names[390];
++ index->groups[10]->materials[29]->data = summer29_iv;
++ index->groups[10]->materials[30]->name = builtin_material_names[391];
++ index->groups[10]->materials[30]->data = summer30_iv;
++ index->groups[10]->materials[31]->name = builtin_material_names[392];
++ index->groups[10]->materials[31]->data = summer31_iv;
++ index->groups[10]->materials[32]->name = builtin_material_names[393];
++ index->groups[10]->materials[32]->data = summer32_iv;
++ index->groups[10]->materials[33]->name = builtin_material_names[394];
++ index->groups[10]->materials[33]->data = summer33_iv;
++ index->groups[10]->materials[34]->name = builtin_material_names[395];
++ index->groups[10]->materials[34]->data = summer34_iv;
++ index->groups[11]->name = builtin_material_names[396];
++ index->groups[11]->materials[0]->name = builtin_material_names[397];
++ index->groups[11]->materials[0]->data = tropical0_iv;
++ index->groups[11]->materials[1]->name = builtin_material_names[398];
++ index->groups[11]->materials[1]->data = tropical1_iv;
++ index->groups[11]->materials[2]->name = builtin_material_names[399];
++ index->groups[11]->materials[2]->data = tropical2_iv;
++ index->groups[11]->materials[3]->name = builtin_material_names[400];
++ index->groups[11]->materials[3]->data = tropical3_iv;
++ index->groups[11]->materials[4]->name = builtin_material_names[401];
++ index->groups[11]->materials[4]->data = tropical4_iv;
++ index->groups[11]->materials[5]->name = builtin_material_names[402];
++ index->groups[11]->materials[5]->data = tropical5_iv;
++ index->groups[11]->materials[6]->name = builtin_material_names[403];
++ index->groups[11]->materials[6]->data = tropical6_iv;
++ index->groups[11]->materials[7]->name = builtin_material_names[404];
++ index->groups[11]->materials[7]->data = tropical7_iv;
++ index->groups[11]->materials[8]->name = builtin_material_names[405];
++ index->groups[11]->materials[8]->data = tropical8_iv;
++ index->groups[11]->materials[9]->name = builtin_material_names[406];
++ index->groups[11]->materials[9]->data = tropical9_iv;
++ index->groups[11]->materials[10]->name = builtin_material_names[407];
++ index->groups[11]->materials[10]->data = tropical10_iv;
++ index->groups[11]->materials[11]->name = builtin_material_names[408];
++ index->groups[11]->materials[11]->data = tropical11_iv;
++ index->groups[11]->materials[12]->name = builtin_material_names[409];
++ index->groups[11]->materials[12]->data = tropical12_iv;
++ index->groups[11]->materials[13]->name = builtin_material_names[410];
++ index->groups[11]->materials[13]->data = tropical13_iv;
++ index->groups[11]->materials[14]->name = builtin_material_names[411];
++ index->groups[11]->materials[14]->data = tropical14_iv;
++ index->groups[11]->materials[15]->name = builtin_material_names[412];
++ index->groups[11]->materials[15]->data = tropical15_iv;
++ index->groups[11]->materials[16]->name = builtin_material_names[413];
++ index->groups[11]->materials[16]->data = tropical16_iv;
++ index->groups[11]->materials[17]->name = builtin_material_names[414];
++ index->groups[11]->materials[17]->data = tropical17_iv;
++ index->groups[11]->materials[18]->name = builtin_material_names[415];
++ index->groups[11]->materials[18]->data = tropical18_iv;
++ index->groups[11]->materials[19]->name = builtin_material_names[416];
++ index->groups[11]->materials[19]->data = tropical19_iv;
++ index->groups[11]->materials[20]->name = builtin_material_names[417];
++ index->groups[11]->materials[20]->data = tropical20_iv;
++ index->groups[11]->materials[21]->name = builtin_material_names[418];
++ index->groups[11]->materials[21]->data = tropical21_iv;
++ index->groups[11]->materials[22]->name = builtin_material_names[419];
++ index->groups[11]->materials[22]->data = tropical22_iv;
++ index->groups[11]->materials[23]->name = builtin_material_names[420];
++ index->groups[11]->materials[23]->data = tropical23_iv;
++ index->groups[11]->materials[24]->name = builtin_material_names[421];
++ index->groups[11]->materials[24]->data = tropical24_iv;
++ index->groups[11]->materials[25]->name = builtin_material_names[422];
++ index->groups[11]->materials[25]->data = tropical25_iv;
++ index->groups[11]->materials[26]->name = builtin_material_names[423];
++ index->groups[11]->materials[26]->data = tropical26_iv;
++ index->groups[11]->materials[27]->name = builtin_material_names[424];
++ index->groups[11]->materials[27]->data = tropical27_iv;
++ index->groups[11]->materials[28]->name = builtin_material_names[425];
++ index->groups[11]->materials[28]->data = tropical28_iv;
++ index->groups[11]->materials[29]->name = builtin_material_names[426];
++ index->groups[11]->materials[29]->data = tropical29_iv;
++ index->groups[11]->materials[30]->name = builtin_material_names[427];
++ index->groups[11]->materials[30]->data = tropical30_iv;
++ index->groups[11]->materials[31]->name = builtin_material_names[428];
++ index->groups[11]->materials[31]->data = tropical31_iv;
++ index->groups[11]->materials[32]->name = builtin_material_names[429];
++ index->groups[11]->materials[32]->data = tropical32_iv;
++ index->groups[11]->materials[33]->name = builtin_material_names[430];
++ index->groups[11]->materials[33]->data = tropical33_iv;
++ index->groups[11]->materials[34]->name = builtin_material_names[431];
++ index->groups[11]->materials[34]->data = tropical34_iv;
++ index->groups[12]->name = builtin_material_names[432];
++ index->groups[12]->materials[0]->name = builtin_material_names[433];
++ index->groups[12]->materials[0]->data = winter0_iv;
++ index->groups[12]->materials[1]->name = builtin_material_names[434];
++ index->groups[12]->materials[1]->data = winter1_iv;
++ index->groups[12]->materials[2]->name = builtin_material_names[435];
++ index->groups[12]->materials[2]->data = winter2_iv;
++ index->groups[12]->materials[3]->name = builtin_material_names[436];
++ index->groups[12]->materials[3]->data = winter3_iv;
++ index->groups[12]->materials[4]->name = builtin_material_names[437];
++ index->groups[12]->materials[4]->data = winter4_iv;
++ index->groups[12]->materials[5]->name = builtin_material_names[438];
++ index->groups[12]->materials[5]->data = winter5_iv;
++ index->groups[12]->materials[6]->name = builtin_material_names[439];
++ index->groups[12]->materials[6]->data = winter6_iv;
++ index->groups[12]->materials[7]->name = builtin_material_names[440];
++ index->groups[12]->materials[7]->data = winter7_iv;
++ index->groups[12]->materials[8]->name = builtin_material_names[441];
++ index->groups[12]->materials[8]->data = winter8_iv;
++ index->groups[12]->materials[9]->name = builtin_material_names[442];
++ index->groups[12]->materials[9]->data = winter9_iv;
++ index->groups[12]->materials[10]->name = builtin_material_names[443];
++ index->groups[12]->materials[10]->data = winter10_iv;
++ index->groups[12]->materials[11]->name = builtin_material_names[444];
++ index->groups[12]->materials[11]->data = winter11_iv;
++ index->groups[12]->materials[12]->name = builtin_material_names[445];
++ index->groups[12]->materials[12]->data = winter12_iv;
++ index->groups[12]->materials[13]->name = builtin_material_names[446];
++ index->groups[12]->materials[13]->data = winter13_iv;
++ index->groups[12]->materials[14]->name = builtin_material_names[447];
++ index->groups[12]->materials[14]->data = winter14_iv;
++ index->groups[12]->materials[15]->name = builtin_material_names[448];
++ index->groups[12]->materials[15]->data = winter15_iv;
++ index->groups[12]->materials[16]->name = builtin_material_names[449];
++ index->groups[12]->materials[16]->data = winter16_iv;
++ index->groups[12]->materials[17]->name = builtin_material_names[450];
++ index->groups[12]->materials[17]->data = winter17_iv;
++ index->groups[12]->materials[18]->name = builtin_material_names[451];
++ index->groups[12]->materials[18]->data = winter18_iv;
++ index->groups[12]->materials[19]->name = builtin_material_names[452];
++ index->groups[12]->materials[19]->data = winter19_iv;
++ index->groups[12]->materials[20]->name = builtin_material_names[453];
++ index->groups[12]->materials[20]->data = winter20_iv;
++ index->groups[12]->materials[21]->name = builtin_material_names[454];
++ index->groups[12]->materials[21]->data = winter21_iv;
++ index->groups[12]->materials[22]->name = builtin_material_names[455];
++ index->groups[12]->materials[22]->data = winter22_iv;
++ index->groups[12]->materials[23]->name = builtin_material_names[456];
++ index->groups[12]->materials[23]->data = winter23_iv;
++ index->groups[12]->materials[24]->name = builtin_material_names[457];
++ index->groups[12]->materials[24]->data = winter24_iv;
++ index->groups[12]->materials[25]->name = builtin_material_names[458];
++ index->groups[12]->materials[25]->data = winter25_iv;
++ index->groups[12]->materials[26]->name = builtin_material_names[459];
++ index->groups[12]->materials[26]->data = winter26_iv;
++ index->groups[12]->materials[27]->name = builtin_material_names[460];
++ index->groups[12]->materials[27]->data = winter27_iv;
++ index->groups[12]->materials[28]->name = builtin_material_names[461];
++ index->groups[12]->materials[28]->data = winter28_iv;
++ index->groups[12]->materials[29]->name = builtin_material_names[462];
++ index->groups[12]->materials[29]->data = winter29_iv;
++ index->groups[12]->materials[30]->name = builtin_material_names[463];
++ index->groups[12]->materials[30]->data = winter30_iv;
++ index->groups[12]->materials[31]->name = builtin_material_names[464];
++ index->groups[12]->materials[31]->data = winter31_iv;
++ index->groups[12]->materials[32]->name = builtin_material_names[465];
++ index->groups[12]->materials[32]->data = winter32_iv;
++ index->groups[12]->materials[33]->name = builtin_material_names[466];
++ index->groups[12]->materials[33]->data = winter33_iv;
++ index->groups[12]->materials[34]->name = builtin_material_names[467];
++ index->groups[12]->materials[34]->data = winter34_iv;
++#endif // ! WITH_STATIC_DEFAULTS
++} // setupBuiltinMaterials()
++
++// *************************************************************************
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoAnyMaterialListBuiltins.cpp.in.m4
+@@ -0,0 +1,141 @@
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// @configure_input@
++
++#if SO at GUI@_DEBUG
++static const char rcsid[] =
++ "$Id$";
++#endif // SO at GUI@_DEBUG
++
++/**************************************************************************
++ * IMPORTANT NOTICE
++ * Be aware that the file So at Gui@MaterialListBuiltins.cpp is generated from
++ * the file So at Gui@MaterialListBuiltins.cpp.m4, so changes has to be done in
++ * the source file with the m4 macros. The generation is done manually,
++ * since it is no point in making this project depend on the user having
++ * m4 installed.
++ **************************************************************************/
++
++#include <assert.h>
++#include <string.h>
++
++#include <Inventor/@Gui@/SoAnyMaterialList.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#ifdef WITH_STATIC_DEFAULTS
++#include <materials/materials.h>
++#endif // WITH_STATIC_DEFAULTS
++
++include(libm4.m4)
++divert(0)dnl
++// *************************************************************************
++define([SOANY_BUILTIN_MATERIAL_GROUPS], [13])dnl
++define([SOANY_BUILTIN_MATERIAL_GROUP_SIZE], [35])dnl
++
++#ifdef WITH_STATIC_DEFAULTS
++static
++const char *
++changequote(,)dnl
++builtin_material_names[] = {
++changequote([,])dnl
++define([matnum], 0)dnl
++m4_foreach([material], [artdeco, autumn, glass, metal, neon, rococo, santafe,
++ sheen, silky, spring, summer, tropical, winter], [dnl
++ "material",
++m4_for([num], 0, m4_eval(SOANY_BUILTIN_MATERIAL_GROUP_SIZE-1),,
++[dnl
++ "material.num",
++])dnl
++define([matnum], m4_eval(matnum+1))dnl
++])dnl
++ NULL
++}; // builtin_material_names
++#endif // WITH_STATIC_DEFAULTS
++
++// *************************************************************************
++
++/*!
++ \internal
++
++ This method fills in the So at Gui@MaterialDirectory structure with the builtin
++ material data.
++*/
++
++void
++SoAnyMaterialList::setupBuiltinMaterials( // private
++ So at Gui@MaterialDirectory * const index ) const
++{
++ assert( index != NULL );
++ index->numGroups = 0;
++ index->groups = NULL;
++#ifdef WITH_STATIC_DEFAULTS
++changequote(,)dnl
++ index->flags |= SO at GUI@_BUILTIN_MATERIALS;
++ index->numGroups = SOANY_BUILTIN_MATERIAL_GROUPS;
++ index->groups = new So at Gui@MaterialGroup * [ SOANY_BUILTIN_MATERIAL_GROUPS ];
++ for ( int i = 0; i < index->numGroups; i++ ) {
++ index->groups[i] = new So at Gui@MaterialGroup;
++ index->groups[i]->numMaterials = SOANY_BUILTIN_MATERIAL_GROUP_SIZE;
++ index->groups[i]->materials = new So at Gui@Material * [ SOANY_BUILTIN_MATERIAL_GROUP_SIZE ];
++ for ( int j = 0; j < SOANY_BUILTIN_MATERIAL_GROUP_SIZE; j++ ) {
++ index->groups[i]->materials[j] = new So at Gui@Material;
++ }
++ }
++
++changequote([,])dnl
++define([matnum], 0)dnl
++m4_foreach([material], [artdeco, autumn, glass, metal, neon, rococo, santafe,
++ sheen, silky, spring, summer, tropical, winter], [dnl
++changequote(<,>)dnl
++ index->groups[matnum]->name = builtin_material_names[m4_eval(matnum*(SOANY_BUILTIN_MATERIAL_GROUP_SIZE+1))];
++changequote([,])dnl
++m4_for([num], 0, m4_eval(SOANY_BUILTIN_MATERIAL_GROUP_SIZE-1),,
++[changequote(<,>)dnl
++ index->groups[matnum]->materials[num]->name = builtin_material_names[m4_eval(matnum*(SOANY_BUILTIN_MATERIAL_GROUP_SIZE+1)+num+1)];
++ index->groups[matnum]->materials[num]->data = material<>num<>_iv;
++changequote([,])dnl
++])dnl
++define([matnum], m4_eval(matnum+1))dnl
++])dnl
++#endif // ! WITH_STATIC_DEFAULTS
++} // setupBuiltinMaterials()
++
++// *************************************************************************
++
++#if SO at GUI@_DEBUG
++static const char * getSoAnyMaterialListBuiltinsRCSId(void) { return rcsid; }
++#endif // SO at GUI@_DEBUG
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGui.h.in
+@@ -0,0 +1,216 @@
++#ifndef SO at GUI@_H
++#define SO at GUI@_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++// FIXME: use configure defines for the header files.
++// 20020613 mortene.
++
++#ifdef __COIN_SOQT__
++
++#if QT_VERSION >= 0x040000
++#include <QtCore/QObject>
++#else
++#include <qobject.h>
++#endif
++
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++#include <X11/Intrinsic.h>
++#include <Xm/Xm.h>
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++// Fetch stdlib.h, so NULL is defined before glib.h is (indirectly)
++// included. Otherwise we get a compile error with KCC on some
++// systems.
++#include <stdlib.h>
++#include <gtk/gtk.h>
++class SoGtkComponent;
++class SbPList;
++#endif // __COIN_SOGTK__
++#ifdef __COIN_SOWIN__
++#include <windows.h>
++#endif // __COIN_SOWIN__
++
++#include <Inventor/SbBasic.h>
++#include <Inventor/SbLinear.h>
++#include <Inventor/SbString.h>
++#include <Inventor/SoDB.h>
++#include <Inventor/errors/SoDebugError.h>
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@
++{
++
++public:
++ static @WIDGET@ init(const char * appname, const char * classname = "So at Gui@");
++ static @WIDGET@ init(int & argc, char ** argv,
++ const char * appname, const char * classname = "So at Gui@");
++ static void init(@WIDGET@ toplevelwidget);
++
++ static void mainLoop(void);
++ static void exitMainLoop(void);
++ static void done(void);
++
++ static @WIDGET@ getTopLevelWidget(void);
++ static @WIDGET@ getShellWidget(const @WIDGET@ w);
++
++ static void show(@WIDGET@ const widget);
++ static void hide(@WIDGET@ const widget);
++
++ static void setWidgetSize(@WIDGET@ const widget, const SbVec2s size);
++ static SbVec2s getWidgetSize(const @WIDGET@ widget);
++
++ static void createSimpleErrorDialog(@WIDGET@ widget,
++ const char * title,
++ const char * string1,
++ const char * string2 = NULL);
++
++ static void getVersionInfo(int * major = NULL,
++ int * minor = NULL,
++ int * micro = NULL);
++ static const char * getVersionString(void);
++ static const char * getVersionToolkitString(void);
++
++ enum FatalErrors {
++ UNSPECIFIED_ERROR = 0,
++ NO_OPENGL_CANVAS,
++ INTERNAL_ASSERT
++ };
++ typedef void FatalErrorCB(const SbString errmsg, So at Gui@::FatalErrors errcode,
++ void * userdata);
++ static FatalErrorCB * setFatalErrorHandler(So at Gui@::FatalErrorCB * cb,
++ void * userdata);
++
++ static SbBool isDebugLibrary(void);
++ static SbBool isCompatible(unsigned int major, unsigned int minor);
++
++ enum ABIType { DLL, LIB, UNKNOWN };
++ static ABIType getABIType(void);
++
++ static void lockGL(void);
++ static void unlockGL(void);
++
++private:
++ // Since the class consists solely of static functions, hide the
++ // default constructor and the destructor so nobody can instantiate
++ // it.
++ So at Gui@(void);
++ virtual ~So at Gui@();
++
++ friend class SoGuiP;
++ friend class So at Gui@P;
++
++
++ // FIXME!: audit and remove as much as possible of the remaining
++ // toolkit specific parts below. 20020117 mortene.
++
++#ifdef __COIN_SOWIN__
++public:
++ static void doIdleTasks(void);
++#endif // __COIN_SOWIN__
++
++#ifdef __COIN_SOXT__
++public:
++ static void nextEvent(XtAppContext, XEvent *);
++ static Boolean dispatchEvent(XEvent * event);
++ static XtAppContext getAppContext(void);
++ static Display * getDisplay(void);
++ static XmString encodeString(const char * const str);
++ static char * decodeString(XmString xstring);
++ static void getPopupArgs(Display * display, int screen,
++ ArgList args, int * n);
++
++ static void registerColormapLoad(Widget widget, Widget shell);
++ static void addColormapToShell(Widget widget, Widget shell);
++ static void removeColormapFromShell(Widget widget, Widget shell);
++
++ static void addExtensionEventHandler(Widget widget,
++ int eventType, XtEventHandler proc,
++ XtPointer clientData);
++ static void removeExtensionEventHandler(Widget widget,
++ int eventType, XtEventHandler proc,
++ XtPointer clientData);
++
++protected:
++ static void getExtensionEventHandler(XEvent * event, Widget & widget,
++ XtEventHandler & proc,
++ XtPointer & clientData);
++#endif // __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++public:
++ friend class SoGtkComponent;
++ enum SoGtkComponentAction { CREATION, DESTRUCTION, CHANGE };
++ typedef void SoGtkComponentActionCallback(SoGtkComponent *, SoGtk::SoGtkComponentAction, void *);
++
++ static void addComponentActionCallback(SoGtkComponentActionCallback *, void *);
++ static void removeComponentActionCallback(SoGtkComponentActionCallback *, void *);
++
++ static int getComponents(SbPList & components);
++
++protected:
++ static void invokeComponentActionCallbacks(SoGtkComponent * component,
++ SoGtkComponentAction action);
++
++ static gint componentCreation(SoGtkComponent * component);
++ static gint componentDestruction(SoGtkComponent * component);
++ static gint componentChange(SoGtkComponent * component);
++
++private:
++ static gint timerSensorCB(gpointer data);
++ static gint idleSensorCB(gpointer data);
++ static gint delaySensorCB(gpointer data);
++
++ static GtkWidget * mainWidget;
++ static SbPList * components;
++ static SbPList * component_callbacks;
++#endif // __COIN_SOGTK__
++};
++
++// *************************************************************************
++// Here's something InventorWin provides for convenience. Belongs more
++// in the application code domain, imo, but we provide these macros
++// for better compile time compatibility with InventorWin. -mortene
++
++#define SO at GUI@_ENTER_GL_SECTION() do { So at Gui@::lockGL(); } while(FALSE)
++#define SO at GUI@_LEAVE_GL_SECTION() do { So at Gui@::unlockGL(); } while(FALSE)
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiBasic.h.in
+@@ -0,0 +1,153 @@
++#ifndef SO at GUI@_BASIC_H
++#define SO at GUI@_BASIC_H
++
++// NB: this is not a pure configure-input file, it's also a config header...
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// *************************************************************************
++
++/* Some useful inline template functions:
++ * So at Gui@Min(Val1, Val2) - returns minimum value
++ * So at Gui@Max(Val1, Val2) - returns maximum value
++ * So at Gui@Clamp(Val, Min, Max) - returns clamped value
++ * So at Gui@Swap(Val1, Val2) - swaps the two values (no return value)
++ */
++
++template <class Type>
++inline Type So at Gui@Abs(Type Val) {
++ return (Val < 0) ? -Val : Val;
++}
++
++template <class Type>
++inline Type So at Gui@Min(Type a, Type b) {
++ return (b < a) ? b : a;
++}
++
++template <class Type>
++inline Type So at Gui@Max(Type a, Type b) {
++ return (b > a) ? b : a;
++}
++
++template <class Type>
++inline Type So at Gui@Clamp(Type val, Type min, Type max) {
++ return So at Gui@Max(min, So at Gui@Min(max, val));
++}
++
++template <class Type>
++inline void So at Gui@Swap(Type & a, Type & b) {
++ Type t = a; a = b; b = t;
++}
++
++// *************************************************************************
++
++#define __COIN_SO at GUI@__
++
++#if ! defined(SO at GUI@_MAJOR_VERSION)
++#undef SO at GUI@_MAJOR_VERSION
++#endif /* ! SO at GUI@_MAJOR_VERSION */
++#if ! defined(SO at GUI@_MINOR_VERSION)
++#undef SO at GUI@_MINOR_VERSION
++#endif /* ! SO at GUI@_MINOR_VERSION */
++#if ! defined(SO at GUI@_MICRO_VERSION)
++#undef SO at GUI@_MICRO_VERSION
++#endif /* ! SO at GUI@_MICRO_VERSION */
++#if ! defined(SO at GUI@_BETA_VERSION)
++#undef SO at GUI@_BETA_VERSION
++#endif /* ! SO at GUI@_BETA_VERSION */
++#if ! defined(SO at GUI@_VERSION)
++#undef SO at GUI@_VERSION
++#endif /* ! SO at GUI@_VERSION */
++
++// *************************************************************************
++
++/* Precaution to avoid an error easily made by the application programmer. */
++#ifdef SO at GUI@_DLL_API
++# error Leave the internal SO at GUI@_DLL_API define alone.
++#endif /* SO at GUI@_DLL_API */
++
++/*
++ On MSWindows platforms, one of these defines must always be set when
++ building application programs:
++
++ - "SO at GUI@_DLL", when the application programmer is using the
++ library in the form of a dynamic link library (DLL)
++
++ - "SO at GUI@_NOT_DLL", when the application programmer is using the
++ library in the form of a static object library (LIB)
++
++ Note that either SO at GUI@_DLL or SO at GUI@_NOT_DLL _must_ be defined by
++ the application programmer on MSWindows platforms, or else the
++ #error statement will hit. Set up one or the other of these two
++ defines in your compiler environment according to how the library
++ was built -- as a DLL (use "SO at GUI@_DLL") or as a LIB (use
++ "SO at GUI@_NOT_DLL").
++
++ (Setting up defines for the compiler is typically done by either
++ adding something like "/DSO at GUI@_DLL" to the compiler's argument
++ line (for command-line build processes), or by adding the define to
++ the list of preprocessor symbols in your IDE GUI (in the MSVC IDE,
++ this is done from the "Project"->"Settings" menu, choose the "C/C++"
++ tab, then "Preprocessor" from the dropdown box and add the
++ appropriate define)).
++
++ It is extremely important that the application programmer uses the
++ correct define, as using "SO at GUI@_NOT_DLL" when "SO at GUI@_DLL" is
++ correct is likely to cause mysterious crashes.
++ */
++#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
++# ifdef SO at GUI@_INTERNAL
++# ifdef SO at GUI@_MAKE_DLL
++# define SO at GUI@_DLL_API __declspec(dllexport)
++# endif /* SO at GUI@_MAKE_DLL */
++# else /* !SO at GUI@_INTERNAL */
++# ifdef SO at GUI@_DLL
++# define SO at GUI@_DLL_API __declspec(dllimport)
++# else /* !SO at GUI@_DLL */
++# ifndef SO at GUI@_NOT_DLL
++# error Define either SO at GUI@_DLL or SO at GUI@_NOT_DLL as appropriate for your linkage! See Inventor/@Gui@/So at Gui@Basic.h for further instructions.
++# endif /* SO at GUI@_NOT_DLL */
++# endif /* !SO at GUI@_DLL */
++# endif /* !SO at GUI@_MAKE_DLL */
++#endif /* Microsoft Windows */
++
++/* Empty define to avoid errors when _not_ compiling an MSWindows DLL. */
++#ifndef SO at GUI@_DLL_API
++# define SO at GUI@_DLL_API
++#endif /* !SO at GUI@_DLL_API */
++
++#ifndef GUI_TOOLKIT_VERSION
++#define GUI_TOOLKIT_VERSION ""
++#endif /* GUI_TOOLKIT_VERSION */
++
++#endif // ! SO at GUI@_BASIC_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiColorEditor.h.in
+@@ -0,0 +1,39 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This include file just forwards to the one under the editors/
++// directory. Done to be compatible with old SGI InventorXt code and
++// TGS SoWin and SoQt code.
++
++#include <Inventor/@Gui@/editors/So at Gui@ColorEditor.h>
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiCommon.cpp.in
+@@ -0,0 +1,682 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/* For the Doxygen tool. */
++
++/*! \defgroup misc Miscellaneous Classes */
++/*! \defgroup devices @Gui@ Device Classes */
++/*! \defgroup components @Gui@ Components */
++/*! \defgroup viewers @Gui@ Viewer Components */
++
++
++// FIXME: the code example shouldn't be duplicated here -- it's
++// already part of the SoQt mainpage-doc. 20020806 mortene.
++
++/*!
++ \class So at Gui@ So at Gui@.h Inventor/@Gui@/So at Gui@.h
++ \brief The So at Gui@ class takes care of @Gui@ initialization and event dispatching.
++ \ingroup misc
++
++ This is the "application-wide" class with solely static methods
++ handling initialization and event processing tasks. You must use
++ this class in any application built on top of the So at Gui@
++ library.
++
++ Typical usage is as follows (complete application code):
++
++ \code
++ #include <Inventor/@Gui@/So at Gui@.h>
++ #include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++ #include <Inventor/nodes/SoBaseColor.h>
++ #include <Inventor/nodes/SoCone.h>
++ #include <Inventor/nodes/SoSeparator.h>
++
++ int
++ main(int argc, char ** argv)
++ {
++ // Initialize So at Gui@ and Inventor API libraries. This returns a main
++ // window to use.
++ @WIDGET@ mainwin = So at Gui@::init(argc, argv, argv[0]);
++
++ // Make a dead simple scene graph, only containing a single
++ // yellow cone under the scenegraph root.
++ SoSeparator * root = new SoSeparator;
++ root->ref();
++
++ SoBaseColor * col = new SoBaseColor;
++ col->rgb = SbColor(1, 1, 0);
++ root->addChild(col);
++
++ root->addChild(new SoCone);
++
++ // Use one of the convenient viewer classes.
++ So at Gui@ExaminerViewer * eviewer = new So at Gui@ExaminerViewer(mainwin);
++ eviewer->setSceneGraph(root);
++ eviewer->show();
++
++ // Pop up the main window.
++ So at Gui@::show(mainwin);
++ // Loop until exit.
++ So at Gui@::mainLoop();
++
++ // Clean up resources.
++ delete eviewer;
++ root->unref();
++ So at Gui@::done();
++
++ return 0;
++ }
++ \endcode
++
++ And voila:
++
++ <center>
++ <img src="http://doc.coin3d.org/images/SoLibs/general/sogui-class-example.png">
++ </center>
++
++ \sa So at Gui@Component
++*/
++
++// *************************************************************************
++
++#include <stdlib.h>
++#include <string.h>
++
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/SoGuiP.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++#include <Inventor/SoDB.h>
++#include <Inventor/SoInteraction.h>
++#include <Inventor/nodekits/SoNodeKit.h>
++
++#include <string>
++
++// *************************************************************************
++
++// Default constructor and the destructor is private (So at Gui@ class
++// consists solely of static functions).
++So at Gui@::So at Gui@(void) { }
++So at Gui@::~So at Gui@() { }
++
++// *************************************************************************
++
++cc_mutex * SoGuiP::gllockmutex = NULL;
++
++// *************************************************************************
++
++void
++SoGuiP::commonInit(void)
++{
++ SoDB::init();
++ SoNodeKit::init();
++ SoInteraction::init();
++
++ SoAny::init();
++
++ SoGuiP::gllockmutex = cc_mutex_construct();
++}
++
++void
++SoGuiP::commonCleanup(void)
++{
++ cc_mutex_destruct(SoGuiP::gllockmutex);
++}
++
++// *************************************************************************
++
++/*!
++ This function initializes the So at Gui@ library, as well as the
++ Inventor API. The latter is done by calling \a SoDB::init(), \a
++ SoNodeKit::init() and \a SoInteraction::init().
++
++ The returned @WIDGET@ is a toplevel shell widget for the
++ application, which can be used as a shell for the main component.
++
++ This method is provided for easier porting / compatibility with the
++ original SGI Inventor InventorXt library. It just adds dummy \a argc
++ and \a argv arguments and calls the So at Gui@::init() method below.
++*/
++ at WIDGET@
++So at Gui@::init(const char * appname, const char * classname)
++{
++ // If this is SoQt, Qt will keep a reference to the appname string
++ // -- so make it guaranteed permanent.
++ char * buf = NULL;
++ if (appname != NULL) {
++ size_t appname_len = strlen(appname);
++ buf = (char *)new char[appname_len+1]; // FIXME: minor memleak, free on app-exit. 20020117 mortene.
++ (void)strncpy(buf, appname, appname_len);
++ buf[appname_len] = '\0';
++ }
++
++ // FIXME: Both SoGui_init_argc/argv need to be static to workaround
++ // a compiler optimization memory corruption bug (observed with gcc
++ // 4.1.1 using -O2 in combination with qt-4.2.x), which would lead
++ // to a segfault. 20070528 tamer.
++
++ // Fake argc and argv setup, forward to real init routine.
++ static int SoGui_init_argc = (buf != NULL) ? 1 : 0;
++ static char * SoGui_init_argv[2]; // use static array to avoid memory corruption in Qt
++ SoGui_init_argv[0] = buf;
++ SoGui_init_argv[1] = NULL;
++
++ return So at Gui@::init(SoGui_init_argc, SoGui_init_argv, appname, classname);
++}
++
++/*!
++ \fn @WIDGET@ So at Gui@::init(int & argc, char ** argv, const char * appname, const char * classname)
++
++ This function initializes the So at Gui@ library, as well as the
++ Inventor API. The latter is done by calling \a SoDB::init(), \a
++ SoNodeKit::init() and \a SoInteraction::init().
++
++ Creates an application framework and constructs and returns a main
++ widget for you.
++
++ The returned @WIDGET@ is a toplevel shell widget for the
++ application, which can be used as a shell for the main component.
++*/
++
++/*!
++ \fn void So at Gui@::init(@WIDGET@ toplevelwidget)
++
++ This function initializes the So at Gui@ library, as well as the
++ Inventor API. The latter is done by calling \a SoDB::init(), \a
++ SoNodeKit::init() and \a SoInteraction::init().
++
++ Assumes you are creating your own application framework and main
++ widget. \a toplevelwidget should be your application's main widget.
++*/
++
++/*!
++ \fn void So at Gui@::done(void)
++
++ Cleans up all static data allocated by the So at Gui@ library on
++ initialization.
++
++ This functions calls SoDB::finish() which means that no Coin classes
++ should be used after it has been called.
++
++ <!-- (Disabled: see FIXME in SoQt.cpp:855)
++ Is called implicitly from the end of So at Gui@::mainLoop(), so the
++ application programmer should not call it explicitly unless she
++ has taken control over the native event loop herself, and is
++ therefore not using So at Gui@::mainLoop().
++
++ (Even then it is usually not necessary to call this method, as the
++ operating system should take care of cleaning up resource use when
++ an application exits. This method is mainly provided as a manner to
++ be able to clean up in "unusual" run-time environments, for instance
++ if So at Gui@ is used as a component in a browser plug-in.)
++ -->
++
++ It should never be invoked more than \e once, and that
++ is just before application exit, as it deallocates \e static data
++ allocated as "one-off" operations in So at Gui@::init().
++
++ NOTE: done() is not present in the original API for SGI's InventorXt
++ library.
++*/
++
++/*!
++ \fn void So at Gui@::mainLoop(void)
++
++ This is the event dispatch loop.
++
++ It doesn't return until application exit is somehow forced, either
++ programmatically from the relevant API-call of the native toolkit,
++ or when the user closes the application's main widget.
++
++ After the main loop has finished execution, call So at Gui@::done() to clean
++ up static data.
++
++ <!-- (Disabled: see FIXME in SoQt.cpp:855)
++ An important note: be careful about how you handle
++ So at Gui@Component-derived objects after the application control returns
++ from mainLoop(), as So at Gui@ will then have been "cleaned up" with
++ regards to various internal resources. So doing for instance
++ something like this:
++
++ \code
++ So at Gui@::mainLoop();
++ viewer->hide();
++ \endcode
++
++ ..spells "undefined behavior, expect a crash".
++
++ \e Deleting a component after mainLoop() returns is allowed, though,
++ and also necessary to avoid getting reports of possible memory leaks
++ from memleak checkers.
++ -->
++*/
++
++/*!
++ \fn void So at Gui@::exitMainLoop(void)
++
++ This function will make the main event loop finish looping.
++
++ NOTE: exitMainLoop() is not present in the original API for SGI's
++ InventorXt library.
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@::getTopLevelWidget(void)
++
++ Returns the @WIDGET@ which is the main widget for the
++ application. When this widget gets closed, So at Gui@::mainLoop() will
++ return (unless the close event is caught by the user).
++
++ \sa getShellWidget()
++*/
++
++// *************************************************************************
++
++/*!
++ This method will fill in the integers pointed to by the arguments
++ with the corresponding part of the version release number of the
++ So at Gui@ library.
++
++ A \c NULL pointer will make that part of the version number be ignored.
++
++ This method is not part of the original InventorXt API from SGI.
++*/
++void
++So at Gui@::getVersionInfo(int * major, int * minor, int * micro)
++{
++ if (major) { *major = SO at GUI@_MAJOR_VERSION; }
++ if (minor) { *minor = SO at GUI@_MINOR_VERSION; }
++ if (micro) { *micro = SO at GUI@_MICRO_VERSION; }
++}
++
++/*!
++ This method returns a string containing the version id of the
++ library.
++
++ This method is not part of the original InventorXt API from SGI.
++*/
++const char *
++So at Gui@::getVersionString(void)
++{
++ static const char version[] = SO at GUI@_VERSION;
++ return version;
++}
++
++/*!
++ This method returns a string containing the version id of the
++ @Gui@ toolkit the So at Gui@ library is linked against.
++
++ This method is not part of the original InventorXt API from SGI.
++*/
++#ifdef SOWIN_INTERNAL
++namespace Win32 {
++ std::string GetOSDisplayString();
++};
++#endif
++
++const char *
++So at Gui@::getVersionToolkitString(void)
++{
++#ifdef SOWIN_INTERNAL
++ static std::string toolkit_version = Win32::GetOSDisplayString();
++#else
++ static std::string toolkit_version = GUI_TOOLKIT_VERSION;
++#endif
++ return toolkit_version.c_str();
++}
++
++// *************************************************************************
++
++/*!
++ This method locks other threads out from a code section until the
++ caller thread invokes So at Gui@::unlockGL().
++
++ It is meant to protect several threads invoking OpenGL calls in
++ parallell, in case the underlying OpenGL implementation is not
++ multi-thread safe.
++
++ For convenience, the function can be invoked through the
++ SO at GUI@_ENTER_GL_SECTION().
++
++ This method is not part of the original InventorXt API from SGI.
++*/
++void
++So at Gui@::lockGL(void)
++{
++ assert(SoGuiP::gllockmutex);
++
++ cc_mutex_lock(SoGuiP::gllockmutex);
++}
++
++/*!
++ See documentation for So at Gui@::lockGL().
++
++ For convenience, the function can be invoked through the
++ SO at GUI@_LEAVE_GL_SECTION().
++
++ This method is not part of the original InventorXt API from SGI.
++*/
++void
++So at Gui@::unlockGL(void)
++{
++ cc_mutex_unlock(SoGuiP::gllockmutex);
++}
++
++// *************************************************************************
++
++/*!
++ \typedef void So at Gui@::FatalErrorCB(const SbString errmsg, So at Gui@::FatalErrors errcode, void * userdata)
++
++ An application function callback for handling fatal errors should be
++ of this type.
++
++ The first argument is an error message in English describing the
++ details of the error. The second argument is an error code used so
++ the application can identify specific conditions. The third argument
++ is the userdata pointer passed in to So at Gui@::setFatalErrorHandler().
++*/
++
++/*!
++ \enum So at Gui@::FatalErrors
++ Numerical identifiers for classifying the different kinds of possible
++ fatal errors.
++*/
++
++/*!
++ \var So at Gui@::FatalErrors So at Gui@::NO_OPENGL_CANVAS
++
++ Could not construct \e any valid OpenGL canvas. Something is very
++ wrong on the client system.
++*/
++/*!
++ \var So at Gui@::FatalErrors So at Gui@::INTERNAL_ASSERT
++
++ An internal error condition that should never happen was
++ detected. The most likely cause of this is programmering errors
++ within the So at Gui@ library itself.
++*/
++/*!
++ \var So at Gui@::FatalErrors So at Gui@::UNSPECIFIED_ERROR
++
++ Signifies that we were not able to specify in any greater detail the
++ error condition that came up.
++*/
++
++/*!
++ Set up a callback to invoke in the case of unexpected fatal error
++ conditions within the So at Gui@ library.
++
++ Almost any error condition within the library is handled in a robust
++ way through return values indicating errors for the offending calls,
++ but there are a few cases that are impossible to handle without
++ seriously crippling the functionality.
++
++ (One example is if we fail to find \e any way of making a valid
++ OpenGL canvas. This is an indication that something is seriously
++ wrong on the end-user's system, and the So at Gui@ library will not work
++ properly.)
++
++ In the case of a fatal error, it is expected that the given
++ application callback function communicates the problem to the
++ end-user and then either exits the application or at least refrains
++ from using any part of the So at Gui@ library.
++
++ If no callback is explicitly set up by the application, the So at Gui@
++ library will display an error message to the end-user and then exit
++ the application.
++
++ When setting a callback, this method returns a pointer to the
++ previous callback function, or \c NULL if none.
++
++ (This is an extension versus the original SGI InventorXt library
++ API.)
++
++
++ On a related note, be aware that the end-user will still be notified
++ about non-fatal errors and warning messages through a dialog box. If
++ you want to handle these yourself, or if you don't want your
++ end-user to see any of these non-critical messages, you will also
++ need to install an error handler callback function on the Coin
++ library itself:
++
++ \code
++ SoDebugError::setHandlerCallback(myErrorHandlerCB, myCBUserData);
++ \endcode
++
++ (Please also see the documentation of
++ SoDebugError::setHandlerCallback().)
++
++ */
++So at Gui@::FatalErrorCB *
++So at Gui@::setFatalErrorHandler(So at Gui@::FatalErrorCB * cb, void * userdata)
++{
++ return SoAny::si()->setFatalErrorHandler(cb, userdata);
++}
++
++// *************************************************************************
++
++/*!
++ Returns \c TRUE if this binary version of the So at Gui@ library was
++ compiled with debug settings on.
++
++ This method was not part of the original SGI InventorXt library, but
++ is an extension specific to the Coin project.
++*/
++SbBool
++So at Gui@::isDebugLibrary(void)
++{
++ return SO at GUI@_DEBUG != 0 ? TRUE : FALSE;
++}
++
++/*!
++ Returns \c TRUE if this version of the So at Gui@ library has an
++ Application Binary Interface compatible with the given version.
++
++ This method was not part of the original SGI InventorXt library, but
++ is an extension specific to the Coin project.
++*/
++SbBool
++So at Gui@::isCompatible(unsigned int major, unsigned int minor)
++{
++ if (major != SO at GUI@_MAJOR_VERSION) { return FALSE; }
++ if (minor > SO at GUI@_MINOR_VERSION) { return FALSE; }
++ return TRUE;
++}
++
++/*!
++ \enum So at Gui@::ABIType
++ Numerical identifiers to identify how the library was built.
++*/
++/*!
++ \var So at Gui@::ABIType So at Gui@::DLL
++ The So at Gui@ library was built as a dynamic link library (aka "shared
++ library").
++*/
++/*!
++ \var So at Gui@::ABIType So at Gui@::LIB
++ The So at Gui@ library was built as a static library.
++*/
++/*!
++ \var So at Gui@::ABIType So at Gui@::UNKNOWN
++ The So at Gui@ introspection mechanisms can not decide how the library
++ was built.
++*/
++
++
++/*!
++ Returns an indication on how the library was compiled: as a dynamic
++ library, or as a static library.
++
++ This method was not part of the original SGI InventorXt library, but
++ is an extension specific to the Coin project.
++*/
++So at Gui@::ABIType
++So at Gui@::getABIType(void)
++{
++ // FIXME: replace this ugly shit with a configure-check to test if
++ // we're on a DLL-capable platform. 20020118 mortene.
++#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
++#ifdef SO at GUI@_MAKE_DLL
++ return So at Gui@::DLL;
++#else
++ return So at Gui@::LIB;
++#endif
++#endif
++ // FIXME: this is rather lame, we have enough information in the
++ // configure / build process to always know whether we're building
++ // static or dynamic. 20020618 mortene.
++ return So at Gui@::UNKNOWN;
++}
++
++#if 0 // FIXME: not in use, see larsa's FIXME below. 20020617 mortene.
++
++// *************************************************************************
++// These sanity checks are designed to detect common pitfall errors for
++// Microsoft Windows linkage with So at Gui@ and Coin.
++
++// FIXME: use an "is-this-a-DLL-capable-platform" configure check
++// and remove the system "#if defined" tests below. 20011203 mortene.
++// FIXME: I disabled this because it wasn't inlined in the client app
++// but compiled into the library by MSVC++ and with SOWIN_DLL undefined,
++// the ABI test always tried the LIB_ABI path. 20020126 larsa
++#if 0 && (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__))
++#define SO at GUI@_SANITY_CHECK(forward_call) \
++ if (So at Gui@::isDebugLibrary() && \
++ SoDB::isInitialized()) \
++ SoDebugError::postWarning("So at Gui@::init", \
++ "unable to verify application linkage sanity " \
++ "because Open Inventor has already been " \
++ "initialized before So at Gui@::init call"); \
++ SO at GUI@_RUNTIME_SANITY_CHECK(); \
++ SO at GUI@_LINKSTYLE_SANITY_CHECK(); \
++ forward_call; \
++ SO at GUI@_LINKTIME_SANITY_CHECK()
++
++#define SO at GUI@_RUNTIME_SANITY_CHECK() \
++ do { \
++ if (!So at Gui@::isCompatible(SO at GUI@_MAJOR_VERSION, \
++ SO at GUI@_MINOR_VERSION)) \
++ So at Gui@::abort(SO at GUI@_RUNTIME_MISMATCH); \
++ } while (FALSE)
++
++#ifdef SO at GUI@_DLL
++#define SO at GUI@_LINKSTYLE_SANITY_CHECK() \
++ do { \
++ if (So at Gui@::getABIType() != SO at GUI@_DLL_ABI) \
++ So at Gui@::abort(SO at GUI@_LINKSTYLE_MISMATCH); \
++ } while (FALSE)
++#else
++#define SO at GUI@_LINKSTYLE_SANITY_CHECK() \
++ do { \
++ if (So at Gui@::getABIType() != SO at GUI@_LIB_ABI) \
++ So at Gui@::abort(SO at GUI@_LINKSTYLE_MISMATCH); \
++ } while (FALSE)
++#endif
++
++#define SO at GUI@_LINKTIME_SANITY_CHECK() \
++ do { \
++ if (!SoDB::isInitialized()) \
++ So at Gui@::abort(SO at GUI@_LINKTIME_MISMATCH); \
++ } while (FALSE)
++#else /* ! MS Windows */
++#define SO at GUI@_SANITY_CHECK(forward_call) \
++ forward_call
++#endif /* ! MS Windows */
++
++#endif // OBSOLETED
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Abort the application due to some kind of mismatch in the ABI
++// settings / configuration. This should hopefully help application
++// programmers avoid shooting themselves in the foot by controlling
++// certain run-time parameters in the client application versus what
++// is expected by the So at Gui@ library.
++//
++// If you're an application programmer, it is very likely that you
++// only need to consider this an internal library method.
++//
++// This method was not part of the original SGI InventorXt library,
++// but is an extension specific to the Coin project.
++void
++SoGuiP::abort(SoGuiP::ABIError error)
++{
++ switch (error) {
++ case SoGuiP::LINKTIME_MISMATCH:
++ So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++ "Detected linktime mismatch error.");
++ break;
++
++ case SoGuiP::LINKSTYLE_MISMATCH:
++ So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++ "Detected linkstyle mismatch error (DLL vs. LIB).");
++ break;
++
++ case SoGuiP::RUNTIME_MISMATCH:
++ So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++ "Detected runtime mismatch error (versioning and ABI compatibility).");
++ break;
++
++ default:
++ // FIXME: shouldn't this rather be an assert? 20020118 mortene.
++ So at Gui@::createSimpleErrorDialog(NULL, "Fatal Error",
++ "Unknown error in So at Gui@ :(");
++ break;
++ }
++
++ // FIXME: call fatal error handler in SoAny. 20020118 mortene.
++ exit(-1);
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++/*!
++ \fn void So at Gui@::createSimpleErrorDialog(@WIDGET@ widget, const char * title, const char * string1, const char * string2)
++
++
++ This is a convenient way for the application programmer to throw up
++ an obtrusive application-global error dialog.
++
++ If \a widget is \c NULL, the dialog will be modal for the whole
++ application (all windows will be blocked for input). If not,
++ only the window for the given \a widget will be blocked.
++
++ \a title is the title of the dialog box. \a string1 and \a string2
++ contains the text which will be shown in the dialog box.
++
++ There will only be a single "Ok" button for the user to press and
++ continue with the application.
++*/
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiComponent.h.in
+@@ -0,0 +1,174 @@
++#ifndef SO at GUI@_COMPONENT_H
++#define SO at GUI@_COMPONENT_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++
++#ifdef __COIN_SOQT__
++class QWidget;
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++#include <X11/Intrinsic.h>
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++#include <gtk/gtk.h>
++#endif // __COIN_SOGTK__
++#ifdef __COIN_SOWIN__
++#include <windows.h>
++#endif // __COIN_SOWIN__
++
++
++class So at Gui@Component;
++class So at Gui@Cursor;
++
++typedef void So at Gui@ComponentCB(void * user, So at Gui@Component * component);
++typedef void So at Gui@ComponentVisibilityCB(void * user, SbBool visible);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Component : public So at Gui@Object {
++ SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@Component, So at Gui@Object);
++
++public:
++ virtual ~So at Gui@Component();
++
++ virtual void show(void);
++ virtual void hide(void);
++
++ virtual void setComponentCursor(const So at Gui@Cursor & cursor);
++ static void setWidgetCursor(@WIDGET@ w, const So at Gui@Cursor & cursor);
++
++ SbBool isFullScreen(void) const;
++ SbBool setFullScreen(const SbBool onoff);
++
++ SbBool isVisible(void);
++ SbBool isTopLevelShell(void) const;
++
++ @WIDGET@ getWidget(void) const;
++ @WIDGET@ getBaseWidget(void) const;
++ @WIDGET@ getShellWidget(void) const;
++ @WIDGET@ getParentWidget(void) const;
++
++ void setSize(const SbVec2s size);
++ SbVec2s getSize(void) const;
++
++ void setTitle(const char * const title);
++ const char * getTitle(void) const;
++ void setIconTitle(const char * const title);
++ const char * getIconTitle(void) const;
++
++ const char * getWidgetName(void) const;
++ const char * getClassName(void) const;
++
++ void setWindowCloseCallback(So at Gui@ComponentCB * const func,
++ void * const user = NULL);
++ static So at Gui@Component * getComponent(@WIDGET@ widget);
++
++ static void initClasses(void);
++
++protected:
++ So at Gui@Component(@WIDGET@ const parent = NULL,
++ const char * const name = NULL,
++ const SbBool embed = TRUE);
++
++ virtual void afterRealizeHook(void);
++
++ // About the wrapping below: this variable was added after SoQt 1.0,
++ // and before SoXt 1.1. To be able to release SoQt 1.1 from this
++ // same branch, sizeof(SoQtComponent) needs to be the same as for
++ // SoQt 1.0, which means we can't add this variable for SoQt.
++#ifndef __COIN_SOQT__
++ SbBool firstRealize;
++#endif // __COIN_SOQT__
++
++ void setClassName(const char * const name);
++ void setBaseWidget(@WIDGET@ widget);
++
++ void registerWidget(@WIDGET@ widget);
++ void unregisterWidget(@WIDGET@ widget);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++ virtual void sizeChanged(const SbVec2s & size);
++
++ void addVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func,
++ void * const user = NULL);
++ void removeVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func,
++ void * const user = NULL);
++
++private:
++ class So at Gui@ComponentP * pimpl;
++ friend class SoGuiComponentP;
++ friend class So at Gui@ComponentP;
++
++ // FIXME!: audit and remove as much as possible of the remaining
++ // toolkit specific parts below. 20020117 mortene.
++
++#ifdef __COIN_SOXT__
++public:
++ Display * getDisplay(void);
++ void fitSize(const SbVec2s size);
++ // FIXME: I guess these should really be part of the common
++ // API. 20011012 mortene.
++ void addWindowCloseCallback(SoXtComponentCB * callback, void * closure = NULL);
++ void removeWindowCloseCallback(SoXtComponentCB * callback, void * closure = NULL);
++
++protected:
++ // FIXME: I guess this should perhaps be part of the common API?
++ // 20011012 mortene.
++ void invokeVisibilityChangeCallbacks(const SbBool enable) const;
++ void invokeWindowCloseCallbacks(void) const;
++ virtual void windowCloseAction(void);
++
++private:
++ // FIXME: get rid of this? 20011012 mortene.
++ static void event_handler(Widget, XtPointer, XEvent *, Boolean *);
++#endif // __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++protected:
++ virtual SbBool eventFilter(GtkWidget * object, GdkEvent * event);
++private:
++ static gint eventHandler(GtkWidget * object, GdkEvent * event, gpointer closure);
++#endif // __COIN_SOGTK__
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_COMPONENT_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiComponentCommon.cpp.in
+@@ -0,0 +1,549 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class So at Gui@Component So at Gui@Component.h Inventor/@Gui@/So at Gui@Component.h
++ \brief The So at Gui@Component class is the base class for all GUI components.
++
++ Components in the So at Gui@ component library all inherit this
++ abstract base class. It provides basic methods for setting and
++ querying about the relationship between the component object and its
++ underlying @Gui@ object(s).
++
++ Application programmers should not need to interface any code
++ against this class, unless they want to extend the So at Gui@ library
++ in entirely new directions. For making new viewer components, for
++ instance, other classes further down the inheritance hierarchy would
++ be better suited for subclassing.
++
++ Note that the relationship between all So at Gui@Component derived
++ classes and @Gui@ widgets is one of "has-A", \e not "is-A" --
++ i.e. So at Gui@Component \e contains a @WIDGET@, it doesn't derive from
++ or subclass it.
++*/
++
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/So at Gui@Component.h>
++#include <Inventor/@Gui@/So at Gui@ComponentP.h>
++
++#include <Inventor/SbPList.h>
++
++/*!
++ \fn void So at Gui@Component::initClasses(void)
++
++ This function initializes the type system for all the component
++ classes. It is called indirectly for you when you call
++ So at Gui@::init().
++
++ \sa So at Gui@::init(), So at Gui@Device::initClasses()
++*/
++
++/*!
++ \fn So at Gui@Component::So at Gui@Component(@WIDGET@ const parent, const char * const name, const SbBool embed)
++
++ This is a protected constructor, used only by derived classes.
++
++ The \a parent argument is the parent widget of the component. If
++ you don't supply a parent, the main window (the one given to or
++ returned from So at Gui@::init()) is used (and the \a embed argument is
++ considered to be \c FALSE).
++
++ The \a name argument is the name of the component. If you don't
++ supply one, the name will default to something, depending on the
++ inheritance hierarchy.
++
++ The \a embed argument tells wether the component should be embedded
++ in the \a parent widget or should create its own shell. This flag is
++ only checked if the \a parent widget argument is specified (not
++ \c NULL).
++
++ If you create a non-embedded component, the component will create
++ its own shell, which will be a toplevelshell type. If you embed the
++ component, the component will create a formwidget type widget inside
++ the \a parent widget, which you can get the handle of by calling
++ So at Gui@Component::getBaseWidget().
++*/
++
++/*!
++ \fn So at Gui@Component::~So at Gui@Component()
++
++ Destructor.
++*/
++
++/*!
++ \fn void So at Gui@Component::addVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func, void * const user)
++
++ Add a callback which will be called whenever the widget component
++ changes visibility status (because of iconification or
++ deiconification, for instance).
++
++ \sa removeVisibilityChangeCallback(), isVisible()
++*/
++
++/*!
++ \fn void So at Gui@Component::removeVisibilityChangeCallback(So at Gui@ComponentVisibilityCB * const func, void * const data)
++
++ Remove one of the callbacks from the list of visibility notification
++ callbacks.
++
++ \sa addVisibilityChangeCallback(), isVisible()
++*/
++
++/*!
++ \fn void So at Gui@Component::setClassName(const char * const name)
++
++ Set class name of component.
++
++ \sa getClassName(), componentClassName()
++*/
++
++/*!
++ \fn void So at Gui@Component::setBaseWidget(@WIDGET@ widget)
++
++ Set the core widget for this So at Gui@ component. It is important that
++ subclasses get this correct, as the widget set here will be the
++ widget returned from query methods.
++
++ \sa baseWidget()
++*/
++
++/*!
++ \fn void So at Gui@Component::show(void)
++
++ This will show the widget, de-iconifiying and raising it if
++ necessary.
++
++ \sa hide(), isVisible()
++*/
++
++/*!
++ \fn void So at Gui@Component::hide(void)
++
++ This will hide the widget.
++
++ \sa show(), isVisible()
++*/
++
++/*!
++ \fn SbBool So at Gui@Component::isVisible(void)
++
++ Returns visibility status on the widget. If any parents of this
++ widget or this widget itself is hidden, returns \c FALSE.
++
++ Note that a widget which is just obscured by other windows on the
++ desktop is not hidden in this sense, and \c TRUE will be returned.
++
++ \sa show(), hide()
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@Component::getWidget(void) const
++
++ Returns a pointer to the component's window system widget.
++
++ \sa getShellWidget(), getParentWidget()
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@Component::getBaseWidget(void) const
++
++ An So at Gui@Component may be composed of any number of widgets in
++ parent-children relationships in a tree structure with any depth.
++ This method will return the root widget in that tree.
++
++ \sa setBaseWidget()
++*/
++
++/*!
++ \fn SbBool So at Gui@Component::isTopLevelShell(void) const
++
++ Returns \c TRUE if this component is a toplevel shell, i.e. it has a
++ window representation on the desktop.
++
++ \sa getShellWidget()
++*/
++
++/*!
++ This method returns the shell widget of the component, but only if
++ it was created as a toplevel shell. \c NULL will be returned for
++ embedded components.
++
++ (The toplevel shell is the desktop window which contains the
++ component.)
++
++ To get the toplevel shell of embedded components, you can use the
++ So at Gui@::getShellWidget() method.
++
++ \sa isTopLevelShell(), getWidget()
++*/
++ at WIDGET@
++So at Gui@Component::getShellWidget(void) const
++{
++ @WIDGET@ w = this->getWidget();
++ // the below assert disables SoXt, so I've removed it for now
++ // 20031001 larsa
++ // assert(w == NULL && "widget not built yet!");
++ return (this->isTopLevelShell() && w) ? So at Gui@::getShellWidget(w) : NULL;
++}
++
++/*!
++ \fn @WIDGET@ So at Gui@Component::getParentWidget(void) const
++
++ Returns the widget which is the parent (i.e. contains) this
++ component's base widget.
++
++ \sa getWidget(), baseWidget(), isTopLevelShell()
++*/
++
++/*!
++ \fn void So at Gui@Component::setTitle(const char * const title)
++
++ Set the window title of this component. The title will appear on the
++ window title bar, if the component manages its own window.
++
++ \if SOQT_DOC
++
++ Note that there is one peculiarity to be aware of if you are using
++ the non-commercial version of Qt: only window titles with the
++ substring "Qt" in them are allowed (!), and attempts to set a window
++ title without this substring will simply be ignored.
++
++ \endif
++
++ \sa getTitle(), setIconTitle(), isTopLevelShell()
++*/
++
++/*!
++ \fn const char * So at Gui@Component::getTitle(void) const
++
++ Returns the window title.
++
++ If a title has been set, that title will be returned.
++ If no title has been set, the default title is returned.
++
++ \sa setTitle(), isTopLevelShell()
++*/
++
++/*!
++ \fn void So at Gui@Component::setIconTitle(const char * const title)
++
++ This method sets the title of the icon representation of the window.
++
++ The title will appear on the window icon, if the component manages
++ its own window.
++
++ \sa getIconTitle(), setTitle(), isTopLevelShell()
++*/
++
++/*!
++ \fn const char * So at Gui@Component::getIconTitle(void) const
++
++ Returns the title the window has when iconfied.
++
++ If an icon title has been set, that icon title is returned. If no
++ icon title has been set, the default icon title is returned.
++
++ \sa setIconTitle(), isTopLevelShell()
++*/
++
++/*!
++ \fn const char * So at Gui@Component::getWidgetName(void) const
++
++ Returns name of the widget.
++*/
++
++/*!
++ \fn const char * So at Gui@Component::getClassName(void) const
++
++ Returns class name of widget.
++*/
++
++/*!
++ This method returns the default name of a component widget class.
++
++ It should be overridden by derived non-abstract classes for the
++ topmost widget in the component to have a proper name.
++*/
++const char *
++So at Gui@Component::getDefaultWidgetName(void) const
++{
++ return "So at Gui@Component";
++}
++
++/*!
++ This method returns the default window caption string of the
++ component.
++
++ It should be overridden by derived non-abstract classes so the
++ window and popup menu will get a proper title.
++*/
++const char *
++So at Gui@Component::getDefaultTitle(void) const
++{
++ return "@Gui@ Component";
++}
++
++/*!
++ This method returns the default icon title of the component.
++
++ It should be overridden by derived non-abstract classes so icons
++ will get proper titles.
++*/
++const char *
++So at Gui@Component::getDefaultIconTitle(void) const
++{
++ return "@Gui@ Component";
++}
++
++/*!
++ \fn void So at Gui@Component::setSize(const SbVec2s size)
++
++ Resize the component widget.
++
++ The method assumes the caller knows what he is doing.
++
++ \sa getSize()
++*/
++
++/*!
++ \fn SbVec2s So at Gui@Component::getSize(void) const
++
++ Returns the component widget size.
++
++ The size that is returned is a cached size value, not a value
++ fetched from the GUI system.
++
++ \sa setSize()
++*/
++
++/*!
++ \fn void So at Gui@Component::sizeChanged(const SbVec2s & size)
++
++ Called internally from within the So at Gui@ library when the widget
++ embedded in a component changes it size, which is usually triggered
++ by end-user interaction.
++
++ This method is then invoked to notify the component that the size
++ has changed. It is called from the top and all the way down to the
++ bottom, the size being adjusted to take into account extra
++ decorations having been added at each level in the component class
++ hierarchy.
++*/
++
++/*!
++ \fn void So at Gui@Component::setWindowCloseCallback(So at Gui@ComponentCB * const func, void * const data)
++
++ Set up a callback function to use when the component gets closed. A
++ component must be a toplevel shell for this to have any effect.
++
++ For toplevel shells with no close callback set, the window will
++ simply be hidden. The typical action to take in the callback would
++ be to delete the component.
++
++ \sa isTopLevelShell()
++*/
++
++/*!
++ \fn SbBool So at Gui@Component::setFullScreen(const SbBool onoff)
++
++ Toggle full screen mode for this component, if possible.
++
++ Returns \c FALSE if operation failed. This might happen if the
++ toolkit doesn't support attempts at making the component cover the
++ complete screen or if the component is not a toplevel window.
++*/
++
++/*!
++ \fn SbBool So at Gui@Component::isFullScreen(void) const
++
++ Returns if this widget/component is in full screen mode.
++*/
++
++/*!
++ \fn void So at Gui@Component::setComponentCursor(const So at Gui@Cursor & cursor)
++
++ Sets the cursor for this component.
++
++ Note: not part of the original SGI InventorXt API.
++*/
++
++/*!
++ \fn void So at Gui@Component::setWidgetCursor(@WIDGET@ w, const So at Gui@Cursor & cursor)
++
++ Set cursor for a native widget in the underlying toolkit.
++
++ Note: not part of the original SGI InventorXt API.
++*/
++
++/*!
++ \fn void So at Gui@Component::afterRealizeHook(void)
++
++ A function "hook" / callback invoked just after the window for the
++ component has been realized.
++
++ Override this if you need specific initialization for your own
++ component or viewer class to happen right after it has been made
++ visible, but remember to call upwards in the inheritance hierarchy:
++
++ \code
++ void
++ MyLittleViewer::afterRealizeHook(void)
++ {
++ <superclass>::afterRealizeHook();
++ // [own initialization here]
++ }
++ \endcode
++*/
++
++
++
++// *************************************************************************
++
++/*!
++ This method should be used by subclasses to register the widgets
++ they set up from the underlying native toolkit, so they can be
++ "reverse" mapped to the owner component.
++
++ Subclasses failing to register the widgets they use will cause the
++ So at Gui@Component::getComponent() method to fail with those widgets.
++
++ \sa unregisterWidget(), getComponent()
++*/
++void
++So at Gui@Component::registerWidget(@WIDGET@ widget)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@Component::registerWidget",
++ "registering widget %p", widget);
++#endif // debug
++
++ // In case widget was already present.
++ void * comp;
++ if (SoGuiComponentP::widget2compdict->find((unsigned long)widget, comp)) {
++ if (((So at Gui@Component *)comp) != this) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@Component::registerWidget",
++ "widget %p already registered on a different "
++ "component", widget);
++#endif // SO at GUI@_DEBUG
++ SoGuiComponentP::widget2compdict->remove((unsigned long)widget);
++ }
++ else {
++ return;
++ }
++ }
++
++ SoGuiComponentP::widget2compdict->enter((unsigned long)widget, (void *)this);
++}
++
++/*!
++ Remove a previously registered native toolkit widget from the
++ widget-to-component mappings used by
++ So at Gui@Component::getComponent().
++
++ \sa registerWidget()
++*/
++void
++So at Gui@Component::unregisterWidget(@WIDGET@ widget)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@Component::unregisterWidget",
++ "unregistering widget %p", widget);
++#endif // debug
++
++ // Ignore return value to allow a widget to be unregistered several
++ // times (it doesn't matter, just as it doesn't matter if a widget
++ // is registered multiple times).
++ (void)SoGuiComponentP::widget2compdict->remove((unsigned long)widget);
++}
++
++/*!
++ Finds and returns the So at Gui@Component corresponding to the given
++ @WIDGET@, if any. If the widget does not seem to belong to any
++ So at Gui@Component, \c NULL will be returned.
++*/
++So at Gui@Component *
++So at Gui@Component::getComponent(@WIDGET@ widget)
++{
++ void * comp;
++ if (!SoGuiComponentP::widget2compdict->find((unsigned long)widget, comp)) {
++ return NULL;
++ }
++ return (So at Gui@Component *)comp;
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the SoGuiComponentP "private implementation"
++// class.
++
++SbDict * SoGuiComponentP::widget2compdict = NULL;
++int SoGuiComponentP::nrofcomponents = 0;
++
++SoGuiComponentP::SoGuiComponentP(So at Gui@Component * publ)
++{
++ this->pub = publ;
++
++ if (SoGuiComponentP::widget2compdict == NULL) {
++ SoGuiComponentP::widget2compdict = new SbDict;
++ }
++ SoGuiComponentP::nrofcomponents++;
++}
++
++SoGuiComponentP::~SoGuiComponentP()
++{
++ SoGuiComponentP::nrofcomponents--;
++ if (SoGuiComponentP::nrofcomponents == 0) {
++#if SO at GUI@_DEBUG
++ // Check to see if widgets were forgotten (ie missing
++ // unregisterWidget() calls).
++ SbPList keys, values;
++ SoGuiComponentP::widget2compdict->makePList(keys, values);
++ for (int i=0; i < keys.getLength(); i++) {
++ SoDebugError::postWarning("SoGuiComponentP::~SoGuiComponentP",
++ "widget %p not unregistered for component %p",
++ keys[i], values[i]);
++ }
++#endif // SO at GUI@_DEBUG
++
++ delete SoGuiComponentP::widget2compdict;
++ SoGuiComponentP::widget2compdict = NULL;
++ }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiComponentP.h.in
+@@ -0,0 +1,67 @@
++#ifndef SOGUICOMPONENTP_H
++#define SOGUICOMPONENTP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbDict.h>
++
++class So at Gui@Component;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiComponent class.
++
++class SoGuiComponentP
++{
++public:
++ ~SoGuiComponentP();
++
++ static SbDict * widget2compdict;
++
++ static int nrofcomponents;
++
++protected:
++ SoGuiComponentP(So at Gui@Component * publ);
++ So at Gui@Component * pub;
++};
++
++// ************************************************************************
++
++#endif // !SOGUICOMPONENTP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiCursor.cpp.in
+@@ -0,0 +1,414 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class So at Gui@Cursor
++ \brief The So at Gui@Cursor class is used to set cursors for GUI components.
++ \ingroup misc
++
++ The class provides both a set of pre-defined cursor shapes, aswell
++ as the option to use custom bitmap graphics.
++
++ Instances of this class is usually made for passing in to the
++ So at Gui@Component::setComponentCursor() and
++ So at Gui@Component::setWidgetCursor() methods.
++*/
++
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++#include <Inventor/@Gui@/SoAny.h>
++#include <assert.h>
++
++/*!
++ \enum So at Gui@Cursor::Shape
++
++ For enumerating built-in shape types, that can be used without
++ having to specify cursor graphics. These are mapped to pre-defined
++ cursor shapes from the underlying toolkit.
++*/
++
++
++/*!
++ \var So at Gui@Cursor::Shape So at Gui@Cursor::CUSTOM_BITMAP
++
++ Cursor is specified with our own bitmap graphics. The bitmap data
++ must be passed into the constructor.
++*/
++
++/*!
++ \var So at Gui@Cursor::Shape So at Gui@Cursor::DEFAULT
++
++ Using the native Window system's default cursor.
++*/
++
++/*!
++ \var So at Gui@Cursor::Shape So at Gui@Cursor::BUSY
++
++ A busy cursor.
++*/
++
++/*!
++ \var So at Gui@Cursor::Shape So at Gui@Cursor::CROSSHAIR
++
++ Two thin lines in a cross.
++*/
++
++/*!
++ \var So at Gui@Cursor::Shape So at Gui@Cursor::UPARROW
++
++ Thick, upward-pointing arrow.
++*/
++
++/*** Graphic data for the mouse pointer bitmaps. ***********************/
++
++/*!
++ \class So at Gui@Cursor::CustomCursor
++ \brief The So at Gui@Cursor::CustomCursor class is used to specify bitmap data for So at Gui@Cursor custom cursors.
++*/
++
++/*!
++ \var SbVec2s So at Gui@Cursor::CustomCursor::dim
++
++ Size of cursor data. Can be anything from 1 pixel wide and high, up
++ to maximum 32 pixels in each dimension.
++*/
++/*!
++ \var SbVec2s So at Gui@Cursor::CustomCursor::hotspot
++
++ Position of cursor hotspot, ie the pixel of the cursor which is
++ considered to be the "pick point" when interacting with the canvas
++ or widgets.
++
++ The hotspot position should be specified relative to the uppermost,
++ leftmost corner (which is position <0, 0>).
++*/
++/*!
++ \var unsigned char * So at Gui@Cursor::CustomCursor::bitmap
++
++ The size of the array of bitmap data should be equal to
++ (width+7)/8*height, as each cursor pixel is specified with just two
++ bits, one in the bitmap array, one in the mask array.
++
++ The bitmap and mask bits should be laid out as follows:
++ \verbatim
++ B=1 and M=1 == black
++ B=0 and M=1 == white
++ B=0 and M=0 == transparency
++ B=1 and M=0 will give undefined results for some platforms, so avoid.
++ \endverbatim
++*/
++/*!
++ \var unsigned char * So at Gui@Cursor::CustomCursor::mask
++
++ See doc of So at Gui@Cursor::CustomCursor::bitmap.
++*/
++
++/*** zoom-style cursor ******/
++
++#define ZOOM_WIDTH 16
++#define ZOOM_HEIGHT 16
++#define ZOOM_BYTES ((ZOOM_WIDTH + 7) / 8) * ZOOM_HEIGHT
++#define ZOOM_HOT_X 5
++#define ZOOM_HOT_Y 7
++
++static unsigned char zoom_bitmap[ZOOM_BYTES] =
++{
++ 0x00, 0x0f, 0x80, 0x1c, 0x40, 0x38, 0x20, 0x70,
++ 0x90, 0xe4, 0xc0, 0xcc, 0xf0, 0xfc, 0x00, 0x0c,
++ 0x00, 0x0c, 0xf0, 0xfc, 0xc0, 0xcc, 0x90, 0xe4,
++ 0x20, 0x70, 0x40, 0x38, 0x80, 0x1c, 0x00, 0x0f
++};
++
++static unsigned char zoom_mask_bitmap[ZOOM_BYTES] =
++{
++ 0x00,0x0f,0x80,0x1f,0xc0,0x3f,0xe0,0x7f,0xf0,0xff,0xf0,0xff,0xf0,0xff,0x00,
++ 0x0f,0x00,0x0f,0xf0,0xff,0xf0,0xff,0xf0,0xff,0xe0,0x7f,0xc0,0x3f,0x80,0x1f,
++ 0x00,0x0f
++};
++
++/*** pan-style cursor *******/
++
++#define PAN_WIDTH 16
++#define PAN_HEIGHT 16
++#define PAN_BYTES ((PAN_WIDTH + 7) / 8) * PAN_HEIGHT
++#define PAN_HOT_X 7
++#define PAN_HOT_Y 7
++
++static unsigned char pan_bitmap[PAN_BYTES] =
++{
++ 0xc0, 0x03, 0x60, 0x02, 0x20, 0x04, 0x10, 0x08,
++ 0x68, 0x16, 0x54, 0x2a, 0x73, 0xce, 0x01, 0x80,
++ 0x01, 0x80, 0x73, 0xce, 0x54, 0x2a, 0x68, 0x16,
++ 0x10, 0x08, 0x20, 0x04, 0x40, 0x02, 0xc0, 0x03
++};
++
++static unsigned char pan_mask_bitmap[PAN_BYTES] =
++{
++ 0xc0,0x03,0xe0,0x03,0xe0,0x07,0xf0,0x0f,0xe8,0x17,0xdc,0x3b,0xff,0xff,0xff,
++ 0xff,0xff,0xff,0xff,0xff,0xdc,0x3b,0xe8,0x17,0xf0,0x0f,0xe0,0x07,0xc0,0x03,
++ 0xc0,0x03
++};
++
++/*** rotate-style cursor ****/
++
++#define ROTATE_WIDTH 16
++#define ROTATE_HEIGHT 16
++#define ROTATE_BYTES ((ROTATE_WIDTH + 7) / 8) * ROTATE_HEIGHT
++#define ROTATE_HOT_X 6
++#define ROTATE_HOT_Y 8
++
++static unsigned char rotate_bitmap[ROTATE_BYTES] = {
++ 0xf0, 0xef, 0x18, 0xb8, 0x0c, 0x90, 0xe4, 0x83,
++ 0x34, 0x86, 0x1c, 0x83, 0x00, 0x81, 0x00, 0xff,
++ 0xff, 0x00, 0x81, 0x00, 0xc1, 0x38, 0x61, 0x2c,
++ 0xc1, 0x27, 0x09, 0x30, 0x1d, 0x18, 0xf7, 0x0f
++};
++
++static unsigned char rotate_mask_bitmap[ROTATE_BYTES] = {
++ 0xf0,0xef,0xf8,0xff,0xfc,0xff,0xfc,0xff,0x3c,0xfe,0x1c,0xff,0x00,0xff,0x00,
++ 0xff,0xff,0x00,0xff,0x00,0xff,0x38,0x7f,0x3c,0xff,0x3f,0xff,0x3f,0xff,0x1f,
++ 0xf7,0x0f
++};
++
++/*** just a blank cursor ****/
++
++#define BLANK_WIDTH 1
++#define BLANK_HEIGHT 1
++#define BLANK_BYTES ((BLANK_WIDTH + 7) / 8) * BLANK_HEIGHT
++#define BLANK_HOT_X 0
++#define BLANK_HOT_Y 0
++
++static unsigned char blank_bitmap[BLANK_BYTES] = { 0x00 };
++static unsigned char blank_mask_bitmap[BLANK_BYTES] = { 0x00 };
++
++/***********************************************************************/
++
++static So at Gui@Cursor::CustomCursor zoom;
++static So at Gui@Cursor::CustomCursor pan;
++static So at Gui@Cursor::CustomCursor rotate;
++static So at Gui@Cursor::CustomCursor blank;
++
++static So at Gui@Cursor * soguicursor_zoomcursor = NULL;
++static So at Gui@Cursor * soguicursor_pancursor = NULL;
++static So at Gui@Cursor * soguicursor_rotatecursor = NULL;
++static So at Gui@Cursor * soguicursor_blankcursor = NULL;
++
++static void soguicursor_atexit_cleanup(void)
++{
++ delete soguicursor_zoomcursor;
++ delete soguicursor_pancursor;
++ delete soguicursor_rotatecursor;
++ delete soguicursor_blankcursor;
++ soguicursor_zoomcursor = NULL;
++ soguicursor_pancursor = NULL;
++ soguicursor_rotatecursor = NULL;
++ soguicursor_blankcursor = NULL;
++}
++
++void
++So at Gui@Cursor::initClass(void)
++{
++ zoom.dim = SbVec2s(ZOOM_WIDTH, ZOOM_HEIGHT);
++ zoom.hotspot = SbVec2s(ZOOM_HOT_X, ZOOM_HOT_Y);
++ zoom.bitmap = zoom_bitmap;
++ zoom.mask = zoom_mask_bitmap;
++
++ pan.dim = SbVec2s(PAN_WIDTH, PAN_HEIGHT);
++ pan.hotspot = SbVec2s(PAN_HOT_X, PAN_HOT_Y);
++ pan.bitmap = pan_bitmap;
++ pan.mask = pan_mask_bitmap;
++
++ rotate.dim = SbVec2s(ROTATE_WIDTH, ROTATE_HEIGHT);
++ rotate.hotspot = SbVec2s(ROTATE_HOT_X, ROTATE_HOT_Y);
++ rotate.bitmap = rotate_bitmap;
++ rotate.mask = rotate_mask_bitmap;
++
++ blank.dim = SbVec2s(BLANK_WIDTH, BLANK_HEIGHT);
++ blank.hotspot = SbVec2s(BLANK_HOT_X, BLANK_HOT_Y);
++ blank.bitmap = blank_bitmap;
++ blank.mask = blank_mask_bitmap;
++
++ soguicursor_zoomcursor = new So at Gui@Cursor(&zoom);
++ soguicursor_pancursor = new So at Gui@Cursor(&pan);
++ soguicursor_rotatecursor = new So at Gui@Cursor(&rotate);
++ soguicursor_blankcursor = new So at Gui@Cursor(&blank);
++ SoAny::atexit((SoAny::atexit_f*)soguicursor_atexit_cleanup, 0);
++}
++
++/*!
++ Default constructor. Creates a default cursor.
++*/
++So at Gui@Cursor::So at Gui@Cursor(void)
++{
++ this->commonConstructor(So at Gui@Cursor::DEFAULT, NULL);
++}
++
++/*!
++ Constructor with Shape argument, for setting up the cursor with a
++ pre-defined shape from the underlying native toolkit.
++*/
++So at Gui@Cursor::So at Gui@Cursor(const Shape shape)
++{
++ assert(shape != CUSTOM_BITMAP && "don't use this constructor for making CUSTOM_BITMAP cursors");
++ this->commonConstructor(shape, NULL);
++}
++
++/*!
++ Constructs a new custom bitmap cursor from \a cc.
++
++ Note that only a \e shallow copy will be made of the CustomCursor
++ bitmap and mask references, so don't deallocate the memory they use
++ until the So at Gui@Cursor has been destructed.
++
++ As for the format of the cursor bitmap data, see documentation of
++ So at Gui@Cursor::CustomCursor.
++*/
++So at Gui@Cursor::So at Gui@Cursor(const CustomCursor * ccarg)
++{
++ this->commonConstructor(CUSTOM_BITMAP, ccarg);
++}
++
++// Private common constructor.
++void
++So at Gui@Cursor::commonConstructor(const Shape shapearg, const CustomCursor * ccarg)
++{
++ this->shape = shapearg;
++ this->cc = NULL;
++
++ if (ccarg) {
++ assert(shape == CUSTOM_BITMAP);
++ this->cc = new CustomCursor;
++ *(this->cc) = *ccarg;
++ }
++}
++
++/*!
++ Constructor.
++*/
++So at Gui@Cursor::So at Gui@Cursor(const So at Gui@Cursor & cursor)
++{
++ this->commonConstructor(cursor.shape, cursor.cc);
++}
++
++/*!
++ Destructor
++*/
++So at Gui@Cursor::~So at Gui@Cursor()
++{
++ delete this->cc;
++}
++
++/*!
++ Equal operator.
++*/
++So at Gui@Cursor &
++So at Gui@Cursor::operator=(const So at Gui@Cursor & c)
++{
++ delete this->cc;
++ this->cc = NULL;
++ this->commonConstructor(c.shape, c.cc);
++ return *this;
++}
++
++/*!
++ Returns the shape type.
++
++ If the cursor has been set by the application programmer to a bitmap
++ cursor, So at Gui@Cursor::CUSTOM_BITMAP is returned.
++*/
++So at Gui@Cursor::Shape
++So at Gui@Cursor::getShape(void) const
++{
++ return this->shape;
++}
++
++/*!
++ Sets the cursor to a predefined shape.
++*/
++void
++So at Gui@Cursor::setShape(const Shape shapearg)
++{
++ this->shape = shapearg;
++}
++
++/*!
++ Returns a reference to the current custom bitmap cursor.
++
++ Do not call this method unless So at Gui@Cursor::getShape() returns
++ So at Gui@Cursor::CUSTOM_BITMAP.
++*/
++const So at Gui@Cursor::CustomCursor &
++So at Gui@Cursor::getCustomCursor(void) const
++{
++ assert(cc!=NULL && "not a custom bitmap cursor");
++ return *(this->cc);
++}
++
++/*!
++ Returns a "zoom" indicator cursor.
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getZoomCursor(void)
++{
++ return *soguicursor_zoomcursor;
++}
++
++/*!
++ Returns a cursor with "pan" graphics (ie for translation in the
++ camera normal plane).
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getPanCursor(void)
++{
++ return *soguicursor_pancursor;
++}
++
++/*!
++ Returns a "rotate" indicator cursor.
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getRotateCursor(void)
++{
++ return *soguicursor_rotatecursor;
++}
++
++/*!
++ Because all toolkits don't easily support setting up a blank cursor
++ from pre-defined shapes or API functions, we also provide a simple
++ completely transparent cursor.
++*/
++const So at Gui@Cursor &
++So at Gui@Cursor::getBlankCursor(void)
++{
++ return *soguicursor_blankcursor;
++}
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiCursor.h.in
+@@ -0,0 +1,87 @@
++#ifndef SO at GUI@_CURSOR_H
++#define SO at GUI@_CURSOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++class SO at GUI@_DLL_API So at Gui@Cursor {
++public:
++ static void initClass(void);
++
++ struct CustomCursor {
++ SbVec2s dim;
++ SbVec2s hotspot;
++ unsigned char * bitmap;
++ unsigned char * mask;
++ };
++
++
++ // FIXME: add more default shapes. 20011119 pederb.
++ enum Shape {
++ CUSTOM_BITMAP = -1,
++ DEFAULT = 0,
++ BUSY,
++ CROSSHAIR,
++ UPARROW
++ };
++
++ So at Gui@Cursor(void);
++ So at Gui@Cursor(const Shape shape);
++ So at Gui@Cursor(const CustomCursor * cc);
++ So at Gui@Cursor(const So at Gui@Cursor & cursor);
++ ~So at Gui@Cursor();
++
++ So at Gui@Cursor & operator=(const So at Gui@Cursor & c);
++
++ Shape getShape(void) const;
++ void setShape(const Shape shape);
++
++ const CustomCursor & getCustomCursor(void) const;
++
++ static const So at Gui@Cursor & getZoomCursor(void);
++ static const So at Gui@Cursor & getPanCursor(void);
++ static const So at Gui@Cursor & getRotateCursor(void);
++ static const So at Gui@Cursor & getBlankCursor(void);
++
++private:
++ void commonConstructor(const Shape shape, const CustomCursor * cc);
++
++ Shape shape;
++ CustomCursor * cc;
++};
++
++#endif // ! SO at GUI@_CURSOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiGLWidget.h.in
+@@ -0,0 +1,229 @@
++#ifndef SO at GUI@_GLWIDGET_H
++#define SO at GUI@_GLWIDGET_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbBasic.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++#ifdef __COIN_SOQT__
++class QEvent;
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++/*
++ * GL/glx.h includes X11/Xmd.h which contains typedefs for BOOL and
++ * INT32 that conflict with the definitions in windef.h (which is
++ * included from windows.h, which may be included from
++ * Inventor/system/gl.h). To avoid this conflict, we rename the
++ * typedefs done in X11/Xmd.h to use other names (tempbool and
++ * tempint32), and try to clean up the hack after the header has been
++ * parsed. 2003-06-25 larsa
++ */
++#ifndef BOOL
++#define BOOL tempbool
++#define COIN_DEFINED_BOOL
++#endif /* !BOOL */
++#ifndef INT32
++#define INT32 tempint32
++#define COIN_DEFINED_INT32
++#endif /* !INT32 */
++#include <GL/glx.h>
++/*
++ * This is the cleanup part of the X11/Xmd.h conflict fix hack set up
++ * above. 2003-06-25 larsa
++ */
++#ifdef COIN_DEFINED_BOOL
++#undef BOOL
++#undef COIN_DEFINED_BOOL
++#endif /* COIN_DEFINED_BOOL */
++#ifdef COIN_DEFINED_INT32
++#undef INT32
++#undef COIN_DEFINED_INT32
++#endif /* COIN_DEFINED_INT32 */
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++#include <gtk/gtk.h>
++#endif // __COIN_SOGTK__
++
++// *************************************************************************
++
++enum GLModes {
++ SO_GL_RGB = 0x01, SO_GLX_RGB = SO_GL_RGB,
++ SO_GL_DOUBLE = 0x02, SO_GLX_DOUBLE = SO_GL_DOUBLE,
++ SO_GL_ZBUFFER = 0x04, SO_GLX_ZBUFFER = SO_GL_ZBUFFER,
++ SO_GL_OVERLAY = 0x08, SO_GLX_OVERLAY = SO_GL_OVERLAY,
++ SO_GL_STEREO = 0x10, SO_GLX_STEREO = SO_GL_STEREO
++};
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@GLWidget : public So at Gui@Component {
++ SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@GLWidget, So at Gui@Component);
++
++public:
++
++ void setBorder(const SbBool enable);
++ SbBool isBorder(void) const;
++
++ virtual void setDoubleBuffer(const SbBool enable);
++ SbBool isDoubleBuffer(void) const;
++
++ void setDrawToFrontBufferEnable(const SbBool enable);
++ SbBool isDrawToFrontBufferEnable(void) const;
++
++ void setQuadBufferStereo(const SbBool enable);
++ SbBool isQuadBufferStereo(void) const;
++
++ void setAccumulationBuffer(const SbBool enable);
++ SbBool getAccumulationBuffer(void) const;
++
++ void setStencilBuffer(const SbBool enable);
++ SbBool getStencilBuffer(void) const;
++
++ void setAlphaChannel(const SbBool enable);
++ SbBool getAlphaChannel(void) const;
++
++ void setOverlayRender(const SbBool onoff);
++ SbBool isOverlayRender(void) const;
++
++ void setSampleBuffers(const int numsamples);
++ int getSampleBuffers(void) const;
++
++ void setStealFocus(SbBool enable);
++ SbBool isStealFocus(void) const;
++
++ @WIDGET@ getGLWidget(void) const;
++ @WIDGET@ getNormalWidget(void) const;
++ @WIDGET@ getOverlayWidget(void) const;
++
++ SbBool hasOverlayGLArea(void) const;
++ SbBool hasNormalGLArea(void) const;
++
++ unsigned long getOverlayTransparentPixel(void);
++
++ // OpenGL query functions.
++ void getPointSizeLimits(SbVec2f & range, float & granularity);
++ void getLineWidthLimits(SbVec2f & range, float & granularity);
++
++protected:
++ So at Gui@GLWidget(@WIDGET@ const parent = NULL,
++ const char * const name = NULL,
++ const SbBool embed = TRUE,
++ const int glmodes = SO_GL_RGB,
++ const SbBool build = TRUE);
++ ~So at Gui@GLWidget();
++
++ virtual void processEvent(@EVENT@ event);
++
++ @WIDGET@ buildWidget(@WIDGET@ parent);
++
++ virtual void redraw(void) = 0;
++ virtual void redrawOverlay(void);
++
++ virtual void initGraphic(void);
++ virtual void initOverlayGraphic(void);
++
++ virtual void sizeChanged(const SbVec2s & size);
++ virtual void widgetChanged(@WIDGET@ w);
++
++ void setGLSize(const SbVec2s size);
++ SbVec2s getGLSize(void) const;
++ float getGLAspectRatio(void) const;
++
++ // old aliases
++ void setGlxSize(const SbVec2s size) { this->setGLSize(size); }
++ SbVec2s getGlxSize(void) const { return this->getGLSize(); }
++ float getGlxAspectRatio(void) const { return this->getGLAspectRatio(); }
++
++ void setStereoBuffer(SbBool flag);
++ SbBool isStereoBuffer(void) const;
++
++ SbBool isRGBMode(void);
++
++ SbBool waitForExpose;
++ SbBool drawToFrontBuffer;
++
++ void glLockNormal(void);
++ void glUnlockNormal(void);
++
++ void glLockOverlay(void);
++ void glUnlockOverlay(void);
++
++ void glSwapBuffers(void);
++ void glFlushBuffer(void);
++
++ virtual SbBool glScheduleRedraw(void);
++
++private:
++ class So at Gui@GLWidgetP * pimpl;
++ friend class SoGuiGLWidgetP;
++ friend class So at Gui@GLWidgetP;
++
++ // FIXME: get rid of toolkit-specific stuff below. 20020613 mortene.
++
++#ifdef __COIN_SOXT__
++public:
++ GLXContext getNormalContext(void);
++ GLXContext getOverlayContext(void);
++
++ Window getNormalWindow(void);
++ Window getOverlayWindow(void);
++
++ int getOverlayColorMapSize(void);
++ int getColorMapSize(void);
++
++ virtual void setNormalVisual(XVisualInfo * visual);
++ XVisualInfo * getNormalVisual(void);
++ virtual void setOverlayVisual(XVisualInfo * visual);
++ XVisualInfo * getOverlayVisual(void);
++
++protected:
++ static void eventHandler(Widget, SoXtGLWidget *, XAnyEvent *, Boolean *);
++
++ int getDisplayListShareGroup(GLXContext context);
++ Widget getGlxMgrWidget(void);
++#endif // __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++protected:
++ virtual SbBool eventFilter(GtkWidget * object, GdkEvent * event);
++#endif // __COIN_SOGTK__
++
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_GLWIDGET_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiGLWidgetCommon.cpp.in
+@@ -0,0 +1,691 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#define PRIVATE(obj) ((SoGuiGLWidgetP *)(obj->pimpl))
++
++// *************************************************************************
++
++/*!
++ \class So at Gui@GLWidget So at Gui@GLWidget.h Inventor/@Gui@/So at Gui@GLWidget.h
++ \brief The So at Gui@GLWidget class manages OpenGL contexts.
++ \ingroup components
++
++ This is the basic, abstract component class which sets up an OpenGL
++ canvas for its subclasses.
++
++ Application programmers will normally not use this class directly,
++ but rather through the interface of either its direct descendent;
++ So at Gui@RenderArea, or through one of the "rapid application
++ development"-style viewer subclasses.
++
++ \if SOQT_DOC
++
++ An important thing to know about embedding So at Gui@GLWidget derived
++ components into other @Gui@ widgets is that you need to set up
++ "focus proxying" to have events still be sent to the OpenGL canvas
++ widget. This is true for both the So at Gui@RenderArea aswell as all
++ the viewer components (like So at Gui@ExaminerViewer,
++ So at Gui@PlaneViewer etc).
++
++ As an example, if you embed an So at Gui@ExaminerViewer inside a QFrame
++ like this:
++
++ \code
++ QMainWindow * toplevel = new QMainWindow;
++ QFrame * frame = new QFrame(toplevel);
++ So at Gui@ExaminerViewer * viewer = new So at Gui@ExaminerViewer(toplevel);
++ \endcode
++
++ ...events from the keyboard will not always automatically be
++ forwarded to the viewer OpenGL canvas. This is the code you need to
++ add in this case:
++
++ \code
++ toplevel->setFocusProxy(viewer->getWidget());
++ \endcode
++
++ \endif
++
++ \if SOWIN_DOC
++
++ For debugging purposes, SoWinGLWidget provides the
++ OIV_FORCE_PIXEL_FORMAT environment variable to make it possible to
++ override the pixel format chosen by the internal attribute match
++ algorithm.
++
++ \endif
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/So at Gui@GLWidget.h>
++#include <Inventor/@Gui@/So at Gui@GLWidgetP.h>
++
++// *************************************************************************
++
++// All shared documentation for functions with specific
++// implementations in the individual toolkits.
++
++/*!
++ \fn So at Gui@GLWidget::So at Gui@GLWidget(@WIDGET@ const parent, const char * const name, const SbBool embed, const int glmodes, const SbBool build)
++
++ The constructor is protected, as this is an abstract class to only
++ be used by it's subclasses.
++*/
++
++/*!
++ \fn So at Gui@GLWidget::~So at Gui@GLWidget()
++
++ Clean up all use of internal resources.
++
++ The destructor is protected, as this is an abstract class to only be
++ used by it's subclasses.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setBorder(const SbBool enable)
++
++ Specify whether or not there should be a border framing the OpenGL
++ canvas. The border will be 2 pixels wide.
++
++ The default is to display the OpenGL canvas with no border.
++
++ \sa isBorder()
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::isBorder(void) const
++
++ Returns whether or not there's a border framing the OpenGL canvas.
++
++ \sa setBorder()
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setOverlayRender(const SbBool onoff)
++
++ Turn on or off the use of overlay planes.
++
++ \sa isOverlayRender()
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::isOverlayRender(void) const
++
++ Returns a flag indicating whether or not overplay planes are
++ currently used.
++
++ \sa setOverlayRender()
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setDoubleBuffer(const SbBool enable)
++
++ Switch between single and double buffer mode for the OpenGL canvas.
++ The default is to use a single buffer canvas.
++
++ \sa isDoubleBuffer()
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::isDoubleBuffer(void) const
++
++ Returns the status of the buffer mode.
++
++ \sa setDoubleBuffer()
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setQuadBufferStereo(const SbBool enable)
++
++ Enables or disables OpenGL quad buffer stereo.
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::isQuadBufferStereo(void) const
++
++ Returns \c TRUE if quad buffer stereo is enabled for this widget.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setAccumulationBuffer(const SbBool enable)
++
++ Enables/disables the OpenGL accumulation buffer.
++
++ For general information about accumulation buffers, confer with your
++ OpenGL reference documentation.
++
++ By default, the accumulation buffer will be attempted disabled.
++ Whether or not it will \e actually be disabled depends on what
++ OpenGL contexts are available on the system. It is perfectly
++ possible that the only usable contexts with regard to the other
++ settings (like double buffering and RGBA mode versus color index
++ mode) causes the context selection to choose an OpenGL format that
++ contains an accumulation buffer, even though it was not
++ requested.
++
++ Vice versa, one is not guaranteed to get accumulation buffers even
++ when requested through this function, either because they are not
++ available, or because they are only available in combination with
++ other OpenGL context settings that are not wanted (like single
++ buffers, non-accellerated rendering, etc).
++
++ If you try to enable accumulation buffers by using this function,
++ you should therefore in succession use the
++ So at Gui@GLWidget::getAccumulationBuffer() to query whether or not an
++ accumulation buffer could actually be set up.
++
++ \sa So at Gui@RenderArea::setAntiAliasing()
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::getAccumulationBuffer(void) const
++
++ Returns whether the OpenGL accumulation buffer is enabled.
++
++ The returned flag will indicate whether or not accumulation buffers
++ are \e actually present, and not just parrot the input value to
++ So at Gui@GLWidget::setAccumulationBuffer(). See documentation of that
++ function for more information.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setStencilBuffer(const SbBool enable)
++
++ Enables/disables the OpenGL stencil buffer.
++
++ For general information about stencil buffers, confer with your
++ OpenGL reference documentation.
++
++ By default, the stencil buffer will be attempted disabled, but the
++ same notes apply for stencil buffers as for accumulation
++ buffers. For an explanation on the issue of stencil and accumulation
++ buffer availability, see the function documentation of
++ So at Gui@GLWidget::setAccumulationBuffer().
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::getStencilBuffer(void) const
++
++ Returns whether the OpenGL stencil buffer is enabled.
++
++ The returned flag will indicate whether or not stencil buffers are
++ \e actually present, in the same manner as for
++ So at Gui@GLWidget::getAccumulationBuffer(). See documentation of
++ So at Gui@GLWidget::setStencilBuffer().
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setAlphaChannel(const SbBool enable)
++
++ Enables/disables the alpha channel for the OpenGL context.
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::getAlphaChannel(void) const
++
++ Returns whether the alpha channel is enabled for the OpenGL context.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setDrawToFrontBufferEnable(const SbBool enable)
++
++ If this is set to \c TRUE, rendering will happen in the front buffer
++ even if the current rendering mode is double buffered.
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::isDrawToFrontBufferEnable(void) const
++ \sa setDrawToFrontBufferEnable()
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@GLWidget::buildWidget(@WIDGET@ parent)
++
++ This method builds the component contents in the given \a parent
++ widget. For subclasses adding new user interface items, this method
++ is typically overridden in the following manner:
++
++ \code
++ @WIDGET@ MyOwnViewer::buildWidget(@WIDGET@ parent)
++ {
++ @WIDGET@ superw = <superclass>::buildWidget(parent);
++ // [then move superw within MyOwnViewer framework and add own
++ // user interface components]
++ }
++ \endcode
++*/
++
++/*!
++ \fn virtual void So at Gui@GLWidget::redraw(void)
++
++ This method is invoked when the GL buffer needs to be redrawn.
++ */
++
++/*!
++ \var SbBool So at Gui@GLWidget::waitForExpose
++
++ If this is \c TRUE, rendering should not be done yet. Upon the first
++ expose event of a newly created OpenGL widget, this variable will
++ be set to \c FALSE.
++*/
++
++/*!
++ \var SbBool So at Gui@GLWidget::drawToFrontBuffer
++
++ If this is \c TRUE, rendering will happen in the front buffer even
++ if the current rendering mode is double buffered.
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@GLWidget::getNormalWidget(void) const
++
++ \if SOQT_DOC
++ For SoQt, this returns the same widget pointer as that of
++ SoQtGLWidget::getGLWidget().
++ \endif
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@GLWidget::getOverlayWidget(void) const
++
++ Returns widget associated with overlay planes, or \c NULL if no
++ overlay planes are available.
++
++ \if SOQT_DOC
++ For the Qt toolkit, overlay planes is a feature of the QGLWidget,
++ and not seen at a separate widget entity. So this call will just
++ return the same widget reference as the SoQt::getGLWidget() call (if
++ overlay planes are supported).
++ \endif
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setGLSize(const SbVec2s size)
++ Sets the size of the GL canvas.
++*/
++
++/*!
++ \fn SbVec2s So at Gui@GLWidget::getGLSize(void) const
++
++ Return the dimensions of the OpenGL canvas.
++*/
++
++/*!
++ \fn float So at Gui@GLWidget::getGLAspectRatio(void) const
++
++ Return the aspect ratio of the OpenGL canvas.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setGlxSize(const SbVec2s size)
++ This function has been renamed to the more appropriate setGLSize.
++ \sa setGLSize
++*/
++
++/*!
++ \fn SbVec2s So at Gui@GLWidget::getGlxSize(void) const
++ This function has been renamed to the more appropriate getGLSize.
++ \sa getGLSize
++*/
++
++/*!
++ \fn float So at Gui@GLWidget::getGlxAspectRatio(void) const
++ This function has been renamed to the more appropriate getGLAspectRatio.
++ \sa getGLAspectRatio
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@GLWidget::getGLWidget(void) const
++
++ Returns a pointer to the toolkit-native GL widget.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::widgetChanged(@WIDGET@ w)
++
++ This is the method which gets called whenever we change which OpenGL
++ widget is used.
++
++ Should be overridden in subclasses which directly or indirectly
++ store the return value from the So at Gui@GLWidget::getGLWidget()
++ method.
++
++ \sa sizeChanged()
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::processEvent(@EVENT@ anyevent)
++
++ Any events from the native window system that goes to the OpenGL
++ canvas gets piped through this method.
++
++ It is overridden in the subclasses to catch user interaction with
++ the render canvas in the viewers, aswell as forwarding relevant
++ events to the scenegraph.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::glLockNormal(void)
++
++ This method calls make-current on the correct context and ups the
++ lock level.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::glUnlockNormal(void)
++
++ This method drops the lock level.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::glSwapBuffers(void)
++ Swap back buffer to front and vice versa.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::glFlushBuffer(void)
++
++ Flush the current GL buffer. Simply calls glFlush().
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::glLockOverlay(void)
++
++ This method calls make-current on the correct context and ups the
++ lock level.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::glUnlockOverlay(void)
++
++ This method drops the lock level.
++*/
++
++/*!
++ \fn unsigned long So at Gui@GLWidget::getOverlayTransparentPixel(void)
++ Returns the overlay transparent pixel.
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::isRGBMode(void)
++
++ Returns \c TRUE if the normal GL context is in RGBA mode.
++ Return \c FALSE if color index mode is used.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::redrawOverlay(void)
++
++ Renders the overlay scene graph. Default method is empty. Subclasses
++ should override this method.
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::hasNormalGLArea(void) const
++
++ Will return \c TRUE if a normal GL drawing area exists.
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::hasOverlayGLArea(void) const
++
++ Will return \c TRUE if an overlay GL drawing area exists.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::initGraphic(void)
++
++ Will be called when GL widget should initialize graphic, after
++ the widget has been created. Default method enabled GL_DEPTH_TEST.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::initOverlayGraphic(void)
++
++ Will be called after the overlay widget has been created, and subclasses
++ should override this to initialize overlay stuff.
++
++ Default method does nothing.
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::glScheduleRedraw(void)
++
++ Will be called whenever scene graph needs to be redrawn. If this
++ method return \c FALSE, redraw() will be called immediately.
++
++ Default method simply returns \c FALSE. Override this method to
++ schedule a redraw and return \c TRUE if you're trying to do The
++ Right Thing.
++*/
++
++/*!
++ \fn void So at Gui@GLWidget::setStealFocus(SbBool enable)
++
++ Sets whether the GL widget should steal keyboard focus when the
++ mouse is over the GL view.
++
++ Default is \c TRUE.
++
++ \sa isStealFocus
++ \since So at Gui@ 1.3.0
++*/
++
++/*!
++ \fn SbBool So at Gui@GLWidget::isStealFocus(void) const
++
++ Returns whether focus stealing policy is on (\c TRUE) or off (\c
++ FALSE).
++
++ Default is \c TRUE.
++
++ \sa setStealFocus
++ \since So at Gui@ 1.3.0
++*/
++
++
++/*!
++ \fn void So at Gui@GLWidget::setSampleBuffers(const int numsamples)
++
++ Set the number of samples use when enabling multisample buffer contexts.
++ Multisampling will be enabled when numsamples > 1.
++
++*/
++
++/*!
++ \fn int So at Gui@GLWidget::getSampleBuffers(void) const
++
++ Returns the number of samples used for multisampling. Returns 1 if
++ multisampling is disabled.
++*/
++
++// Documented in common/SoGuiGLWidgetCommon.cpp.in.
++void
++So at Gui@GLWidget::setStealFocus(SbBool enable)
++{
++ PRIVATE(this)->stealFocus = enable;
++}
++
++// Documented in common/SoGuiGLWidgetCommon.cpp.in.
++SbBool
++So at Gui@GLWidget::isStealFocus(void) const
++{
++ return PRIVATE(this)->stealFocus;
++}
++
++// *************************************************************************
++
++/*!
++ This function is provided as a convenience for the application
++ programmer to help with acquiring the OpenGL implementation limits
++ for rendering points.
++
++ For robust application code, one needs to consider the range limits
++ when setting the SoDrawStyle::pointSize field.
++*/
++void
++So at Gui@GLWidget::getPointSizeLimits(SbVec2f & range, float & granularity)
++{
++ this->glLockNormal();
++
++ GLfloat vals[2];
++ glGetFloatv(GL_POINT_SIZE_RANGE, vals);
++
++ // Matthias Koenig reported on coin-discuss that the OpenGL
++ // implementation on SGI Onyx 2 InfiniteReality returns 0 for the
++ // lowest pointsize, but it will still set the return value of
++ // glGetError() to GL_INVALID_VALUE if this size is attempted
++ // used. So the boundary range fix in the next line of code is a
++ // workaround for that OpenGL implementation bug.
++ //
++ // 0.0f and lower values are explicitly disallowed, according to
++ // the OpenGL 1.3 specification, Chapter 3.3.
++
++ if (vals[0] <= 0.0f) { vals[0] = So at Gui@Min(1.0f, vals[1]); }
++
++ range.setValue(vals[0], vals[1]);
++
++ GLfloat gran[1];
++ glGetFloatv(GL_POINT_SIZE_GRANULARITY, gran);
++ granularity = gran[0];
++
++ this->glUnlockNormal();
++}
++
++/*!
++ This function is provided as a convenience for the application
++ programmer to help with acquiring the OpenGL implementation limits
++ for rendering lines.
++
++ For robust application code, one needs to consider the range limits
++ when setting the SoDrawStyle::lineWidth field.
++*/
++void
++So at Gui@GLWidget::getLineWidthLimits(SbVec2f & range, float & granularity)
++{
++ this->glLockNormal();
++
++ GLfloat vals[2];
++ glGetFloatv(GL_LINE_WIDTH_RANGE, vals);
++
++ // Matthias Koenig reported on coin-discuss that the OpenGL
++ // implementation on SGI Onyx 2 InfiniteReality returns 0 for the
++ // lowest linewidth, but it will still set the return value of
++ // glGetError() to GL_INVALID_VALUE if this size is attempted
++ // used. This is a workaround for what looks like an OpenGL bug.
++
++ if (vals[0] <= 0.0f) { vals[0] = So at Gui@Min(1.0f, vals[1]); }
++
++ range.setValue(vals[0], vals[1]);
++
++ GLfloat gran[1];
++ glGetFloatv(GL_LINE_WIDTH_GRANULARITY, gran);
++ granularity = gran[0];
++
++ this->glUnlockNormal();
++}
++
++// FIXME: other implementation specifics to check are
++//
++// * maximum stack depths (attribute, modelview matrix, name,
++// projection matrix, texture matrix)
++//
++// * max display list nesting
++//
++// * max nr of clipplanes
++//
++// * max nr of light sources
++//
++// * max 3D texture size (needs specific extension?)
++//
++// 20020802 mortene.
++
++/*!
++ Sets whether OpenGL stereo buffers (quad buffer stereo) should be
++ used.
++*/
++void
++So at Gui@GLWidget::setStereoBuffer(SbBool flag)
++{
++ // FIXME: is this really correct? 20011012 mortene.
++ this->setQuadBufferStereo(flag);
++}
++
++/*!
++ Returns whether OpenGL stereo buffers are being used.
++*/
++SbBool
++So at Gui@GLWidget::isStereoBuffer(void) const
++{
++ // FIXME: is this really correct? 20011012 mortene.
++ return this->isQuadBufferStereo();
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the SoGuiGLWidgetP "private implementation"
++// class.
++
++
++SoGuiGLWidgetP::SoGuiGLWidgetP(So at Gui@GLWidget * publ)
++{
++ this->pub = publ;
++ this->stealFocus = TRUE;
++}
++
++SoGuiGLWidgetP::~SoGuiGLWidgetP()
++{
++}
++
++// Just forward from a static function, so we can find out from
++// anywhere within the library -- without exposing the API for the app
++// programmer.
++SbBool
++SoGuiGLWidgetP::isDirectRendering(So at Gui@GLWidget * w)
++{
++ return ((SoGuiGLWidgetP *)(w->pimpl))->isDirectRendering();
++}
++
++#undef PRIVATE
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiGLWidgetP.h.in
+@@ -0,0 +1,68 @@
++#ifndef SOGUIGLWIDGETP_H
++#define SOGUIGLWIDGETP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbBasic.h>
++
++class So at Gui@GLWidget;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiGLWidget class.
++
++class SoGuiGLWidgetP
++{
++public:
++ virtual ~SoGuiGLWidgetP();
++
++ static SbBool isDirectRendering(class So at Gui@GLWidget * w);
++ SbBool stealFocus;
++
++protected:
++ SoGuiGLWidgetP(So at Gui@GLWidget * publ);
++ So at Gui@GLWidget * pub;
++
++ virtual SbBool isDirectRendering(void) = 0;
++};
++
++// ************************************************************************
++
++#endif // !SOGUIGLWIDGETP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiMaterialEditor.h.in
+@@ -0,0 +1,39 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This include file just forwards to the one under the editors/
++// directory. Done to be compatible with old SGI InventorXt code and
++// TGS SoWin and SoQt code.
++
++#include <Inventor/@Gui@/editors/So at Gui@MaterialEditor.h>
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiMaterialList.h.in
+@@ -0,0 +1,110 @@
++#ifndef SO at GUI@_MATERIALLIST_H
++#define SO at GUI@_MATERIALLIST_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++class SoMaterial;
++class SoAnyMaterialList;
++
++typedef void So at Gui@MaterialListCB(void * closure, const SoMaterial * material);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@MaterialList : public So at Gui@Component {
++ SO at GUI@_OBJECT_HEADER(So at Gui@MaterialList, So at Gui@Component);
++
++public:
++ So at Gui@MaterialList(
++ @WIDGET@ parent = NULL,
++ const char * const name = NULL,
++ SbBool embed = TRUE,
++ const char * const dir = NULL);
++ ~So at Gui@MaterialList(void);
++
++ void addCallback(
++ So at Gui@MaterialListCB * const callback,
++ void * const closure = NULL);
++ void removeCallback(
++ So at Gui@MaterialListCB * const callback,
++ void * const closure = NULL);
++
++protected:
++ So at Gui@MaterialList(
++ @WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ const char * const dir,
++ SbBool build);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++ @WIDGET@ buildWidget(@WIDGET@ parent);
++ @WIDGET@ buildPulldownMenu(@WIDGET@ parent);
++
++private:
++ void constructor(const char * const dir, const SbBool build);
++
++ // FIXME: remove all this and set it up for use with a
++ // SoGuiMaterialListP class. 2001???? larsa.
++
++ void selectionCallback(int i);
++ static void selection_cb(@WIDGET@, void *, void *);
++
++ void paletteMenuCallback(@WIDGET@);
++ static void palette_menu_cb(@WIDGET@, void *, void *);
++
++
++#ifdef __COIN_SOGTK__
++ void menuactivation(GtkWidget * menuitem);
++ static void menuactivationCB(GtkObject * obj, gpointer closure);
++
++ void itemactivation(int item);
++ static void itemactivationCB(GtkObject * obj, gint row, gint column,
++ GdkEvent * event, gpointer closure);
++#endif // __COIN_SOGTK__
++
++ @WIDGET@ listwidget;
++
++ SoAnyMaterialList * common;
++
++}; // public So at Gui@MaterialList
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_MATERIALLIST_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiObject.cpp.in
+@@ -0,0 +1,166 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// Pulls in __COIN_SO at GUI@__ define used below.
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++/*!
++ \class So at Gui@Object Inventor/@Gui@/So at Gui@Object.h
++ \brief The So at Gui@Object class is the common superclass for all So at Gui@ component classes.
++ \ingroup misc
++
++ The purpose of making this class the superclass of all So at Gui@
++ device, component and viewer classes is to be able to do run-time
++ type checking of the So at Gui@ objects.
++
++
++ You can place the macro SO at GUI@_OBJECT_HEADER(classname,parentname)
++ within a class definition header for So at Gui@ extension components to
++ automatically make the necessary definitions for setting up a
++ run-time type system for your extension classes:
++
++ \code
++ #ifndef MYSPECIALVIEWER_H
++ #define MYSPECIALVIEWER_H
++
++ class MySpecialViewer : public So at Gui@ExaminerViewer {
++ SO at GUI@_OBJECT_HEADER(MySpecialViewer, So at Gui@ExaminerViewer);
++ // [rest of class definition follows]
++ };
++
++ #endif // !MYSPECIALVIEWER_H
++ \endcode
++
++ Then put the SO at GUI@_OBJECT_SOURCE(classname) macro within the
++ actual implementation sourcecode file to include the necessary
++ code for the run-time type system:
++
++ \code
++ #include <MySpecialViewer.h>
++
++ SOQT_OBJECT_SOURCE(MySpecialViewer);
++
++ // [rest of class implementation]
++ \endcode
++
++
++ See also the documentation of the SoType class in Coin or Inventor.
++ */
++
++// *************************************************************************
++
++/*!
++ \fn SoType So at Gui@Object::getTypeId
++
++ Returns the type identification of an object derived from a class
++ inheriting So at Gui@Object. This is used for run-time type checking
++ and "downward" casting.
++
++ Usage example:
++
++ \code
++ void foo(So at Gui@Viewer * comp)
++ {
++ if (comp->getTypeId() == So at Gui@ExaminerViewer::getClassTypeId()) {
++ // safe downward cast, knows the type
++ So at Gui@ExaminerViewer * exviewer = (So at Gui@ExaminerViewer *)comp;
++ /// [then something] ///
++ }
++ else if (comp->getTypeId().isOfType(So at Gui@FlyViewer::getClassTypeId())) {
++ // safe downward cast, knows the type
++ So at Gui@FlyViewer * flyviewer = (So at Gui@FlyViewer *)comp;
++ // then something else
++ }
++ }
++ \endcode
++*/
++// FIXME: add doc above to explain how external developers can use the
++// type system for their own extension classes. 20020502 mortene.
++
++// This is a private variable.
++SoType So at Gui@Object::classTypeId SO at GUI@_STATIC_SOTYPE_INIT;
++
++/*!
++ Sets up initialization for data common to all instances of this
++ class, submitting necessary information to the internal So at Gui@ type
++ system.
++*/
++void
++So at Gui@Object::initClass(void)
++{
++ assert(So at Gui@Object::classTypeId == SoType::badType());
++ So at Gui@Object::classTypeId =
++ SoType::createType(SoType::badType(), "So at Gui@Object");
++}
++
++/*!
++ Returns \c TRUE if the type of this object is either of the same
++ type or inherited from \a type.
++*/
++SbBool
++So at Gui@Object::isOfType(SoType type) const
++{
++ return this->getTypeId().isDerivedFrom(type);
++}
++
++/*!
++ This static method returns the SoType object associated with
++ objects of this class.
++*/
++SoType
++So at Gui@Object::getClassTypeId(void)
++{
++ return So at Gui@Object::classTypeId;
++}
++
++/*!
++ Initialize the type system of So at Gui@Object, all So at Gui@ device
++ classes and all So at Gui@ components (including viewers).
++*/
++void
++So at Gui@Object::init(void)
++{
++ So at Gui@Object::initClass();
++ So at Gui@Device::initClasses();
++ So at Gui@Component::initClasses();
++}
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiObject.h.in
+@@ -0,0 +1,146 @@
++#ifndef SO at GUI@OBJECT_H
++#define SO at GUI@OBJECT_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/SbBasic.h>
++#include <Inventor/SbString.h>
++#include <Inventor/SoType.h>
++
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Object {
++ static SoType classTypeId;
++
++public:
++ static void initClass(void);
++ static SoType getClassTypeId(void);
++ virtual SoType getTypeId(void) const = 0;
++ SbBool isOfType(SoType type) const;
++
++ static void init(void);
++
++ // FIXME: gcc-4 generates a warning when a class has virtual functions
++ // but no virtual destructor. Currently this warning is suppressed using
++ // the -Wno-non-virtual-dtor option, but this should be addressed for the
++ // next major version... 20060404 kyrah
++
++#if (SO at GUI@_MAJOR_VERSION > 1)
++#error Resolve missing virtual destructor issue for the new major release!
++#endif
++
++}; // So at Gui@Object
++
++// *************************************************************************
++
++// For a discussion about this #define, see Coin's SbBasic.h.
++
++#define SO at GUI@_SUN_CC_4_0_SOTYPE_INIT_BUG 0 /* assume compiler is ok for now */
++
++#if SO at GUI@_SUN_CC_4_0_SOTYPE_INIT_BUG
++#define SO at GUI@_STATIC_SOTYPE_INIT
++#else
++#define SO at GUI@_STATIC_SOTYPE_INIT = SoType::badType()
++#endif
++
++// *************************************************************************
++
++// The getTypeId() method should be abstract for abstract objects, but doing
++// that would cause custom components derived from abstract components to
++// have to include the typed object header / source, which could be a
++// problem if the custom component wasn't written for Coin in the first
++// place.
++
++#define SO at GUI@_OBJECT_ABSTRACT_HEADER(classname, parentname) \
++public: \
++ static void initClass(void); \
++ static SoType getClassTypeId(void); \
++ virtual SoType getTypeId(void) const /* = 0 (see comment above) */; \
++private: \
++ typedef parentname inherited; \
++ static SoType classTypeId
++
++#define SO at GUI@_OBJECT_HEADER(classname, parentname) \
++public: \
++ static void initClass(void); \
++ static SoType getClassTypeId(void); \
++ virtual SoType getTypeId(void) const; \
++ static void * createInstance(void); \
++private: \
++ typedef parentname inherited; \
++ static SoType classTypeId
++
++#define SO at GUI@_OBJECT_ABSTRACT_SOURCE(classname) \
++void classname::initClass(void) { \
++ assert(classname::classTypeId == SoType::badType()); \
++ classname::classTypeId = \
++ SoType::createType(inherited::getClassTypeId(), \
++ SO__QUOTE(classname)); \
++} \
++SoType classname::getClassTypeId(void) { \
++ return classname::classTypeId; \
++} \
++SoType classname::getTypeId(void) const { \
++ return classname::classTypeId; \
++} \
++SoType classname::classTypeId SO at GUI@_STATIC_SOTYPE_INIT
++
++#define SO at GUI@_OBJECT_SOURCE(classname) \
++void classname::initClass(void) { \
++ assert(classname::classTypeId == SoType::badType()); \
++ classname::classTypeId = \
++ SoType::createType(inherited::getClassTypeId(), \
++ SO__QUOTE(classname), \
++ classname::createInstance); \
++} \
++SoType classname::getClassTypeId(void) { \
++ return classname::classTypeId; \
++} \
++SoType classname::getTypeId(void) const { \
++ return classname::classTypeId; \
++} \
++void * classname::createInstance(void) { \
++ assert(classname::classTypeId != SoType::badType()); \
++ return (void *) new classname; \
++} \
++SoType classname::classTypeId SO at GUI@_STATIC_SOTYPE_INIT
++
++// *************************************************************************
++
++#endif // ! SO at GUI@OBJECT_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiP.h.in
+@@ -0,0 +1,69 @@
++#ifndef SOGUIP_H
++#define SOGUIP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++// ************************************************************************
++
++#include <Inventor/C/threads/mutex.h>
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// So at Gui@ class.
++
++class SoGuiP
++{
++public:
++ static void commonInit(void);
++ static void commonCleanup(void);
++
++ enum ABIError {
++ LINKTIME_MISMATCH, LINKSTYLE_MISMATCH, RUNTIME_MISMATCH
++ };
++ static void abort(SoGuiP::ABIError error);
++
++ static void sensorQueueChanged(void * cbdata);
++
++ static cc_mutex * gllockmutex;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiRenderArea.cpp.in
+@@ -0,0 +1,2244 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/**************************************************************************\
++ *
++ * A WORD OF ADVICE
++ *
++ * It is fruitless to modify the contents of the So at Gui@RenderArea.cpp file
++ * because it is autogenerated by configure from the SoGuiRenderArea.cpp.in
++ * file which you will find in the src/Inventor/@Gui@/common/ directory.
++ * Do your modifications to that file instead.
++ *
++\**************************************************************************/
++
++// *************************************************************************
++
++/*!
++ \class So at Gui@RenderArea Inventor/@Gui@/So at Gui@RenderArea.h
++ \brief The So at Gui@RenderArea class adds scenegraph handling and event management.
++ \ingroup components viewers
++
++ The So at Gui@RenderArea class is a component that adds scenegraph
++ management and input device event handling to the So at Gui@GLWidget
++ component.
++
++ The class has many convenient methods for controlling aspects of the
++ rendering, like for instance transparency, aliasing and for
++ scheduling of redraws.
++
++ Native toolkit events are caught by So at Gui@RenderArea components,
++ translated to Coin SoEvent instances and passed on to the
++ scenegraph, in case the user is doing interactive operations on for
++ instance Coin geometry draggers.
++
++
++ So at Gui@RenderArea is the first non-abstract component in it's
++ inheritance hierarchy that you can use directly from client
++ application code to set up a scenegraph viewer canvas.
++
++ For an So at Gui@RenderArea component to properly display your
++ scenegraph, it must contain an SoCamera-derived node and at least
++ one SoLight-derived lightsource node.
++
++ Here's a complete, stand-alone example on how to set up an
++ So at Gui@RenderArea with a scenegraph:
++
++ \code
++ #include <Inventor/@Gui@/So at Gui@.h>
++ #include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++ #include <Inventor/nodes/SoCube.h>
++ #include <Inventor/nodes/SoRotor.h>
++ #include <Inventor/nodes/SoArray.h>
++ #include <Inventor/nodes/SoDirectionalLight.h>
++ #include <Inventor/nodes/SoPerspectiveCamera.h>
++ #include <Inventor/nodes/SoSeparator.h>
++
++ // Set up a simple scenegraph, just for demonstration purposes.
++ static SoSeparator *
++ get_scene_graph(void)
++ {
++ SoSeparator * root = new SoSeparator;
++
++ SoGroup * group = new SoGroup;
++
++ SoRotor * rotor = new SoRotor;
++ rotor->rotation = SbRotation(SbVec3f(0.2, 0.5, 0.9), M_PI/4.0);
++ group->addChild(rotor);
++
++ SoCube * cube = new SoCube;
++ group->addChild(cube);
++
++ SoArray * array = new SoArray;
++ array->origin = SoArray::CENTER;
++ array->addChild(group);
++ array->numElements1 = 2;
++ array->numElements2 = 2;
++ array->separation1 = SbVec3f(4, 0, 0);
++ array->separation2 = SbVec3f(0, 4, 0);
++
++ root->addChild(array);
++ return root;
++ }
++
++ int
++ main(int argc, char ** argv)
++ {
++ @WIDGET@ window = So at Gui@::init(argv[0]);
++
++ SoSeparator * root = new SoSeparator;
++ root->ref();
++
++ SoPerspectiveCamera * camera;
++ root->addChild(camera = new SoPerspectiveCamera);
++
++ root->addChild(new SoDirectionalLight);
++
++ SoSeparator * userroot = get_scene_graph();
++ root->addChild(userroot);
++
++ So at Gui@RenderArea * renderarea = new So at Gui@RenderArea(window);
++ camera->viewAll(userroot, renderarea->getViewportRegion());
++ renderarea->setSceneGraph(root);
++ renderarea->setBackgroundColor(SbColor(0.0f, 0.2f, 0.3f));
++ if (argc > 1) {
++ renderarea->setTitle(argv[1]);
++ renderarea->setIconTitle(argv[1]);
++ }
++ renderarea->show();
++
++ So at Gui@::show(window);
++ So at Gui@::mainLoop();
++
++ delete renderarea;
++ root->unref();
++
++ return 0;
++ }
++ \endcode
++*/
++
++// *************************************************************************
++
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++#include <string.h> // strchr()
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#if SOQT_DEBUG // For the "soinfo" debugging backdoor.
++#include <qgl.h>
++#include <qapplication.h>
++#endif // SOQT_DEBUG
++
++#include <Inventor/@Gui@/common/gl.h> // glDrawBuffer()
++
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/actions/SoWriteAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/misc/SoBasic.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <Inventor/nodes/SoSelection.h>
++#include <Inventor/SoOffscreenRenderer.h>
++#include <Inventor/SbColor4f.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/devices/So at Gui@Keyboard.h>
++#include <Inventor/@Gui@/devices/So at Gui@Mouse.h>
++#ifdef HAVE_JOYSTICK_LINUX
++#include <Inventor/@Gui@/devices/So at Gui@LinuxJoystick.h>
++#endif // HAVE_JOYSTICK_LINUX
++#ifdef HAVE_SPACENAV_SUPPORT
++#include <Inventor/@Gui@/devices/So at Gui@SpacenavDevice.h>
++#endif // HAVE_SPACENAV_SUPPORT
++
++#include <Inventor/@Gui@/So at Gui@GLWidgetP.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++#define RENDERAREA_DEBUG_REDRAWS 0
++
++#define PRIVATE(obj) ((obj)->pimpl)
++#define PUBLIC(obj) ((obj)->pub)
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@RenderArea);
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++class So at Gui@RenderAreaP {
++public:
++
++ So at Gui@RenderAreaP(class So at Gui@RenderArea * pub);
++ ~So at Gui@RenderAreaP(void);
++
++ SbBool clear;
++ SbBool clearZBuffer;
++ SbBool clearOverlay;
++
++ SoSceneManager * normalManager;
++ SoSceneManager * overlayManager;
++
++ SbColor * normalColormap;
++ int normalColormapSize;
++ int normalColormapStart;
++ SbColor * overlayColormap;
++ int overlayColormapSize;
++ int overlayColormapStart;
++
++ SbPList * devicelist;
++
++ struct {
++ So at Gui@Keyboard * keyboard;
++ So at Gui@Mouse * mouse;
++#ifdef HAVE_SPACENAV_SUPPORT
++ So at Gui@SpacenavDevice * spacenav;
++#endif // HAVE_SPACENAV_SUPPORT
++ } devices;
++
++ SbBool autoRedraw;
++
++ void replaceSoSelectionMonitor(SoSelection * newsel, SoSelection * oldsel) const;
++ SoSelection * normalselection;
++ SoSelection * overlayselection;
++
++ static const int GL_DEFAULT_MODE;
++
++ void constructor(SbBool mouseInput, SbBool keyboardInput, SbBool build);
++ static void renderCB(void * user, SoSceneManager * manager);
++ static void selection_redraw_cb(void * data, SoSelection * sel);
++ void setDevicesWindowSize(const SbVec2s size);
++
++ // OpenGL info-window hack.
++ enum { NONE, OPENGL, INVENTOR, TOOLKIT, DUMPSCENEGRAPH, DUMPCAMERAS, OFFSCREENGRAB };
++ int checkMagicSequences(const char c);
++ void showOpenGLDriverInformation(void);
++ void showInventorInformation(void);
++ void showToolkitInformation(void);
++ void dumpScenegraph(void);
++ void dumpCameras(void);
++ void offScreenGrab(void);
++
++ SbBool invokeAppCB(@EVENT@ event);
++ const SoEvent * getSoEvent(@EVENT@ event);
++
++ So at Gui@RenderAreaEventCB * appeventhandler;
++ void * appeventhandlerdata;
++
++private:
++ So at Gui@RenderArea * pub; // public interface class
++ SbString currentinput; // For the OpenGL info-window hack.
++};
++
++const int So at Gui@RenderAreaP::GL_DEFAULT_MODE = (SO_GL_RGB |
++ SO_GL_ZBUFFER |
++ SO_GL_DOUBLE );
++
++#if SO at GUI@_DEBUG && defined(__COIN__)
++// Disabled when compiling against SGI / TGS Inventor, as we're using
++// our Coin-specific extension SbString::sprintf() a lot.
++#define DEBUGGING_EGGS 1
++#endif // SO at GUI@_DEBUG && __COIN__
++
++// Note: assumes a valid current OpenGL context.
++void
++So at Gui@RenderAreaP::showOpenGLDriverInformation(void)
++{
++#if DEBUGGING_EGGS
++ const GLubyte * vendor = glGetString(GL_VENDOR);
++ const GLubyte * renderer = glGetString(GL_RENDERER);
++ const GLubyte * version = glGetString(GL_VERSION);
++ const GLubyte * extensions = glGetString(GL_EXTENSIONS);
++
++ SbString info = "GL_VENDOR: \""; info += (const char *)vendor; info += "\"\n";
++ info += "GL_RENDERER: \""; info += (const char *)renderer; info += "\"\n";
++ info += "GL_VERSION: \""; info += (const char *)version; info += "\"\n";
++ info += "GL_EXTENSIONS: \"\n ";
++
++ SbString exts = (const char *)extensions;
++ const char * p;
++ int count = 0;
++ // (the extra parentheses in the while-expression kills a gcc warning)
++ while ((p = strchr(exts.getString(), ' '))) {
++ const char * start = exts.getString();
++ info += exts.getSubString(0, p - start);
++ exts.deleteSubString(0, p - start);
++ count++;
++ if (count == 4) { // number of extensions listed on each line
++ info += "\n ";
++ count = 0;
++ }
++ }
++ if (exts.getLength() > 0) { info += "\n "; info += exts; }
++ info += "\"\n";
++
++ // FIXME: should also show available GLX / WGL / AGL
++ // extensions. 20020802 mortene.
++
++ // Misc implementation info
++ {
++ SbVec2f range;
++ float granularity;
++ PUBLIC(this)->getPointSizeLimits(range, granularity);
++
++ SbString s;
++ s.sprintf("glPointSize(): range=[%f, %f], granularity=%f\n",
++ range[0], range[1], granularity);
++ info += s;
++
++
++ PUBLIC(this)->getLineWidthLimits(range, granularity);
++
++ s.sprintf("glLineWidth(): range=[%f, %f], granularity=%f\n",
++ range[0], range[1], granularity);
++ info += s;
++
++ GLint depthbits[1];
++ glGetIntegerv(GL_DEPTH_BITS, depthbits);
++ s.sprintf("GL_DEPTH_BITS==%d\n", depthbits[0]);
++ info += s;
++
++ GLint colbits[4];
++ glGetIntegerv(GL_RED_BITS, &colbits[0]);
++ glGetIntegerv(GL_GREEN_BITS, &colbits[1]);
++ glGetIntegerv(GL_BLUE_BITS, &colbits[2]);
++ glGetIntegerv(GL_ALPHA_BITS, &colbits[3]);
++ s.sprintf("GL_[RED|GREEN|BLUE|ALPHA]_BITS==[%d, %d, %d, %d]\n",
++ colbits[0], colbits[1], colbits[2], colbits[3]);
++ info += s;
++
++ GLint accumbits[4];
++ glGetIntegerv(GL_ACCUM_RED_BITS, &accumbits[0]);
++ glGetIntegerv(GL_ACCUM_GREEN_BITS, &accumbits[1]);
++ glGetIntegerv(GL_ACCUM_BLUE_BITS, &accumbits[2]);
++ glGetIntegerv(GL_ACCUM_ALPHA_BITS, &accumbits[3]);
++ s.sprintf("GL_ACCUM_[RED|GREEN|BLUE|ALPHA]_BITS==[%d, %d, %d, %d]\n",
++ accumbits[0], accumbits[1], accumbits[2], accumbits[3]);
++ info += s;
++
++ GLint stencilbits;
++ glGetIntegerv(GL_STENCIL_BITS, &stencilbits);
++ s.sprintf("GL_STENCIL_BITS==%d\n", stencilbits);
++ info += s;
++
++ GLint maxdims[2];
++ glGetIntegerv(GL_MAX_VIEWPORT_DIMS, maxdims);
++ s.sprintf("GL_MAX_VIEWPORT_DIMS==<%d, %d>\n", maxdims[0], maxdims[1]);
++ info += s;
++
++ GLint texdim;
++ glGetIntegerv(GL_MAX_TEXTURE_SIZE, &texdim);
++ s.sprintf("GL_MAX_TEXTURE_SIZE==%d\n", texdim);
++ info += s;
++
++ GLint maxlights;
++ glGetIntegerv(GL_MAX_LIGHTS, &maxlights);
++ s.sprintf("GL_MAX_LIGHTS==%d\n", maxlights);
++ info += s;
++
++ GLint maxplanes;
++ glGetIntegerv(GL_MAX_CLIP_PLANES, &maxplanes);
++ s.sprintf("GL_MAX_CLIP_PLANES==%d\n", maxplanes);
++ info += s;
++
++ // FIXME: other implementation specifics to print are
++ //
++ // * maximum stack depths (attribute, modelview matrix, name,
++ // projection matrix, texture matrix)
++ //
++ // * max display list nesting
++ //
++ // * max 3D texture size (needs specific extension?)
++ //
++ // 20020802 mortene.
++ }
++
++ SbString s;
++ s.sprintf("\n"
++ "Rendering is %sdirect.\n",
++ SoGuiGLWidgetP::isDirectRendering(PUBLIC(this)) ? "" : "in");
++ info += s;
++
++ So at Gui@::createSimpleErrorDialog(NULL, "OpenGL driver information",
++ info.getString());
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::showInventorInformation(void)
++{
++#if DEBUGGING_EGGS
++ SbString info;
++ info.sprintf("%s\n", SoDB::getVersion());
++
++ // Display calculated maximum resolution of SbTime::getTimeOfDay().
++ {
++ const double DURATION = 0.2; // in seconds
++ SbTime current = SbTime::getTimeOfDay();
++ SbTime end(current + DURATION);
++ SbTime last = current;
++ unsigned int ticks = 0;
++ do {
++ current = SbTime::getTimeOfDay();
++ if (current.getValue() != last.getValue()) { ticks++; last = current; }
++ } while (current < end);
++ SbString s;
++ s.sprintf("\nSbTime::getTimeOfDay() resolution: ~ %d Hz\n",
++ (int)(((double)ticks) / DURATION));
++ info += s;
++ }
++
++ // FIXME: dump list of available node classes? 20010927 mortene.
++ So at Gui@::createSimpleErrorDialog(NULL, "Inventor implementation info",
++ info.getString());
++
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::showToolkitInformation(void)
++{
++#if DEBUGGING_EGGS
++ SbString info = "So at Gui@ version "; info += SO at GUI@_VERSION; info += "\n";
++#if SO at GUI@_MAKE_DLL
++ info += "Built as MSWindows DLL.\n";
++#endif // !SO at GUI@_MAKE_DLL
++
++ // FIXME: include information about the underlying toolkit library,
++ // if possible, like we do for Qt below (ie Gtk version, Motif
++ // implementation, MSWindows version, ...). 20010927 mortene.
++
++#ifdef SOQT_INTERNAL
++ // Qt implementation info.
++ {
++ SbString s;
++ s.sprintf("\nQt version: %s\n", qVersion());
++ info += s;
++ }
++#endif // SOQT_INTERNAL
++
++ // FIXME: information about DLL path(s) (both for the So at Gui@ and
++ // Coin/Inventor library) would be _extremely_ useful for debugging
++ // "remote" applications, as application programmers (including
++ // ourselves) tend to spread those files around misc diskdrive
++ // directories -- especially on MSWindows platforms. Mismatches for
++ // run-time binding and link-time binding then causes bugs which are
++ // impossible to make sense of.
++ //
++ // I don't know if any platforms have enough introspection
++ // functionality to enable us to do this, though. Should
++ // investigate. (update: GetModuleHandle() looks like the place to
++ // start looking in the Win32 API.)
++ //
++ // 20010927 mortene.
++
++ // OpenGL canvas settings.
++ {
++ SbString s;
++ s.sprintf("\nCurrent OpenGL canvas:\n"
++ " %sbuffer\n"
++ " drawing to %sbuffer\n"
++ " %s rendering%s\n"
++ " %s mode\n"
++ " with%s overlay planes\n",
++ PUBLIC(this)->isDoubleBuffer() ? "double" : "single",
++ PUBLIC(this)->isDrawToFrontBufferEnable() ? "front" : "back",
++ PUBLIC(this)->isStereoBuffer() ? "stereo" : "mono",
++ PUBLIC(this)->isQuadBufferStereo() ? " (OpenGL quadbuffer)" : "",
++ PUBLIC(this)->isRGBMode() ? "RGB" : "colorindex",
++ PUBLIC(this)->isOverlayRender() ? "" : "out");
++
++ // FIXME: information about the native OpenGL widget format?
++ // 20010927 mortene.
++
++ info += s;
++ }
++
++ // Underlying Inventor implementation.
++ {
++ SbString s;
++ s.sprintf("\nInventor implementation: %s\n", SoDB::getVersion());
++ info += s;
++ }
++
++ So at Gui@::createSimpleErrorDialog(NULL, "So at Gui@ implementation info",
++ info.getString());
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::dumpScenegraph(void)
++{
++#ifdef DEBUGGING_EGGS
++ SoOutput out;
++ SbString filename = SbTime::getTimeOfDay().format();
++ filename += "-dump.iv";
++ SbBool ok = out.openFile(filename.getString());
++ if (!ok) {
++ SoDebugError::post("So at Gui@RenderAreaP::dumpScenegraph",
++ "couldn't open file '%s'", filename.getString());
++ return;
++ }
++ SoWriteAction wa(&out);
++ wa.apply(this->normalManager->getSceneGraph());
++ SoDebugError::postInfo("So at Gui@RenderAreaP::dumpScenegraph",
++ "dumped scenegraph to '%s'", filename.getString());
++#endif // DEBUGGING_EGGS
++}
++
++void
++So at Gui@RenderAreaP::dumpCameras(void)
++{
++#ifdef DEBUGGING_EGGS
++ const SbBool kitsearch = SoBaseKit::isSearchingChildren();
++ SoBaseKit::setSearchingChildren(TRUE);
++
++ SoSearchAction search;
++ search.setType(SoCamera::getClassTypeId());
++ search.setInterest(SoSearchAction::ALL);
++ search.setSearchingAll(TRUE);
++ search.apply(this->normalManager->getSceneGraph());
++
++ SoBaseKit::setSearchingChildren(kitsearch);
++
++ const SoPathList & pl = search.getPaths();
++ const unsigned int numcams = pl.getLength();
++ SoDebugError::postInfo("So at Gui@RenderAreaP::dumpCameras",
++ "Number of cameras in scene graph: %d",
++ numcams);
++
++ for (unsigned int i = 0; i < numcams; i++) {
++ const SoPath * p = pl[i];
++ SoNode * n = p->getTail();
++ assert(n->isOfType(SoCamera::getClassTypeId()));
++ SoCamera * cam = (SoCamera *)n;
++
++ const SbVec3f pos = cam->position.getValue();
++ const SbRotation rot = cam->orientation.getValue();
++ SbVec3f axis;
++ float angle;
++ rot.getValue(axis, angle);
++
++ SoDebugError::postInfo("So at Gui@RenderAreaP::dumpCameras",
++ "type==%s, name=='%s', position==<%f, %f, %f>, "
++ "orientation-rotation==<%f, %f, %f>--%f",
++ cam->getTypeId().getName().getString(),
++ cam->getName().getString(),
++ pos[0], pos[1], pos[2],
++ axis[0], axis[1], axis[2], angle);
++ }
++#endif // DEBUGGING_EGGS
++}
++
++/*
++ Behaviour controlled by environment variables
++ COIN_SOGRAB_GEOMETRY (maximum geometry - on-screen aspect is preserved)
++ COIN_SOGRAB_FILENAME (filename template - can use %d to insert counter)
++
++ Examples:
++ export COIN_SOGRAB_GEOMETRY=1024x768
++ export COIN_SOGRAB_FILENAME=c:\\grab%03d.png
++
++*/
++
++void
++So at Gui@RenderAreaP::offScreenGrab(void)
++{
++#ifdef DEBUGGING_EGGS
++ static int maxwidth = -1;
++ static int maxheight = -1;
++ static int counter = 0;
++ static const char fallback_ext[] = ".rgb";
++ static const char fallback_name[] = "coingrab%03d.rgb";
++
++ /*
++ FIXME:
++
++ - schedule a regular render-pass and hook into the render
++ pipe-line to check all the interesting GL context features that
++ might need to be enabled for the offscreen renderer context.
++ Then set up the offscreen renderer context to match those
++ features, so the rendering becomes the same.
++ - create a clone of the on-screen renderaction to get the same
++ kind of custom rendering.
++ - check if we might be able to hook up the on-screen pre-render
++ callback to the offscreen renderer as well, if any point.
++ - disable accidentally enabled seek mode again (from typing 'osgrab').
++
++ 20050606 larsa.
++ */
++
++ counter++;
++ if ( maxwidth <= 0 ) {
++ const char * env =
++ SoAny::si()->getenv("COIN_SOGRAB_GEOMETRY");
++ if ( env ) {
++ sscanf(env, "%dx%d", &maxwidth, &maxheight);
++ }
++ if ( (maxwidth <= 0) || !env ) {
++ SbVec2s vp = PUBLIC(this)->getViewportRegion().getWindowSize();
++ maxwidth = vp[0];
++ maxheight = vp[1];
++ }
++ }
++
++ if ( maxwidth <= 0 || maxheight <= 0 ) {
++ SoDebugError::post("So at Gui@RenderAreaP::offScreenGrab",
++ "invalid geometry: %dx%d", maxwidth, maxheight);
++ return;
++ }
++ SbVec2s vp = PUBLIC(this)->getViewportRegion().getWindowSize();
++
++ const char * filenametpl =
++ SoAny::si()->getenv("COIN_SOGRAB_FILENAME");
++ if ( !filenametpl ) filenametpl = fallback_name;
++
++ SbString filename;
++ filename.sprintf(filenametpl, counter);
++ const char * ext = strrchr(filename.getString(), '.');
++ if ( !ext ) ext = fallback_ext;
++ ext++;
++
++ SbVec2s osvp(maxwidth, maxheight);
++ if ( vp[0] > maxwidth || vp[1] > maxheight ||
++ (vp[0] < maxwidth && vp[1] < maxheight) ) {
++ float onscaspect = float(vp[0]) / float(vp[1]);
++ float offscaspect = float(maxwidth) / float(maxheight);
++
++ osvp[1] = maxheight;
++ osvp[0] = short(maxheight * onscaspect);
++ if ( osvp[0] > maxwidth ) {
++ osvp[0] = maxwidth;
++ osvp[1] = short(maxwidth * (1.0f / onscaspect));
++ }
++ }
++
++ SoOffscreenRenderer os(osvp);
++ if ( !os.render(PUBLIC(this)->getSceneManager()->getSceneGraph()) ) {
++ return;
++ }
++
++ SbBool written = FALSE;
++ if (strcmp(ext, "rgb") == 0) {
++ written = os.writeToRGB(filename.getString());
++ }
++ else {
++ written = os.writeToFile(filename, ext);
++ }
++
++ if (written) {
++ SoDebugError::postInfo("So at Gui@RenderAreaP::offScreenGrab",
++ "wrote image #%d, %dx%d as '%s'",
++ counter, osvp[0], osvp[1],
++ filename.getString());
++ }
++ else {
++ SoDebugError::post("So at Gui@RenderAreaP::offScreenGrab",
++ "tried to write image '%s', but failed for unknown "
++ "reason",
++ filename.getString());
++ }
++#endif // DEBUGGING_EGGS
++}
++
++int
++So at Gui@RenderAreaP::checkMagicSequences(const char c)
++{
++#if DEBUGGING_EGGS
++ this->currentinput += c;
++
++ if (0) { // handy for debugging keyboard handling
++ SoDebugError::postInfo("So at Gui@RenderAreaP::checkMagicSequences",
++ "'%s'", this->currentinput.getString());
++ }
++
++ const int cl = this->currentinput.getLength();
++
++ static const char * keyseq[] = {
++ "glinfo", "ivinfo", "soinfo", "dumpiv", "cameras", "osgrab"
++ };
++ static const int id[] = {
++ So at Gui@RenderAreaP::OPENGL,
++ So at Gui@RenderAreaP::INVENTOR,
++ So at Gui@RenderAreaP::TOOLKIT,
++ So at Gui@RenderAreaP::DUMPSCENEGRAPH,
++ So at Gui@RenderAreaP::DUMPCAMERAS,
++ So at Gui@RenderAreaP::OFFSCREENGRAB
++ };
++
++ for (unsigned int i = 0; i < (sizeof(keyseq) / sizeof(keyseq[0])); i++) {
++ const int ml = strlen(keyseq[i]);
++ if (cl >= ml && this->currentinput.getSubString(cl - ml) == keyseq[i]) {
++ return id[i];
++ }
++ }
++
++ // Limit memory usage.
++ if (cl > 1024) { this->currentinput = ""; }
++#endif // DEBUGGING_EGGS
++
++ return So at Gui@RenderAreaP::NONE;
++}
++
++// This method sets the window size data in all the connected device
++// classes.
++void
++So at Gui@RenderAreaP::setDevicesWindowSize(const SbVec2s size)
++{
++ if (!this->devicelist) return;
++ const int num = this->devicelist->getLength();
++ for (int i = 0; i < num; i++)
++ ((So at Gui@Device *)(*this->devicelist)[i])->setWindowSize(size);
++}
++
++// *************************************************************************
++
++void
++So at Gui@RenderAreaP::renderCB(void * closure, SoSceneManager * manager)
++{
++ assert(closure && manager);
++ So at Gui@RenderArea * thisptr = (So at Gui@RenderArea *) closure;
++ if (manager == PRIVATE(thisptr)->normalManager) {
++ thisptr->render();
++ } else if (manager == PRIVATE(thisptr)->overlayManager) {
++ thisptr->renderOverlay();
++ } else {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@RenderAreaP::renderCB",
++ "invoked for unknown SoSceneManager (%p)", manager);
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++}
++
++// Callback for automatic redraw on SoSelection changes.
++void
++So at Gui@RenderAreaP::selection_redraw_cb(void * closure, SoSelection * sel)
++{
++ So at Gui@RenderArea * ra = (So at Gui@RenderArea *) closure;
++ if (sel == PRIVATE(ra)->normalselection)
++ ra->scheduleRedraw();
++ else if (sel == PRIVATE(ra)->overlayselection)
++ ra->scheduleOverlayRedraw();
++ else
++ assert(0 && "callback on unknown SoSelection node");
++}
++
++// Private class constructor.
++So at Gui@RenderAreaP::So at Gui@RenderAreaP(So at Gui@RenderArea * api)
++{
++ PUBLIC(this) = api;
++
++ this->normalManager = new SoSceneManager;
++ this->overlayManager = new SoSceneManager;
++
++ this->normalColormap = NULL;
++ this->normalColormapSize = 0;
++ this->overlayColormap = NULL;
++ this->overlayColormapSize = 0;
++
++ this->clear = TRUE;
++ this->clearZBuffer = TRUE;
++ this->clearOverlay = TRUE;
++ this->autoRedraw = TRUE;
++
++ this->normalselection = NULL;
++ this->overlayselection = NULL;
++
++ this->devices.mouse = NULL;
++ this->devices.keyboard = NULL;
++#ifdef HAVE_SPACENAV_SUPPORT
++ this->devices.spacenav = NULL;
++#endif // HAVE_SPACENAV_SUPPORT
++
++}
++
++// Private class destructor.
++So at Gui@RenderAreaP::~So at Gui@RenderAreaP()
++{
++ delete this->normalManager;
++ delete this->overlayManager;
++ delete [] this->normalColormap;
++ delete [] this->overlayColormap;
++}
++
++// Common code for all constructors.
++void
++So at Gui@RenderAreaP::constructor(SbBool mouseInput,
++ SbBool keyboardInput,
++ SbBool build)
++{
++ this->normalManager->setRenderCallback(So at Gui@RenderAreaP::renderCB, PUBLIC(this));
++ this->normalManager->activate();
++ this->overlayManager->setRenderCallback(So at Gui@RenderAreaP::renderCB, PUBLIC(this));
++ this->overlayManager->activate();
++ // FIXME: what is this magic number doing here - shouldn't we use
++ // SoGLCacheContextElement::getUniqueCacheContext() for Coin, and
++ // magic numbers just for SGI / TGS Inventor?
++ //
++ // On a side note: won't this code fail if we construct several
++ // So at Gui@RenderArea instances with overlays? They will all use
++ // cachecontext==1 for their SoGLRenderAction instances -- is that
++ // kosher?
++ //
++ // 20010831 mortene.
++ this->overlayManager->getGLRenderAction()->setCacheContext(1);
++
++ this->appeventhandler = NULL;
++ this->appeventhandlerdata = NULL;
++
++ this->devicelist = new SbPList;
++
++ if (mouseInput) {
++ this->devices.mouse = new So at Gui@Mouse;
++ PUBLIC(this)->registerDevice(this->devices.mouse);
++ }
++
++ if (keyboardInput) {
++ this->devices.keyboard = new So at Gui@Keyboard;
++ PUBLIC(this)->registerDevice(this->devices.keyboard);
++ }
++
++ if (! build) return;
++ PUBLIC(this)->setClassName("So at Gui@RenderArea");
++ @WIDGET@ glarea = PUBLIC(this)->buildWidget(PUBLIC(this)->getParentWidget());
++ PUBLIC(this)->setBaseWidget(glarea);
++ PUBLIC(this)->setSize(SbVec2s(400, 400));
++}
++
++// This method invokes the application event handler, if one is set.
++SbBool
++So at Gui@RenderAreaP::invokeAppCB(@EVENT@ event)
++{
++ if (this->appeventhandler != NULL)
++ return this->appeventhandler(this->appeventhandlerdata, event);
++ return FALSE;
++}
++
++// This method returns an SoEvent * corresponding to the given \a
++// event, or \c NULL if there are none.
++const SoEvent *
++So at Gui@RenderAreaP::getSoEvent(@EVENT@ event)
++{
++ if (!this->devicelist)
++ return (SoEvent *) NULL;
++
++ const SoEvent * soevent = NULL;
++ const int num = this->devicelist->getLength();
++ for (int i = 0; (i < num) && (soevent == NULL); i++)
++ soevent = ((So at Gui@Device *)(*this->devicelist)[i])->translateEvent(event);
++
++ return soevent;
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++/*!
++ Public constructor.
++*/
++So at Gui@RenderArea::So at Gui@RenderArea(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ SbBool mouseInput,
++ SbBool keyboardInput)
++ : inherited(parent, name, embed, So at Gui@RenderAreaP::GL_DEFAULT_MODE, FALSE)
++{
++ PRIVATE(this) = new So at Gui@RenderAreaP(this);
++ PRIVATE(this)->constructor(mouseInput, keyboardInput, TRUE);
++}
++
++/*!
++ Protected constructor used by derived classes.
++*/
++So at Gui@RenderArea::So at Gui@RenderArea(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ SbBool mouseInput,
++ SbBool keyboardInput,
++ SbBool build)
++ : inherited(parent, name, embed, So at Gui@RenderAreaP::GL_DEFAULT_MODE, FALSE)
++{
++ PRIVATE(this) = new So at Gui@RenderAreaP(this);
++ PRIVATE(this)->constructor(mouseInput, keyboardInput, build);
++}
++
++/*!
++ Destructor.
++*/
++So at Gui@RenderArea::~So at Gui@RenderArea()
++{
++ // Clean out any callbacks we may have registered with SoSelection
++ // nodes.
++ this->redrawOverlayOnSelectionChange(NULL);
++ this->redrawOnSelectionChange(NULL);
++
++ for (int i = PRIVATE(this)->devicelist->getLength() - 1; i >= 0; i--) {
++ So at Gui@Device * device = (So at Gui@Device *) ((*PRIVATE(this)->devicelist)[i]);
++ this->unregisterDevice(device);
++ delete device;
++ }
++ delete PRIVATE(this)->devicelist;
++ delete PRIVATE(this);
++}
++
++// *************************************************************************
++
++/*!
++ This method adds \a device to the list of devices handling events
++ for this component.
++*/
++void
++So at Gui@RenderArea::registerDevice(So at Gui@Device * device)
++{
++ int idx = PRIVATE(this)->devicelist->find(device);
++ if (idx != -1) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@RenderArea::registerDevice",
++ "device already registered");
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++
++ PRIVATE(this)->devicelist->append(device);
++ @WIDGET@ w = this->getGLWidget();
++ if (w != NULL) {
++#ifdef __COIN_SOXT__
++ device->enable(w, (SoXtEventHandler *) &So at Gui@GLWidget::eventHandler, (void *)this);
++#else
++ device->enable(w, &So at Gui@GLWidgetP::eventHandler, (void *)this);
++#endif
++ device->setWindowSize(this->getGLSize());
++ }
++}
++
++/*!
++ This method removes \a device from the list of devices handling
++ events for this component.
++*/
++void
++So at Gui@RenderArea::unregisterDevice(So at Gui@Device * device)
++{
++ assert(PRIVATE(this)->devicelist != NULL);
++ const int idx = PRIVATE(this)->devicelist->find(device);
++ if (idx == -1) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@RenderArea::unregisterDevice",
++ "tried to remove nonexisting device");
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++
++ PRIVATE(this)->devicelist->remove(idx);
++ @WIDGET@ w = this->getGLWidget();
++ if (w != NULL) { device->disable(w, NULL, NULL); }
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@RenderArea::afterRealizeHook(void)
++{
++ inherited::afterRealizeHook();
++
++#ifdef HAVE_JOYSTICK_LINUX
++ if (So at Gui@LinuxJoystick::exists())
++ this->registerDevice(new So at Gui@LinuxJoystick);
++#endif // HAVE_JOYSTICK_LINUX
++
++#ifdef HAVE_SPACENAV_SUPPORT
++ PRIVATE(this)->devices.spacenav = new So at Gui@SpacenavDevice;
++ this->registerDevice(PRIVATE(this)->devices.spacenav);
++#endif // HAVE_SPACENAV_SUPPORT
++}
++
++/*!
++ This method sets the scene graph to be rendered in the normal bitmap
++ planes.
++
++ \sa getSceneGraph(), setOverlaySceneGraph()
++*/
++void
++So at Gui@RenderArea::setSceneGraph(SoNode * scene)
++{
++ PRIVATE(this)->normalManager->setSceneGraph(scene);
++}
++
++/*!
++ This method returns a reference to the scene graph root node as set
++ by the user.
++
++ \sa So at Gui@RenderArea::getSceneManager()
++*/
++SoNode *
++So at Gui@RenderArea::getSceneGraph(void)
++{
++ return PRIVATE(this)->normalManager->getSceneGraph();
++}
++
++/*!
++ This method sets the scene graph to render for the overlay bitmap
++ planes.
++
++ It will automatically take care of setting up overplay planes in the
++ OpenGL canvas if the OpenGL hardware and driver supports it.
++
++ Important note: not all graphics hardware and / or drivers for
++ graphics hardware support overlay planes, so application programmers
++ are adviced to find some other way of accomplishing what they want
++ to do before resorting to using overlay planes. Using overlay
++ planes will in practice severely limit the portability of
++ applications which depend on them being available.
++
++ \sa setSceneGraph(), getOverlaySceneGraph()
++*/
++void
++So at Gui@RenderArea::setOverlaySceneGraph(SoNode * scene)
++{
++ SoNode * oldroot = this->getOverlaySceneGraph();
++ PRIVATE(this)->overlayManager->setSceneGraph(scene);
++
++ if (!oldroot && scene) { this->setOverlayRender(TRUE); }
++ else if (oldroot && !scene) { this->setOverlayRender(FALSE); }
++}
++
++/*!
++ This method returns the scene graph for the overlay scene.
++*/
++SoNode *
++So at Gui@RenderArea::getOverlaySceneGraph(void)
++{
++ return PRIVATE(this)->overlayManager->getSceneGraph();
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the background color of the scene.
++*/
++void
++So at Gui@RenderArea::setBackgroundColor(const SbColor & color)
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ PRIVATE(this)->normalManager->setBackgroundColor(color);
++ this->scheduleRedraw();
++}
++
++/*!
++ This method returns the background color for the scene.
++*/
++const SbColor &
++So at Gui@RenderArea::getBackgroundColor(void) const
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++#if HAVE_SBCOLOR4F_GETBACKGROUNDCOLOR
++ SbColor4f bgcol = PRIVATE(this)->normalManager->getBackgroundColor();
++ return SbColor(bgcol[0], bgcol[1], bgcol[2]);
++#else
++ return PRIVATE(this)->normalManager->getBackgroundColor();
++#endif
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the index of the background color for the scene.
++*/
++void
++So at Gui@RenderArea::setBackgroundIndex(int idx)
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ PRIVATE(this)->normalManager->setBackgroundIndex(idx);
++ this->scheduleRedraw();
++}
++
++/*!
++ This method returns the index of the background color for the scene.
++*/
++int
++So at Gui@RenderArea::getBackgroundIndex(void) const
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ return PRIVATE(this)->normalManager->getBackgroundIndex();
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the index of the background for the overlay scene.
++*/
++void
++So at Gui@RenderArea::setOverlayBackgroundIndex(int idx)
++{
++ assert(PRIVATE(this)->overlayManager != NULL);
++ PRIVATE(this)->overlayManager->setBackgroundIndex(idx);
++ this->scheduleOverlayRedraw();
++}
++
++/*!
++ This method returns the index of the background for the overlay scene.
++*/
++int
++So at Gui@RenderArea::getOverlayBackgroundIndex(void) const
++{
++ assert(PRIVATE(this)->overlayManager != NULL);
++ return PRIVATE(this)->overlayManager->getBackgroundIndex();
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the colormap for the scene.
++*/
++void
++So at Gui@RenderArea::setColorMap(int start, int num, const SbColor * colors)
++{
++ delete [] PRIVATE(this)->normalColormap;
++ PRIVATE(this)->normalColormapStart = start;
++ PRIVATE(this)->normalColormapSize = num;
++ PRIVATE(this)->normalColormap = new SbColor [ num ];
++ for (int i = 0; i < num; i++)
++ PRIVATE(this)->normalColormap[i] = colors[i];
++ this->scheduleRedraw();
++}
++
++/*!
++ This method sets the colormap for the overlay scene.
++*/
++void
++So at Gui@RenderArea::setOverlayColorMap(int start, int num,
++ const SbColor * colors)
++{
++ delete [] PRIVATE(this)->overlayColormap;
++ PRIVATE(this)->overlayColormapStart = start;
++ PRIVATE(this)->overlayColormapSize = num;
++ PRIVATE(this)->overlayColormap = new SbColor [ num ];
++ for (int i = 0; i < num; i++) {
++ PRIVATE(this)->overlayColormap[i] = colors[i];
++ }
++ this->scheduleOverlayRedraw();
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the viewport region.
++*/
++void
++So at Gui@RenderArea::setViewportRegion(const SbViewportRegion & region)
++{
++ if (region.getWindowSize()[0] == -1) return;
++
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@RenderArea::setViewportRegion",
++ "size=<%d, %d>",
++ region.getWindowSize()[0],
++ region.getWindowSize()[1]);
++#endif // debug
++
++ PRIVATE(this)->normalManager->setViewportRegion(region);
++ PRIVATE(this)->overlayManager->setViewportRegion(region);
++ this->scheduleRedraw();
++}
++
++/*!
++ This method returns the viewport region.
++*/
++const SbViewportRegion &
++So at Gui@RenderArea::getViewportRegion(void) const
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ return PRIVATE(this)->normalManager->getGLRenderAction()->getViewportRegion();
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the transparency type to be used for the scene.
++*/
++void
++So at Gui@RenderArea::setTransparencyType(SoGLRenderAction::TransparencyType type)
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ PRIVATE(this)->normalManager->getGLRenderAction()->setTransparencyType(type);
++ PRIVATE(this)->overlayManager->getGLRenderAction()->setTransparencyType(type);
++ this->scheduleRedraw();
++}
++
++/*!
++ This method returns the transparency type used for the scene.
++*/
++SoGLRenderAction::TransparencyType
++So at Gui@RenderArea::getTransparencyType(void) const
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ return PRIVATE(this)->normalManager->getGLRenderAction()->getTransparencyType();
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the antialiasing used for the scene.
++
++ The \a smoothing flag signifies whether or not line and point
++ aliasing should be turned on. See documentation of
++ SoGLRenderAction::setSmoothing(), which will be called from this
++ function.
++
++ \a numPasses gives the number of re-renderings to do of the scene,
++ blending together the results from slight "jitters" of the camera
++ view, into the OpenGL accumulation buffer. For further information,
++ see documentation of SoGLRenderAction::setNumPasses() and
++ So at Gui@GLWidget::setAccumulationBuffer().
++*/
++void
++So at Gui@RenderArea::setAntialiasing(SbBool smoothing, int numPasses)
++{
++ // FIXME: is this really necessary? I think we should either ignore
++ // the call or store values for later migration if the scenemanager
++ // instance(s) haven't been made yet. 20010331 mortene.
++ assert(PRIVATE(this)->normalManager != NULL);
++
++ // Instead of piping the call further to
++ // SoSceneManager::setAntialiasing(), we duplicate the code found in
++ // that function. The reason for this is that we want to work around
++ // a bug found in SGI Inventor, where they define the
++ // setAntialiasing() method, but doesn't actually implement it. So
++ // we don't use it to avoid a linker error for those compiling So*
++ // libraries on top of the older SGI Inventor versions with this
++ // bug.
++ //
++ // We should perhaps throw in a configure check for the
++ // SoSceneManager::setAntialiasing() method and only activate this
++ // code when actually needed?
++ // mortene at sim.no
++ enum { MGRS = 2 };
++ SoSceneManager * mgrs[MGRS] = { PRIVATE(this)->normalManager,
++ PRIVATE(this)->overlayManager };
++ for (int i=0; i < MGRS; i++) {
++ SoGLRenderAction * glra = mgrs[i]->getGLRenderAction();
++ if (glra) {
++ glra->setSmoothing(smoothing);
++ glra->setNumPasses(numPasses);
++ }
++ }
++
++ this->scheduleRedraw();
++}
++
++/*!
++ This method returns the antialiasing used for the scene.
++*/
++void
++So at Gui@RenderArea::getAntialiasing(SbBool & smoothing, int & numPasses) const
++{
++ // FIXME: there's an API design flaw here, as it is assumed that the
++ // antialiasing setting for the renderaction in the "normal"
++ // rendering context always matches what is the case for the
++ // renderaction in the overlay manager. This is not necessarily
++ // true. Could be solved by an additional argument to
++ // getAntialiasing(): a boolean indicator on whether or not we want
++ // the overlay context with a default value (false) to keep API
++ // compatibility. 20010331 mortene.
++
++ assert(PRIVATE(this)->normalManager != NULL);
++
++ // About why we don't use SoSceneManager::getAntialiasing()
++ // directly, see comment in SoGuiRenderArea::setAntiAliasing().
++ SoGLRenderAction * glra = PRIVATE(this)->normalManager->getGLRenderAction();
++ smoothing = glra->isSmoothing();
++ numPasses = glra->getNumPasses();
++}
++
++/*!
++ This method sets whether the render buffer should be cleared before
++ rendering.
++
++ The first argument specifies whether or not to clear out the pixels
++ in the buffer, the second argument specifies whether or not the
++ z-buffer values should be cleared between renderings.
++
++ Setting the first argument to \c FALSE can for instance be used when
++ you want to clear out the buffer yourself, for instance by drawing a
++ background image "under" the 3D scene rendered by Coin / Inventor.
++*/
++void
++So at Gui@RenderArea::setClearBeforeRender(SbBool enable, SbBool zbEnable)
++{
++ PRIVATE(this)->clear = enable;
++ PRIVATE(this)->clearZBuffer = zbEnable;
++
++ this->scheduleRedraw();
++}
++
++/*!
++ This method returns whether the render buffer is cleared before each
++ render.
++*/
++SbBool
++So at Gui@RenderArea::isClearBeforeRender(void) const
++{
++ return PRIVATE(this)->clear;
++}
++
++/*!
++ This method returns whether the render buffer's Z buffer is cleared
++ before each render.
++*/
++SbBool
++So at Gui@RenderArea::isClearZBufferBeforeRender(void) const
++{
++ return PRIVATE(this)->clearZBuffer;
++}
++
++/*!
++ This method sets whether the overlay render buffer should be cleared
++ before each render or not.
++*/
++void
++So at Gui@RenderArea::setClearBeforeOverlayRender(SbBool enable)
++{
++ PRIVATE(this)->clearOverlay = enable;
++ this->scheduleOverlayRedraw();
++}
++
++/*!
++ This method returns whether the overlay render buffer is cleared
++ before each redraw or not.
++*/
++SbBool
++So at Gui@RenderArea::isClearBeforeOverlayRender(void) const
++{
++ return PRIVATE(this)->clearOverlay;
++}
++
++/*!
++ This method sets whether redrawing should be handled automatically
++ or not when data in the scenegraph changes.
++
++ The default setting causes the renderarea to automatically trigger a
++ redraw of the scenegraph contents.
++*/
++void
++So at Gui@RenderArea::setAutoRedraw(SbBool enable)
++{
++ if (enable) {
++ PRIVATE(this)->normalManager->activate();
++ PRIVATE(this)->overlayManager->activate();
++ }
++ else {
++ PRIVATE(this)->normalManager->deactivate();
++ PRIVATE(this)->overlayManager->deactivate();
++ }
++ PRIVATE(this)->autoRedraw = enable;
++}
++
++/*!
++ This method returns whether redrawing is handled automatically
++ not.
++*/
++SbBool
++So at Gui@RenderArea::isAutoRedraw(void) const
++{
++ return PRIVATE(this)->autoRedraw;
++}
++
++/*!
++ This method sets the redraw priority.
++*/
++void
++So at Gui@RenderArea::setRedrawPriority(uint32_t priority)
++{
++ PRIVATE(this)->normalManager->setRedrawPriority(priority);
++ PRIVATE(this)->overlayManager->setRedrawPriority(priority);
++}
++
++/*!
++ This method returns the redraw priority.
++*/
++uint32_t
++So at Gui@RenderArea::getRedrawPriority(void) const
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ return PRIVATE(this)->normalManager->getRedrawPriority();
++}
++
++/*!
++ This function returns the default redraw priority.
++*/
++uint32_t
++So at Gui@RenderArea::getDefaultRedrawPriority(void)
++{
++ return SoSceneManager::getDefaultRedrawPriority();
++}
++
++/*!
++ This method causes the immediate rendering of the scene, by calling
++ So at Gui@RenderArea::redraw().
++*/
++void
++So at Gui@RenderArea::render(void)
++{
++ this->redraw();
++}
++
++/*!
++ This method renders the overlay scene.
++*/
++void
++So at Gui@RenderArea::renderOverlay(void)
++{
++ this->redrawOverlay();
++}
++
++/*!
++ This method schedules a redraw to happen at a later time (when the
++ application has processed it's other events first).
++*/
++void
++So at Gui@RenderArea::scheduleRedraw(void)
++{
++#if SO at GUI@_DEBUG && RENDERAREA_DEBUG_REDRAWS // debug
++ SoDebugError::postInfo("So at Gui@RenderArea::scheduleRedraw",
++ "invoked");
++#endif // debug
++
++ assert(PRIVATE(this)->normalManager != NULL);
++ PRIVATE(this)->normalManager->scheduleRedraw(); // Redraw when idle.
++}
++
++/*!
++ This method schedules a redraw of the overlay scene.
++*/
++void
++So at Gui@RenderArea::scheduleOverlayRedraw(void)
++{
++ assert(PRIVATE(this)->overlayManager != NULL);
++ PRIVATE(this)->overlayManager->scheduleRedraw(); // Redraw when idle.
++}
++
++#ifndef DOXYGEN_SKIP_THIS
++void
++So at Gui@RenderAreaP::replaceSoSelectionMonitor(SoSelection * newsel,
++ SoSelection * oldsel) const
++{
++ if (newsel) { newsel->ref(); }
++
++ if (oldsel) {
++ oldsel->removeChangeCallback(So at Gui@RenderAreaP::selection_redraw_cb,
++ PUBLIC(this));
++ oldsel->unref();
++ }
++
++ if (newsel) {
++ newsel->addChangeCallback(So at Gui@RenderAreaP::selection_redraw_cb,
++ PUBLIC(this));
++ }
++}
++#endif // DOXYGEN_SKIP_THIS
++
++// FIXME: the interface below is badly designed, see the comment in
++// the function documentation. 20001002 mortene.
++
++/*!
++ Do automatic redraw of the scenegraph when a selection under the
++ SoSelection node is changed.
++
++ Pass \c NULL to deactivate.
++
++ (Only one SoSelection node can be monitored at any given time. This
++ is obviously a rather silly design flaw. We choose to match the
++ original Inventor API here, but this will probably change in the
++ next major revision of the library.)
++*/
++void
++So at Gui@RenderArea::redrawOnSelectionChange(SoSelection * selection)
++{
++ PRIVATE(this)->replaceSoSelectionMonitor(selection, PRIVATE(this)->normalselection);
++ PRIVATE(this)->normalselection = selection;
++}
++
++/*!
++ Do automatic redraw of the scenegraph in the overlay planes when a
++ selection under the SoSelection node is changed.
++
++ Pass \c NULL to deactivate.
++
++ \sa So at Gui@RenderArea::redrawOnSelectionChange()
++*/
++void
++So at Gui@RenderArea::redrawOverlayOnSelectionChange(SoSelection * selection)
++{
++ PRIVATE(this)->replaceSoSelectionMonitor(selection, PRIVATE(this)->overlayselection);
++ PRIVATE(this)->overlayselection = selection;
++}
++
++/*!
++ This method sets the render area event callback.
++*/
++void
++So at Gui@RenderArea::setEventCallback(So at Gui@RenderAreaEventCB * func,
++ void * user)
++{
++ PRIVATE(this)->appeventhandler = func;
++ PRIVATE(this)->appeventhandlerdata = user;
++}
++
++/*!
++ This method sets the normal scene SoSceneManager object.
++
++ The previous set scene manager is deleted, and there is no way to
++ currently avoid that. This might change in the future.
++*/
++void
++So at Gui@RenderArea::setSceneManager(SoSceneManager * manager)
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ PRIVATE(this)->normalManager->setRenderCallback(NULL, NULL);
++
++ // NOTE: Although deleting the previous scene manager here is correct
++ // behaviour from a compatibility-POV, I think it is ugly and should
++ // be addressed in some other way if possible. It is also inconsistent
++ // with overlay scenemanager management. 20061015 larsa
++ delete PRIVATE(this)->normalManager;
++
++ PRIVATE(this)->normalManager = manager;
++ if (PRIVATE(this)->normalManager) {
++ PRIVATE(this)->normalManager->setSize(this->getGLSize());
++ }
++}
++
++/*!
++ This method returns the normal scene SoSceneManager object.
++
++ Having a reference to the SoSceneManager instance is useful for
++ getting at the \e real root node of the rendering scenegraph,
++ including camera, headlight and miscellaneous drawstyle nodes. The
++ getSceneGraph() method will only return the \e user scenegrah for
++ So at Gui@RenderArea subclass So at Gui@Viewer and further subclasses. The
++ reason this is not always what you want is because certain actions
++ (like the SoRayPickAction) needs to traverse a valid camera if it
++ should work as expected.
++
++ If you need to get a pointer to the \e real root node use this
++ method to get the SoSceneManager instance reference used by the
++ So at Gui@RenderArea, then use SoSceneManager::getSceneGraph() to get
++ the root node Coin uses for rendering.
++*/
++SoSceneManager *
++So at Gui@RenderArea::getSceneManager(void) const
++{
++ return PRIVATE(this)->normalManager;
++}
++
++/*!
++ This method sets the overlay scene SoSceneManager object.
++
++ The previous set scene manager is not freed and will leak unless
++ the user frees it.
++*/
++void
++So at Gui@RenderArea::setOverlaySceneManager(SoSceneManager * manager)
++{
++ PRIVATE(this)->overlayManager = manager;
++ if (PRIVATE(this)->overlayManager) {
++ PRIVATE(this)->overlayManager->setSize(this->getGLSize());
++ }
++}
++
++/*!
++ This method returns the overlay scene SoSceneManager object.
++*/
++SoSceneManager *
++So at Gui@RenderArea::getOverlaySceneManager(void) const
++{
++ return PRIVATE(this)->overlayManager;
++}
++
++/*!
++ This method sets the SoGLRenderAction object for the normal scene.
++*/
++void
++So at Gui@RenderArea::setGLRenderAction(SoGLRenderAction * action)
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ PRIVATE(this)->normalManager->setGLRenderAction(action);
++ // Force an update of the SoGLRenderAction to the correct
++ // updatearea, aspectratio, etc.
++ this->sizeChanged(this->getSize());
++}
++
++/*!
++ This method returns the SoGLRenderAction object for the normal scene.
++*/
++SoGLRenderAction *
++So at Gui@RenderArea::getGLRenderAction(void) const
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ return PRIVATE(this)->normalManager->getGLRenderAction();
++}
++
++/*!
++ This method sets the SoGLRenderAction object for rendering the
++ overlay scenegraph.
++*/
++void
++So at Gui@RenderArea::setOverlayGLRenderAction(SoGLRenderAction * action)
++{
++ assert(PRIVATE(this)->overlayManager != NULL);
++ PRIVATE(this)->overlayManager->setGLRenderAction(action);
++}
++
++/*!
++ This method returns the SoGLRenderAction object for the overlay scene
++ graph.
++*/
++SoGLRenderAction *
++So at Gui@RenderArea::getOverlayGLRenderAction(void) const
++{
++ assert(PRIVATE(this)->overlayManager != NULL);
++ return PRIVATE(this)->overlayManager->getGLRenderAction();
++}
++
++/*!
++ This method is called from the render() method and takes care of
++ setting up the context for OpenGL rendering (by making the OpenGL
++ canvas the current context and specifying either the front or back
++ buffer for rendering, depending on whether we're in singlebuffer or
++ doublebuffer mode).
++
++ After setting up the OpenGL context, it calls actualRedraw() for the
++ actual scenegraph rendering to take place.
++
++ Finally, the OpenGL buffers are either swapped back-to-front (for
++ doublebuffering) or flushed (for singlebuffering), and our OpenGL
++ context is unlocked.
++
++ The application programmer may override this method if extreme
++ low-level control of the rendering process is necessary. Usually,
++ you should be able to get away with overriding actualRedraw() for
++ special cases, though.
++*/
++void
++So at Gui@RenderArea::redraw(void)
++{
++#if SO at GUI@_DEBUG && RENDERAREA_DEBUG_REDRAWS // debug
++ SoDebugError::postInfo("So at Gui@RenderArea::redraw",
++ "start (isVisible=%s waitForExpose=%s)",
++ this->isVisible() ? "TRUE" : "FALSE",
++ this->waitForExpose ? "TRUE" : "FALSE");
++#endif // debug
++
++ if (! this->isVisible() || !this->hasNormalGLArea() || this->waitForExpose)
++ return;
++ this->glLockNormal(); // this makes the GL context "current"
++
++ SbBool drawfront =
++ ! this->isDoubleBuffer() ||
++ this->isDrawToFrontBufferEnable();
++
++ glDrawBuffer(drawfront ? GL_FRONT : GL_BACK);
++
++ this->actualRedraw();
++
++ if (!drawfront) { this->glSwapBuffers(); }
++ else { this->glFlushBuffer(); }
++ this->glUnlockNormal();
++
++#if SO at GUI@_DEBUG && RENDERAREA_DEBUG_REDRAWS // debug
++ SoDebugError::postInfo("So at Gui@RenderArea::render", "done");
++#endif // debug
++}
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++ This method instantly redraws the normal (non-overlay) scenegraph by
++ calling SoSceneManager::render().
++
++ Subclasses may override this method to add their own rendering
++ before or after Coin renders it's scenegraph.
++
++ The following is a complete example that demonstrates one way of
++ adding both a background image and foreground (overlay) geometry to
++ the "normal" rendering:
++
++ \code
++ // This example shows how to put a permanent background image on
++ // your viewer canvas, below the 3D graphics, plus overlay
++ // foreground geometry. Written by mortene.
++ // Copyright Kongsberg Oil & Gas Technologies 2002.
++
++ // *************************************************************************
++
++ #include <Inventor/@Gui@/So at Gui@.h>
++ #include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++ #include <Inventor/nodes/SoBaseColor.h>
++ #include <Inventor/nodes/SoCone.h>
++ #include <Inventor/nodes/SoCube.h>
++ #include <Inventor/nodes/SoImage.h>
++ #include <Inventor/nodes/SoLightModel.h>
++ #include <Inventor/nodes/SoOrthographicCamera.h>
++ #include <Inventor/nodes/SoRotationXYZ.h>
++ #include <Inventor/nodes/SoSeparator.h>
++ #include <Inventor/nodes/SoTranslation.h>
++
++ #include <GL/gl.h>
++
++ // *************************************************************************
++
++ class MyExaminerViewer : public So at Gui@ExaminerViewer {
++
++ public:
++ MyExaminerViewer(@WIDGET@ parent, const char * filename);
++ ~MyExaminerViewer();
++
++ protected:
++ virtual void actualRedraw(void);
++
++ private:
++ SoSeparator * bckgroundroot;
++ SoSeparator * foregroundroot;
++ SoRotationXYZ * arrowrotation;
++ };
++
++ MyExaminerViewer::MyExaminerViewer(@WIDGET@ parent, const char * filename)
++ : So at Gui@ExaminerViewer(parent)
++ {
++ // Coin should not clear the pixel-buffer, so the background image
++ // is not removed.
++ this->setClearBeforeRender(FALSE, TRUE);
++
++
++ // Set up background scenegraph with image in it.
++
++ this->bckgroundroot = new SoSeparator;
++ this->bckgroundroot->ref();
++
++ SoOrthographicCamera * cam = new SoOrthographicCamera;
++ cam->position = SbVec3f(0, 0, 1);
++ cam->height = 1;
++ // SoImage will be at z==0.0.
++ cam->nearDistance = 0.5;
++ cam->farDistance = 1.5;
++
++ SoImage * img = new SoImage;
++ img->vertAlignment = SoImage::HALF;
++ img->horAlignment = SoImage::CENTER;
++ img->filename = filename;
++
++ this->bckgroundroot->addChild(cam);
++ this->bckgroundroot->addChild(img);
++
++ // Set up foreground, overlayed scenegraph.
++
++ this->foregroundroot = new SoSeparator;
++ this->foregroundroot->ref();
++
++ SoLightModel * lm = new SoLightModel;
++ lm->model = SoLightModel::BASE_COLOR;
++
++ SoBaseColor * bc = new SoBaseColor;
++ bc->rgb = SbColor(1, 1, 0);
++
++ cam = new SoOrthographicCamera;
++ cam->position = SbVec3f(0, 0, 5);
++ cam->height = 10;
++ cam->nearDistance = 0;
++ cam->farDistance = 10;
++
++ const double ARROWSIZE = 2.0;
++
++ SoTranslation * posit = new SoTranslation;
++ posit->translation = SbVec3f(-2.5 * ARROWSIZE, 1.5 * ARROWSIZE, 0);
++
++ arrowrotation = new SoRotationXYZ;
++ arrowrotation->axis = SoRotationXYZ::Z;
++
++ SoTranslation * offset = new SoTranslation;
++ offset->translation = SbVec3f(ARROWSIZE/2.0, 0, 0);
++
++ SoCube * cube = new SoCube;
++ cube->width = ARROWSIZE;
++ cube->height = ARROWSIZE/15.0;
++
++ this->foregroundroot->addChild(cam);
++ this->foregroundroot->addChild(lm);
++ this->foregroundroot->addChild(bc);
++ this->foregroundroot->addChild(posit);
++ this->foregroundroot->addChild(arrowrotation);
++ this->foregroundroot->addChild(offset);
++ this->foregroundroot->addChild(cube);
++ }
++
++ MyExaminerViewer::~MyExaminerViewer()
++ {
++ this->bckgroundroot->unref();
++ this->foregroundroot->unref();
++ }
++
++ void
++ MyExaminerViewer::actualRedraw(void)
++ {
++ // Must set up the OpenGL viewport manually, as upon resize
++ // operations, Coin won't set it up until the SoGLRenderAction is
++ // applied again. And since we need to do glClear() before applying
++ // the action..
++ const SbViewportRegion vp = this->getViewportRegion();
++ SbVec2s origin = vp.getViewportOriginPixels();
++ SbVec2s size = vp.getViewportSizePixels();
++ glViewport(origin[0], origin[1], size[0], size[1]);
++
++ const SbColor col = this->getBackgroundColor();
++ glClearColor(col[0], col[1], col[2], 0.0f);
++ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
++
++ // Render our scenegraph with the image.
++ SoGLRenderAction * glra = this->getGLRenderAction();
++ glra->apply(this->bckgroundroot);
++
++
++ // Render normal scenegraph.
++ So at Gui@ExaminerViewer::actualRedraw();
++
++
++ // Increase arrow angle with 1/1000 � every frame.
++ arrowrotation->angle = arrowrotation->angle.getValue() + (0.001 / M_PI * 180);
++ // Render overlay front scenegraph.
++ glClear(GL_DEPTH_BUFFER_BIT);
++ glra->apply(this->foregroundroot);
++ }
++
++ // *************************************************************************
++
++ int
++ main(int argc, char ** argv)
++ {
++ if (argc != 2) {
++ (void)fprintf(stderr, "\n\n\tUsage: %s <image-filename>\n\n", argv[0]);
++ exit(1);
++ }
++
++ @WIDGET@ window = So at Gui@::init(argv[0]);
++
++ MyExaminerViewer * viewer = new MyExaminerViewer(window, argv[1]);
++
++ viewer->setSceneGraph(new SoCone);
++ viewer->show();
++
++ So at Gui@::show(window);
++ So at Gui@::mainLoop();
++
++ delete viewer;
++ return 0;
++ }
++
++ // *************************************************************************
++ \endcode
++*/
++void
++So at Gui@RenderArea::actualRedraw(void)
++{
++ assert(PRIVATE(this)->normalManager != NULL);
++ if ( !this->isVisible() ) return;
++ PRIVATE(this)->normalManager->render(PRIVATE(this)->clear, PRIVATE(this)->clearZBuffer);
++}
++
++/*!
++ This method redraws the overlay scene.
++*/
++void
++So at Gui@RenderArea::redrawOverlay(void)
++{
++ if (!this->isVisible() || this->waitForExpose || !this->hasOverlayGLArea()) {
++ return;
++ }
++
++ this->glLockOverlay();
++ this->actualOverlayRedraw();
++ this->glFlushBuffer();
++ this->glUnlockOverlay();
++}
++
++/*!
++ This method renders the overlay scene.
++*/
++void
++So at Gui@RenderArea::actualOverlayRedraw(void)
++{
++ assert(PRIVATE(this)->overlayManager != NULL);
++ if (! this->isVisible()) return;
++ PRIVATE(this)->overlayManager->render(PRIVATE(this)->clearOverlay,
++ PRIVATE(this)->clearZBuffer);
++}
++
++/*!
++ This method is invoked to initialize the normal graphics.
++*/
++void
++So at Gui@RenderArea::initGraphic(void)
++{
++ SoSceneManager * mgr = this->getSceneManager();
++ if (mgr) {
++ mgr->reinitialize();
++ mgr->setRGBMode(this->isRGBMode());
++
++ SoGLRenderAction * renderaction = mgr->getGLRenderAction();
++ renderaction->setCacheContext(SoAny::si()->getSharedCacheContextId(this));
++ SbBool isdirect = SoGuiGLWidgetP::isDirectRendering(this);
++ renderaction->setRenderingIsRemote(!isdirect);
++ }
++ // FIXME: if not RGB mode, load colormap. pederb.
++
++ inherited::initGraphic();
++}
++
++/*!
++ This method is invoked to initialize the overlay graphics.
++*/
++void
++So at Gui@RenderArea::initOverlayGraphic(void)
++{
++ SoSceneManager * mgr = this->getOverlaySceneManager();
++ if (mgr) {
++ mgr->reinitialize();
++ // FIXME: does overlays really _have_ to be in colorindex mode?
++ // 20020916 mortene.
++ mgr->setRGBMode(FALSE);
++
++ SoGLRenderAction * renderaction = mgr->getGLRenderAction();
++ SbBool isdirect = SoGuiGLWidgetP::isDirectRendering(this);
++ renderaction->setRenderingIsRemote(!isdirect);
++ // FIXME: shouldn't we also setCacheContext() on the renderaction?
++ // 20020916 mortene.
++ }
++ // FIXME: if not RGB mode, load colormap. pederb.
++
++ // FIXME: shouldn't we do inherited::initOverlayGraphic() ? 20010831 mortene.
++}
++
++// doc in super
++void
++So at Gui@RenderArea::sizeChanged(const SbVec2s & size)
++{
++#if SO at GUI@_DEBUG && 0
++ SoDebugError::postInfo("So at Gui@RenderArea::sizeChanged",
++ "invoked, <%d, %d>", size[0], size[1]);
++#endif // SO at GUI@_DEBUG
++
++ SbVec2s newsize(size);
++
++ if (size[0] == -1)
++ return;
++
++ assert(PRIVATE(this)->normalManager != NULL);
++ assert(PRIVATE(this)->overlayManager != NULL);
++
++ // Workaround for a bug in Qt/Mac 3.1.0 and 3.1.1 (which has been
++ // confirmed fixed in 3.1.2):
++ //
++ // If the OpenGL context overlaps with the QSizeGrip widget
++ // (generated by default), resizing does not work any more. The
++ // workaround is to leave 15 pixels at the lower border of the
++ // window blank...
++
++#if defined Q_WS_MAC && ((QT_VERSION == 0x030100) || (QT_VERSION == 0x030101))
++
++ // Environment variable to override Qt/Mac 3.1.x workarounds.
++ const char * forcenoresizeworkaround =
++ SoAny::si()->getenv("FORCE_NO_QTMAC_31_RESIZE_WORKAROUND");
++ if (!forcenoresizeworkaround || (atoi(forcenoresizeworkaround) == 0)) {
++
++ if (this->getTypeId() == So at Gui@RenderArea::getClassTypeId()) {
++ // SoQtRenderArea used as standalone component
++ newsize -= SbVec2s(0, 15);
++
++ // spit out a warning that this is a Qt/Mac bug, not an SoQt problem
++ const char * env = SoAny::si()->getenv("SOQT_NO_QTMAC_BUG_WARNINGS");
++ if (!env || !atoi(env)) {
++ SoDebugError::postWarning("SoQtRenderArea::sizeChanged",
++ "\nThis version of Qt/Mac contains a bug "
++ "that makes it necessary to leave the\n"
++ "lowermost 15 pixels of the viewer window "
++ "blank. Set the environment variable\n"
++ "FORCE_NO_QTMAC_31_RESIZE_WORKAROUND=1 to "
++ "override this workaround. \n"
++ "You can turn off warnings about Qt/Mac "
++ "bugs permanently by setting \n"
++ "SOQT_NO_QTMAC_BUG_WARNINGS=1.\n");
++ }
++ }
++ }
++
++#endif
++
++ this->setGLSize(newsize);
++ const SbVec2s glsize = this->getGLSize();
++
++
++#if SO at GUI@_DEBUG && 0
++ SoDebugError::postInfo("So at Gui@RenderArea::sizeChanged",
++ "glsize==<%d, %d>", glsize[0], glsize[1]);
++#endif // SO at GUI@_DEBUG
++
++ if (glsize[0] <= 0 || glsize[1] <= 0)
++ return;
++
++ this->setViewportRegion(SbViewportRegion(glsize));
++ PRIVATE(this)->setDevicesWindowSize(glsize);
++
++ // FIXME: aren't both these calls unnecessary as we set the full
++ // viewportregion a few lines above this one? 20020103 mortene.
++ PRIVATE(this)->normalManager->setWindowSize(glsize);
++ PRIVATE(this)->normalManager->setSize(glsize);
++
++ // FIXME: aren't both these calls unnecessary as we set the full
++ // viewportregion a few lines above this one? 20020103 mortene.
++ PRIVATE(this)->overlayManager->setWindowSize(glsize);
++ PRIVATE(this)->overlayManager->setSize(glsize);
++
++ inherited::sizeChanged(glsize);
++
++ // this->scheduleRedraw(); // already done through setViewportRegion()
++}
++
++// Documented in superclass.
++void
++So at Gui@RenderArea::widgetChanged(@WIDGET@ widget)
++{
++ PRIVATE(this)->normalManager->reinitialize();
++ PRIVATE(this)->overlayManager->reinitialize();
++ // FIXME: colorindex mode not supported yet, so this has no
++ // effect. 20001121 mortene.
++#if 0
++ PRIVATE(this)->normalManager->setRGBMode(this->isRGBMode());
++ PRIVATE(this)->overlayManager->setRGBMode(this->isRGBMode());
++#endif
++
++ // FIXME: should also walk through all registered devices and do a
++ // disable() on the old widget and enable() on the new one.
++ // 20001121 mortene.
++}
++
++// Documented in superclass.
++ at WIDGET@
++So at Gui@RenderArea::buildWidget(@WIDGET@ parent)
++{
++ @WIDGET@ widget = inherited::buildWidget(parent);
++
++ if (PRIVATE(this)->devicelist != NULL) {
++ const int num = PRIVATE(this)->devicelist->getLength();
++ for (int i = 0; i < num; i++) {
++ So at Gui@Device * device = (So at Gui@Device *) (*PRIVATE(this)->devicelist)[i];
++#ifdef __COIN_SOXT__
++ device->enable(this->getGLWidget(),
++ (SoXtEventHandler *) &So at Gui@GLWidget::eventHandler,
++ (void *) this);
++#else
++ device->enable(this->getGLWidget(),
++ &So at Gui@GLWidgetP::eventHandler, (void *) this);
++#endif
++ }
++ }
++
++ return widget;
++}
++
++// Documented in superclass.
++const char *
++So at Gui@RenderArea::getDefaultWidgetName(void) const
++{
++ static const char defaultWidgetName[] = "So at Gui@WidgetName";
++ return defaultWidgetName;
++}
++
++// Documented in superclass.
++const char *
++So at Gui@RenderArea::getDefaultTitle(void) const
++{
++ static const char defaultTitle[] = "@Gui@ RenderArea";
++ return defaultTitle;
++}
++
++// Documented in superclass.
++const char *
++So at Gui@RenderArea::getDefaultIconTitle(void) const
++{
++ static const char defaultIconTitle[] = "@Gui@ RenderArea";
++ return defaultIconTitle;
++}
++
++// *************************************************************************
++
++/*!
++ Toolkit-native events are attempted converted to Coin-generic events
++ in the So at Gui@RenderArea::processEvent() method. If this succeeds,
++ they are forwarded to this method.
++
++ This is a virtual method, and is overridden in it's subclasses to
++ catch events of particular interest to the viewer classes, for
++ instance.
++
++ Return \c TRUE iff the event was processed. If not it should be
++ passed on further up in the inheritance hierarchy by the caller.
++ This last point is extremely important to take note of if you are
++ expanding the toolkit with your own viewer class.
++
++ This method is not part of the original SGI InventorXt API. Note
++ that you can still override the toolkit-native processEvent() method
++ instead of this "generic" method.
++*/
++SbBool
++So at Gui@RenderArea::processSoEvent(const SoEvent * const event)
++{
++ if (PRIVATE(this)->overlayManager->processEvent(event)) { return TRUE; }
++ if (PRIVATE(this)->normalManager->processEvent(event)) { return TRUE; }
++ return FALSE;
++}
++
++// *************************************************************************
++
++/*!
++ Overrides So at Gui@GLWidget::processEvent() to attempt to convert
++ toolkit-native events to Coin-generic events. If this succeeds, the
++ generic SoEvent is forwarded to So at Gui@RenderArea::processSoEvent().
++ */
++void
++So at Gui@RenderArea::processEvent(@EVENT@ event)
++{
++ // FIXME: This method is not reentrant, but certain GUI toolkits may
++ // run the event-loop recursively with events injected while processing
++ // other events. We must detect when this happens, and queue up the
++ // event for delayed processing after the primary event is done processing.
++ // This means event instances can not be static and rewritten in the
++ // device handlers like they are currently... 20051013 larsa
++
++ if (PRIVATE(this)->invokeAppCB(event)) { return; }
++
++ const SoEvent * soevent = PRIVATE(this)->getSoEvent(event);
++
++ if (soevent != NULL) {
++#if SO at GUI@_DEBUG || defined(DEBUGGING_EGGS)
++ // Undocumented feature: there are several "magic" sequences of
++ // keys when tapped into the rendering canvas which'll pop up a
++ // dialog box with information about that particular feature.
++ //
++ // See code comments behind "case" statements below for which
++ // sequences are available so far.
++
++ if (soevent->isOfType(SoKeyboardEvent::getClassTypeId())) {
++ SoKeyboardEvent * ke = (SoKeyboardEvent *)soevent;
++ if (ke->getState() == SoButtonEvent::UP) {
++ char c = ke->getPrintableCharacter();
++ switch (PRIVATE(this)->checkMagicSequences(c)) {
++ case So at Gui@RenderAreaP::NONE:
++ break;
++ case So at Gui@RenderAreaP::OPENGL: // "glinfo"
++ this->glLockNormal();
++ PRIVATE(this)->showOpenGLDriverInformation();
++ this->glUnlockNormal();
++ break;
++ case So at Gui@RenderAreaP::INVENTOR: // "ivinfo"
++ PRIVATE(this)->showInventorInformation();
++ break;
++ case So at Gui@RenderAreaP::TOOLKIT: // "soinfo"
++ PRIVATE(this)->showToolkitInformation();
++ break;
++ case So at Gui@RenderAreaP::DUMPSCENEGRAPH: // "dumpiv"
++ PRIVATE(this)->dumpScenegraph();
++ break;
++ case So at Gui@RenderAreaP::DUMPCAMERAS: // "cameras"
++ PRIVATE(this)->dumpCameras();
++ break;
++ case So at Gui@RenderAreaP::OFFSCREENGRAB: // "osgrab"
++ PRIVATE(this)->offScreenGrab();
++ break;
++ default:
++ assert(FALSE && "unknown debug key sequence");
++ break;
++ }
++ }
++ }
++#endif // SO at GUI@_DEBUG
++
++ SbBool processed = this->processSoEvent(soevent);
++ if (processed) return;
++ }
++
++ inherited::processEvent(event);
++}
++
++// *************************************************************************
++
++// doc from parent
++SbBool
++So at Gui@RenderArea::glScheduleRedraw(void)
++{
++ this->scheduleRedraw();
++ if (this->hasOverlayGLArea() && this->getOverlaySceneGraph()) {
++ this->scheduleOverlayRedraw();
++ }
++ return TRUE;
++}
++
++// *************************************************************************
++
++/*!
++ This method posts and processes an SoEvent object to the
++ So at Gui@RenderArea-based component and returns the result value from the
++ event handler. This is a synchronous operation.
++*/
++SbBool
++So at Gui@RenderArea::sendSoEvent(const SoEvent * event)
++{
++ return this->processSoEvent(event);
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/SoGuiRenderArea.h.in
+@@ -0,0 +1,157 @@
++#ifndef SO at GUI@_RENDERAREA_H
++#define SO at GUI@_RENDERAREA_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbColor.h>
++#include <Inventor/SbViewportRegion.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/SoSceneManager.h>
++
++#include <Inventor/@Gui@/So at Gui@GLWidget.h>
++
++class SbColor;
++class SoNode;
++class SoSelection;
++
++class So at Gui@Device;
++// So at Gui@RenderAreaP is only used in the "friend class" statement in
++// the class definition, so this shouldn't really be necessary. But
++// the OSF1/cxx compiler complains if it's left out.
++class So at Gui@RenderAreaP;
++
++typedef SbBool So at Gui@RenderAreaEventCB(void * closure, @EVENT@ event);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@RenderArea : public So at Gui@GLWidget {
++ SO at GUI@_OBJECT_HEADER(So at Gui@RenderArea, So at Gui@GLWidget);
++
++public:
++ So at Gui@RenderArea(@WIDGET@ parent = NULL,
++ const char * name = NULL,
++ SbBool embed = TRUE,
++ SbBool mouseInput = TRUE,
++ SbBool keyboardInput = TRUE);
++ ~So at Gui@RenderArea();
++
++ virtual void setSceneGraph(SoNode * scene);
++ virtual SoNode * getSceneGraph(void);
++ void setOverlaySceneGraph(SoNode * scene);
++ SoNode * getOverlaySceneGraph(void);
++
++ void setBackgroundColor(const SbColor & color);
++ const SbColor & getBackgroundColor(void) const;
++ void setBackgroundIndex(int idx);
++ int getBackgroundIndex(void) const;
++ void setOverlayBackgroundIndex(int idx);
++ int getOverlayBackgroundIndex(void) const;
++ void setColorMap(int start, int num, const SbColor * colors);
++ void setOverlayColorMap(int start, int num, const SbColor * colors);
++ void setViewportRegion(const SbViewportRegion & newRegion);
++ const SbViewportRegion & getViewportRegion(void) const;
++ void setTransparencyType(SoGLRenderAction::TransparencyType type);
++ SoGLRenderAction::TransparencyType getTransparencyType(void) const;
++ void setAntialiasing(SbBool smoothing, int numPasses);
++ void getAntialiasing(SbBool & smoothing, int & numPasses) const;
++ void setClearBeforeRender(SbBool enable, SbBool zbEnable = TRUE);
++ SbBool isClearBeforeRender(void) const;
++ SbBool isClearZBufferBeforeRender(void) const;
++ void setClearBeforeOverlayRender(SbBool enable);
++ SbBool isClearBeforeOverlayRender(void) const;
++ void setAutoRedraw(SbBool enable);
++ SbBool isAutoRedraw(void) const;
++ void setRedrawPriority(uint32_t priority);
++ uint32_t getRedrawPriority(void) const;
++ static uint32_t getDefaultRedrawPriority(void);
++ void render(void);
++ void renderOverlay(void);
++ void scheduleRedraw(void);
++ void scheduleOverlayRedraw(void);
++ void redrawOnSelectionChange(SoSelection * selection);
++ void redrawOverlayOnSelectionChange(SoSelection * selection);
++ void setEventCallback(So at Gui@RenderAreaEventCB * func, void * user = NULL);
++ void setSceneManager(SoSceneManager * manager);
++ SoSceneManager * getSceneManager(void) const;
++ void setOverlaySceneManager(SoSceneManager * manager);
++ SoSceneManager * getOverlaySceneManager(void) const;
++ void setGLRenderAction(SoGLRenderAction * action);
++ SoGLRenderAction * getGLRenderAction(void) const;
++ void setOverlayGLRenderAction(SoGLRenderAction * action);
++ SoGLRenderAction * getOverlayGLRenderAction(void) const;
++
++ SbBool sendSoEvent(const SoEvent * event);
++
++ void registerDevice(So at Gui@Device * device);
++ void unregisterDevice(So at Gui@Device * device);
++
++
++protected:
++ So at Gui@RenderArea(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ SbBool mouseInput,
++ SbBool keyboardInput,
++ SbBool build);
++
++ virtual void redraw(void);
++ virtual void actualRedraw(void);
++ virtual void redrawOverlay(void);
++ virtual void actualOverlayRedraw(void);
++
++ virtual SbBool processSoEvent(const SoEvent * const event);
++ virtual void processEvent(@EVENT@ event);
++ virtual void initGraphic(void);
++ virtual void initOverlayGraphic(void);
++ virtual void sizeChanged(const SbVec2s & size);
++ virtual void widgetChanged(@WIDGET@ widget);
++ virtual void afterRealizeHook(void);
++
++ @WIDGET@ buildWidget(@WIDGET@ parent);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++ virtual SbBool glScheduleRedraw(void);
++
++private:
++ class So at Gui@RenderAreaP * pimpl;
++ friend class So at Gui@RenderAreaP;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_RENDERAREA_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiDevice.cpp.in
+@@ -0,0 +1,293 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains common sourcecode and documentation for the
++// So[Gui]Device classes, in template form.
++
++/*!
++ \class So at Gui@Device So at Gui@Device.h Inventor/@Gui@/devices/So at Gui@Device.h
++ \brief The So at Gui@Device class is the base class for the translation devices.
++ \ingroup devices
++
++ The So at Gui@ device classes provide glue functionality for
++ translating native GUI events from the underlying toolkit to
++ Inventor scenegraph SoEvent events.
++
++ The device classes are mainly of interest to application programmers
++ when writing extensions for new types of devices, and seldom in
++ other contexts -- so they can most often be ignored.
++*/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++#include <Inventor/@Gui@/devices/So at Gui@DeviceP.h>
++#include <Inventor/SbPList.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoEvent.h>
++
++#include <Inventor/@Gui@/devices/So at Gui@InputFocus.h>
++#include <Inventor/@Gui@/devices/So at Gui@Keyboard.h>
++#include <Inventor/@Gui@/devices/So at Gui@Mouse.h>
++
++#ifdef HAVE_JOYSTICK_LINUX
++#include <Inventor/@Gui@/devices/So at Gui@LinuxJoystick.h>
++#endif // HAVE_JOYSTICK_LINUX
++
++#define PRIVATE(p) (p->pimpl)
++#define PUBLIC(p) (p->pub)
++
++// *************************************************************************
++
++/*!
++ \fn So at Gui@Device::So at Gui@Device(void)
++ Constructor. Protected to only enable invocation from derived device
++ classes.
++*/
++/*!
++ \fn So at Gui@Device::~So at Gui@Device()
++ Public virtual destructor.
++*/
++
++/*!
++ \fn void So at Gui@Device::enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure)
++
++ This method will enable the device for the widget.
++
++ \a handler is invoked with the \a closure argument when an event
++ occur in \a widget.
++*/
++
++/*!
++ \fn void So at Gui@Device::disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure)
++
++ This method will disable the handler for the device.
++*/
++
++/*!
++ \fn const SoEvent * So at Gui@Device::translateEvent(@EVENT@ event)
++
++ This method translates from native events to Open Inventor SoEvent
++ events.
++*/
++
++/*!
++ \fn void So at Gui@Device::invokeHandlers(@EVENT@ event)
++
++ Invoke all handlers registered with So at Gui@Device::addEventHandler().
++*/
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_ABSTRACT_SOURCE(So at Gui@Device);
++
++// *************************************************************************
++
++/*!
++ This function initializes the type system for all the So at Gui@
++ device classes. It is called indirectly when calling
++ So at Gui@::init(), so the application programmer doesn't have to
++ bother with it.
++*/
++void
++So at Gui@Device::initClasses(void)
++{
++ So at Gui@Device::initClass();
++ So at Gui@InputFocus::initClass();
++ So at Gui@Keyboard::initClass();
++ So at Gui@Mouse::initClass();
++#ifdef HAVE_JOYSTICK_LINUX
++ So at Gui@LinuxJoystick::initClass();
++#endif // HAVE_JOYSTICK_LINUX
++}
++
++// *************************************************************************
++
++/*!
++ This method sets the cached size of the window the device is
++ "attached" to.
++*/
++void
++So at Gui@Device::setWindowSize(const SbVec2s size)
++{
++ PRIVATE(this)->widgetsize = size;
++}
++
++/*!
++ This method returns the cached window size.
++*/
++SbVec2s
++So at Gui@Device::getWindowSize(void) const
++{
++ return PRIVATE(this)->widgetsize;
++}
++
++// *************************************************************************
++
++/*!
++ This method fills in the position information of \a event,
++ translating the coordinates into the correct coordinate system.
++*/
++void
++So at Gui@Device::setEventPosition(SoEvent * event, int x, int y) const
++{
++ SoGuiDeviceP::lasteventposition = SbVec2s(x, y);
++ event->setPosition(SbVec2s(x, PRIVATE(this)->widgetsize[1] - y - 1));
++}
++
++/*!
++ Returns last event position that was set with
++ So at Gui@Device::setEventPosition().
++ */
++SbVec2s
++So at Gui@Device::getLastEventPosition(void)
++{
++ return SoGuiDeviceP::lasteventposition;
++}
++
++// *************************************************************************
++
++/*!
++ Stores an event \a handler for the \a widget, which can later be
++ invoked with So at Gui@Device::invokeHandlers(). Used by extension
++ device types.
++ */
++void
++So at Gui@Device::addEventHandler(@WIDGET@ widget,
++ So at Gui@EventHandler * handler,
++ void * closure)
++{
++ PRIVATE(this)->addEventHandler(widget, handler, closure);
++}
++
++/*!
++ Remove a \a handler registered with So at Gui@Device::addEventHandler().
++ */
++void
++So at Gui@Device::removeEventHandler(@WIDGET@ widget,
++ So at Gui@EventHandler * handler,
++ void * closure)
++{
++ PRIVATE(this)->removeEventHandler(widget, handler, closure);
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the internal, private hidden implementation
++// class.
++
++SbVec2s SoGuiDeviceP::lasteventposition;
++
++struct SoGuiDevicePHandlerInfo {
++ @WIDGET@ widget;
++ So at Gui@EventHandler * handler;
++ void * closure;
++};
++
++SoGuiDeviceP::SoGuiDeviceP(So at Gui@Device * p)
++{
++ PUBLIC(this) = p;
++ this->handlers = NULL;
++ this->widgetsize = SbVec2s(0, 0);
++}
++
++SoGuiDeviceP::~SoGuiDeviceP()
++{
++ if (this->handlers) {
++ for (int i = 0; i < this->handlers->getLength(); i++) {
++ SoGuiDevicePHandlerInfo * info =
++ (SoGuiDevicePHandlerInfo *) (*this->handlers)[i];
++ delete info;
++ }
++ delete this->handlers;
++ }
++}
++
++void
++SoGuiDeviceP::addEventHandler(@WIDGET@ widget,
++ So at Gui@EventHandler * handler,
++ void * closure)
++{
++ if (this->handlers == NULL) { this->handlers = new SbPList; }
++ SoGuiDevicePHandlerInfo * info = new SoGuiDevicePHandlerInfo;
++ info->widget = widget;
++ info->handler = handler;
++ info->closure = closure;
++ this->handlers->append(info);
++}
++
++void
++SoGuiDeviceP::removeEventHandler(@WIDGET@ widget,
++ So at Gui@EventHandler * handler,
++ void * closure)
++{
++ if (this->handlers) {
++ for (int i = 0; i < this->handlers->getLength(); i++) {
++ SoGuiDevicePHandlerInfo * info =
++ (SoGuiDevicePHandlerInfo *) (*this->handlers)[i];
++ if ((info->widget == widget) && (info->handler == handler) &&
++ (info->closure == closure)) {
++ delete info;
++ this->handlers->remove(i);
++ return;
++ }
++ }
++ }
++#if SO at GUI@_DEBUG
++ SoDebugError::post("SoGuiDeviceP::removeEventHandler",
++ "tried to remove nonexisting handler");
++#endif // SO at GUI@_DEBUG
++}
++
++void
++SoGuiDeviceP::invokeHandlers(HandlerCB * cb, @EVENT@ event)
++{
++ if (this->handlers) {
++ for (int i = 0; i < this->handlers->getLength(); i++) {
++ SoGuiDevicePHandlerInfo * info =
++ (SoGuiDevicePHandlerInfo *) (*this->handlers)[i];
++ cb(info->handler, info->widget, event, info->closure);
++ }
++ }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiDevice.h.in
+@@ -0,0 +1,106 @@
++#ifndef SO at GUI@_DEVICE_H
++#define SO at GUI@_DEVICE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// *************************************************************************
++//
++// Toolkit-specific typedef and include(s). Put these before any Coin
++// and/or So at Gui@ includes, in case there are any dependency bugs in
++// the underlying native toolkit set of include files versus the
++// compiler environment's include files.
++
++#include <Inventor/@Gui@/So at Gui@Basic.h> // Contains __COIN_SO at GUI@__ define.
++
++#ifdef __COIN_SOQT__
++#include <qevent.h>
++typedef void So at Gui@EventHandler(@WIDGET@, void *, @EVENT@, bool *);
++#endif // __COIN_SOQT__
++#ifdef __COIN_SOXT__
++#include <X11/Intrinsic.h>
++typedef void So at Gui@EventHandler(@WIDGET@, XtPointer, XEvent *, Boolean *);
++#endif // __COIN_SOXT__
++#ifdef __COIN_SOGTK__
++#include <gtk/gtk.h>
++typedef gint So at Gui@EventHandler(@WIDGET@, @EVENT@, gpointer);
++#endif // __COIN_SOGTK__
++#ifdef __COIN_SOWIN__
++#include <windows.h>
++typedef LRESULT So at Gui@EventHandler(@WIDGET@, UINT, WPARAM, LPARAM);
++#endif // __COIN_SOWIN__
++
++// *************************************************************************
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/So at Gui@Object.h>
++
++class SoEvent;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Device : public So at Gui@Object {
++ SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@Device, So at Gui@Object);
++
++public:
++ virtual ~So at Gui@Device();
++
++ virtual void enable(@WIDGET@ w, So at Gui@EventHandler * handler, void * closure) = 0;
++ virtual void disable(@WIDGET@ w, So at Gui@EventHandler * handler, void * closure) = 0;
++
++ virtual const SoEvent * translateEvent(@EVENT@ event) = 0;
++
++ void setWindowSize(const SbVec2s size);
++ SbVec2s getWindowSize(void) const;
++
++ static void initClasses(void);
++
++protected:
++ So at Gui@Device(void);
++
++ void setEventPosition(SoEvent * event, int x, int y) const;
++ static SbVec2s getLastEventPosition(void);
++
++ void addEventHandler(@WIDGET@, So at Gui@EventHandler *, void *);
++ void removeEventHandler(@WIDGET@, So at Gui@EventHandler *, void *);
++ void invokeHandlers(@EVENT@ event);
++
++private:
++ class So at Gui@DeviceP * pimpl;
++ friend class So at Gui@DeviceP;
++};
++
++// *************************************************************************
++
++#endif // !SO at GUI@_DEVICE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiDeviceP.h.in
+@@ -0,0 +1,76 @@
++#ifndef SOGUI_DEVICEP_H
++#define SOGUI_DEVICEP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++// *************************************************************************
++
++class SoGuiDeviceP {
++
++public:
++ SoGuiDeviceP(So at Gui@Device * p);
++ virtual ~SoGuiDeviceP();
++
++ void addEventHandler(@WIDGET@ widget,
++ So at Gui@EventHandler * handler,
++ void * closure);
++ void removeEventHandler(@WIDGET@ widget,
++ So at Gui@EventHandler * handler,
++ void * closure);
++
++ typedef SbBool HandlerCB(So at Gui@EventHandler * handler,
++ @WIDGET@ widget,
++ @EVENT@ event,
++ void * handlerclosure);
++
++ void invokeHandlers(HandlerCB * cb, @EVENT@ event);
++
++ SbPList * handlers;
++ static SbVec2s lasteventposition;
++ SbVec2s widgetsize;
++
++private:
++ class So at Gui@Device * pub;
++};
++
++// *************************************************************************
++
++#endif // !SOGUI_DEVICEP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiInputFocus.cpp.in
+@@ -0,0 +1,102 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class So at Gui@InputFocus So at Gui@InputFocus.h Inventor/@Gui@/devices/So at Gui@InputFocus.h
++ \brief The So at Gui@InputFocus class is an abstraction for widget focus events as an input device.
++ \ingroup devices
++
++ This device class is a "virtual device" which can be used to get
++ events when the mouse pointer enters or leaves a specific widget.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@InputFocus.h>
++#include <Inventor/@Gui@/devices/SoGuiInputFocusP.h>
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@InputFocus);
++
++// *************************************************************************
++
++/*!
++ \enum So at Gui@InputFocus::Events
++
++ Bit-wise enumeration over events handled by the So at Gui@InputFocus
++ device class. Used in the So at Gui@InputFocus constructor.
++*/
++
++/*!
++ \var So at Gui@InputFocus::Events So at Gui@InputFocus::ENTER_WINDOW
++
++ Maskbit for receiving events when focus comes to a widget.
++*/
++
++/*!
++ \var So at Gui@InputFocus::Events So at Gui@InputFocus::LEAVE_WINDOW
++
++ Maskbit for receiving events when focus leaves a widget.
++*/
++
++/*!
++ \var So at Gui@InputFocus::Events So at Gui@InputFocus::ALL_EVENTS
++
++ Combined bitmask for all possible events.
++*/
++
++/*!
++ \fn So at Gui@InputFocus::So at Gui@InputFocus(int mask)
++
++ Constructor. The \a mask specifies which focus-related events to
++ handle. Others will just be ignored.
++*/
++
++// *************************************************************************
++
++SoGuiInputFocusP::SoGuiInputFocusP(So at Gui@InputFocus * p)
++{
++ this->pub = p;
++}
++
++SoGuiInputFocusP::~SoGuiInputFocusP()
++{
++}
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiInputFocus.h.in
+@@ -0,0 +1,70 @@
++#ifndef SO at GUI@_INPUTFOCUS_H
++#define SO at GUI@_INPUTFOCUS_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@InputFocus : public So at Gui@Device {
++ SO at GUI@_OBJECT_HEADER(So at Gui@InputFocus, So at Gui@Device);
++
++public:
++ enum Events {
++ ENTER_WINDOW = 1 << 0,
++ LEAVE_WINDOW = 1 << 1,
++ ALL_EVENTS = ENTER_WINDOW | LEAVE_WINDOW
++ };
++
++ So at Gui@InputFocus(int mask = ALL_EVENTS);
++ virtual ~So at Gui@InputFocus();
++
++ virtual void enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++ virtual void disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++
++ virtual const SoEvent * translateEvent(@EVENT@ event);
++
++private:
++ class So at Gui@InputFocusP * pimpl;
++ friend class SoGuiInputFocusP;
++ friend class So at Gui@InputFocusP;
++};
++
++#define SO_ at GUI@_ALL_FOCUS_EVENTS So at Gui@InputFocus::ALL_EVENTS;
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_INPUTFOCUS_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiInputFocusP.h.in
+@@ -0,0 +1,57 @@
++#ifndef SOGUI_INPUTFOCUSP_H
++#define SOGUI_INPUTFOCUSP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++// *************************************************************************
++
++class SoGuiInputFocusP {
++public:
++ SoGuiInputFocusP(class So at Gui@InputFocus * p);
++ ~SoGuiInputFocusP();
++
++ int eventmask;
++
++protected:
++ class So at Gui@InputFocus * pub;
++};
++
++// *************************************************************************
++
++#endif // ! SOGUI_INPUTFOCUSP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiKeyboard.cpp.in
+@@ -0,0 +1,112 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class So at Gui@Keyboard So at Gui@Keyboard.h Inventor/@Gui@/devices/So at Gui@Keyboard.h
++ \brief The So at Gui@Keyboard class is the keyboard input device abstraction.
++ \ingroup devices
++
++ The So at Gui@Keyboard class is the glue between native keyboard
++ handling and keyboard interaction with the Inventor scenegraph.
++
++ All components derived from the So at Gui@RenderArea have got an
++ So at Gui@Keyboard device attached by default.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Keyboard.h>
++#include <Inventor/@Gui@/devices/SoGuiKeyboardP.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@Keyboard);
++
++// *************************************************************************
++
++/*!
++ \enum So at Gui@Keyboard::Events
++ Enumeration over supported event types.
++*/
++
++/*!
++ \var So at Gui@Keyboard::Events So at Gui@Keyboard::KEY_PRESS
++ Maskbit for a keyboard button press event.
++*/
++
++/*!
++ \var So at Gui@Keyboard::Events So at Gui@Keyboard::KEY_RELEASE
++ Maskbit for a keyboard button release event.
++*/
++
++/*!
++ \var So at Gui@Keyboard::Events So at Gui@Keyboard::ALL_EVENTS
++ Combined bitmask for all possible events.
++*/
++
++/*!
++ \fn So at Gui@Keyboard::So at Gui@Keyboard(int mask)
++
++ Constructor. The \a mask specifies which keyboard-related events to
++ handle. Others will just be ignored.
++*/
++
++/*!
++ \fn So at Gui@Keyboard::~So at Gui@Keyboard()
++
++ Destructor.
++*/
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiKeyboardP::SoGuiKeyboardP(void)
++{
++ this->kbdevent = new SoKeyboardEvent;
++}
++
++SoGuiKeyboardP::~SoGuiKeyboardP()
++{
++ delete this->kbdevent;
++}
++
++#endif // !DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiKeyboard.h.in
+@@ -0,0 +1,72 @@
++#ifndef SO at GUI@_KEYBOARD_H
++#define SO at GUI@_KEYBOARD_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++class SoKeyboardEvent;
++
++// *************************************************************************
++
++#define SO_ at GUI@_ALL_KEYBOARD_EVENTS So at Gui@Keyboard::ALL
++
++class SO at GUI@_DLL_API So at Gui@Keyboard : public So at Gui@Device {
++ SO at GUI@_OBJECT_HEADER(So at Gui@Keyboard, So at Gui@Device);
++
++public:
++ enum Events {
++ KEY_PRESS = 0x01,
++ KEY_RELEASE = 0x02,
++ ALL_EVENTS = KEY_PRESS | KEY_RELEASE
++ };
++
++ So at Gui@Keyboard(int eventmask = ALL_EVENTS);
++ virtual ~So at Gui@Keyboard(void);
++
++ virtual void enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++ virtual void disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++
++ virtual const SoEvent * translateEvent(@EVENT@ event);
++
++private:
++ class So at Gui@KeyboardP * pimpl;
++ friend class So at Gui@KeyboardP;
++ friend class SoGuiKeyboardP;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_KEYBOARD_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiKeyboardP.h.in
+@@ -0,0 +1,57 @@
++#ifndef SOGUI_KEYBOARDP_H
++#define SOGUI_KEYBOARDP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++class SoKeyboardEvent;
++
++// *************************************************************************
++
++class SoGuiKeyboardP {
++public:
++ SoGuiKeyboardP(void);
++ ~SoGuiKeyboardP();
++
++ int eventmask;
++ SoKeyboardEvent * kbdevent;
++};
++
++// *************************************************************************
++
++#endif // ! SOGUI_KEYBOARDP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiMouse.cpp.in
+@@ -0,0 +1,174 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Mouse.h>
++#include <Inventor/@Gui@/devices/SoGuiMouseP.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++
++/*!
++ \class So at Gui@Mouse So at Gui@Mouse.h Inventor/@Gui@/devices/So at Gui@Mouse.h
++ \brief The So at Gui@Mouse class is the mouse input device abstraction.
++ \ingroup devices
++
++ The So at Gui@Mouse class is the glue between native mouse handling and
++ mouse interaction in the Inventor scenegraph.
++
++ All components derived from the So at Gui@RenderArea have got an
++ So at Gui@Mouse device attached by default.
++
++ One important note for application programmers: our mappings to
++ SoMouseButtonEvent::BUTTON2 and SoMouseButtonEvent::BUTTON3 do not
++ match the mappings in SGI's InventorXt library or TGS's SoWin
++ library for 3-button mice. They map mouse buttons like this:
++
++ <ul>
++ <li>left button: SoMouseButtonEvent::BUTTON1</li>
++ <li>middle button: SoMouseButtonEvent::BUTTON2</li>
++ <li>right button: SoMouseButtonEvent::BUTTON3</li>
++ </ul>
++
++ While in this SIM So at Gui@ library the mappings are:
++
++ <ul>
++ <li>left button: SoMouseButtonEvent::BUTTON1</li>
++ <li>middle button: SoMouseButtonEvent::BUTTON3</li>
++ <li>right button: SoMouseButtonEvent::BUTTON2</li>
++ </ul>
++
++ This is a conscious design decision we've made. The reason is that
++ BUTTON2 should be the right mouse button whether you have a 2-button
++ mouse or a 3-button mouse.
++*/
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@Mouse);
++
++// *************************************************************************
++
++/*!
++ \enum So at Gui@Mouse::Events
++ Enumeration over supported mouse events.
++*/
++/*!
++ \var So at Gui@Mouse::Events So at Gui@Mouse::BUTTON_PRESS
++ Maskbit for mousebutton press events.
++*/
++/*!
++ \var So at Gui@Mouse::Events So at Gui@Mouse::BUTTON_RELEASE
++ Maskbit for mousebutton release events.
++*/
++/*!
++ \var So at Gui@Mouse::Events So at Gui@Mouse::POINTER_MOTION
++ Maskbit for mousepointer motion events.
++*/
++/*!
++ \var So at Gui@Mouse::Events So at Gui@Mouse::BUTTON_MOTION
++ Maskbit for mousepointer motion events with one or more mousebuttons
++ pressed.
++*/
++/*!
++ \var So at Gui@Mouse::Events So at Gui@Mouse::ALL_EVENTS
++
++ Mask which includes all the maskbits in the enum (ie use this to
++ signal interest in all kinds of events for the mouse device).
++*/
++
++// *************************************************************************
++
++/*!
++ \fn So at Gui@Mouse::So at Gui@Mouse(int mask)
++
++ Constructor. The \a mask argument should contain the set of
++ So at Gui@Mouse::Events one is interested in tracking.
++*/
++
++/*!
++ \fn So at Gui@Mouse::~So at Gui@Mouse()
++ Destructor.
++*/
++
++/*!
++ \fn const SoEvent * So at Gui@Mouse::translateEvent(@EVENT@ event)
++
++ Translates a native event from the underlying toolkit into a generic
++ event.
++
++ This is then returned in the form of an instance of a subclass of
++ the Inventor API's SoEvent class, either an SoMouseButtonEvent or an
++ SoLocation2Event, depending on whether the native event is a
++ mousebutton press / release, or a mousecursor movement event.
++
++ The mapping of the mousebuttons upon generation of
++ SoMouseButtonEvent events will be done as follows:
++
++ <ul>
++ <li>left mousebutton: SoMouseButtonEvent::BUTTON1</li>
++ <li>right mousebutton: SoMouseButtonEvent::BUTTON2</li>
++ <li>middle mousebutton, if available: SoMouseButtonEvent::BUTTON3</li>
++ <li>forward motion on a wheel mouse: SoMouseButtonEvent::BUTTON4</li>
++ <li>backward motion on a wheel mouse: SoMouseButtonEvent::BUTTON5</li>
++ </ul>
++
++ Note that the rightmost mousebutton will always map to
++ SoMouseButtonEvent::BUTTON2, even on a 3-button mouse.
++*/
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiMouseP::SoGuiMouseP(So at Gui@Mouse * p)
++{
++ this->pub = p;
++
++ // Allocate system-neutral event objects once and reuse.
++ this->buttonevent = new SoMouseButtonEvent;
++ this->locationevent = new SoLocation2Event;
++}
++
++SoGuiMouseP::~SoGuiMouseP()
++{
++ delete this->buttonevent;
++ delete this->locationevent;
++}
++
++#endif // !DOXYGEN_SKIP_THIS
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiMouse.h.in
+@@ -0,0 +1,74 @@
++#ifndef SO at GUI@_MOUSE_H
++#define SO at GUI@_MOUSE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++class SoMouseButtonEvent;
++class SoLocation2Event;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Mouse : public So at Gui@Device {
++ SO at GUI@_OBJECT_HEADER(So at Gui@Mouse, So at Gui@Device);
++
++public:
++ enum Events {
++ BUTTON_PRESS = 0x01,
++ BUTTON_RELEASE = 0x02,
++ POINTER_MOTION = 0x04,
++ BUTTON_MOTION = 0x08,
++
++ ALL_EVENTS = BUTTON_PRESS | BUTTON_RELEASE | POINTER_MOTION | BUTTON_MOTION
++ };
++
++ So at Gui@Mouse(int eventmask = ALL_EVENTS);
++ virtual ~So at Gui@Mouse(void);
++
++ virtual void enable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++ virtual void disable(@WIDGET@ widget, So at Gui@EventHandler * handler, void * closure);
++
++ virtual const SoEvent * translateEvent(@EVENT@ event);
++
++private:
++ class So at Gui@MouseP * pimpl;
++ friend class So at Gui@MouseP;
++ friend class SoGuiMouseP;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_MOUSE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiMouseP.h.in
+@@ -0,0 +1,62 @@
++#ifndef SOGUI_MOUSEP_H
++#define SOGUI_MOUSEP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++class SoMouseButtonEvent;
++class SoLocation2Event;
++
++// *************************************************************************
++
++class SoGuiMouseP {
++public:
++ SoGuiMouseP(class So at Gui@Mouse * p);
++ ~SoGuiMouseP();
++
++ SoMouseButtonEvent * buttonevent;
++ SoLocation2Event * locationevent;
++ int eventmask;
++
++protected:
++ class So at Gui@Mouse * pub;
++};
++
++// *************************************************************************
++
++#endif // ! SOGUI_MOUSEP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiSpacenavDevice.cpp.in
+@@ -0,0 +1,74 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/misc/SoBasic.h>
++#include <Inventor/@Gui@/devices/So at Gui@SpacenavDevice.h>
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@SpacenavDevice);
++
++So at Gui@SpacenavDevice::So at Gui@SpacenavDevice()
++{
++}
++
++
++So at Gui@SpacenavDevice::~So at Gui@SpacenavDevice()
++{
++}
++
++
++void
++So at Gui@SpacenavDevice::enable(HWND w, So at Gui@EventHandler * handler, void * closure)
++{
++}
++
++
++void
++So at Gui@SpacenavDevice::disable(HWND w, So at Gui@EventHandler * handler, void * closure)
++{
++}
++
++
++const SoEvent *
++So at Gui@SpacenavDevice::translateEvent(MSG * inevent)
++{
++ return NULL;
++}
++
++
++
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/devices/SoGuiSpacenavDevice.h.in
+@@ -0,0 +1,61 @@
++#ifndef SO at GUI@_SPACENAVDEVICE_H
++#define SO at GUI@_SPACENAVDEVICE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/devices/So at Gui@Device.h>
++
++class SOWIN_DLL_API So at Gui@SpacenavDevice : public So at Gui@Device {
++ SOWIN_OBJECT_HEADER(So at Gui@SpacenavDevice, So at Gui@Device);
++
++ public:
++ So at Gui@SpacenavDevice();
++ virtual ~So at Gui@SpacenavDevice();
++
++ virtual void enable(HWND w, So at Gui@EventHandler * handler, void * closure);
++ virtual void disable(HWND w, So at Gui@EventHandler * handler, void * closure);
++ virtual const SoEvent * translateEvent(MSG * event);
++
++ private:
++ class So at Gui@SpacenavDeviceP * pimpl;
++ friend class So at Gui@SpacenavDeviceP;
++};
++
++
++#endif // !SO at GUI@_SPACENAVDEVICE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/README
+@@ -0,0 +1,2 @@
++This directory contains common development-related documentation for
++all So* toolkits.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/api-wish-list.txt
+@@ -0,0 +1,59 @@
++WHAT'S THIS?
++============
++
++This document describes API extension ideas where we think the So*
++libraries lacks necessary functionality.
++
++The listing of an API change or API extension in this file does not
++mean that it will be implemented, only that it will be considered for
++implementation.
++
++Ideas for this wish list can be submitted by anyone.
++
++
++THE WISH LIST
++=============
++
++* Mouse control configuration API
++ 2001-12-17 write-up by <mortene at sim.no>
++ [upwards compatible extension]
++
++ A request from coin-discuss: it should be possible for application
++ programmers to change the default mousebutton combination
++ configurations for dragging / zooming / panning for the
++ So*ExaminerViewer, and likewise for the other viewer classes.
++
++
++* Doubleclick handling
++ 2002-01-16 Morten Eriksen <mortene at sim.no>
++
++ The So*Mouse device class has no notion of doubleclick events, which
++ complicates matters for application programmers who wants to offer
++ those to the end-user for interaction. They can of course just
++ compare timings between single clicks, but those numbers will then
++ have to be compared to the murky details of the underlying GUI
++ toolkit manually to make it blend in with the rest (end-users tend
++ to configure their OS doubleclick interval setting to wildly
++ differing values, in my experience).
++
++ To fix this API deficiency, we would probably also need to add to
++ the API of Coin's SoMouseEvent, which have no concept of
++ doubleclicks either.
++
++
++* API for the viewer scenegraph
++ 2002-05-28 Peder Blekken <pederb at sim.no>, writeup by <mortene at sim.no>
++
++ Parts of the viewer scenegraphs are interesting to get access to for
++ the application programmers, to configure certain viewer parameters
++ like color settings in wireframe / point / bbox rendering styles,
++ etc.
++
++ At the same time, we want to avoid bloating the So at Gui@*Viewer APIs
++ with all these simple accessor (set*()/get*()) methods.
++
++ Peder's idea for a solution: we can hide the actual scenegraph
++ structure within an extension nodekit class, setting up a separate
++ public API on this nodekit. This would give us implementation
++ hiding, full control over what gets exposed, and no additional bloat
++ on the So at Gui@*Viewer classes.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/doxygen/footer.html
+@@ -0,0 +1,6 @@
++<hr noshade>
++<p align="right">Copyright © by <a href="http://www.kongsberg.com/kogt">Kongsberg Oil & Gas Technologies</a>. All rights reserved.</p>
++<address style="align: right;"><small>
++Generated on $datetime for $projectname by <a href="http://www.doxygen.org/">Doxygen</a> $doxygenversion.</small></address>
++</body>
++</html>
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/doxygen/header.html
+@@ -0,0 +1,16 @@
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
++<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
++<title>$title</title>
++<link href="stylesheet.css" rel="stylesheet" type="text/css">
++</head><body><table width="100%">
++<tr>
++ <td>
++ <img src="Coin_logo.png" alt="Coin Logo">
++ </td>
++ <td align="right">
++ <a href="http://www.coin3d.org/">http://www.coin3d.org/</a><br />
++ <a href="http://www.kongsberg.com/kogt/">http://www.kongsberg.com/kogt/</a><br />
++ </td>
++</tr>
++</table>
++<hr noshade />
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/doxygen/stylesheet.css
+@@ -0,0 +1,362 @@
++BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
++ font-family: Geneva, Arial, Helvetica, sans-serif;
++}
++BODY,TD {
++ font-size: 90%;
++}
++H1 {
++ text-align: center;
++ font-size: 160%;
++}
++H2 {
++ font-size: 120%;
++}
++H3 {
++ font-size: 100%;
++}
++IMG {
++ border: 0;
++}
++CAPTION { font-weight: bold }
++DIV.qindex {
++ width: 100%;
++ background-color: #e8eef2;
++ border: 1px solid #84b0c7;
++ text-align: center;
++ margin: 2px;
++ padding: 2px;
++ line-height: 140%;
++}
++DIV.nav {
++ width: 100%;
++ background-color: #e8eef2;
++ border: 1px solid #84b0c7;
++ text-align: center;
++ margin: 2px;
++ padding: 2px;
++ line-height: 140%;
++}
++DIV.navtab {
++ background-color: #e8eef2;
++ border: 1px solid #84b0c7;
++ text-align: center;
++ margin: 2px;
++ margin-right: 15px;
++ padding: 2px;
++}
++TD.navtab {
++ font-size: 70%;
++}
++A.qindex {
++ text-decoration: none;
++ font-weight: bold;
++ color: #1A419D;
++}
++A.qindex:visited {
++ text-decoration: none;
++ font-weight: bold;
++ color: #1A419D
++}
++A.qindex:hover {
++ text-decoration: none;
++ background-color: #ddddff;
++}
++A.qindexHL {
++ text-decoration: none;
++ font-weight: bold;
++ background-color: #6666cc;
++ color: #ffffff;
++ border: 1px double #9295C2;
++}
++A.qindexHL:hover {
++ text-decoration: none;
++ background-color: #6666cc;
++ color: #ffffff;
++}
++A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
++A.el { text-decoration: none; font-weight: bold }
++A.elRef { font-weight: bold }
++A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
++A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
++A.codeRef:link { font-weight: normal; color: #0000FF}
++A.codeRef:visited { font-weight: normal; color: #0000FF}
++A:hover { text-decoration: none; background-color: #f2f2ff }
++DL.el { margin-left: -1cm }
++.fragment {
++ font-family: monospace, fixed;
++ font-size: 95%;
++}
++PRE.fragment {
++ border: 1px solid #CCCCCC;
++ background-color: #f5f5f5;
++ margin-top: 4px;
++ margin-bottom: 4px;
++ margin-left: 2px;
++ margin-right: 8px;
++ padding-left: 6px;
++ padding-right: 6px;
++ padding-top: 4px;
++ padding-bottom: 4px;
++}
++DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
++
++DIV.groupHeader {
++ margin-left: 16px;
++ margin-top: 12px;
++ margin-bottom: 6px;
++ font-weight: bold;
++}
++DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
++BODY {
++ background: white;
++ color: black;
++ margin-right: 20px;
++ margin-left: 20px;
++}
++TD.indexkey {
++ background-color: #e8eef2;
++ font-weight: bold;
++ padding-right : 10px;
++ padding-top : 2px;
++ padding-left : 10px;
++ padding-bottom : 2px;
++ margin-left : 0px;
++ margin-right : 0px;
++ margin-top : 2px;
++ margin-bottom : 2px;
++ border: 1px solid #CCCCCC;
++}
++TD.indexvalue {
++ background-color: #e8eef2;
++ font-style: italic;
++ padding-right : 10px;
++ padding-top : 2px;
++ padding-left : 10px;
++ padding-bottom : 2px;
++ margin-left : 0px;
++ margin-right : 0px;
++ margin-top : 2px;
++ margin-bottom : 2px;
++ border: 1px solid #CCCCCC;
++}
++TR.memlist {
++ background-color: #f0f0f0;
++}
++P.formulaDsp { text-align: center; }
++IMG.formulaDsp { }
++IMG.formulaInl { vertical-align: middle; }
++SPAN.keyword { color: #008000 }
++SPAN.keywordtype { color: #604020 }
++SPAN.keywordflow { color: #e08000 }
++SPAN.comment { color: #800000 }
++SPAN.preprocessor { color: #806020 }
++SPAN.stringliteral { color: #002080 }
++SPAN.charliteral { color: #008080 }
++.mdescLeft {
++ padding: 0px 8px 4px 8px;
++ font-size: 80%;
++ font-style: italic;
++ background-color: #FAFAFA;
++ border-top: 1px none #E0E0E0;
++ border-right: 1px none #E0E0E0;
++ border-bottom: 1px none #E0E0E0;
++ border-left: 1px none #E0E0E0;
++ margin: 0px;
++}
++.mdescRight {
++ padding: 0px 8px 4px 8px;
++ font-size: 80%;
++ font-style: italic;
++ background-color: #FAFAFA;
++ border-top: 1px none #E0E0E0;
++ border-right: 1px none #E0E0E0;
++ border-bottom: 1px none #E0E0E0;
++ border-left: 1px none #E0E0E0;
++ margin: 0px;
++}
++.memItemLeft {
++ padding: 1px 0px 0px 8px;
++ margin: 4px;
++ border-top-width: 1px;
++ border-right-width: 1px;
++ border-bottom-width: 1px;
++ border-left-width: 1px;
++ border-top-color: #E0E0E0;
++ border-right-color: #E0E0E0;
++ border-bottom-color: #E0E0E0;
++ border-left-color: #E0E0E0;
++ border-top-style: solid;
++ border-right-style: none;
++ border-bottom-style: none;
++ border-left-style: none;
++ background-color: #FAFAFA;
++ font-size: 80%;
++}
++.memItemRight {
++ padding: 1px 8px 0px 8px;
++ margin: 4px;
++ border-top-width: 1px;
++ border-right-width: 1px;
++ border-bottom-width: 1px;
++ border-left-width: 1px;
++ border-top-color: #E0E0E0;
++ border-right-color: #E0E0E0;
++ border-bottom-color: #E0E0E0;
++ border-left-color: #E0E0E0;
++ border-top-style: solid;
++ border-right-style: none;
++ border-bottom-style: none;
++ border-left-style: none;
++ background-color: #FAFAFA;
++ font-size: 80%;
++}
++.memTemplItemLeft {
++ padding: 1px 0px 0px 8px;
++ margin: 4px;
++ border-top-width: 1px;
++ border-right-width: 1px;
++ border-bottom-width: 1px;
++ border-left-width: 1px;
++ border-top-color: #E0E0E0;
++ border-right-color: #E0E0E0;
++ border-bottom-color: #E0E0E0;
++ border-left-color: #E0E0E0;
++ border-top-style: none;
++ border-right-style: none;
++ border-bottom-style: none;
++ border-left-style: none;
++ background-color: #FAFAFA;
++ font-size: 80%;
++}
++.memTemplItemRight {
++ padding: 1px 8px 0px 8px;
++ margin: 4px;
++ border-top-width: 1px;
++ border-right-width: 1px;
++ border-bottom-width: 1px;
++ border-left-width: 1px;
++ border-top-color: #E0E0E0;
++ border-right-color: #E0E0E0;
++ border-bottom-color: #E0E0E0;
++ border-left-color: #E0E0E0;
++ border-top-style: none;
++ border-right-style: none;
++ border-bottom-style: none;
++ border-left-style: none;
++ background-color: #FAFAFA;
++ font-size: 80%;
++}
++.memTemplParams {
++ padding: 1px 0px 0px 8px;
++ margin: 4px;
++ border-top-width: 1px;
++ border-right-width: 1px;
++ border-bottom-width: 1px;
++ border-left-width: 1px;
++ border-top-color: #E0E0E0;
++ border-right-color: #E0E0E0;
++ border-bottom-color: #E0E0E0;
++ border-left-color: #E0E0E0;
++ border-top-style: solid;
++ border-right-style: none;
++ border-bottom-style: none;
++ border-left-style: none;
++ color: #606060;
++ background-color: #FAFAFA;
++ font-size: 80%;
++}
++.search { color: #003399;
++ font-weight: bold;
++}
++FORM.search {
++ margin-bottom: 0px;
++ margin-top: 0px;
++}
++INPUT.search { font-size: 75%;
++ color: #000080;
++ font-weight: normal;
++ background-color: #e8eef2;
++}
++TD.tiny { font-size: 75%;
++}
++a {
++ color: #1A41A8;
++}
++a:visited {
++ color: #2A3798;
++}
++.dirtab { padding: 4px;
++ border-collapse: collapse;
++ border: 1px solid #84b0c7;
++}
++TH.dirtab { background: #e8eef2;
++ font-weight: bold;
++}
++HR { height: 1px;
++ border: none;
++ border-top: 1px solid black;
++}
++
++/* Style for detailed member documentation */
++.memtemplate {
++ font-size: 80%;
++ color: #606060;
++ font-weight: normal;
++ margin-left: 3px;
++}
++.memnav {
++ background-color: #e8eef2;
++ border: 1px solid #84b0c7;
++ text-align: center;
++ margin: 2px;
++ margin-right: 15px;
++ padding: 2px;
++}
++.memitem {
++ padding: 4px;
++ background-color: #eef3f5;
++ border-width: 1px;
++ border-style: solid;
++ border-color: #dedeee;
++ -moz-border-radius: 8px 8px 8px 8px;
++}
++.memname {
++ white-space: nowrap;
++ font-weight: bold;
++}
++.memdoc{
++ padding-left: 10px;
++}
++.memproto {
++ background-color: #d5e1e8;
++ width: 100%;
++ border-width: 1px;
++ border-style: solid;
++ border-color: #84b0c7;
++ font-weight: bold;
++ -moz-border-radius: 8px 8px 8px 8px;
++}
++.paramkey {
++ text-align: right;
++}
++.paramtype {
++ white-space: nowrap;
++}
++.paramname {
++ color: #602020;
++ font-style: italic;
++ white-space: nowrap;
++}
++/* End Styling for detailed member documentation */
++
++/* for the tree view */
++.ftvtree {
++ font-family: sans-serif;
++ margin:0.5em;
++}
++.directory { font-size: 9pt; font-weight: bold; }
++.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }
++.directory > h3 { margin-top: 0; }
++.directory p { margin: 0px; white-space: nowrap; }
++.directory div { display: none; margin: 0px; }
++.directory img { vertical-align: -30%; }
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/docs/todo.txt
+@@ -0,0 +1,24 @@
++WHAT'S THIS?
++============
++
++This document contains a list of various common deficiencies in the
++So*-libraries that are larger in scope than just simple API additions
++/ changes (see the api-wish-list.txt file for that kind of "mini"
++projects).
++
++
++
++COMMON STUFF TO FIX IN THE SO* LIBRARIES
++========================================
++
++
++* Cross-platform spaceball and joystick device support
++ 2002-01-03 Morten Eriksen <mortene at sim.no>
++
++ Requested by Coin PEL holder Daniel Soto Alvarez.
++
++ We already have support for spaceballs and joysticks implemented for
++ some of the So*-libraries.
++
++ For spaceball SDKs, see
++ <URL:http://www.3dconnexion.com/software/sdk/>.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiColorEditor.cpp.in
+@@ -0,0 +1,647 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// FIXME: overload the getClassName() type functions
++
++#include <Inventor/SbPList.h>
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/fields/SoSFColor.h>
++#include <Inventor/fields/SoMFColor.h>
++#include <Inventor/fields/SoMFUInt32.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <Inventor/@Gui@/editors/So at Gui@ColorEditor.h>
++
++/*
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++*/
++
++
++/*!
++ \class So at Gui@ColorEditor Inventor/@Gui@/editors/So at Gui@ColorEditor.h
++ \brief The So at Gui@ColorEditor class is a GUI component for interactively
++ editing color fields.
++*/
++
++/*!
++ \enum So at Gui@ColorEditor::Sliders
++*/
++
++/*!
++ \val So at Gui@ColorEditor::NONE
++*/
++
++/*!
++ \val So at Gui@ColorEditor::INTENSITY
++*/
++
++/*!
++ \val So at Gui@ColorEditor::RGB
++*/
++
++/*!
++ \val So at Gui@ColorEditor::HSV
++*/
++
++/*!
++ \val So at Gui@ColorEditor::RGB_V
++*/
++
++/*!
++ \val So at Gui@ColorEditor::RGB_HSV
++*/
++
++/*!
++ \enum So at Gui@ColorEditor::UpdateFrequency
++*/
++
++/*!
++ \val So at Gui@ColorEditor::CONTINUOUS
++*/
++
++/*!
++ \val So at Gui@ColorEditor::AFTER_ACCEPT
++*/
++
++// *************************************************************************
++
++static const SbBool SGI_ATTACHMENT_REF_COMPATIBILITY = TRUE;
++
++enum Attachment {
++ DETACHED,
++ SFCOLOR,
++ MFCOLOR,
++ MFUINT32
++};
++
++// Name suffix used to avoid conflict with private part of the ColorEditor
++// node kit.
++
++class ColorEditorComponent {
++public:
++ So at Gui@ColorEditor * api;
++
++ static const char * superscene[];
++
++ SbPList callbacks;
++
++ // attachment is redundant - the existence of the field sensor, and the
++ // field type it is attached to is all the info needed really
++ Attachment attachment;
++ // the field pointers can actually be dropped since the sensor will have
++ // that info
++ SoSFColor * sfcolor;
++ SoMFColor * mfcolor;
++ SoMFUInt32 * mfuint32;
++ int mfindex;
++
++ SoFieldSensor * editor_sensor;
++ static void editor_update_cb(void * closure, SoSensor * sensor);
++
++ SoFieldSensor * attachment_sensor;
++ static void attachment_update_cb(void * closure, SoSensor * sensor);
++
++ SoGuiColorEditor * editor;
++
++ void invokeColorChangeCallbacks(void);
++ SbBool colorsEqual(void);
++};
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@ColorEditor);
++
++#define PRIVATE(obj) ((ColorEditorComponent *) ((So at Gui@ColorEditor *) obj)->internals)
++#define PUBLIC(obj) (((ColorEditorComponent *) obj)->api)
++
++So at Gui@ColorEditor::So at Gui@ColorEditor(@WIDGET@ parent, const char * name, SbBool embed)
++ : inherited(parent, name, embed)
++{
++ this->internals = (void *) new ColorEditorComponent;
++ PRIVATE(this)->api = this;
++
++ PRIVATE(this)->attachment = DETACHED;
++ PRIVATE(this)->sfcolor = NULL;
++ PRIVATE(this)->sfcolor = NULL;
++ PRIVATE(this)->mfcolor = NULL;
++ PRIVATE(this)->mfuint32 = NULL;
++ PRIVATE(this)->mfindex = 0;
++
++ PRIVATE(this)->editor_sensor = NULL;
++ PRIVATE(this)->attachment_sensor = NULL;
++
++ PRIVATE(this)->editor = NULL;
++
++ this->setSize(SbVec2s(320, 256));
++
++ SoNode * root = SoAny::loadSceneGraph(ColorEditorComponent::superscene);
++ assert(root != NULL);
++ assert(root->isOfType(SoSeparator::getClassTypeId()));
++ SoSeparator * superscene = (SoSeparator *) root;
++
++ PRIVATE(this)->editor = new SoGuiColorEditor;
++ superscene->addChild(PRIVATE(this)->editor);
++ this->setSceneGraph(superscene);
++
++ PRIVATE(this)->attachment_sensor = new SoFieldSensor(ColorEditorComponent::attachment_update_cb, PRIVATE(this));
++
++ PRIVATE(this)->editor_sensor = new SoFieldSensor(ColorEditorComponent::editor_update_cb, PRIVATE(this));
++ PRIVATE(this)->editor_sensor->attach(&(PRIVATE(this)->editor->color));
++}
++
++So at Gui@ColorEditor::~So at Gui@ColorEditor(void)
++{
++ if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++ delete PRIVATE(this)->attachment_sensor;
++ delete PRIVATE(this)->editor_sensor;
++ this->setSceneGraph(NULL);
++ ColorEditorComponent * instance = PRIVATE(this);
++ delete instance;
++}
++
++/*!
++ Attach the editor to a color single field. Any existing attachments are
++ detached.
++
++ The node argument defaults to NULL and is ignored. It is part of the
++ argument list for compatibility reasons.
++*/
++
++void
++So at Gui@ColorEditor::attach(SoSFColor * color, SoBase * node)
++{
++ if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++ if ( color != NULL ) {
++ if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++ SoFieldContainer * container = color->getContainer();
++ if ( container != NULL ) container->ref();
++ }
++ PRIVATE(this)->attachment = SFCOLOR;
++ PRIVATE(this)->sfcolor = color;
++ assert(PRIVATE(this)->attachment_sensor != NULL);
++ PRIVATE(this)->attachment_sensor->attach(color);
++ PRIVATE(this)->editor->color.setValue(color->getValue());
++ }
++}
++
++/*!
++ Attach the editor to an element in a color multi field. Any existing attachments are
++ detached.
++
++ The node argument defaults to NULL and is ignored. It is part of the
++ argument list for compatibility reasons.
++*/
++
++void
++So at Gui@ColorEditor::attach(SoMFColor * color, int idx, SoBase * node)
++{
++ if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++ if ( color != NULL ) {
++ if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++ SoFieldContainer * container = color->getContainer();
++ if ( container != NULL ) container->ref();
++ }
++ PRIVATE(this)->attachment = MFCOLOR;
++ PRIVATE(this)->mfcolor = color;
++ PRIVATE(this)->mfindex = idx;
++ assert(PRIVATE(this)->attachment_sensor != NULL);
++ PRIVATE(this)->attachment_sensor->attach(color);
++ PRIVATE(this)->editor->color.setValue(color->operator[](idx));
++ }
++}
++
++/*!
++ Attach the editor to an element in an uint32 multi field. The field
++ is assumed to be of the RGBA packed color format. Any existing attachments are
++ detached.
++
++ The node argument defaults to NULL and is ignored. It is part of the
++ argument list for compatibility reasons.
++*/
++
++void
++So at Gui@ColorEditor::attach(SoMFUInt32 * color, int idx, SoBase * node)
++{
++ if ( PRIVATE(this)->attachment != DETACHED ) this->detach();
++ if ( color != NULL ) {
++ if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++ SoFieldContainer * container = color->getContainer();
++ if ( container != NULL ) container->ref();
++ }
++ PRIVATE(this)->attachment = MFUINT32;
++ PRIVATE(this)->mfuint32 = color;
++ PRIVATE(this)->mfindex = idx;
++ assert(PRIVATE(this)->attachment_sensor != NULL);
++ PRIVATE(this)->attachment_sensor->attach(color);
++ SbColor col;
++ float transparency = 0.0f;
++ col.setPackedValue(color->operator[](idx), transparency);
++ PRIVATE(this)->editor->color.setValue(col);
++ }
++}
++
++/*!
++ Detach the editor from the field it is attached to.
++*/
++
++void
++So at Gui@ColorEditor::detach(void)
++{
++ if ( PRIVATE(this)->attachment != DETACHED ) {
++ SoField * field = NULL;
++ switch ( PRIVATE(this)->attachment ) {
++ case SFCOLOR:
++ field = PRIVATE(this)->sfcolor;
++ PRIVATE(this)->sfcolor = NULL;
++ break;
++ case MFCOLOR:
++ field = PRIVATE(this)->mfcolor;
++ PRIVATE(this)->mfcolor = NULL;
++ break;
++ case MFUINT32:
++ field = PRIVATE(this)->mfuint32;
++ PRIVATE(this)->mfuint32 = NULL;
++ break;
++ case DETACHED:
++ default:
++ assert(0 && "impossible switch case");
++ break;
++ }
++ assert(field != NULL);
++ if ( field != NULL ) {
++ assert(PRIVATE(this)->attachment_sensor != NULL);
++ PRIVATE(this)->attachment_sensor->detach();
++ if ( SGI_ATTACHMENT_REF_COMPATIBILITY ) {
++ SoFieldContainer * container = field->getContainer();
++ if ( container != NULL ) container->unref();
++ }
++ }
++ PRIVATE(this)->attachment = DETACHED;
++ }
++}
++
++/*!
++ This method returns whether or not the editor is currently attached to a field.
++*/
++
++SbBool
++So at Gui@ColorEditor::isAttached(void) const
++{
++ return (PRIVATE(this)->attachment != DETACHED) ? TRUE : FALSE;
++}
++
++/*
++ Add a callback to be triggered when the color value is changed.
++
++ \sa So at Gui@ColorEditor::setUpdateFrequency
++*/
++
++void
++So at Gui@ColorEditor::addColorChangedCallback(So at Gui@ColorEditorCB * callback, void * closure)
++{
++ PRIVATE(this)->callbacks.append((void *) callback);
++ PRIVATE(this)->callbacks.append(closure);
++}
++
++/*!
++ Remove all color change callbacks matching the given arguments.
++*/
++
++void
++So at Gui@ColorEditor::removeColorChangedCallback(So at Gui@ColorEditorCB * callback, void * closure)
++{
++ const int len = PRIVATE(this)->callbacks.getLength();
++ int i;
++ for ( i = 0; i < len; i += 2 ) {
++ So at Gui@ColorEditorCB * cb =
++ (So at Gui@ColorEditorCB *) PRIVATE(this)->callbacks[i];
++ if ( (callback == cb) && (closure == PRIVATE(this)->callbacks[i+1]) ) {
++ PRIVATE(this)->callbacks.remove(i+1);
++ PRIVATE(this)->callbacks.remove(i);
++ i -= 2;
++ }
++ }
++}
++
++/*!
++ Set a new color value.
++
++ If the field value gets updated, the color change callbacks will be triggered.
++*/
++
++void
++So at Gui@ColorEditor::setColor(const SbColor & color)
++{
++ // callbacks are triggered on the sensor rebound...
++ switch ( PRIVATE(this)->attachment ) {
++ case DETACHED:
++ break;
++ case SFCOLOR:
++ assert(PRIVATE(this)->sfcolor != NULL);
++ if ( PRIVATE(this)->sfcolor->getValue() != color ) {
++ PRIVATE(this)->sfcolor->setValue(color);
++ }
++ break;
++ case MFCOLOR:
++ assert(PRIVATE(this)->mfcolor != NULL);
++ if ( PRIVATE(this)->mfcolor->operator[](PRIVATE(this)->mfindex) != color ) {
++ PRIVATE(this)->mfcolor->set1Value(PRIVATE(this)->mfindex, color);
++ }
++ break;
++ case MFUINT32:
++ assert(PRIVATE(this)->mfuint32 != NULL);
++ if ( PRIVATE(this)->mfuint32->operator[](PRIVATE(this)->mfindex) != color.getPackedValue() ) {
++ PRIVATE(this)->mfuint32->set1Value(PRIVATE(this)->mfindex, color.getPackedValue());
++ }
++ break;
++ }
++ assert(PRIVATE(this)->editor != NULL);
++ PRIVATE(this)->editor->color.setValue(color);
++}
++
++/*!
++ Get the current color value.
++*/
++
++const SbColor &
++So at Gui@ColorEditor::getColor(void) const
++{
++ assert(PRIVATE(this)->editor != NULL);
++ return PRIVATE(this)->editor->color.getValue();
++}
++
++/*!
++ Not implemented yet.
++
++ Sets whether or not the color sliders should be in WYSIWYG mode.
++ When enabled, the color backgrounds in the sliders will be updated to
++ reflect what the color will be, taken all color components into account.
++ When disabled, the color backgrounds only reflect the component the slider
++ controls.
++*/
++
++void
++So at Gui@ColorEditor::setWYSIWYG(SbBool enable)
++{
++ assert(PRIVATE(this)->editor != NULL);
++ PRIVATE(this)->editor->wysiwyg.setValue(enable);
++}
++
++/*!
++ Returns whether or not the editor sliders are in WYSIWYG mode.
++*/
++
++SbBool
++So at Gui@ColorEditor::isWYSIWYG(void) const
++{
++ assert(PRIVATE(this)->editor != NULL);
++ return PRIVATE(this)->editor->wysiwyg.getValue();
++}
++
++/*!
++ Sets which if the slider sets is to be used.
++
++ \sa So at Gui@ColorEditor::Sliders
++*/
++
++void
++So at Gui@ColorEditor::setCurrentSliders(So at Gui@ColorEditor::Sliders which)
++{
++ assert(PRIVATE(this)->editor != NULL);
++ PRIVATE(this)->editor->sliders.setValue((So at Gui@ColorEditor::Sliders) which);
++}
++
++/*!
++ Returns which slider sets is being used.
++
++ \sa So at Gui@ColorEditor::Sliders
++*/
++
++So at Gui@ColorEditor::Sliders
++So at Gui@ColorEditor::getCurrentSliders(void) const
++{
++ assert(PRIVATE(this)->editor != NULL);
++ return (So at Gui@ColorEditor::Sliders) PRIVATE(this)->editor->sliders.getValue();
++}
++
++/*!
++ Sets the update-frequency setting, which affects when color change callbacks
++ will be triggered.
++
++ \sa So at Gui@ColorEditor::UpdateFrequency
++*/
++
++void
++So at Gui@ColorEditor::setUpdateFrequency(So at Gui@ColorEditor::UpdateFrequency freq)
++{
++ assert(PRIVATE(this)->editor != NULL);
++ PRIVATE(this)->editor->update.setValue((So at Gui@ColorEditor::UpdateFrequency) freq);
++}
++
++/*!
++ Returns the update-frequency setting.
++
++ \sa So at Gui@ColorEditor::UpdateFrequency
++*/
++
++So at Gui@ColorEditor::UpdateFrequency
++So at Gui@ColorEditor::getUpdateFrequency(void) const
++{
++ assert(PRIVATE(this)->editor != NULL);
++ return (So at Gui@ColorEditor::UpdateFrequency) PRIVATE(this)->editor->update.getValue();
++}
++
++SoGuiColorEditor *
++So at Gui@ColorEditor::getEditor(void) const
++{
++ return PRIVATE(this)->editor;
++}
++
++// *************************************************************************
++
++const char *
++So at Gui@ColorEditor::getDefaultWidgetName(void) const
++{
++ static const char widgetName[] = "So at Gui@ColorEditor";
++ return widgetName;
++}
++
++const char *
++So at Gui@ColorEditor::getDefaultTitle(void) const
++{
++ static const char title[] = "ColorEditor";
++ return title;
++}
++
++const char *
++So at Gui@ColorEditor::getDefaultIconTitle(void) const
++{
++ static const char iconTitle[] = "ColEd";
++ return iconTitle;
++}
++
++// *************************************************************************
++// ColorEditorComponent
++// *************************************************************************
++
++const char *
++ColorEditorComponent::superscene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " DirectionalLight { direction 0 0 -1 color 1 1 1 intensity 0.8 }",
++ " OrthographicCamera { }",
++ " DEF viewportfix SoGuiViewportFix { }",
++ " Material { ambientColor 0.8 0.8 0.8 }",
++ "}",
++ NULL
++};
++
++// *************************************************************************
++
++void
++ColorEditorComponent::invokeColorChangeCallbacks(void)
++{
++ int i;
++ for ( i = 0; i < this->callbacks.getLength(); i += 2 ) {
++ So at Gui@ColorEditorCB * callback = (So at Gui@ColorEditorCB *) this->callbacks[i];
++ void * closure = this->callbacks[i+1];
++ callback(closure, &this->editor->color.getValue());
++ }
++}
++
++SbBool
++ColorEditorComponent::colorsEqual(void)
++{
++ SbColor attachmentColor;
++ switch ( this->attachment ) {
++ case SFCOLOR:
++ assert(this->sfcolor != NULL);
++ attachmentColor = this->sfcolor->getValue();
++ break;
++ case MFCOLOR:
++ assert(this->mfcolor != NULL);
++ attachmentColor = this->mfcolor->operator[](this->mfindex);
++ break;
++ case MFUINT32:
++ assert(this->mfcolor != NULL);
++ do {
++ float transparency = 0.0f;
++ attachmentColor.setPackedValue(this->mfuint32->operator[](this->mfindex), transparency);
++ } while ( FALSE );
++ break;
++ case DETACHED:
++ default:
++ return TRUE;
++ }
++ return (attachmentColor == this->editor->color.getValue()) ? TRUE : FALSE;
++}
++
++void
++ColorEditorComponent::attachment_update_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure != NULL);
++ ColorEditorComponent * me = (ColorEditorComponent *) closure;
++ if ( me->colorsEqual() ) return;
++
++ switch ( me->attachment ) {
++ case SFCOLOR:
++ assert(me->sfcolor != NULL);
++ me->editor->color.setValue(me->sfcolor->getValue());
++ break;
++ case MFCOLOR:
++ assert(me->mfcolor != NULL);
++ me->editor->color.setValue(me->mfcolor->operator[](me->mfindex));
++ break;
++ case MFUINT32:
++ assert(me->mfcolor != NULL);
++ do {
++ SbColor color;
++ float transparency = 0.0f;
++ color.setPackedValue(me->mfuint32->operator[](me->mfindex), transparency);
++ me->editor->color.setValue(color);
++ } while ( FALSE );
++ break;
++ case DETACHED:
++ default:
++ break;
++ }
++}
++
++void
++ColorEditorComponent::editor_update_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure != NULL);
++ ColorEditorComponent * me = (ColorEditorComponent *) closure;
++ if ( me->colorsEqual() ) return;
++
++ SbColor color = me->editor->color.getValue();
++
++ switch ( me->attachment ) {
++ case SFCOLOR:
++ assert(me->sfcolor != NULL);
++ me->sfcolor->setValue(color);
++ break;
++ case MFCOLOR:
++ assert(me->mfcolor != NULL);
++ me->mfcolor->set1Value(me->mfindex, color);
++ break;
++ case MFUINT32:
++ assert(me->mfuint32 != NULL);
++ me->mfuint32->set1Value(me->mfindex, color.getPackedValue());
++ break;
++ case DETACHED:
++ default:
++ break;
++ }
++
++ if ( me->editor->update.getValue() == SoGuiColorEditor::CONTINUOUS )
++ me->invokeColorChangeCallbacks();
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiColorEditor.h.in
+@@ -0,0 +1,102 @@
++#ifndef COIN_SO at GUI@COLOREDITOR_H
++#define COIN_SO at GUI@COLOREDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++typedef void So at Gui@ColorEditorCB(void * closure, const SbColor * color);
++
++class SbColor;
++class SoSFColor;
++class SoMFColor;
++class SoMFUInt32;
++
++class So at Gui@ColorEditor : public So at Gui@RenderArea {
++ SO at GUI@_OBJECT_HEADER(So at Gui@ColorEditor, So at Gui@RenderArea);
++
++public:
++ So at Gui@ColorEditor(@WIDGET@ parent = NULL, const char * name = NULL, SbBool embed = TRUE);
++ ~So at Gui@ColorEditor(void);
++
++ enum Sliders {
++ NONE = SoGuiColorEditor::NONE,
++ INTENSITY = SoGuiColorEditor::INTENSITY,
++ RGB = SoGuiColorEditor::RGB,
++ HSV = SoGuiColorEditor::HSV,
++ RGB_V = SoGuiColorEditor::RGB_V,
++ RGB_HSV = SoGuiColorEditor::RGB_HSV
++ };
++
++ enum UpdateFrequency {
++ CONTINUOUS = SoGuiColorEditor::CONTINUOUS,
++ AFTER_ACCEPT = SoGuiColorEditor::AFTER_ACCEPT
++ };
++
++ void attach(SoSFColor * color, SoBase * node = NULL);
++ void attach(SoMFColor * color, int idx = 0, SoBase * node = NULL);
++ void attach(SoMFUInt32 * color, int idx = 0, SoBase * node = NULL);
++ void detach(void);
++ SbBool isAttached(void) const;
++
++ void addColorChangedCallback(So at Gui@ColorEditorCB * cb, void * closure = NULL);
++ void removeColorChangedCallback(So at Gui@ColorEditorCB * cb, void * closure = NULL);
++
++ void setColor(const SbColor & color);
++ const SbColor & getColor(void) const;
++
++ void setWYSIWYG(SbBool enable);
++ SbBool isWYSIWYG(void) const;
++
++ void setCurrentSliders(Sliders which);
++ Sliders getCurrentSliders(void) const;
++
++ void setUpdateFrequency(UpdateFrequency freq);
++ UpdateFrequency getUpdateFrequency(void) const;
++
++ SoGuiColorEditor * getEditor(void) const;
++
++protected:
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SO at GUI@COLOREDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiMaterialEditor.cpp.in
+@@ -0,0 +1,356 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/SbPList.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoNodeSensor.h>
++#ifdef HAVE_SOVRMLMATERIAL
++#include <Inventor/VRMLnodes/SoVRMLMaterial.h>
++#endif // HAVE_SOVRMLMATERIAL
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++#include <Inventor/@Gui@/editors/So at Gui@ColorEditor.h>
++#include <Inventor/@Gui@/editors/So at Gui@MaterialEditor.h>
++
++// *************************************************************************
++
++class MaterialEditorComponent {
++public:
++ MaterialEditorComponent(void);
++ ~MaterialEditorComponent(void);
++
++ So at Gui@MaterialEditor * api;
++
++ void constructor(void);
++
++ So at Gui@MaterialEditor::UpdateFrequency frequency;
++
++ SbPList * callbacks;
++ void invokeCallbacks(void);
++
++ SoNodeSensor * attachment;
++ SoMaterial * material;
++ SoGuiMaterialEditor * editor;
++
++ static SoGuiColorEditor * coloreditoropen_cb(void * closure);
++ static void coloreditorclose_cb(void * closure, SoGuiColorEditor * editor);
++ So at Gui@ColorEditor * coloreditor;
++
++ static SoSeparator * getSuperScene(void);
++ static SoNode * getSceneGraph(void);
++ static const char * superscene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((MaterialEditorComponent *) obj->internals)
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@MaterialEditor);
++
++So at Gui@MaterialEditor::So at Gui@MaterialEditor(@WIDGET@ parent, const char * name, SbBool embed)
++ : inherited(parent, name, embed)
++{
++ this->internals = new MaterialEditorComponent;
++ PRIVATE(this)->api = this;
++ PRIVATE(this)->constructor();
++}
++
++So at Gui@MaterialEditor::So at Gui@MaterialEditor(@WIDGET@ parent, const char * const name, SbBool embed, SbBool build)
++: inherited(parent, name, embed)
++{
++ this->internals = new MaterialEditorComponent;
++ PRIVATE(this)->api = this;
++ PRIVATE(this)->constructor();
++}
++
++So at Gui@MaterialEditor::~So at Gui@MaterialEditor(void)
++{
++ assert(PRIVATE(this)->editor);
++ MaterialEditorComponent * obj = PRIVATE(this);
++ delete obj;
++}
++
++void
++So at Gui@MaterialEditor::attach(SoMaterial * material, int index)
++{
++ assert(PRIVATE(this)->editor);
++ PRIVATE(this)->editor->material.setValue(material);
++ PRIVATE(this)->editor->index.setValue(index);
++}
++
++void
++So at Gui@MaterialEditor::attach(SoVRMLMaterial * material)
++{
++ assert(PRIVATE(this)->editor);
++#ifdef HAVE_SOVRMLMATERIAL
++ PRIVATE(this)->editor->material.setValue(material);
++#else // !HAVE_SOVRMLMATERIAL
++ PRIVATE(this)->editor->material.setValue((SoNode *) material);
++#endif // !HAVE_SOVRMLMATERIAL
++}
++
++void
++So at Gui@MaterialEditor::detach(void)
++{
++ PRIVATE(this)->editor->material.setValue(NULL);
++}
++
++SbBool
++So at Gui@MaterialEditor::isAttached(void)
++{
++ assert(PRIVATE(this)->editor != NULL);
++ return (PRIVATE(this)->editor->material.getValue() != NULL) ? TRUE : FALSE;
++}
++
++void
++So at Gui@MaterialEditor::addMaterialChangedCallback(So at Gui@MaterialEditorCB * callback, void * closure)
++{
++ if ( PRIVATE(this)->callbacks == NULL )
++ PRIVATE(this)->callbacks = new SbPList;
++ PRIVATE(this)->callbacks->append((void *) callback);
++ PRIVATE(this)->callbacks->append(closure);
++}
++
++void
++So at Gui@MaterialEditor::removeMaterialChangedCallback(So at Gui@MaterialEditorCB * callback, void * closure)
++{
++ assert(PRIVATE(this)->callbacks);
++ int i;
++ for ( i = PRIVATE(this)->callbacks->getLength(); i > 0; i -= 2 ) {
++ So at Gui@MaterialEditorCB * cb = (So at Gui@MaterialEditorCB *) (*(PRIVATE(this)->callbacks))[i-2];
++ void * cl = (*(PRIVATE(this)->callbacks))[i-1];
++ if ( cb == callback && cl == closure ) {
++ PRIVATE(this)->callbacks->remove(i-1);
++ PRIVATE(this)->callbacks->remove(i-2);
++ }
++ }
++}
++
++void
++So at Gui@MaterialEditor::setUpdateFrequency(So at Gui@MaterialEditor::UpdateFrequency frequency)
++{
++ PRIVATE(this)->frequency = frequency;
++}
++
++So at Gui@MaterialEditor::UpdateFrequency
++So at Gui@MaterialEditor::getUpdateFrequency(void) const
++{
++ return PRIVATE(this)->frequency;
++}
++
++void
++So at Gui@MaterialEditor::setMaterial(const SoMaterial & material)
++{
++ PRIVATE(this)->material->ambientColor.setValue(material.ambientColor[0]);
++ PRIVATE(this)->material->diffuseColor.setValue(material.diffuseColor[0]);
++ PRIVATE(this)->material->specularColor.setValue(material.specularColor[0]);
++ PRIVATE(this)->material->emissiveColor.setValue(material.emissiveColor[0]);
++ PRIVATE(this)->material->shininess.setValue(material.shininess[0]);
++ PRIVATE(this)->material->transparency.setValue(material.transparency[0]);
++}
++
++void
++So at Gui@MaterialEditor::setMaterial(const SoVRMLMaterial & material)
++{
++#ifdef HAVE_SOVRMLMATERIAL
++ float h, s, v;
++ h = 0.0f;
++ s = 0.0f;
++ v = material.ambientIntensity.getValue();
++ SbColor ambient;
++ ambient.setHSVValue(h, s, v);
++ PRIVATE(this)->material->ambientColor.setValue(ambient);
++ PRIVATE(this)->material->diffuseColor.setValue(material.diffuseColor.getValue());
++ PRIVATE(this)->material->specularColor.setValue(material.specularColor.getValue());
++ PRIVATE(this)->material->emissiveColor.setValue(material.emissiveColor.getValue());
++ PRIVATE(this)->material->shininess.setValue(material.shininess.getValue());
++ PRIVATE(this)->material->transparency.setValue(material.transparency.getValue());
++#endif // HAVE_SOVRMLMATERIAL
++}
++
++const SoMaterial &
++So at Gui@MaterialEditor::getMaterial(void) const
++{
++ return *(PRIVATE(this)->material);
++}
++
++SbBool
++So at Gui@MaterialEditor::isAttachedVRML(void)
++{
++ SoNode * material = PRIVATE(this)->editor->material.getValue();
++#ifdef HAVE_SOVRMLMATERIAL
++ return (material && material->isOfType(SoVRMLMaterial::getClassTypeId())) ? TRUE : FALSE;
++#endif
++ return FALSE;
++}
++
++SoGuiMaterialEditor *
++So at Gui@MaterialEditor::getEditor(void) const
++{
++ assert(0);
++ return NULL;
++}
++
++// *************************************************************************
++
++const char *
++So at Gui@MaterialEditor::getDefaultWidgetName(void) const
++{
++ static const char widgetName[] = "So at Gui@MaterialEditor";
++ return widgetName;
++}
++
++const char *
++So at Gui@MaterialEditor::getDefaultTitle(void) const
++{
++ static const char title[] = "MaterialEditor";
++ return title;
++}
++
++const char *
++So at Gui@MaterialEditor::getDefaultIconTitle(void) const
++{
++ static const char iconTitle[] = "MatEd";
++ return iconTitle;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++// MaterialEditorComponent
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++MaterialEditorComponent::superscene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " DirectionalLight { direction 0 0 -1 color 1 1 1 intensity 0.8 }",
++ " OrthographicCamera { }",
++ " DEF viewportfix SoGuiViewportFix { }",
++ " Material { ambientColor 0.8 0.8 0.8 }",
++ "}",
++ NULL
++};
++
++// *************************************************************************
++
++MaterialEditorComponent::MaterialEditorComponent(void)
++{
++ this->api = NULL;
++ this->attachment = NULL;
++ this->editor = NULL;
++ this->callbacks = NULL;
++ this->material = NULL;
++}
++
++MaterialEditorComponent::~MaterialEditorComponent(void)
++{
++ if ( this->attachment != NULL ) {
++ delete this->attachment;
++ }
++ if ( this->callbacks != NULL )
++ delete this->callbacks;
++}
++
++void
++MaterialEditorComponent::constructor(void)
++{
++ PUBLIC(this)->setSize(SbVec2s(550,300));
++ SoNode * scene = MaterialEditorComponent::getSceneGraph();
++ PUBLIC(this)->setSceneGraph(scene);
++ assert(scene->isOfType(SoSeparator::getClassTypeId()));
++ SoSeparator * sceneroot = (SoSeparator *) scene;
++ this->editor = (SoGuiMaterialEditor *) sceneroot->getChild(sceneroot->getNumChildren()-1);
++ assert(this->editor->isOfType(SoGuiMaterialEditor::getClassTypeId()));
++ this->material = this->editor->getSphereMaterialNode();
++ this->editor->setColorEditorCallbacks(MaterialEditorComponent::coloreditoropen_cb, MaterialEditorComponent::coloreditorclose_cb, this);
++}
++
++void
++MaterialEditorComponent::invokeCallbacks(void)
++{
++ // FIXME
++}
++
++SoSeparator *
++MaterialEditorComponent::getSuperScene(void)
++{
++ SoNode * root = SoAny::loadSceneGraph(MaterialEditorComponent::superscene);
++ assert(root != NULL);
++ assert(root->isOfType(SoSeparator::getClassTypeId()));
++ return (SoSeparator *) root;
++}
++
++SoNode *
++MaterialEditorComponent::getSceneGraph(void)
++{
++ SoSeparator * root = MaterialEditorComponent::getSuperScene();
++ assert(root != NULL);
++ // FIXME: route ViewportFix field value into editor
++ root->addChild(new SoGuiMaterialEditor);
++ return root;
++}
++
++SoGuiColorEditor *
++MaterialEditorComponent::coloreditoropen_cb(void * closure)
++{
++ MaterialEditorComponent * me = (MaterialEditorComponent *) closure;
++ me->coloreditor = new So at Gui@ColorEditor;
++ me->coloreditor->show();
++ return me->coloreditor->getEditor();
++}
++
++void
++MaterialEditorComponent::coloreditorclose_cb(void * closure, SoGuiColorEditor * editor)
++{
++ assert(closure);
++ MaterialEditorComponent * me = (MaterialEditorComponent *) closure;
++ me->coloreditor->hide();
++ delete me->coloreditor;
++ me->coloreditor = NULL;
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/editors/SoGuiMaterialEditor.h.in
+@@ -0,0 +1,94 @@
++#ifndef COIN_SO at GUI@MATERIALEDITOR_H
++#define COIN_SO at GUI@MATERIALEDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++class SoMaterial;
++class SoVRMLMaterial;
++
++// *************************************************************************
++
++typedef void So at Gui@MaterialEditorCB(void * userdata, const SoMaterial * material);
++
++class SO at GUI@_DLL_API So at Gui@MaterialEditor : public So at Gui@RenderArea {
++ SO at GUI@_OBJECT_HEADER(So at Gui@MaterialEditor, So at Gui@RenderArea);
++
++public:
++ So at Gui@MaterialEditor(@WIDGET@ parent = NULL, const char * name = NULL, SbBool embed = TRUE);
++ ~So at Gui@MaterialEditor(void);
++
++ enum UpdateFrequency {
++ CONTINUOUS = SoGuiMaterialEditor::CONTINUOUS,
++ AFTER_ACCEPT = SoGuiMaterialEditor::AFTER_ACCEPT
++ };
++
++ void attach(SoMaterial * material, int index = 0);
++ void attach(SoVRMLMaterial * material);
++ void detach(void);
++ SbBool isAttached(void);
++
++ void addMaterialChangedCallback(
++ So at Gui@MaterialEditorCB * callback, void * closure = NULL);
++ void removeMaterialChangedCallback(
++ So at Gui@MaterialEditorCB * callback, void * closure = NULL);
++
++ void setUpdateFrequency(So at Gui@MaterialEditor::UpdateFrequency frequency);
++ So at Gui@MaterialEditor::UpdateFrequency getUpdateFrequency(void) const;
++
++ void setMaterial(const SoMaterial & material);
++ void setMaterial(const SoVRMLMaterial & material);
++ const SoMaterial & getMaterial(void) const;
++ SbBool isAttachedVRML(void);
++
++ SoGuiMaterialEditor * getEditor(void) const;
++
++protected:
++ So at Gui@MaterialEditor(@WIDGET@ parent, const char * const name, SbBool embed, SbBool build);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++private:
++ void * internals;
++
++}; // class So at Gui@MaterialEditor
++
++// *************************************************************************
++
++#endif // !COIN_SO at GUI@MATERIALEDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Engines.cpp.in
+@@ -0,0 +1,43 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/engines/SoGuiEngines.h>
++
++void
++SoGuiEngines::initClasses(void)
++{
++ SoGuiRadioGroup::initClass();
++ SoGuiFormat::initClass();
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Engines.h.in
+@@ -0,0 +1,51 @@
++#ifndef COIN_SOGUIENGINES_H
++#define COIN_SOGUIENGINES_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/@Gui@/engines/SoGuiRadioGroup.h>
++#include <Inventor/@Gui@/engines/SoGuiFormat.h>
++
++class SoGuiEngines {
++public:
++ static void initClasses(void);
++
++};
++
++#endif // !COIN_SOGUIENGINES_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Format.cpp.in
+@@ -0,0 +1,84 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/SbString.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <stdio.h>
++
++#include <Inventor/@Gui@/engines/SoGuiFormat.h>
++
++void
++SoGuiFormat::initClass(void)
++{
++ SO_ENGINE_INIT_CLASS(SoGuiFormat, SoEngine, "Engine");
++}
++
++SO_ENGINE_SOURCE(SoGuiFormat);
++
++SoGuiFormat::SoGuiFormat(void)
++{
++ this->internals = NULL;
++
++ SO_ENGINE_CONSTRUCTOR(SoGuiFormat);
++
++ SO_ENGINE_ADD_INPUT(float1, (0.0f));
++ SO_ENGINE_ADD_INPUT(format, (""));
++
++ SO_ENGINE_ADD_OUTPUT(output, SoSFString);
++}
++
++SoGuiFormat::~SoGuiFormat(void)
++{
++}
++
++void
++SoGuiFormat::evaluate(void)
++{
++#ifdef __COIN__
++ SbString result;
++ result.sprintf(this->format.getValue().getString(), this->float1.getValue());
++#else // __COIN__
++ char buf[4096]; // FIXME: temporary workaround
++ sprintf(buf, this->format.getValue().getString(), this->float1.getValue());
++ SbString result = buf;
++#endif // ! __COIN__
++
++ // SoDebugError::postInfo("SoGuiFormat::evaluate", "%s", result.getString());
++ SO_ENGINE_OUTPUT(output, SoSFString, setValue(result));
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/Format.h.in
+@@ -0,0 +1,73 @@
++#ifndef COIN_SOGUIFORMAT_H
++#define COIN_SOGUIFORMAT_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFString.h>
++#include <Inventor/fields/SoSFFloat.h>
++#include <Inventor/engines/SoSubEngine.h>
++#ifdef __COIN__
++#include <Inventor/engines/SoEngineOutput.h>
++#endif // __COIN__
++#include <Inventor/engines/SoEngine.h>
++
++class SoGuiFormat : public SoEngine {
++ typedef SoEngine inherited;
++ SO_ENGINE_HEADER(SoGuiFormat);
++
++public:
++ static void initClass(void);
++ SoGuiFormat(void);
++
++ SoSFFloat float1;
++
++ SoSFString format;
++
++ SoEngineOutput output;
++
++protected:
++ virtual ~SoGuiFormat(void);
++ virtual void evaluate(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIFORMAT_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/RadioGroup.cpp.in
+@@ -0,0 +1,122 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/engines/SoGuiRadioGroup.h>
++#include <assert.h>
++
++SO_ENGINE_SOURCE(SoGuiRadioGroup);
++
++void
++SoGuiRadioGroup::initClass(void)
++{
++ SO_ENGINE_INIT_CLASS(SoGuiRadioGroup, SoEngine, "Engine");
++}
++
++SoGuiRadioGroup::SoGuiRadioGroup(void)
++{
++ this->index = -1;
++
++ SO_ENGINE_CONSTRUCTOR(SoGuiRadioGroup);
++
++ SO_ENGINE_ADD_INPUT(in0, (FALSE));
++ SO_ENGINE_ADD_INPUT(in1, (FALSE));
++ SO_ENGINE_ADD_INPUT(in2, (FALSE));
++ SO_ENGINE_ADD_INPUT(in3, (FALSE));
++ SO_ENGINE_ADD_INPUT(in4, (FALSE));
++ SO_ENGINE_ADD_INPUT(in5, (FALSE));
++ SO_ENGINE_ADD_INPUT(in6, (FALSE));
++ SO_ENGINE_ADD_INPUT(in7, (FALSE));
++
++ SO_ENGINE_ADD_OUTPUT(out0, SoSFBool);
++ SO_ENGINE_ADD_OUTPUT(out1, SoSFBool);
++ SO_ENGINE_ADD_OUTPUT(out2, SoSFBool);
++ SO_ENGINE_ADD_OUTPUT(out3, SoSFBool);
++ SO_ENGINE_ADD_OUTPUT(out4, SoSFBool);
++ SO_ENGINE_ADD_OUTPUT(out5, SoSFBool);
++ SO_ENGINE_ADD_OUTPUT(out6, SoSFBool);
++ SO_ENGINE_ADD_OUTPUT(out7, SoSFBool);
++}
++
++SoGuiRadioGroup::~SoGuiRadioGroup(void)
++{
++}
++
++void
++SoGuiRadioGroup::inputChanged(SoField * which)
++{
++ SoSFBool * fields[] = {
++ &(this->in0),
++ &(this->in1),
++ &(this->in2),
++ &(this->in3),
++ &(this->in4),
++ &(this->in5),
++ &(this->in6),
++ &(this->in7),
++ NULL
++ };
++ int i;
++ for ( i = 0; which != fields[i] && fields[i] != NULL; i++ ) { }
++ assert(fields[i] != NULL );
++ if ( ((SoSFBool *)which)->getValue() != FALSE ) {
++ this->index = i;
++ } else {
++ if ( this->index == i ) this->index = -1;
++ }
++}
++
++void
++SoGuiRadioGroup::evaluate(void)
++{
++ if ( this->index == -1 ) return; // avoid update
++ SoSFBool * fields[] = {
++ &(this->in0), &(this->in1), &(this->in2), &(this->in3),
++ &(this->in4), &(this->in5), &(this->in6), &(this->in7),
++ NULL
++ };
++ SoEngineOutput * outputs[] = {
++ &(this->out0), &(this->out1), &(this->out2), &(this->out3),
++ &(this->out4), &(this->out5), &(this->out6), &(this->out7),
++ NULL
++ };
++ int i;
++ for ( i = 0; i < 8; i++ ) {
++ if ( i == this->index ) {
++ SO_ENGINE_OUTPUT((*outputs[i]), SoSFBool, setValue(TRUE));
++ } else {
++ SO_ENGINE_OUTPUT((*outputs[i]), SoSFBool, setValue(FALSE));
++ }
++ }
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/engines/RadioGroup.h.in
+@@ -0,0 +1,85 @@
++#ifndef COIN_SOGUIRADIOGROUP_H
++#define COIN_SOGUIRADIOGROUP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/engines/SoSubEngine.h>
++#ifdef __COIN__
++#include <Inventor/engines/SoEngineOutput.h>
++#endif // __COIN__
++#include <Inventor/engines/SoEngine.h>
++
++class SoGuiRadioGroup : public SoEngine {
++ typedef SoEngine inherited;
++ SO_ENGINE_HEADER(SoGuiRadioGroup);
++
++public:
++ static void initClass(void);
++ SoGuiRadioGroup(void);
++
++ SoSFBool in0;
++ SoSFBool in1;
++ SoSFBool in2;
++ SoSFBool in3;
++ SoSFBool in4;
++ SoSFBool in5;
++ SoSFBool in6;
++ SoSFBool in7;
++
++ SoEngineOutput out0;
++ SoEngineOutput out1;
++ SoEngineOutput out2;
++ SoEngineOutput out3;
++ SoEngineOutput out4;
++ SoEngineOutput out5;
++ SoEngineOutput out6;
++ SoEngineOutput out7;
++
++protected:
++ virtual ~SoGuiRadioGroup(void);
++
++private:
++ virtual void inputChanged(SoField * which);
++ virtual void evaluate(void);
++
++ int index;
++};
++
++#endif // !COIN_SOGUIRADIOGROUP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/gl.h.in
+@@ -0,0 +1,91 @@
++#ifndef SO at GUI@_GL_H
++#define SO at GUI@_GL_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/* This header file is supposed to take care of all operating system
++ * dependent anomalies connected to the gl.h include file. It is only
++ * for use while building the Coin library, and should not be installed
++ * with the rest of the header files (at least not yet). 20010913 larsa */
++
++#ifndef SO at GUI@_VERSION
++#error "you must include config.h before including Inventor/system/gl.h"
++#endif /* !SO at GUI_VERSION */
++
++#ifdef HAVE_WINDOWS_H
++/* on windows, headers do not include their dependencies */
++#include <windows.h>
++#endif /* HAVE_WINDOWS_H */
++
++#ifdef HAVE_GL_GL_H
++/* the preferred gl.h path */
++#include <GL/gl.h>
++#else
++#ifdef HAVE_OPENGL_GL_H
++/* how Mac OS X organizes things - should we now stuff Coin header in
++ OpenInventor/? (that *was* irony) */
++#include <OpenGL/gl.h>
++#else
++#error "don't know how to include gl.h header"
++#endif /* !HAVE_GL_GL_H */
++#endif /* !HAVE_OPENGL_GL_H */
++
++#ifdef HAVE_GL_GLU_H
++#include <GL/glu.h>
++#else
++#ifdef HAVE_OPENGL_GLU_H
++#include <OpenGL/glu.h>
++#endif
++#endif
++
++/*
++ At least MS Windows often has very old gl.h files, so we just define
++ these values here if not defined already. Run-time checks are used
++ to determine which feature to use.
++*/
++
++#ifndef GL_CLAMP_TO_EDGE
++#define GL_CLAMP_TO_EDGE 0x812F
++#endif /* GL_CLAMP_TO_EDGE */
++
++#ifndef GL_CLAMP_TO_EDGE_EXT
++#define GL_CLAMP_TO_EDGE_EXT 0x812F
++#endif /* GL_CLAMP_TO_EDGE_EXT */
++
++#ifndef GL_CLAMP_TO_EDGE_SGIS
++#define GL_CLAMP_TO_EDGE_SGIS 0x812F
++#endif /* GL_CLAMP_TO_EDGE_SGIS */
++
++#endif /* ! COIN_GL_H */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/libm4.m4
+@@ -0,0 +1,695 @@
++divert(-1) -*- Autoconf -*-
++# This file is part of Autoconf.
++# Base m4 layer.
++# Requires GNU m4.
++# Copyright (C) 1999, 2000 Free Software Foundation, Inc.
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2, or (at your option)
++# any later version.
++#
++# This program is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++# GNU General Public License for more details.
++#
++# You should have received a copy of the GNU General Public License
++# along with this program; if not, write to the Free Software
++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++# 02111-1307, USA.
++#
++# As a special exception, the Free Software Foundation gives unlimited
++# permission to copy, distribute and modify the configure scripts that
++# are the output of Autoconf. You need not follow the terms of the GNU
++# General Public License when using or distributing such scripts, even
++# though portions of the text of Autoconf appear in them. The GNU
++# General Public License (GPL) does govern all other use of the material
++# that constitutes the Autoconf program.
++#
++# Certain portions of the Autoconf source text are designed to be copied
++# (in certain cases, depending on the input) into the output of
++# Autoconf. We call these the "data" portions. The rest of the Autoconf
++# source text consists of comments plus executable code that decides which
++# of the data portions to output in any given case. We call these
++# comments and executable code the "non-data" portions. Autoconf never
++# copies any of the non-data portions into its output.
++#
++# This special exception to the GPL applies to versions of Autoconf
++# released by the Free Software Foundation. When you make and
++# distribute a modified version of Autoconf, you may extend this special
++# exception to the GPL to apply to your modified version as well, *unless*
++# your modified version has the potential to copy into its output some
++# of the text that was the non-data portion of the version that you started
++# with. (In other words, unless your change moves or copies text from
++# the non-data portions to the data portions.) If your modification has
++# such potential, you must delete any notice of this special exception
++# to the GPL from your modified version.
++#
++# Written by Akim Demaille.
++#
++
++# Set the quotes, whatever the current quoting system.
++changequote()
++changequote([, ])
++
++# Some old m4's don't support m4exit. But they provide
++# equivalent functionality by core dumping because of the
++# long macros we define.
++ifdef([__gnu__], ,
++[errprint(Autoconf requires GNU m4. Install it before installing Autoconf or
++set the M4 environment variable to its path name.)
++m4exit(2)])
++
++
++## --------------------------------- ##
++## Defining macros and name spaces. ##
++## --------------------------------- ##
++
++# m4_rename(SRC, DST)
++# -------------------
++#
++# Rename the macro SRC as DST.
++define([m4_rename],
++[define([$2], defn([$1]))undefine([$1])])
++
++# Some m4 internals have names colliding with tokens we might use.
++# Rename them a` la `m4 --prefix-builtins'.
++m4_rename([eval], [m4_eval])
++m4_rename([format], [m4_format])
++m4_rename([shift], [m4_shift])
++m4_rename([symbols], [m4_symbols])
++
++
++## --------------------------------------------- ##
++## Move some m4 builtins to a safer name space. ##
++## --------------------------------------------- ##
++
++# m4_errprint(MSG)
++# ----------------
++# Same as `errprint', but reports the file and line.
++define([m4_errprint], [errprint(__file__:__line__: [$1
++])])
++
++
++# m4_warn(MSG)
++# ------------
++# Warn the user.
++define([m4_warn], [m4_errprint([warning: $1])])
++
++
++# m4_fatal(MSG, [EXIT-STATUS])
++# ----------------------------
++# Fatal the user. :)
++define([m4_fatal],
++[m4_errprint([error: $1])dnl
++m4exit(ifelse([$2],, 1, [$2]))])
++
++
++# m4_assert( EXPRESSION [, EXIT-STATUS = 1 ])
++# ------------------------------------------
++# This macro ensures that EXPRESSION evaluates to true, and exits if
++# EXPRESSION evaluates to false.
++define([m4_assert],
++[ifelse(m4_eval([$1]), 0,
++ [m4_fatal([assert failed: $1], [$2])],
++ [])])
++
++
++# We also want to neutralize include (and sinclude for symmetry),
++# but we want to extend them slightly: warn when a file is included
++# several times. This is in general a dangerous operation because
++# quite nobody quotes the first argument of define.
++#
++# For instance in the following case:
++# define(foo, [bar])
++# then a second reading will turn into
++# define(bar, [bar])
++# which is certainly not what was meant.
++
++# m4_include_unique(FILE)
++# -----------------------
++# Declare that the FILE was loading; and warn if it has already
++# been included.
++define([m4_include_unique],
++[ifdef([m4_include($1)],
++ [m4_warn([file `$1' included several times])])dnl
++define([m4_include($1)])])
++
++
++# m4_include(FILE)
++# ----------------
++# As the builtin include, but warns against multiple inclusions.
++define([m4_include],
++[m4_include_unique([$1])dnl
++builtin([include], [$1])])
++
++
++# m4_sinclude(FILE)
++# -----------------
++# As the builtin sinclude, but warns against multiple inclusions.
++define([m4_sinclude],
++[m4_include_unique([$1])dnl
++builtin([sinclude], [$1])])
++
++# Neutralize include and sinclude.
++undefine([include])
++undefine([sinclude])
++
++
++## --------------------------------------- ##
++## Some additional m4 structural control. ##
++## --------------------------------------- ##
++
++# Both `ifval' and `ifset' tests against the empty string. The
++# difference is that `ifset' is specialized on macros.
++#
++# In case of arguments of macros, eg $[1], it makes little difference.
++# In the case of a macro `FOO', you don't want to check `ifval(FOO,
++# TRUE)', because if `FOO' expands with commas, there is a shifting of
++# the arguments. So you want to run `ifval([FOO])', but then you just
++# compare the *string* `FOO' against `', which, of course fails.
++#
++# So you want a variation of `ifset' that expects a macro name as $[1].
++# If this macro is both defined and defined to a non empty value, then
++# it runs TRUE etc.
++
++
++# ifval(COND, [IF-TRUE], [IF-FALSE])
++# ----------------------------------
++# If COND is not the empty string, expand IF-TRUE, otherwise IF-FALSE.
++# Comparable to ifdef.
++define([ifval], [ifelse([$1],[],[$3],[$2])])
++
++
++# ifset(MACRO, [IF-TRUE], [IF-FALSE])
++# -----------------------------------
++# If MACRO has no definition, or of its definition is the empty string,
++# expand IF-FALSE, otherwise IF-TRUE.
++define([ifset],
++[ifdef([$1],
++ [ifelse(defn([$1]), [], [$3], [$2])],
++ [$3])])
++
++
++# ifndef(NAME, [IF-NOT-DEFINED], [IF-DEFINED])
++# --------------------------------------------
++define([ifndef],
++[ifdef([$1], [$3], [$2])])
++
++
++# m4_default(EXP1, EXP2)
++# ----------------------
++# Returns EXP1 if non empty, otherwise EXP2.
++define([m4_default], [ifval([$1], [$1], [$2])])
++
++
++# m4_shiftn( N, ... )
++# -------------------
++# Returns ... shifted N times. Useful for recursive "varargs" constructs.
++define([m4_shiftn],
++[m4_assert(($1 >= 0) && ($# > $1))dnl
++_m4_shiftn($@)])
++
++define([_m4_shiftn],
++[ifelse([$1], 0,
++ [m4_shift($@)],
++ [_m4_shiftn(m4_eval([$1]-1), m4_shift(m4_shift($@)))])])
++
++
++# m4_case(SWITCH, VAL1, IF-VAL1, VAL2, IF-VAL2, ..., DEFAULT)
++# -----------------------------------------------------------
++# m4 equivalent of
++# switch (SWITCH)
++# {
++# case VAL1:
++# IF-VAL1;
++# break;
++# case VAL2:
++# IF-VAL2;
++# break;
++# ...
++# default:
++# DEFAULT;
++# break;
++# }.
++# All the values are optional, and the macro is robust to active
++# symbols properly quoted.
++define([m4_case],
++[ifelse([$#], 0, [],
++ [$#], 1, [],
++ [$#], 2, [$2],
++ [$1], [$2], [$3],
++ [m4_case([$1], m4_shiftn(3, $@))])])
++
++
++# m4_match(SWITCH, RE1, VAL1, RE2, VAL2, ..., DEFAULT)
++# ----------------------------------------------------
++# m4 equivalent of
++#
++# if (SWITCH =~ RE1)
++# VAL1;
++# elif (SWITCH =~ RE2)
++# VAL2;
++# elif ...
++# ...
++# else
++# DEFAULT
++#
++# All the values are optional, and the macro is robust to active symbols
++# properly quoted.
++define([m4_match],
++[ifelse([$#], 0, [],
++ [$#], 1, [],
++ [$#], 2, [$2],
++ regexp([$1], [$2]), -1, [m4_match([$1], m4_shiftn(3, $@))],
++ [$3])])
++
++# m4_do(STRING, ...)
++# ------------------
++# This macro invokes all its arguments (in sequence, of course). It is
++# useful for making your macros more structured and readable by dropping
++# unecessary dnl's and have the macros indented properly.
++
++define([m4_do],
++ [ifelse($#, 0, [],
++ $#, 1, [$1],
++ [$1[]m4_do(m4_shift($@))])])
++
++## --------------------- ##
++## Implementing m4 loops ##
++## --------------------- ##
++
++
++# m4_for(VARIABLE, FIRST, LAST, [STEP = +/-1], EXPRESSION)
++# --------------------------------------
++# Expand EXPRESSION defining VARIABLE to FROM, FROM + 1, ..., TO.
++# Both limits are included.
++
++define([m4_for],
++[m4_case(m4_sign(m4_eval($3 - $2)),
++ 1, [m4_assert(m4_sign(m4_default($4, 1)) == 1)],
++ -1, [m4_assert(m4_sign(m4_default($4, -1)) == -1)])dnl
++pushdef([$1], [$2])dnl
++ifelse(m4_eval([$3 > $2]), 1,
++ [_m4_for([$1], [$3], m4_default([$4], 1), [$5])],
++ [_m4_for([$1], [$3], m4_default([$4], -1), [$5])])dnl
++popdef([$1])])
++
++define([_m4_for],
++[$4[]dnl
++ifelse($1, [$2], [],
++ [define([$1], m4_eval($1+[$3]))_m4_for([$1], [$2], [$3], [$4])])])
++
++
++# Implementing `foreach' loops in m4 is much more tricky than it may
++# seem. Actually, the example of a `foreach' loop in the m4
++# documentation is wrong: it does not quote the arguments properly,
++# which leads to undesired expansions.
++#
++# The example in the documentation is:
++#
++# | # foreach(VAR, (LIST), STMT)
++# | define([foreach],
++# | [pushdef([$1])_foreach([$1], [$2], [$3])popdef([$1])])
++# | define([_arg1], [$1])
++# | define([_foreach],
++# | [ifelse([$2], [()], ,
++# | [define([$1], _arg1$2)$3[]_foreach([$1],
++# | (shift$2),
++# | [$3])])])
++#
++# But then if you run
++#
++# | define(a, 1)
++# | define(b, 2)
++# | define(c, 3)
++# | foreach([f], [([a], [(b], [c)])], [echo f
++# | ])
++#
++# it gives
++#
++# => echo 1
++# => echo (2,3)
++#
++# which is not what is expected.
++#
++# Of course the problem is that many quotes are missing. So you add
++# plenty of quotes at random places, until you reach the expected
++# result. Alternatively, if you are a quoting wizard, you directly
++# reach the following implementation (but if you really did, then
++# apply to the maintenance of libm4!).
++#
++# | # foreach(VAR, (LIST), STMT)
++# | define([foreach], [pushdef([$1])_foreach($@)popdef([$1])])
++# | define([_arg1], [[$1]])
++# | define([_foreach],
++# | [ifelse($2, [()], ,
++# | [define([$1], [_arg1$2])$3[]_foreach([$1],
++# | [(shift$2)],
++# | [$3])])])
++#
++# which this time answers
++#
++# => echo a
++# => echo (b
++# => echo c)
++#
++# Bingo!
++#
++# Well, not quite.
++#
++# With a better look, you realize that the parens are more a pain than
++# a help: since anyway you need to quote properly the list, you end up
++# with always using an outermost pair of parens and an outermost pair
++# of quotes. Rejecting the parens both eases the implementation, and
++# simplifies the use:
++#
++# | # foreach(VAR, (LIST), STMT)
++# | define([foreach], [pushdef([$1])_foreach($@)popdef([$1])])
++# | define([_arg1], [$1])
++# | define([_foreach],
++# | [ifelse($2, [], ,
++# | [define([$1], [_arg1($2)])$3[]_foreach([$1],
++# | [shift($2)],
++# | [$3])])])
++#
++#
++# Now, just replace the `$2' with `m4_quote($2)' in the outer `ifelse'
++# to improve robustness, and you come up with a quite satisfactory
++# implementation.
++
++
++# m4_foreach(VARIABLE, LIST, EXPRESSION)
++# --------------------------------------
++#
++# Expand EXPRESSION assigning each value of the LIST to VARIABLE.
++# LIST should have the form `item_1, item_2, ..., item_n', i.e. the
++# whole list must *quoted*. Quote members too if you don't want them
++# to be expanded.
++#
++# This macro is robust to active symbols:
++# | define(active, [ACT, IVE])
++# | m4_foreach(Var, [active, active], [-Var-])
++# => -ACT--IVE--ACT--IVE-
++#
++# | m4_foreach(Var, [[active], [active]], [-Var-])
++# => -ACT, IVE--ACT, IVE-
++#
++# | m4_foreach(Var, [[[active]], [[active]]], [-Var-])
++# => -active--active-
++define([m4_foreach],
++[pushdef([$1])_m4_foreach($@)popdef([$1])])
++
++# Low level macros used to define m4_foreach.
++define([m4_car], [$1])
++define([_m4_foreach],
++[ifelse(m4_quote($2), [], [],
++ [define([$1], [m4_car($2)])$3[]_m4_foreach([$1],
++ [m4_shift($2)],
++ [$3])])])
++
++
++## ----------------- ##
++## Text processing. ##
++## ----------------- ##
++
++
++# m4_quote(STRING)
++# ----------------
++# Return STRING quoted.
++#
++# It is important to realize the difference between `quote(exp)' and
++# `[exp]': in the first case you obtain the quoted *result* of the
++# expansion of EXP, while in the latter you just obtain the string
++# `exp'.
++define([m4_quote], [[$*]])
++
++
++# m4_noquote(STRING)
++# ------------------
++# Return the result of ignoring all quotes in STRING and invoking the
++# macros it contains. Amongst other things useful for enabling macro
++# invocations inside strings with [] blocks (for instance regexps and
++# help-strings).
++define([m4_noquote],
++[changequote(-=<{,}>=-)$1-=<{}>=-changequote([,])])
++
++
++# m4_split(STRING, [REGEXP])
++# --------------------------
++#
++# Split STRING into an m4 list of quoted elements. The elements are
++# quoted with [ and ]. Beginning spaces and end spaces *are kept*.
++# Use m4_strip to remove them.
++#
++# REGEXP specifies where to split. Default is [\t ]+.
++#
++# Pay attention to the changequotes. Inner changequotes exist for
++# obvious reasons (we want to insert square brackets). Outer
++# changequotes are needed because otherwise the m4 parser, when it
++# sees the closing bracket we add to the result, believes it is the
++# end of the body of the macro we define.
++#
++# Also, notice that $1 is quoted twice, since we want the result to
++# be quoted. Then you should understand that the argument of
++# patsubst is ``STRING'' (i.e., with additional `` and '').
++#
++# This macro is safe on active symbols, i.e.:
++# define(active, ACTIVE)
++# m4_split([active active ])end
++# => [active], [active], []end
++
++changequote(<<, >>)
++define(<<m4_split>>,
++<<changequote(``, '')dnl
++[dnl Can't use m4_default here instead of ifelse, because m4_default uses
++dnl [ and ] as quotes.
++patsubst(````$1'''',
++ ifelse(``$2'',, ``[ ]+'', ``$2''),
++ ``], ['')]dnl
++changequote([, ])>>)
++changequote([, ])
++
++
++
++# m4_join(STRING)
++# ---------------
++# If STRING contains end of lines, replace them with spaces. If there
++# are backslashed end of lines, remove them. This macro is safe with
++# active symbols.
++# define(active, ACTIVE)
++# m4_join([active
++# act\
++# ive])end
++# => active activeend
++define([m4_join],
++[translit(patsubst([[[$1]]], [\\
++]), [
++], [ ])])
++
++
++# m4_strip(STRING)
++# ----------------
++# Expands into STRING with tabs and spaces singled out into a single
++# space, and removing leading and trailing spaces.
++#
++# This macro is robust to active symbols.
++# define(active, ACTIVE)
++# m4_strip([ active active ])end
++# => active activeend
++#
++# This macro is fun! Because we want to preserve active symbols, STRING
++# must be quoted for each evaluation, which explains there are 4 levels
++# of brackets around $1 (don't forget that the result must be quoted
++# too, hence one more quoting than applications).
++#
++# Then notice the patsubst of the middle: it is in charge of removing
++# the leading space. Why not just `patsubst(..., [^ ])'? Because this
++# macro will receive the output of the preceding patsubst, i.e. more or
++# less [[STRING]]. So if there is a leading space in STRING, then it is
++# the *third* character, since there are two leading `['; Equally for
++# the outer patsubst.
++define([m4_strip],
++[patsubst(patsubst(patsubst([[[[$1]]]],
++ [[ ]+], [ ]),
++ [^\(..\) ], [\1]),
++ [ \(.\)$], [\1])])
++
++
++
++# m4_append(MACRO-NAME, STRING)
++# -----------------------------
++# Redefine MACRO-NAME to hold its former content plus STRING at the
++# end. It is valid to use this macro with MACRO-NAME undefined.
++#
++# This macro is robust to active symbols. It can be used to grow
++# strings.
++#
++# | define(active, ACTIVE)
++# | m4_append([sentence], [This is an])
++# | m4_append([sentence], [ active ])
++# | m4_append([sentence], [symbol.])
++# | sentence
++# | undefine([active])dnl
++# | sentence
++# => This is an ACTIVE symbol.
++# => This is an active symbol.
++#
++# It can be used to define hooks.
++#
++# | define(active, ACTIVE)
++# | m4_append([hooks], [define([act1], [act2])])
++# | m4_append([hooks], [define([act2], [active])])
++# | undefine([active])
++# | act1
++# | hooks
++# | act1
++# => act1
++# =>
++# => active
++define([m4_append],
++[define([$1],
++ifdef([$1], [defn([$1])])[$2])])
++
++
++# m4_list_append(MACRO-NAME, STRING)
++# ----------------------------------
++# Same as `m4_append', but each element is separated by `, '.
++define([m4_list_append],
++[define([$1],
++ifdef([$1], [defn([$1]), ])[$2])])
++
++
++
++
++## ----------------------------------- ##
++## Helping macros to display strings. ##
++## ----------------------------------- ##
++
++# m4_foreach_quoted(VARIABLE, LIST, EXPRESSION)
++# ---------------------------------------------
++# FIXME: This macro should not exists. Currently it's used only in
++# m4_wrap, which needs to be rewritten. But it's godam hard.
++define([m4_foreach_quoted],
++[pushdef([$1], [])_m4_foreach_quoted($@)popdef([$1])])
++
++# Low level macros used to define m4_foreach.
++define([m4_car_quoted], [[$1]])
++define([_m4_foreach_quoted],
++[ifelse($2, [()], ,
++ [define([$1], [m4_car_quoted$2])$3[]_m4_foreach_quoted([$1],
++ [(m4_shift$2)],
++ [$3])])])
++
++
++# m4_wrap(STRING, [PREFIX], [FIRST-PREFIX], [WIDTH])
++# --------------------------------------------------
++# Expands into STRING wrapped to hold in WIDTH columns (default = 79).
++# If prefix is set, each line is prefixed with it. If FIRST-PREFIX is
++# specified, then the first line is prefixed with it. As a special
++# case, if the length of the first prefix is greater than that of
++# PREFIX, then FIRST-PREFIX will be left alone on the first line.
++#
++# Typical outputs are:
++#
++# m4_wrap([Short string */], [ ], [/* ], 20)
++# => /* Short string */
++#
++# m4_wrap([Much longer string */], [ ], [/* ], 20)
++# => /* Much longer
++# => string */
++#
++# m4_wrap([Short doc.], [ ], [ --short ], 30)
++# => --short Short doc.
++#
++# m4_wrap([Short doc.], [ ], [ --too-wide ], 30)
++# => --too-wide
++# => Short doc.
++#
++# m4_wrap([Super long documentation.], [ ], [ --too-wide ], 30)
++# => --too-wide
++# => Super long
++# => documentation.
++#
++# FIXME: there is no checking of a longer PREFIX than WIDTH, but do
++# we really want to bother with people trying each single corner
++# of a software?
++#
++# This macro does not leave a trailing space behind the last word,
++# what complicates it a bit. The algorithm is stupid simple: all the
++# words are preceded by m4_Separator which is defined to empty for the
++# first word, and then ` ' (single space) for all the others.
++define([m4_wrap],
++[pushdef([m4_Prefix], m4_default([$2], []))dnl
++pushdef([m4_Prefix1], m4_default([$3], [m4_Prefix]))dnl
++pushdef([m4_Width], m4_default([$4], 79))dnl
++pushdef([m4_Cursor], len(m4_Prefix1))dnl
++pushdef([m4_Separator], [])dnl
++m4_Prefix1[]dnl
++ifelse(m4_eval(m4_Cursor > len(m4_Prefix)),
++ 1, [define([m4_Cursor], len(m4_Prefix))
++m4_Prefix])[]dnl
++m4_foreach_quoted([m4_Word], (m4_split(m4_strip(m4_join([$1])))),
++[define([m4_Cursor], m4_eval(m4_Cursor + len(m4_Word) + 1))dnl
++dnl New line if too long, else insert a space unless it is the first
++dnl of the words.
++ifelse(m4_eval(m4_Cursor > m4_Width),
++ 1, [define([m4_Cursor], m4_eval(len(m4_Prefix) + len(m4_Word) + 1))]
++m4_Prefix,
++ [m4_Separator])[]dnl
++m4_Word[]dnl
++define([m4_Separator], [ ])])dnl
++popdef([m4_Separator])dnl
++popdef([m4_Cursor])dnl
++popdef([m4_Width])dnl
++popdef([m4_Prefix1])dnl
++popdef([m4_Prefix])dnl
++])
++
++
++
++## ------------------- ##
++## Number processing. ##
++## ------------------- ##
++
++# m4_sign(A)
++# ----------
++#
++# The sign of the integer A.
++define([m4_sign],
++[m4_match([$1],
++ [^-], -1,
++ [^0+], 0,
++ 1)])
++
++# m4_cmp(A, B)
++# ------------
++#
++# Compare two integers.
++# A < B -> -1
++# A = B -> 0
++# A > B -> 1
++define([m4_cmp],
++[m4_sign(m4_eval([$1 - $2]))])
++
++
++# m4_list_cmp(A, B)
++# -----------------
++#
++# Compare the two lists of integers A and B. For instance:
++# m4_list_cmp((1, 0), (1)) -> 0
++# m4_list_cmp((1, 0), (1, 0)) -> 0
++# m4_list_cmp((1, 2), (1, 0)) -> 1
++# m4_list_cmp((1, 2, 3), (1, 2)) -> 1
++# m4_list_cmp((1, 2, -3), (1, 2)) -> -1
++# m4_list_cmp((1, 0), (1, 2)) -> -1
++# m4_list_cmp((1), (1, 2)) -> -1
++define([m4_list_cmp],
++[ifelse([$1$2], [()()], 0,
++ [$1], [()], [m4_list_cmp((0), [$2])],
++ [$2], [()], [m4_list_cmp([$1], (0))],
++ [m4_case(m4_cmp(m4_car$1, m4_car$2),
++ -1, -1,
++ 1, 1,
++ 0, [m4_list_cmp((m4_shift$1), (m4_shift$2))])])])
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ClickCounter.cpp.in
+@@ -0,0 +1,246 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoIndexedFaceSet.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoTextureCoordinate2.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoLists.h>
++
++#include <Inventor/SbColor.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <assert.h>
++
++// SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++// SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++// SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++// SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++// SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++// SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++
++// SoSFVec3f size;
++// SoSFInt32 value;
++// SoSFTrigger click;
++// SoSFInt32 first;
++// SoSFInt32 last;
++
++class ClickCounter {
++public:
++ SoGuiClickCounter * api;
++
++ SoFieldSensor * sizesensor;
++ static void sizeCB(void * closure, SoSensor * sensor);
++
++ SoFieldSensor * firstsensor;
++ static void firstCB(void * closure, SoSensor * sensor);
++
++ ClickCounter(void);
++ ~ClickCounter(void);
++};
++
++// *************************************************************************
++
++void
++SoGuiClickCounter::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiClickCounter, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiClickCounter);
++
++#define PRIVATE(obj) ((ClickCounter *) this->internals)
++
++SoGuiClickCounter::SoGuiClickCounter(void)
++{
++ this->internals = new ClickCounter;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiClickCounter);
++
++ SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++ SO_KIT_ADD_FIELD(first, (0));
++ SO_KIT_ADD_FIELD(last, (0));
++ SO_KIT_ADD_FIELD(value, (0));
++ SO_KIT_ADD_FIELD(click, ());
++
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceFaceSet, SoIndexedFaceSet, FALSE, topSeparator, "", FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceCoords, SoCoordinate3, FALSE, topSeparator, surfaceFaceSet, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceTexCoords, SoTextureCoordinate2, FALSE, topSeparator, surfaceCoords, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceTexture, SoTexture2, TRUE, topSeparator, surfaceTexCoords, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceMaterial, SoMaterial, TRUE, topSeparator, surfaceTexture, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ static float surfacetexturecoordinates[][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} };
++ SoTextureCoordinate2 * surfacetexcoords = SO_GET_ANY_PART(this, "surfaceTexCoords", SoTextureCoordinate2);
++ assert(surfacetexcoords);
++ surfacetexcoords->point.setValues(0, 4, surfacetexturecoordinates);
++
++ static int32_t surfaceindices[] = { 0, 1, 2, -1, 0, 2, 3, -1 };
++ SoIndexedFaceSet * surfacefaceset = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++ assert(surfacefaceset);
++ surfacefaceset->textureCoordIndex.setValues(0, 8, surfaceindices);
++ surfacefaceset->coordIndex.setValues(0, 8, surfaceindices);
++
++ // SoMaterial * surfacematerial = SO_GET_ANY_PART(this, "surfaceMaterial", SoMaterial);
++ // surfacematerial->diffuseColor.setValue(SbColor(0.0f, 0.0f, 0.0f));
++
++ this->sizeUpdate();
++
++ PRIVATE(this)->sizesensor = new SoFieldSensor(ClickCounter::sizeCB, PRIVATE(this));
++ PRIVATE(this)->sizesensor->attach(&(this->size));
++ PRIVATE(this)->firstsensor = new SoFieldSensor(ClickCounter::firstCB, PRIVATE(this));
++ PRIVATE(this)->firstsensor->attach(&(this->first));
++}
++
++SoGuiClickCounter::~SoGuiClickCounter(void)
++{
++ ClickCounter * obj = PRIVATE(this);
++ delete obj;
++}
++
++void
++SoGuiClickCounter::handleEvent(SoHandleEventAction * action)
++{
++ const SoEvent * ev = action->getEvent();
++ if ( ev->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++ const SoMouseButtonEvent * event = (SoMouseButtonEvent *) ev;
++ if ( event->getState() == SoButtonEvent::DOWN ) {
++ const SoPickedPointList & ppoints = action->getPickedPointList();
++ SbBool hit = FALSE;
++ int i = 0;
++ SoIndexedFaceSet * target = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++ assert(target);
++ for ( i = 0; !hit && i < ppoints.getLength(); i++ ) {
++ const SoPickedPoint * point = ppoints[i];
++ const SoFullPath * path = (const SoFullPath *) point->getPath();
++ assert(path);
++ SoNode * node = path->getTail();
++ if ( node == (SoNode *) target ) hit = TRUE;
++ }
++ if ( hit ) {
++ int32_t firstval = this->first.getValue();
++ int32_t lastval = this->last.getValue();
++ if ( firstval < lastval ) {
++ int32_t val = this->value.getValue() + 1;
++ if ( val > lastval ) val = firstval;
++ this->value.setValue(val);
++ } else if ( firstval > lastval ) {
++ int32_t val = this->value.getValue() - 1;
++ if ( val < lastval ) val = firstval;
++ this->value.setValue(val);
++ }
++ this->click.touch();
++ }
++ }
++ }
++}
++
++void
++SoGuiClickCounter::setSurfaceColor(const SbColor & valuearg)
++{
++}
++
++void
++SoGuiClickCounter::sizeUpdate(void)
++{
++ SbVec3f sizeval = this->size.getValue();
++ if ( sizeval[0] != 0.0f && sizeval[1] != 0.0f ) {
++ float coordinates[][3] = { {0.0f, 0.0f, 0.0f}, {sizeval[0], 0.0f, 0.0f}, {sizeval[0], sizeval[1], 0.0f}, {0.0f, sizeval[1], 0.0f} };
++ SoCoordinate3 * coords = SO_GET_ANY_PART(this, "surfaceCoords", SoCoordinate3);
++ assert(coords);
++ coords->point.setValues(0, sizeof(coordinates) / sizeof(coordinates[0]), coordinates);
++ }
++}
++
++void
++SoGuiClickCounter::firstUpdate(void)
++{
++ this->value.setValue(this->first.getValue());
++}
++
++SbBool
++SoGuiClickCounter::readInstance(SoInput * in, unsigned short flags)
++{
++ assert(PRIVATE(this)->firstsensor != NULL);
++ PRIVATE(this)->firstsensor->detach();
++ SbBool retval = inherited::readInstance(in, flags);
++ PRIVATE(this)->firstsensor->attach(&(this->first));
++ return retval;
++}
++
++// *************************************************************************
++
++ClickCounter::ClickCounter(void)
++{
++ this->api = NULL;
++ this->sizesensor = NULL;
++ this->firstsensor = NULL;
++}
++
++ClickCounter::~ClickCounter(void)
++{
++}
++
++void
++ClickCounter::sizeCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ ClickCounter * me = (ClickCounter *) closure;
++ assert(me->api);
++ me->api->sizeUpdate();
++}
++
++void
++ClickCounter::firstCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ ClickCounter * me = (ClickCounter *) closure;
++ assert(me->api);
++ me->api->firstUpdate();
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ClickCounter.h.in
+@@ -0,0 +1,92 @@
++#ifndef COIN_SOGUICLICKCOUNTER_H
++#define COIN_SOGUICLICKCOUNTER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFTrigger.h>
++#include <Inventor/fields/SoSFInt32.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SbColor;
++
++class SoGuiClickCounter : public SoBaseKit {
++ typedef SoBaseKit inherited;
++
++ SO_KIT_HEADER(SoGuiClickCounter);
++
++ SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++
++public:
++ static void initClass(void);
++
++ SoGuiClickCounter(void);
++
++ SoSFVec3f size;
++
++ SoSFInt32 value;
++ SoSFTrigger click;
++
++ SoSFInt32 first;
++ SoSFInt32 last;
++
++ virtual void handleEvent(SoHandleEventAction * action);
++
++ virtual void setSurfaceColor(const SbColor & value);
++
++ void sizeUpdate(void);
++ void firstUpdate(void);
++
++protected:
++ virtual ~SoGuiClickCounter(void);
++
++ virtual SbBool readInstance(SoInput * in, unsigned short flags);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUICLICKCOUNTER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ColorEditor.cpp.in
+@@ -0,0 +1,890 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbPList.h>
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/fields/SoSFColor.h>
++#include <Inventor/fields/SoMFColor.h>
++#include <Inventor/fields/SoMFUInt32.h>
++#include <Inventor/nodes/SoSwitch.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <assert.h>
++
++/*!
++ \class SoGuiColorEditor Inventor/@Gui@/editors/SoGuiColorEditor.h
++ \brief The SoGuiColorEditor class is a GUI component for interactively
++ editing color fields.
++*/
++
++/*!
++ \enum SoGuiColorEditor::Sliders
++*/
++
++/*!
++ \val SoGuiColorEditor::NONE
++*/
++
++/*!
++ \val SoGuiColorEditor::INTENSITY
++*/
++
++/*!
++ \val SoGuiColorEditor::RGB
++*/
++
++/*!
++ \val SoGuiColorEditor::HSV
++*/
++
++/*!
++ \val SoGuiColorEditor::RGB_V
++*/
++
++/*!
++ \val SoGuiColorEditor::RGB_HSV
++*/
++
++/*!
++ \enum SoGuiColorEditor::Update
++*/
++
++/*!
++ \val SoGuiColorEditor::CONTINUOUS
++*/
++
++/*!
++ \val SoGuiColorEditor::AFTER_ACCEPT
++*/
++
++// *************************************************************************
++
++class ColorEditor {
++public:
++ SoGuiColorEditor * api;
++
++ void colorChange(void);
++
++ SoFieldSensor * color_sensor;
++ static void color_update_cb(void * closure, SoSensor * sensor);
++
++ SoGuiPane * editor;
++ SoGuiClickCounter * switcher;
++ SoGuiSlider1 * slider_r; // red
++ SoGuiSlider1 * slider_g; // green
++ SoGuiSlider1 * slider_b; // blue
++ SoGuiSlider1 * slider_h; // hue
++ SoGuiSlider1 * slider_s; // saturation
++ SoGuiSlider1 * slider_v; // value
++ SoGuiSlider2 * slider_wheel;
++
++ SoFieldSensor * sensor_r;
++ SoFieldSensor * sensor_g;
++ SoFieldSensor * sensor_b;
++ SoFieldSensor * sensor_h;
++ SoFieldSensor * sensor_s;
++ SoFieldSensor * sensor_v;
++ SoFieldSensor * sensor_wheel;
++
++ static void update_r_cb(void * closure, SoSensor * sensor);
++ static void update_g_cb(void * closure, SoSensor * sensor);
++ static void update_b_cb(void * closure, SoSensor * sensor);
++ static void update_h_cb(void * closure, SoSensor * sensor);
++ static void update_s_cb(void * closure, SoSensor * sensor);
++ static void update_v_cb(void * closure, SoSensor * sensor);
++ static void update_wheel_cb(void * closure, SoSensor * sensor);
++
++ static const char * editorscene[];
++
++ static float calculateHue(float x, float y);
++ static SbVec2f calculateFromHue(float h, float s, float v);
++
++ void generateSliderTextureR(const SbColor & current, SbBool wysiwyg);
++ void generateSliderTextureG(const SbColor & current, SbBool wysiwyg);
++ void generateSliderTextureB(const SbColor & current, SbBool wysiwyg);
++ void generateSliderTextureH(const SbColor & current, SbBool wysiwyg);
++ void generateSliderTextureS(const SbColor & current, SbBool wysiwyg);
++ void generateSliderTextureV(const SbColor & current, SbBool wysiwyg);
++ void generateSliderTextureHSV(const SbColor & current, SbBool wysiwyg);
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((ColorEditor *) ((SoGuiColorEditor *) obj)->internals)
++#define PUBLIC(obj) (((ColorEditor *) obj)->api)
++
++void
++SoGuiColorEditor::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiColorEditor, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiColorEditor);
++
++SoGuiColorEditor::SoGuiColorEditor(void)
++{
++ this->internals = (void *) new ColorEditor;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiColorEditor);
++
++ SO_KIT_ADD_FIELD(wysiwyg, (FALSE));
++ SO_KIT_ADD_FIELD(color, (SbColor(0.0f, 0.0f, 0.0f)));
++ SO_KIT_ADD_FIELD(sliders, (SoGuiColorEditor::RGB_V));
++ SO_KIT_ADD_FIELD(update, (SoGuiColorEditor::AFTER_ACCEPT));
++
++ SO_KIT_DEFINE_ENUM_VALUE(Sliders, NONE);
++ SO_KIT_DEFINE_ENUM_VALUE(Sliders, INTENSITY);
++ SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB);
++ SO_KIT_DEFINE_ENUM_VALUE(Sliders, HSV);
++ SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB_V);
++ SO_KIT_DEFINE_ENUM_VALUE(Sliders, RGB_HSV);
++
++ SO_KIT_DEFINE_ENUM_VALUE(Update, CONTINUOUS);
++ SO_KIT_DEFINE_ENUM_VALUE(Update, AFTER_ACCEPT);
++
++ SO_KIT_SET_SF_ENUM_TYPE(sliders, Sliders);
++ SO_KIT_SET_SF_ENUM_TYPE(update, Update);
++
++ SO_KIT_ADD_CATALOG_ENTRY(root, SoGuiPane, TRUE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ PRIVATE(this)->switcher = NULL;
++ PRIVATE(this)->sensor_r = NULL;
++ PRIVATE(this)->sensor_g = NULL;
++ PRIVATE(this)->sensor_b = NULL;
++ PRIVATE(this)->sensor_h = NULL;
++ PRIVATE(this)->sensor_s = NULL;
++ PRIVATE(this)->sensor_v = NULL;
++ PRIVATE(this)->sensor_wheel = NULL;
++
++ PRIVATE(this)->editor = NULL;
++
++ SoNode * scene = SoAny::loadSceneGraph(ColorEditor::editorscene);
++ assert(scene != NULL);
++ assert(scene->isOfType(SoGuiPane::getClassTypeId()));
++
++ PRIVATE(this)->editor = (SoGuiPane *) scene;
++ PRIVATE(this)->editor->ref();
++ PRIVATE(this)->switcher = (SoGuiClickCounter *) SoAny::scanSceneForName(PRIVATE(this)->editor, "switcher");
++ PRIVATE(this)->slider_r = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_r", TRUE);
++ PRIVATE(this)->slider_g = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_g", TRUE);
++ PRIVATE(this)->slider_b = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_b", TRUE);
++ PRIVATE(this)->slider_h = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_h", TRUE);
++ PRIVATE(this)->slider_s = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_s", TRUE);
++ PRIVATE(this)->slider_v = (SoGuiSlider1 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "slider_v", TRUE);
++ PRIVATE(this)->slider_wheel = (SoGuiSlider2 *) SoAny::scanSceneForName(PRIVATE(this)->editor, "colorwheel", TRUE);
++ if ( PRIVATE(this)->slider_r ) {
++ PRIVATE(this)->slider_r->ref();
++ PRIVATE(this)->sensor_r = new SoFieldSensor(ColorEditor::update_r_cb, PRIVATE(this));
++ PRIVATE(this)->sensor_r->attach(&(PRIVATE(this)->slider_r->value));
++ PRIVATE(this)->generateSliderTextureR(this->color.getValue(), FALSE);
++ }
++ if ( PRIVATE(this)->slider_g ) {
++ PRIVATE(this)->slider_g->ref();
++ PRIVATE(this)->sensor_g = new SoFieldSensor(ColorEditor::update_g_cb, PRIVATE(this));
++ PRIVATE(this)->sensor_g->attach(&(PRIVATE(this)->slider_g->value));
++ PRIVATE(this)->generateSliderTextureG(this->color.getValue(), FALSE);
++ }
++ if ( PRIVATE(this)->slider_b ) {
++ PRIVATE(this)->slider_b->ref();
++ PRIVATE(this)->sensor_b = new SoFieldSensor(ColorEditor::update_b_cb, PRIVATE(this));
++ PRIVATE(this)->sensor_b->attach(&(PRIVATE(this)->slider_b->value));
++ PRIVATE(this)->generateSliderTextureB(this->color.getValue(), FALSE);
++ }
++ if ( PRIVATE(this)->slider_h ) {
++ PRIVATE(this)->slider_h->ref();
++ PRIVATE(this)->sensor_h = new SoFieldSensor(ColorEditor::update_h_cb, PRIVATE(this));
++ PRIVATE(this)->sensor_h->attach(&(PRIVATE(this)->slider_h->value));
++ PRIVATE(this)->generateSliderTextureH(this->color.getValue(), FALSE);
++ }
++ if ( PRIVATE(this)->slider_s ) {
++ PRIVATE(this)->slider_s->ref();
++ PRIVATE(this)->sensor_s = new SoFieldSensor(ColorEditor::update_s_cb, PRIVATE(this));
++ PRIVATE(this)->sensor_s->attach(&(PRIVATE(this)->slider_s->value));
++ PRIVATE(this)->generateSliderTextureS(this->color.getValue(), FALSE);
++
++ }
++ if ( PRIVATE(this)->slider_v ) {
++ PRIVATE(this)->slider_v->ref();
++ PRIVATE(this)->sensor_v = new SoFieldSensor(ColorEditor::update_v_cb, PRIVATE(this));
++ PRIVATE(this)->sensor_v->attach(&(PRIVATE(this)->slider_v->value));
++ PRIVATE(this)->generateSliderTextureV(this->color.getValue(), FALSE);
++ }
++ if ( PRIVATE(this)->slider_wheel ) {
++ PRIVATE(this)->slider_wheel->ref();
++ PRIVATE(this)->sensor_wheel = new SoFieldSensor(ColorEditor::update_wheel_cb, PRIVATE(this));
++ PRIVATE(this)->sensor_wheel->attach(&(PRIVATE(this)->slider_wheel->value));
++ PRIVATE(this)->generateSliderTextureHSV(this->color.getValue(), FALSE);
++ }
++
++ PRIVATE(this)->editor->unrefNoDelete();
++ this->setAnyPart("root", scene);
++
++ PRIVATE(this)->color_sensor = new SoFieldSensor(ColorEditor::color_update_cb, PRIVATE(this));
++ PRIVATE(this)->color_sensor->attach(&(this->color));
++
++ // SoGuiViewportFix * viewportfix = (SoGuiViewportFix *) SoAny::scanSceneForName(inherited::getSceneGraph(), "viewportfix", FALSE);
++ // assert(viewportfix != NULL);
++ // PRIVATE(this)->editor->objectSize.connectFrom(&(viewportfix->viewportSize));
++}
++
++SoGuiColorEditor::~SoGuiColorEditor(void)
++{
++ ColorEditor * instance = PRIVATE(this);
++ delete instance;
++}
++
++// *************************************************************************
++
++// CAT_MOD BEGIN
++const char *
++ColorEditor::editorscene[] = {
++ "#Inventor V2.1 ascii",
++ "DEF pane SoGuiPane {",
++ " worldSize 1 1 0",
++ " objectSize 400 340 0",
++ // Calculate positions
++ " SoGuiPosition {",
++ " position = DEF windowgeometry Calculator {",
++ " A = USE pane.objectSize",
++ " B 120 120 0", // colorwheel size
++ " C 140 30 0", // clickcounter size
++ " a 2", // width of frame
++ " expression [",
++ " \"oA = vec3f(a, A[1] - C[1] - a, 0)\"", // clickcounter pos
++ " \"oB = vec3f(A[0] - B[0] - a, A[1] - B[1] - a, 0)\"", // colorwheel pos
++ " ]",
++ " }.oA",
++ " }",
++ // Create a click counter
++ " DEF switcher SoGuiClickCounter {",
++ " size = USE windowgeometry.C",
++ " first 2 # the INTENSITY sliders",
++ " last 6 # the RGB_HSV sliders",
++ " value 5 # start with the RGB_V group",
++ " }",
++ // Create a frame around the click counter area
++ " SoGuiFrame {",
++ " size = USE windowgeometry.C",
++ " width 2",
++ " design EMBOSS",
++ " }",
++ // Create labels for the click counter
++ " Separator {",
++ " Scale {",
++ " scaleFactor 2 2 2",
++ " }",
++ " DEF sliderlabel SoGuiLabel {",
++ " which = USE switcher.value",
++ " text [",
++ " \"?\"",
++ " \"NONE\"",
++ " \"VALUE\"",
++ " \"RGB\"",
++ " \"HSV\"",
++ " \"RGBV\"",
++ " \"RGBHSV\"",
++ " ]",
++ " }",
++ " }",
++ // Create a frame around the color wheel
++ " SoGuiPosition { position = USE windowgeometry.oB }",
++ " SoGuiFrame {",
++ " size = USE windowgeometry.B",
++ " design EMBOSS",
++ " width 2",
++ " complement TRUE",
++ " }",
++ // Create the color wheel
++ " DEF colorwheel SoGuiSlider2 {",
++ " size = USE windowgeometry.B",
++ " }",
++ // Position the sliders
++ " SoGuiPosition {",
++ " position = DEF slidergeometry Calculator {",
++ " A = USE pane.objectSize",
++ " B = USE windowgeometry.B", // color wheel size
++ " a = USE windowgeometry.a", // width of frame
++ " b 10", // space
++ " c 30", // width of text
++ " expression [",
++ " \"ta = (A[1] - (2*a + B[1]) - 7*b) / 6\"", // slider height
++ " \"tb = A[0] - 2*b - c\"", // slider width
++ " \"oA = vec3f(tb, ta, 0)\"", // slider size
++ " \"oB = vec3f(c+b , b, 0)\"", // slider pos
++ " \"oC = vec3f(0, ta + b, 0)\"", // slider translation
++ " \"oD = vec3f(-c, 0, 0)\"", // slider label translation
++ " ]",
++ " }.oB",
++ " }",
++ // Create the sliders depending on the click count value
++ " Switch {",
++ " whichChild = USE switcher.value",
++ " Group {", // never to be rendered...
++ " DEF slider_r SoGuiSlider1 { size = USE slidergeometry.oA }",
++ " DEF slider_g SoGuiSlider1 { size = USE slidergeometry.oA }",
++ " DEF slider_b SoGuiSlider1 { size = USE slidergeometry.oA }",
++ " DEF slider_h SoGuiSlider1 { size = USE slidergeometry.oA }",
++ " DEF slider_s SoGuiSlider1 { size = USE slidergeometry.oA }",
++ " DEF slider_v SoGuiSlider1 { size = USE slidergeometry.oA }",
++ " DEF slider_translation SoGuiTranslation { translation = USE slidergeometry.oC }",
++ " DEF slider_frame SoGuiFrame {",
++ " size = USE slidergeometry.oA ",
++ " design EMBOSS",
++ " width 2",
++ " complement TRUE",
++ " }",
++ " DEF label_translation SoGuiTranslation { translation = USE slidergeometry.oD }",
++ " DEF label_scale Scale { scaleFactor 2 2 2 }",
++ " DEF label_r Separator {",
++ " USE label_translation",
++ " USE label_scale",
++ " SoGuiLabel { text \"R\" }",
++ " }",
++ " DEF label_g Separator {",
++ " USE label_translation",
++ " USE label_scale",
++ " SoGuiLabel { text \"G\" }",
++ " }",
++ " DEF label_b Separator {",
++ " USE label_translation",
++ " USE label_scale",
++ " SoGuiLabel { text \"B\" }",
++ " }",
++ " DEF label_h Separator {",
++ " USE label_translation",
++ " USE label_scale",
++ " SoGuiLabel { text \"H\" }",
++ " }",
++ " DEF label_s Separator {",
++ " USE label_translation",
++ " USE label_scale",
++ " SoGuiLabel { text \"S\" }",
++ " }",
++ " DEF label_v Separator {",
++ " USE label_translation",
++ " USE label_scale",
++ " SoGuiLabel { text \"V\" }",
++ " }",
++ " }",
++ " DEF sliders_NONE Group {", // in case we search for names once, instead of indexing
++ " }", // children directly inside setCurrentSliders()
++ " DEF sliders_INTENSITY Group {",
++ " USE slider_frame", // frames before sliders - the knobs must paint over frames
++ " USE slider_v",
++ " USE label_v",
++ " }",
++ " DEF sliders_RGB Group {",
++ " USE slider_frame",
++ " USE slider_b",
++ " USE label_b",
++ " USE slider_translation",
++ " USE slider_frame",
++ " USE slider_g",
++ " USE label_g",
++ " USE slider_translation",
++ " USE slider_frame",
++ " USE slider_r",
++ " USE label_r",
++ " }",
++ " DEF sliders_HSV Group {",
++ " USE slider_frame",
++ " USE slider_v",
++ " USE label_v",
++ " USE slider_translation",
++ " USE slider_frame",
++ " USE slider_s",
++ " USE label_s",
++ " USE slider_translation",
++ " USE slider_frame",
++ " USE slider_h",
++ " USE label_h",
++ " }",
++ " DEF sliders_RGB_V Group {",
++ " USE sliders_INTENSITY",
++ " USE slider_translation",
++ " USE sliders_RGB",
++ " }",
++ " DEF sliders_RGB_HSV Group {",
++ " USE sliders_HSV",
++ " USE slider_translation",
++ " USE sliders_RGB",
++ " }",
++ " } # Switch",
++ "} # Pane pane",
++ NULL
++};
++// CAT_MOD END
++
++// *************************************************************************
++
++void
++ColorEditor::colorChange(void)
++{
++ float r = 0.0f, g = 0.0f, b = 0.0f, h = 0.0f, s = 0.0f, v = 0.0f;
++ SbColor color(PUBLIC(this)->color.getValue());
++ color.getValue(r, g, b);
++ color.getHSVValue(h, s, v);
++
++ SbVec2f wheel(this->calculateFromHue(h, s, v));
++
++ this->sensor_r->detach();
++ this->sensor_g->detach();
++ this->sensor_b->detach();
++ this->sensor_h->detach();
++ this->sensor_s->detach();
++ this->sensor_v->detach();
++ this->sensor_wheel->detach();
++
++ if ( r != this->slider_r->value.getValue() ) this->slider_r->value.setValue(r);
++ if ( g != this->slider_g->value.getValue() ) this->slider_g->value.setValue(g);
++ if ( b != this->slider_b->value.getValue() ) this->slider_b->value.setValue(b);
++ if ( h != this->slider_h->value.getValue() ) this->slider_h->value.setValue(h);
++ if ( s != this->slider_s->value.getValue() ) this->slider_s->value.setValue(s);
++ if ( v != this->slider_v->value.getValue() ) this->slider_v->value.setValue(v);
++ if ( wheel != this->slider_wheel->value.getValue() ) this->slider_wheel->value.setValue(wheel);
++
++ assert(PUBLIC(this) != NULL);
++ if ( PUBLIC(this)->wysiwyg.getValue() ) {
++ this->generateSliderTextureR(color, TRUE);
++ this->generateSliderTextureG(color, TRUE);
++ this->generateSliderTextureB(color, TRUE);
++ this->generateSliderTextureH(color, TRUE);
++ this->generateSliderTextureS(color, TRUE);
++ this->generateSliderTextureV(color, TRUE);
++ this->generateSliderTextureHSV(color, TRUE);
++ }
++
++ this->sensor_r->attach(&(this->slider_r->value));
++ this->sensor_g->attach(&(this->slider_g->value));
++ this->sensor_b->attach(&(this->slider_b->value));
++ this->sensor_h->attach(&(this->slider_h->value));
++ this->sensor_s->attach(&(this->slider_s->value));
++ this->sensor_v->attach(&(this->slider_v->value));
++ this->sensor_wheel->attach(&(this->slider_wheel->value));
++}
++
++void
++ColorEditor::color_update_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure != NULL);
++ ColorEditor * me = (ColorEditor *) closure;
++ me->colorChange();
++}
++
++// *************************************************************************
++
++void
++ColorEditor::update_r_cb(void * closure, SoSensor * sensor)
++{
++ ColorEditor * me = (ColorEditor *) closure;
++ float r, g, b;
++ SbColor color = PUBLIC(me)->color.getValue();
++ color.getValue(r, g, b);
++ r = me->slider_r->value.getValue();
++ color.setValue(r, g, b);
++ PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_g_cb(void * closure, SoSensor * sensor)
++{
++ ColorEditor * me = (ColorEditor *) closure;
++ float r, g, b;
++ SbColor color = PUBLIC(me)->color.getValue();
++ color.getValue(r, g, b);
++ g = me->slider_g->value.getValue();
++ color.setValue(r, g, b);
++ PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_b_cb(void * closure, SoSensor * sensor)
++{
++ ColorEditor * me = (ColorEditor *) closure;
++ float r, g, b;
++ SbColor color = PUBLIC(me)->color.getValue();
++ color.getValue(r, g, b);
++ b = me->slider_b->value.getValue();
++ color.setValue(r, g, b);
++ PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_h_cb(void * closure, SoSensor * sensor)
++{
++ ColorEditor * me = (ColorEditor *) closure;
++ float h, s, v;
++ SbColor color = PUBLIC(me)->color.getValue();
++ color.getHSVValue(h, s, v);
++ h = me->slider_h->value.getValue();
++ color.setHSVValue(h, s, v);
++ PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_s_cb(void * closure, SoSensor * sensor)
++{
++ ColorEditor * me = (ColorEditor *) closure;
++ float h, s, v;
++ SbColor color = PUBLIC(me)->color.getValue();
++ color.getHSVValue(h, s, v);
++ s = me->slider_s->value.getValue();
++ color.setHSVValue(h, s, v);
++ PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_v_cb(void * closure, SoSensor * sensor)
++{
++ ColorEditor * me = (ColorEditor *) closure;
++ float h, s, v;
++ SbColor color = PUBLIC(me)->color.getValue();
++ color.getHSVValue(h, s, v);
++ v = me->slider_v->value.getValue();
++ color.setHSVValue(h, s, v);
++ PUBLIC(me)->color.setValue(color);
++}
++
++void
++ColorEditor::update_wheel_cb(void * closure, SoSensor * sensor)
++{
++ ColorEditor * me = (ColorEditor *) closure;
++ SbVec2f value = me->slider_wheel->value.getValue();
++ value = value * 2.0f - SbVec2f(1.0f, 1.0f);
++ if ( value.length() > 1.0f ) {
++ value.normalize();
++ SbVec2f reverse = (value + SbVec2f(1.0f, 1.0f)) / 2.0f;
++ me->slider_wheel->value.setValue(reverse);
++ }
++ float h;
++ if ( value[0] == 0.0f ) h = ((value[1] < 0.0f) ? 3.0f : 1.0f) * float(M_PI) / 2.0f;
++ else h = (float) atan(value[1] / value[0]);
++ if ( value[0] < 0.0f ) h += float(M_PI);
++ if ( h < 0.0f ) h += (2.0f * float(M_PI));
++ h /= 2.0f * float(M_PI);
++ float s = So at Gui@Min(value.length(), 1.0f); // float precision bugfix
++
++ float a = 0.0f, b = 0.0f, v = 1.0f;
++ SbColor existing = PUBLIC(me)->color.getValue();
++ existing.getHSVValue(a, b, v);
++
++ SbColor color;
++ color.setHSVValue(h, s, v);
++ PUBLIC(me)->color.setValue(color);
++}
++
++// *************************************************************************
++
++float
++ColorEditor::calculateHue(float x, float y)
++{
++ float hue;
++ if ( x == 0.0f ) hue = ((y < 0.0f) ? 3.0f : 1.0f) * float(M_PI) / 2.0f;
++ else hue = (float) atan(y / x);
++ if ( x < 0.0f ) hue += float(M_PI);
++ if ( hue < 0.0f ) hue += (2.0f * float(M_PI));
++ return hue / (2.0f * float(M_PI));
++}
++
++SbVec2f
++ColorEditor::calculateFromHue(float h, float s, float v)
++{
++ float hue = h * 2.0f * float(M_PI);
++ return SbVec2f(((float) cos(hue) * s + 1.0f) / 2.0f, ((float) sin(hue) * s + 1.0f) / 2.0f);
++}
++
++// *************************************************************************
++
++void
++ColorEditor::generateSliderTextureR(const SbColor & current, SbBool wysiwyg)
++{
++ assert(this->slider_r != NULL);
++ float red, green, blue;
++ current.getValue(red, green, blue);
++ if ( ! wysiwyg ) {
++ green = blue = 0.0f;
++ }
++ SoTexture2 * texture = SO_GET_PART(this->slider_r, "surfaceTexture", SoTexture2);
++ assert(texture);
++ texture->wrapS.setValue(SoTexture2::CLAMP);
++ texture->wrapT.setValue(SoTexture2::CLAMP);
++ SbVec2s size(256, 1);
++ int nc = 3;
++ texture->image.setValue(size, nc, NULL);
++ texture->model.setValue(SoTexture2::DECAL);
++ unsigned char * bytes = texture->image.startEditing(size, nc);
++ int x, y;
++ for ( x = 0; x < size[0]; x++ ) {
++ red = (float) x / (float) (size[0] - 1);
++ for ( y = 0; y < size[1]; y++ ) {
++ bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++ bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++ bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++ // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++ }
++ }
++ texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureG(const SbColor & current, SbBool wysiwyg)
++{
++ assert(this->slider_g != NULL);
++ float red, green, blue;
++ current.getValue(red, green, blue);
++ if ( ! wysiwyg ) {
++ red = blue = 0.0f;
++ }
++ SoTexture2 * texture = SO_GET_PART(this->slider_g, "surfaceTexture", SoTexture2);
++ assert(texture);
++ texture->wrapS.setValue(SoTexture2::CLAMP);
++ texture->wrapT.setValue(SoTexture2::CLAMP);
++ SbVec2s size(256, 1);
++ int nc = 3;
++ texture->image.setValue(size, nc, NULL);
++ texture->model.setValue(SoTexture2::DECAL);
++ unsigned char * bytes = texture->image.startEditing(size, nc);
++ int x, y;
++ for ( x = 0; x < size[0]; x++ ) {
++ green = (float) x / (float) (size[0] - 1);
++ for ( y = 0; y < size[1]; y++ ) {
++ bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++ bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++ bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++ // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++ }
++ }
++ texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureB(const SbColor & current, SbBool wysiwyg)
++{
++ assert(this->slider_b != NULL);
++ float red, green, blue;
++ current.getValue(red, green, blue);
++ if ( ! wysiwyg ) {
++ red = green = 0.0f;
++ }
++ SoTexture2 * texture = SO_GET_PART(this->slider_b, "surfaceTexture", SoTexture2);
++ assert(texture);
++ texture->wrapS.setValue(SoTexture2::CLAMP);
++ texture->wrapT.setValue(SoTexture2::CLAMP);
++ SbVec2s size(256, 1);
++ int nc = 3;
++ texture->image.setValue(size, nc, NULL);
++ texture->model.setValue(SoTexture2::DECAL);
++ unsigned char * bytes = texture->image.startEditing(size, nc);
++ int x, y;
++ for ( x = 0; x < size[0]; x++ ) {
++ blue = (float) x / (float) (size[0] - 1);
++ for ( y = 0; y < size[1]; y++ ) {
++ bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++ bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++ bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++ // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++ }
++ }
++ texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureH(const SbColor & current, SbBool wysiwyg)
++{
++ assert(this->slider_h != NULL);
++ float hue, saturation, value;
++ current.getHSVValue(hue, saturation, value);
++ if ( ! wysiwyg ) {
++ saturation = 1.0f;
++ value = 1.0f;
++ }
++ SoTexture2 * texture = SO_GET_PART(this->slider_h, "surfaceTexture", SoTexture2);
++ assert(texture);
++ texture->wrapS.setValue(SoTexture2::CLAMP);
++ texture->wrapT.setValue(SoTexture2::CLAMP);
++ SbVec2s size(256, 1);
++ int nc = 3;
++ texture->image.setValue(size, nc, NULL);
++ texture->model.setValue(SoTexture2::DECAL);
++ unsigned char * bytes = texture->image.startEditing(size, nc);
++ int x, y;
++ for ( x = 0; x < size[0]; x++ ) {
++ const float hue = (float) x / (float) (size[0] - 1);
++ for ( y = 0; y < size[1]; y++ ) {
++ float r = 0.0f, g = 0.0f, b = 0.0f;
++ SbColor color(r, g, b);
++ color.setHSVValue(hue, saturation, value);
++ color.getValue(r, g, b);
++ bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f);
++ bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f);
++ bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f);
++ // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++ }
++ }
++ texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureS(const SbColor & current, SbBool wysiwyg)
++{
++ assert(this->slider_s != NULL);
++ float hue, saturation, value;
++ current.getHSVValue(hue, saturation, value);
++ if ( ! wysiwyg ) {
++ hue = 0.0f;
++ value = 1.0f;
++ }
++ SoTexture2 * texture = SO_GET_PART(this->slider_s, "surfaceTexture", SoTexture2);
++ assert(texture);
++ texture->wrapS.setValue(SoTexture2::CLAMP);
++ texture->wrapT.setValue(SoTexture2::CLAMP);
++ SbVec2s size(256, 1);
++ int nc = 3;
++ texture->image.setValue(size, nc, NULL);
++ texture->model.setValue(SoTexture2::DECAL);
++ unsigned char * bytes = texture->image.startEditing(size, nc);
++ int x, y;
++ for ( x = 0; x < size[0]; x++ ) {
++ const float saturation = (float) x / (float) (size[0] - 1);
++ for ( y = 0; y < size[1]; y++ ) {
++ float r = 0.0f, g = 0.0f, b = 0.0f;
++ SbColor color(r, g, b);
++ color.setHSVValue(hue, saturation, value);
++ color.getValue(r, g, b);
++ bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f);
++ bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f);
++ bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f);
++ // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++ }
++ }
++ texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureV(const SbColor & current, SbBool wysiwyg)
++{
++ assert(this->slider_v != NULL);
++ float hue, saturation, value;
++ current.getHSVValue(hue, saturation, value);
++ if ( ! wysiwyg ) {
++ hue = 0.0f;
++ saturation = 1.0f;
++ }
++ SoTexture2 * texture = SO_GET_PART(this->slider_v, "surfaceTexture", SoTexture2);
++ assert(texture);
++ texture->wrapS.setValue(SoTexture2::CLAMP);
++ texture->wrapT.setValue(SoTexture2::CLAMP);
++ SbVec2s size(256, 1);
++ int nc = 3;
++ texture->image.setValue(size, nc, NULL);
++ texture->model.setValue(SoTexture2::DECAL);
++ unsigned char * bytes = texture->image.startEditing(size, nc);
++ int x, y;
++ for ( x = 0; x < size[0]; x++ ) {
++ const float value = (float) x / (float) (size[0] - 1);
++ for ( y = 0; y < size[1]; y++ ) {
++ float r = 0.0f, g = 0.0f, b = 0.0f;
++ SbColor color(r, g, b);
++ color.setHSVValue(hue, saturation, value);
++ color.getValue(r, g, b);
++ bytes[(size[0]*y+x)*nc+0] = (unsigned char) (r * 255.0f);
++ bytes[(size[0]*y+x)*nc+1] = (unsigned char) (g * 255.0f);
++ bytes[(size[0]*y+x)*nc+2] = (unsigned char) (b * 255.0f);
++ // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++ }
++ }
++ texture->image.finishEditing();
++}
++
++void
++ColorEditor::generateSliderTextureHSV(const SbColor & current, SbBool wysiwyg)
++{
++ assert(this->slider_wheel != NULL);
++ float hue, saturation, value;
++ current.getHSVValue(hue, saturation, value);
++ if ( ! wysiwyg ) {
++ value = 1.0f;
++ }
++
++ SoTexture2 * texture = SO_GET_PART(this->slider_wheel, "surfaceTexture", SoTexture2);
++ assert(texture);
++ texture->wrapS.setValue(SoTexture2::CLAMP);
++ texture->wrapT.setValue(SoTexture2::CLAMP);
++ SbVec2s size(256, 256);
++ int nc = 3;
++ texture->image.setValue(size, nc, NULL);
++ texture->model.setValue(SoTexture2::DECAL);
++ unsigned char * bytes = texture->image.startEditing(size, nc);
++ int x, y;
++ const float halfx = (float) size[0] / 2.0f;
++ const float halfy = (float) size[1] / 2.0f;
++ for ( y = 0; y < size[1]; y++ ) {
++ const float ypos = ((float) y - halfy) / halfy;
++ for ( x = 0; x < size[0]; x++ ) {
++ const float xpos = ((float) x - halfx) / halfx;
++ const float saturation = (float) sqrt(xpos * xpos + ypos * ypos);
++ float hue = ColorEditor::calculateHue(xpos, ypos);
++ float red = 0.0f, green = 0.0f, blue = 0.0f;
++ SbColor color(red, green, blue);
++ if ( saturation <= 1.0f ) color.setHSVValue(hue, saturation, value);
++ color.getValue(red, green, blue);
++ bytes[(size[0]*y+x)*nc+0] = (unsigned char) (red * 255.0f);
++ bytes[(size[0]*y+x)*nc+1] = (unsigned char) (green * 255.0f);
++ bytes[(size[0]*y+x)*nc+2] = (unsigned char) (blue * 255.0f);
++ // if ( nc > 3 ) bytes[(size[0]*y+x)*nc+4] = 255;
++ }
++ }
++ texture->image.finishEditing();
++}
++
++// *************************************************************************
++
++#undef PUBLIC
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ColorEditor.h.in
+@@ -0,0 +1,79 @@
++#ifndef COIN_SOGUICOLOREDITOR_H
++#define COIN_SOGUICOLOREDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFColor.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiColorEditor : public SoBaseKit {
++ typedef SoBaseKit inherited;
++ SO_KIT_HEADER(SoGuiColorEditor);
++ SO_KIT_CATALOG_ENTRY_HEADER(root);
++
++public:
++ static void initClass(void);
++ SoGuiColorEditor(void);
++
++ enum Sliders {
++ NONE,
++ INTENSITY,
++ RGB,
++ HSV,
++ RGB_V,
++ RGB_HSV
++ };
++
++ enum Update {
++ CONTINUOUS,
++ AFTER_ACCEPT
++ };
++
++ SoSFEnum sliders;
++ SoSFEnum update;
++ SoSFBool wysiwyg;
++ SoSFColor color;
++
++protected:
++ ~SoGuiColorEditor(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUICOLOREDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Frame.cpp.in
+@@ -0,0 +1,257 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/elements/SoLazyElement.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiFrame.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class Frame {
++public:
++ SoGuiFrame * api;
++
++ SoCoordinate3 * coords;
++ SoMaterial * light;
++ SoMaterial * shade;
++
++ SoFieldSensor * size_sensor;
++ SoFieldSensor * width_sensor;
++ static void size_updated_cb(void * closure, SoSensor * sensor);
++
++ SoFieldSensor * design_sensor;
++ static void design_updated_cb(void * closure, SoSensor * sensor);
++ SoFieldSensor * complement_sensor;
++
++ static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Frame *)obj->internals)
++
++void
++SoGuiFrame::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiFrame, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiFrame);
++
++SoGuiFrame::SoGuiFrame(void)
++{
++ this->internals = new Frame;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiFrame);
++
++ SO_KIT_ADD_FIELD(size, (SbVec3f(0.0f, 0.0f, 0.0f)));
++ SO_KIT_ADD_FIELD(design, (SoGuiFrame::BLACK));
++ SO_KIT_ADD_FIELD(width, (1.0f));
++ SO_KIT_ADD_FIELD(complement, (FALSE));
++
++ SO_KIT_DEFINE_ENUM_VALUE(FrameDesign, BLACK);
++ SO_KIT_DEFINE_ENUM_VALUE(FrameDesign, COLOR);
++ SO_KIT_DEFINE_ENUM_VALUE(FrameDesign, EMBOSS);
++
++ SO_KIT_SET_SF_ENUM_TYPE(design, FrameDesign);
++
++ SO_KIT_ADD_CATALOG_ENTRY(scene, SoSeparator, TRUE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ SoNode * node = SoAny::loadSceneGraph(Frame::scene);
++ assert(node);
++
++ this->setAnyPart("scene", node);
++
++ PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(node, "coordinates");
++ PRIVATE(this)->light = (SoMaterial *) SoAny::scanSceneForName(node, "light");
++ PRIVATE(this)->shade = (SoMaterial *) SoAny::scanSceneForName(node, "shade");
++
++ assert(PRIVATE(this)->coords);
++ assert(PRIVATE(this)->light);
++ assert(PRIVATE(this)->shade);
++
++ PRIVATE(this)->coords->ref();
++ PRIVATE(this)->light->ref();
++ PRIVATE(this)->shade->ref();
++
++ PRIVATE(this)->size_sensor = new SoFieldSensor(Frame::size_updated_cb, PRIVATE(this));
++ PRIVATE(this)->size_sensor->attach(&(this->size));
++ PRIVATE(this)->width_sensor = new SoFieldSensor(Frame::size_updated_cb, PRIVATE(this));
++ PRIVATE(this)->width_sensor->attach(&(this->size));
++ PRIVATE(this)->design_sensor = new SoFieldSensor(Frame::design_updated_cb, PRIVATE(this));
++ PRIVATE(this)->design_sensor->attach(&(this->design));
++ PRIVATE(this)->complement_sensor = new SoFieldSensor(Frame::design_updated_cb, PRIVATE(this));
++ PRIVATE(this)->complement_sensor->attach(&(this->complement));
++ this->design.touch();
++}
++
++SoGuiFrame::~SoGuiFrame(void)
++{
++ PRIVATE(this)->coords->unref();
++ PRIVATE(this)->light->unref();
++ PRIVATE(this)->shade->unref();
++ delete PRIVATE(this)->size_sensor;
++ delete PRIVATE(this)->width_sensor;
++ delete PRIVATE(this)->design_sensor;
++ delete PRIVATE(this)->complement_sensor;
++ Frame * obj = PRIVATE(this);
++ delete obj;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) ((SoGuiFrame *)obj->api)
++
++const char *
++Frame::scene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " DEF coordinates Coordinate3 {",
++ " point [",
++ " 0 0 0,",
++ " 1 0 0,",
++ " 1 1 0,",
++ " 0 1 0,",
++ " -1 -1 0,",
++ " 2 -1 0,",
++ " 2 2 0,",
++ " -1 2 0",
++ " ]",
++ " }",
++ // shadow
++ " DEF shade Material {",
++ " diffuseColor 0.9 0.9 0.9",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [",
++ " 4 5 1 -1",
++ " 4 1 0 -1",
++ " 5 6 2 -1",
++ " 5 2 1 -1",
++ " ]",
++ " }",
++ // light
++ " DEF light Material {",
++ " diffuseColor 0.5 0.5 0.5",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [",
++ " 6 7 3 -1",
++ " 6 3 2 -1",
++ " 7 4 0 -1",
++ " 7 0 3 -1",
++ " ]",
++ " }",
++ "}",
++ NULL
++};
++
++void
++Frame::size_updated_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure != NULL);
++ Frame * me = (Frame *) closure;
++ SoCoordinate3 * coords = me->coords;
++ assert(coords);
++ SbVec3f size = PUBLIC(me)->size.getValue();
++ float width = PUBLIC(me)->width.getValue();
++ SbBool save = coords->point.enableNotify(FALSE);
++ coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++ coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++ coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++ coords->point.set1Value(4, SbVec3f(-width, -width, 0.0f));
++ coords->point.set1Value(5, SbVec3f(size[0]+width, -width, 0.0f));
++ coords->point.set1Value(6, SbVec3f(size[0]+width, size[1]+width, 0.0f));
++ coords->point.set1Value(7, SbVec3f(-width, size[1]+width, 0.0f));
++ coords->point.enableNotify(save);
++ if ( save ) coords->point.touch();
++}
++
++void
++Frame::design_updated_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure != NULL);
++ Frame * me = (Frame *) closure;
++ SoMaterial * light = me->light;
++ SoMaterial * shade = me->shade;
++ assert(light);
++ assert(shade);
++ switch ( PUBLIC(me)->design.getValue() ) {
++ case SoGuiFrame::EMBOSS:
++ if ( PUBLIC(me)->complement.getValue() ) {
++ light->diffuseColor.setValue(SbColor(0.5f, 0.5f, 0.5f));
++ shade->diffuseColor.setValue(SbColor(0.9f, 0.9f, 0.9f));
++ } else {
++ light->diffuseColor.setValue(SbColor(0.9f, 0.9f, 0.9f));
++ shade->diffuseColor.setValue(SbColor(0.5f, 0.5f, 0.5f));
++ }
++ break;
++ case SoGuiFrame::BLACK:
++ if ( PUBLIC(me)->complement.getValue() ) {
++ light->diffuseColor.setValue(SbColor(1.0f, 0.0f, 0.0f));
++ shade->diffuseColor.setValue(SbColor(1.0f, 0.0f, 0.0f));
++ } else {
++ light->diffuseColor.setValue(SbColor(0.0f, 0.0f, 0.0f));
++ shade->diffuseColor.setValue(SbColor(0.0f, 0.0f, 0.0f));
++ }
++ break;
++ default:
++ break;
++ }
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Frame.h.in
+@@ -0,0 +1,80 @@
++#ifndef COIN_SOGUIFRAME_H
++#define COIN_SOGUIFRAME_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFFloat.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiFrame : public SoBaseKit {
++ typedef SoBaseKit inherited;
++
++ SO_KIT_HEADER(SoGuiFrame);
++
++ SO_KIT_CATALOG_ENTRY_HEADER(scene);
++
++public:
++ static void initClass(void);
++
++ SoGuiFrame(void);
++
++ enum FrameDesign {
++ BLACK,
++ COLOR,
++ EMBOSS
++ };
++
++ SoSFVec3f size;
++ SoSFFloat width;
++ SoSFEnum design;
++ SoSFBool complement;
++
++protected:
++ virtual ~SoGuiFrame(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIFRAME_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Image.cpp.in
+@@ -0,0 +1,164 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiImage.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class Image {
++public:
++ Image(void);
++
++ SoGuiImage * api;
++
++ SoFieldSensor * size_sensor;
++ static void size_updated_cb(void * closure, SoSensor * sensor);
++
++ SoCoordinate3 * coords;
++
++ static const char * geometryscene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Image *)obj->internals)
++
++void
++SoGuiImage::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiImage, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiImage);
++
++SoGuiImage::SoGuiImage(void)
++{
++ this->internals = new Image;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiImage);
++ SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++
++ SO_KIT_ADD_CATALOG_ENTRY(geometry, SoGroup, FALSE, topSeparator, "", FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(texture, SoTexture2, FALSE, topSeparator, geometry, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ SoNode * geometryroot = SoAny::loadSceneGraph(Image::geometryscene);
++ assert(geometryroot);
++ geometryroot->ref();
++ geometryroot->isOfType(SoSeparator::getClassTypeId());
++ SoNode * realgeometry = ((SoSeparator *) geometryroot)->getChild(0);
++ assert(realgeometry);
++ realgeometry->ref();
++
++ PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(realgeometry, "coords");
++ assert(PRIVATE(this)->coords);
++ assert(PRIVATE(this)->coords->isOfType(SoCoordinate3::getClassTypeId()));
++
++ realgeometry->unrefNoDelete();
++ SbBool ok = this->setAnyPart("geometry", realgeometry);
++ assert(ok);
++ geometryroot->unref();
++
++ PRIVATE(this)->size_sensor = new SoFieldSensor(Image::size_updated_cb, PRIVATE(this));
++ PRIVATE(this)->size_sensor->attach(&(this->size));
++}
++
++SoGuiImage::~SoGuiImage(void)
++{
++ delete PRIVATE(this)->size_sensor;
++ Image * obj = PRIVATE(this);
++ delete obj;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++Image::geometryscene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "Group {",
++ " DEF coords Coordinate3 {",
++ " point [ 0 0 0, 1 0 0, 1 1 0, 0 1 0 ]",
++ " }",
++ " TextureCoordinate2 {",
++ " point [ 0 0, 1 0, 1 1, 0 1 ]",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [ 0 1 2 -1 0 2 3 -1 ]",
++ " textureCoordIndex [ 0 1 2 -1 0 2 3 -1 ]",
++ " }",
++ "}",
++ NULL
++};
++
++Image::Image(void)
++{
++ this->api = NULL;
++ this->size_sensor = NULL;
++ this->coords = NULL;
++}
++
++void
++Image::size_updated_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Image * me = (Image *) closure;
++ SbVec3f size = PUBLIC(me)->size.getValue();
++ SbBool save = me->coords->point.enableNotify(FALSE);
++ me->coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++ me->coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++ me->coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++ me->coords->point.enableNotify(save);
++ if ( save ) me->coords->point.touch();
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Image.h.in
+@@ -0,0 +1,68 @@
++#ifndef COIN_SOGUIIMAGE_H
++#define COIN_SOGUIIMAGE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiImage : public SoBaseKit {
++ typedef SoBaseKit inherited;
++
++ SO_KIT_HEADER(SoGuiImage);
++
++ SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++ SO_KIT_CATALOG_ENTRY_HEADER(texture);
++ SO_KIT_CATALOG_ENTRY_HEADER(geometry);
++
++public:
++ static void initClass(void);
++ SoGuiImage(void);
++
++ SoSFVec3f size;
++
++protected:
++ virtual ~SoGuiImage(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIIMAGE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Label.cpp.in
+@@ -0,0 +1,154 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoAsciiText.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiLabel.h>
++
++// *************************************************************************
++
++class Label {
++public:
++ Label(void);
++
++ SoGuiLabel * api;
++
++ SoAsciiText * text;
++
++ SoFieldSensor * text_sensor;
++ SoFieldSensor * which_sensor;
++ static void text_updated_cb(void * closure, SoSensor * sensor);
++
++ static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Label *)this->internals)
++
++void
++SoGuiLabel::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiLabel, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiLabel);
++
++SoGuiLabel::SoGuiLabel(void)
++{
++ this->internals = new Label;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiLabel);
++ SO_KIT_ADD_FIELD(text, (""));
++ SO_KIT_ADD_FIELD(which, (0));
++
++ SO_KIT_ADD_CATALOG_ENTRY(scene, SoSeparator, FALSE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ SoNode * thescene = SoAny::loadSceneGraph(Label::scene);
++ assert(thescene);
++ thescene->ref();
++
++ PRIVATE(this)->text = (SoAsciiText *) SoAny::scanSceneForName(thescene, "text");
++ assert(PRIVATE(this)->text);
++
++ thescene->unrefNoDelete();
++ SbBool ok = this->setAnyPart("scene", thescene);
++ assert(ok);
++
++ PRIVATE(this)->text_sensor = new SoFieldSensor(Label::text_updated_cb, PRIVATE(this));
++ PRIVATE(this)->text_sensor->attach(&(this->text));
++ PRIVATE(this)->which_sensor = new SoFieldSensor(Label::text_updated_cb, PRIVATE(this));
++ PRIVATE(this)->which_sensor->attach(&(this->which));
++ Label::text_updated_cb(PRIVATE(this), NULL);
++}
++
++SoGuiLabel::~SoGuiLabel(void)
++{
++ delete PRIVATE(this)->text_sensor;
++ delete PRIVATE(this)->which_sensor;
++ Label * obj = PRIVATE(this);
++ delete obj;
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++Label::scene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " SoGuiTranslation { translation 1 1 0 }",
++ " Scale { scaleFactor 1.5 1.5 1 }",
++ " BaseColor { rgb 0 0 0 }",
++ " DEF text AsciiText { }",
++ "}",
++ NULL
++};
++
++Label::Label(void)
++{
++ this->api = NULL;
++ this->text = NULL;
++ this->which_sensor = NULL;
++}
++
++void
++Label::text_updated_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Label * me = (Label *) closure;
++ assert(me->text);
++ int which = PUBLIC(me)->which.getValue();
++ // SbString string = PUBLIC(me)->text.getValue();
++ SbString string = PUBLIC(me)->text[which];
++ me->text->string.setValue(string);
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Label.h.in
+@@ -0,0 +1,66 @@
++#ifndef COIN_SOGUILABEL_H
++#define COIN_SOGUILABEL_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFShort.h>
++#include <Inventor/fields/SoMFString.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiLabel : public SoBaseKit {
++ typedef SoBaseKit inherited;
++ SO_KIT_HEADER(SoGuiLabel);
++ SO_KIT_CATALOG_ENTRY_HEADER(scene);
++
++public:
++ static void initClass(void);
++ SoGuiLabel(void);
++
++ SoMFString text;
++ SoSFShort which;
++
++protected:
++ ~SoGuiLabel(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUILABEL_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/MaterialEditor.cpp.in
+@@ -0,0 +1,898 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/sensors/SoNodeSensor.h>
++#ifdef HAVE_SOVRMLMATERIAL
++#include <Inventor/VRMLnodes/SoVRMLMaterial.h>
++#endif // HAVE_SOVRMLMATERIAL
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiImage.h>
++#include <Inventor/@Gui@/nodes/SoGuiSceneTexture2.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiToggleButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiRadioButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++
++// *************************************************************************
++
++class MaterialEditor {
++public:
++ MaterialEditor(void);
++ ~MaterialEditor(void);
++
++ SoGuiMaterialEditor * api;
++
++ SoMaterial * material;
++ SoNodeSensor * material_sensor;
++ static void material_cb(void * closure, SoSensor * sensor);
++
++ SoFieldSensor * material_field_sensor;
++ static void material_field_cb(void * closure, SoSensor * sensor);
++
++ SoGuiToggleButton * button1;
++ SoGuiToggleButton * button2;
++ SoGuiToggleButton * button3;
++ SoGuiToggleButton * button4;
++ SoFieldSensor * button1_sensor;
++ SoFieldSensor * button2_sensor;
++ SoFieldSensor * button3_sensor;
++ SoFieldSensor * button4_sensor;
++ static void button1_cb(void * closure, SoSensor * sensor);
++ static void button2_cb(void * closure, SoSensor * sensor);
++ static void button3_cb(void * closure, SoSensor * sensor);
++ static void button4_cb(void * closure, SoSensor * sensor);
++ SoGuiRadioButton * radio1;
++ SoGuiRadioButton * radio2;
++ SoGuiRadioButton * radio3;
++ SoGuiRadioButton * radio4;
++
++ SoGuiSlider1 * slider1;
++ SoGuiSlider1 * slider2;
++ SoGuiSlider1 * slider3;
++ SoGuiSlider1 * slider4;
++ SoGuiSlider1 * slider5;
++ SoGuiSlider1 * slider6;
++ SoFieldSensor * ambient_slider_sensor;
++ SoFieldSensor * diffuse_slider_sensor;
++ SoFieldSensor * specular_slider_sensor;
++ SoFieldSensor * emissive_slider_sensor;
++ SoFieldSensor * shininess_slider_sensor;
++ SoFieldSensor * transparency_slider_sensor;
++ static void ambient_slider_cb(void * closure, SoSensor * sensor);
++ static void diffuse_slider_cb(void * closure, SoSensor * sensor);
++ static void specular_slider_cb(void * closure, SoSensor * sensor);
++ static void emissive_slider_cb(void * closure, SoSensor * sensor);
++ static void shininess_slider_cb(void * closure, SoSensor * sensor);
++ static void transparency_slider_cb(void * closure, SoSensor * sensor);
++
++ SoGuiColorEditorOpenCB * openeditorcb;
++ SoGuiColorEditorCloseCB * closeeditorcb;
++ void * cbclosure;
++
++ static SoGuiColorEditor * coloreditoropen_cb(void * closure);
++ static void coloreditorclose_cb(void * closure, SoGuiColorEditor * editor);
++
++ SbBool coloreditoropen;
++ SoGuiColorEditor * coloreditor;
++ SoFieldSensor * coloreditor_sensor;
++ static void coloreditor_cb(void * closure, SoSensor * sensor);
++
++ void checkColorEditorOpenStatus(void);
++
++ static const char * texturescene[];
++ static const char * editorscene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((MaterialEditor *) ((SoGuiMaterialEditor *) obj)->internals)
++
++void
++SoGuiMaterialEditor::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiMaterialEditor, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiMaterialEditor);
++
++SoGuiMaterialEditor::SoGuiMaterialEditor(void)
++{
++ this->internals = new MaterialEditor;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiMaterialEditor);
++
++ SO_KIT_ADD_FIELD(material, (NULL));
++ SO_KIT_ADD_FIELD(index, (0));
++ SO_KIT_ADD_FIELD(update, (CONTINUOUS));
++
++ SO_KIT_DEFINE_ENUM_VALUE(Update, CONTINUOUS);
++ SO_KIT_DEFINE_ENUM_VALUE(Update, AFTER_ACCEPT);
++
++ SO_KIT_SET_SF_ENUM_TYPE(update, Update);
++
++ SO_KIT_ADD_CATALOG_ENTRY(root, SoGuiPane, TRUE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ SoNode * scene = SoAny::loadSceneGraph(MaterialEditor::editorscene);
++ assert(scene != NULL);
++ assert(scene->isOfType(SoGuiPane::getClassTypeId()));
++ scene->ref();
++
++ SoGuiImage * sphereimage =
++ (SoGuiImage *) SoAny::scanSceneForName(scene, "image");
++ assert(sphereimage != NULL);
++ scene->unrefNoDelete();
++ SbBool ok = this->setAnyPart("root", scene);
++ assert(ok);
++
++ PRIVATE(this)->button1 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton1");
++ PRIVATE(this)->button2 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton2");
++ PRIVATE(this)->button3 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton3");
++ PRIVATE(this)->button4 = (SoGuiToggleButton *) SoAny::scanSceneForName(scene, "tbutton4");
++ assert(PRIVATE(this)->button1);
++ assert(PRIVATE(this)->button2);
++ assert(PRIVATE(this)->button3);
++ assert(PRIVATE(this)->button4);
++ PRIVATE(this)->radio1 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton1");
++ PRIVATE(this)->radio2 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton2");
++ PRIVATE(this)->radio3 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton3");
++ PRIVATE(this)->radio4 = (SoGuiRadioButton *) SoAny::scanSceneForName(scene, "rbutton4");
++ assert(PRIVATE(this)->radio1);
++ assert(PRIVATE(this)->radio2);
++ assert(PRIVATE(this)->radio3);
++ assert(PRIVATE(this)->radio4);
++
++ PRIVATE(this)->slider1 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider1");
++ PRIVATE(this)->slider2 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider2");
++ PRIVATE(this)->slider3 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider3");
++ PRIVATE(this)->slider4 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider4");
++ PRIVATE(this)->slider5 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider5");
++ PRIVATE(this)->slider6 = (SoGuiSlider1 *) SoAny::scanSceneForName(scene, "slider6");
++ assert(PRIVATE(this)->slider1);
++ assert(PRIVATE(this)->slider2);
++ assert(PRIVATE(this)->slider3);
++ assert(PRIVATE(this)->slider4);
++ assert(PRIVATE(this)->slider5);
++ assert(PRIVATE(this)->slider6);
++ PRIVATE(this)->slider1->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++ PRIVATE(this)->slider2->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++ PRIVATE(this)->slider3->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++ PRIVATE(this)->slider4->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++ PRIVATE(this)->slider5->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++ PRIVATE(this)->slider6->setSurfaceColor(SbColor(0,0,0), SbColor(1,1,1));
++
++ SoNode * textureroot = SoAny::loadSceneGraph(MaterialEditor::texturescene);
++ assert(textureroot != NULL);
++ assert(textureroot->isOfType(SoSeparator::getClassTypeId()));
++ SoNode * texture = ((SoSeparator *) textureroot)->getChild(0);
++ assert(texture != NULL);
++ assert(texture->isOfType(SoGuiSceneTexture2::getClassTypeId()));
++
++ SoNode * subscene = ((SoGuiSceneTexture2 *) texture)->scene.getValue();
++ assert(subscene);
++ subscene->ref();
++ PRIVATE(this)->material = (SoMaterial *) SoAny::scanSceneForName(subscene, "material");
++ subscene->unrefNoDelete();
++ assert(PRIVATE(this)->material);
++
++ ok = sphereimage->setPart("texture", texture);
++ assert(ok);
++
++ PRIVATE(this)->ambient_slider_sensor = new SoFieldSensor(MaterialEditor::ambient_slider_cb, PRIVATE(this));
++ PRIVATE(this)->diffuse_slider_sensor = new SoFieldSensor(MaterialEditor::diffuse_slider_cb, PRIVATE(this));
++ PRIVATE(this)->specular_slider_sensor = new SoFieldSensor(MaterialEditor::specular_slider_cb, PRIVATE(this));
++ PRIVATE(this)->emissive_slider_sensor = new SoFieldSensor(MaterialEditor::emissive_slider_cb, PRIVATE(this));
++ PRIVATE(this)->shininess_slider_sensor = new SoFieldSensor(MaterialEditor::shininess_slider_cb, PRIVATE(this));
++ PRIVATE(this)->transparency_slider_sensor = new SoFieldSensor(MaterialEditor::transparency_slider_cb, PRIVATE(this));
++ PRIVATE(this)->ambient_slider_sensor->attach(&(PRIVATE(this)->slider1->value));
++ PRIVATE(this)->diffuse_slider_sensor->attach(&(PRIVATE(this)->slider2->value));
++ PRIVATE(this)->specular_slider_sensor->attach(&(PRIVATE(this)->slider3->value));
++ PRIVATE(this)->emissive_slider_sensor->attach(&(PRIVATE(this)->slider4->value));
++ PRIVATE(this)->shininess_slider_sensor->attach(&(PRIVATE(this)->slider5->value));
++ PRIVATE(this)->transparency_slider_sensor->attach(&(PRIVATE(this)->slider6->value));
++
++ PRIVATE(this)->button1_sensor = new SoFieldSensor(MaterialEditor::button1_cb, PRIVATE(this));
++ PRIVATE(this)->button2_sensor = new SoFieldSensor(MaterialEditor::button2_cb, PRIVATE(this));
++ PRIVATE(this)->button3_sensor = new SoFieldSensor(MaterialEditor::button3_cb, PRIVATE(this));
++ PRIVATE(this)->button4_sensor = new SoFieldSensor(MaterialEditor::button4_cb, PRIVATE(this));
++ PRIVATE(this)->button1_sensor->attach(&(PRIVATE(this)->button1->on));
++ PRIVATE(this)->button2_sensor->attach(&(PRIVATE(this)->button2->on));
++ PRIVATE(this)->button3_sensor->attach(&(PRIVATE(this)->button3->on));
++ PRIVATE(this)->button4_sensor->attach(&(PRIVATE(this)->button4->on));
++
++ PRIVATE(this)->material_sensor = new SoNodeSensor(MaterialEditor::material_cb, PRIVATE(this));
++ PRIVATE(this)->material_sensor->attach(PRIVATE(this)->material);
++ PRIVATE(this)->material->touch();
++
++ PRIVATE(this)->material_field_sensor = new SoFieldSensor(MaterialEditor::material_field_cb, PRIVATE(this));
++ PRIVATE(this)->material_field_sensor->attach(&(this->material));
++
++ this->setColorEditorCallbacks(MaterialEditor::coloreditoropen_cb, MaterialEditor::coloreditorclose_cb, PRIVATE(this));
++}
++
++SoGuiMaterialEditor::~SoGuiMaterialEditor(void)
++{
++ MaterialEditor * obj = PRIVATE(this);
++ delete obj;
++}
++
++void
++SoGuiMaterialEditor::setColorEditorCallbacks(
++ SoGuiColorEditorOpenCB * open,
++ SoGuiColorEditorCloseCB * close,
++ void * closure)
++{
++ PRIVATE(this)->openeditorcb = open;
++ PRIVATE(this)->closeeditorcb = close;
++ PRIVATE(this)->cbclosure = closure;
++}
++
++SoMaterial *
++SoGuiMaterialEditor::getSphereMaterialNode(void) const
++{
++ return PRIVATE(this)->material;
++}
++
++// *************************************************************************
++// MaterialEditor
++// *************************************************************************
++
++#define PUBLIC(obj) (((MaterialEditor *) obj)->api)
++
++// +--------------------------------------------------------------------+
++// | | o x Ambient |======================| 0.00 |
++// | | o x Diffuse |======================| 0.00 |
++// | | o x Specular |======================| 0.00 |
++// | | o x Emissive |======================| 0.00 |
++// | | |
++// | | Shininess |======================| 0.00 |
++// | | Transp |======================| 0.00 |
++// +--------------------------------------------------------------------+
++// [nice - Ed]
++
++const char *
++MaterialEditor::texturescene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "SoGuiSceneTexture2 {",
++ " scene",
++ " Separator {",
++ " OrthographicCamera {",
++ " position 0 0 2",
++ " nearDistance 1",
++ " farDistance 3",
++ " height 2",
++ " }",
++ " LightModel { model BASE_COLOR }",
++ " BaseColor {",
++ " rgb [ 0.3 0.3 0.3, 0.6 0.6 0.6, 0.6 0.6 0.6, 0.3 0.3 0.3 ]",
++ " }",
++ " MaterialBinding { value PER_FACE }",
++ " Coordinate3 {",
++ " point [",
++ " -3 3 0, 0 3 0, 3 3 0,",
++ " -3 0 0, 0 0 0, 3 0 0,",
++ " -3 -3 0, 0 -3 0, 3 -3 0",
++ " ]",
++ " }",
++ " QuadMesh {",
++ " verticesPerColumn 3",
++ " verticesPerRow 3",
++ " }",
++ " LightModel { model PHONG }",
++ " DirectionalLight { direction 0.556 -0.623 -0.551 }",
++ " DirectionalLight { direction -0.556 -0.623 -0.551 }",
++ " DEF material Material { }",
++ " Complexity { value 0.8 }",
++ " ShapeHints { vertexOrdering COUNTERCLOCKWISE shapeType SOLID }",
++ " Sphere { radius 0.85 }",
++ " }",
++ " }",
++ "}",
++ NULL
++};
++
++// FIXME: add labels
++// FIXME: adjust geometry
++
++const char *
++MaterialEditor::editorscene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "DEF pane SoGuiPane {",
++ " worldSize 1 1 0",
++ " objectSize 550 300 0",
++ " SoGuiPosition {",
++ " position = DEF wm Calculator {",
++ " A = USE pane.objectSize",
++ " expression [",
++ " \"ta = (A[0] / 2 < A[1]) ? (A[0]/2)-20 : A[1]-20\"",
++ " \"tb = (A[1] - ta) / 2\"",
++ " \"oA = vec3f(10, tb, 0)\"", // image position
++ " \"oB = vec3f(ta, ta, 0)\"", // image size
++ " \"oC = vec3f(ta + 30, A[1] - 25, 0)\"", // radio1 position
++ " \"oD = vec3f(0, -30, 0)\"", // ratio translation
++ " ]",
++ " } . oA",
++ " }",
++ " DEF image SoGuiImage { size = USE wm.oB }",
++ " SoGuiFrame {",
++ " size = USE image.size",
++ " design EMBOSS",
++ " width 2",
++ " complement TRUE",
++ " }",
++ " SoGuiPosition { position = USE wm.oC }",
++ " DEF rbutton1 SoGuiRadioButton {",
++ " size 10 10 0",
++ " on = DEF rbuttons SoGuiRadioGroup {",
++ " in0 = USE rbutton1.on",
++ " in1 = DEF rbutton2 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out1 } . on",
++ " in2 = DEF rbutton3 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out2 } . on",
++ " in3 = DEF rbutton4 SoGuiRadioButton { size 10 10 0 on = USE rbuttons.out3 } . on",
++ " } . out0",
++ " }",
++ " SoGuiFrame {",
++ " size = USE rbutton1.size",
++ " width 2",
++ " complement = USE rbutton1.on",
++ " }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE rbutton2",
++ " SoGuiFrame {",
++ " size = USE rbutton2.size",
++ " width 2",
++ " complement = USE rbutton2.on",
++ " }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE rbutton3",
++ " SoGuiFrame {",
++ " size = USE rbutton3.size",
++ " width 2",
++ " complement = USE rbutton3.on",
++ " }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE rbutton4",
++ " SoGuiFrame {",
++ " size = USE rbutton4.size",
++ " width 2",
++ " complement = USE rbutton4.on",
++ " }",
++ " SoGuiPosition {",
++ " position = DEF wm2 Calculator {",
++ " A = USE pane.objectSize",
++ " expression [",
++ " \"ta = (A[0] / 2 < A[1]) ? (A[0]/2)-20 : A[1]-20\"",
++ " \"oA = vec3f(ta + 60, A[1] - 25, 0)\"",
++ " \"oB = vec3f(ta + 90, A[1] - 25, 0)\"",
++ " \"oC = vec3f(ta - 100, 15, 0)\"",
++ " ]",
++ " } . oA",
++ " }",
++ " DEF tbutton1 SoGuiToggleButton {",
++ " size 10 10 0"
++ " on = USE rbuttons.out0",
++ " }",
++ " SoGuiFrame {",
++ " size = USE tbutton1.size",
++ " width 2",
++ " complement = USE tbutton1.on",
++ " design EMBOSS",
++ " }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " DEF tbutton2 SoGuiToggleButton {",
++ " size 10 10 0"
++ " on = USE rbuttons.out1",
++ " }",
++ " SoGuiFrame {",
++ " size = USE tbutton2.size",
++ " width 2",
++ " complement = USE tbutton2.on",
++ " design EMBOSS",
++ " }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " DEF tbutton3 SoGuiToggleButton {",
++ " size 10 10 0"
++ " on = USE rbuttons.out2",
++ " }",
++ " SoGuiFrame {",
++ " size = USE tbutton3.size",
++ " width 2",
++ " complement = USE tbutton3.on",
++ " design EMBOSS",
++ " }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " DEF tbutton4 SoGuiToggleButton {",
++ " size 10 10 0"
++ " on = USE rbuttons.out3",
++ " }",
++ " SoGuiFrame {",
++ " size = USE tbutton4.size",
++ " width 2",
++ " complement = USE tbutton4.on",
++ " design EMBOSS",
++ " }",
++
++ " SoGuiPosition { position = USE wm2.oB }",
++ " DEF sliderframe SoGuiFrame {",
++ " size = USE wm2.oC",
++ " width 2",
++ " complement TRUE",
++ " design EMBOSS",
++ " }",
++ " DEF slider1 SoGuiSlider1 { size = USE sliderframe.size }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE sliderframe",
++ " DEF slider2 SoGuiSlider1 { size = USE sliderframe.size }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE sliderframe",
++ " DEF slider3 SoGuiSlider1 { size = USE sliderframe.size }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE sliderframe",
++ " DEF slider4 SoGuiSlider1 { size = USE sliderframe.size }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE sliderframe",
++ " DEF slider5 SoGuiSlider1 { size = USE sliderframe.size }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE sliderframe",
++ " DEF slider6 SoGuiSlider1 { size = USE sliderframe.size }",
++
++ " SoGuiPosition { position = USE pane.objectSize }",
++ " SoGuiTranslation { translation -35 -25 0 }",
++ " DEF labelframe SoGuiFrame { size 25 15 0 width 2 design EMBOSS complement TRUE }",
++ " SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider1.value } . output }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE labelframe",
++ " SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider2.value } . output }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE labelframe",
++ " SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider3.value } . output }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE labelframe",
++ " SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider4.value } . output }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE labelframe",
++ " SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider5.value } . output }",
++ " SoGuiTranslation { translation = USE wm.oD }",
++ " USE labelframe",
++ " SoGuiLabel { text = SoGuiFormat { format \"%4.2f\" float1 = USE slider6.value } . output }",
++ "}",
++ NULL
++};
++
++MaterialEditor::MaterialEditor(void)
++{
++ this->api = NULL;
++ this->material = NULL;
++ this->button1 = NULL;
++ this->button2 = NULL;
++ this->button3 = NULL;
++ this->button4 = NULL;
++ this->radio1 = NULL;
++ this->radio2 = NULL;
++ this->radio3 = NULL;
++ this->radio4 = NULL;
++ this->slider1 = NULL;
++ this->slider2 = NULL;
++ this->slider3 = NULL;
++ this->slider4 = NULL;
++ this->slider5 = NULL;
++ this->slider6 = NULL;
++ this->ambient_slider_sensor = NULL;
++ this->diffuse_slider_sensor = NULL;
++ this->specular_slider_sensor = NULL;
++ this->emissive_slider_sensor = NULL;
++ this->shininess_slider_sensor = NULL;
++ this->transparency_slider_sensor = NULL;
++ this->coloreditoropen = FALSE;
++ this->coloreditor = NULL;
++ this->coloreditor_sensor = NULL;
++}
++
++MaterialEditor::~MaterialEditor(void)
++{
++ if ( this->coloreditor_sensor ) delete this->coloreditor_sensor;
++}
++
++void
++MaterialEditor::ambient_slider_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ assert(me->material);
++ assert(me->slider1);
++ SbColor ambient = me->material->ambientColor[0];
++ float h, s, v;
++ ambient.getHSVValue(h, s, v);
++ v = me->slider1->value.getValue();
++ ambient.setHSVValue(h, s, v);
++ if ( ambient != me->material->ambientColor[0] )
++ me->material->ambientColor.set1Value(0, ambient);
++}
++
++void
++MaterialEditor::diffuse_slider_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ assert(me->material);
++ assert(me->slider2);
++ SbColor diffuse = me->material->diffuseColor[0];
++ float h, s, v;
++ diffuse.getHSVValue(h, s, v);
++ v = me->slider2->value.getValue();
++ diffuse.setHSVValue(h, s, v);
++ if ( diffuse != me->material->diffuseColor[0] )
++ me->material->diffuseColor.set1Value(0, diffuse);
++}
++
++void
++MaterialEditor::specular_slider_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ assert(me->material);
++ assert(me->slider3);
++ SbColor specular = me->material->specularColor[0];
++ float h, s, v;
++ specular.getHSVValue(h, s, v);
++ v = me->slider3->value.getValue();
++ specular.setHSVValue(h, s, v);
++ if ( specular != me->material->specularColor[0] )
++ me->material->specularColor.set1Value(0, specular);
++}
++
++void
++MaterialEditor::emissive_slider_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ assert(me->material);
++ assert(me->slider4);
++ SbColor emissive = me->material->emissiveColor[0];
++ float h, s, v;
++ emissive.getHSVValue(h, s, v);
++ v = me->slider4->value.getValue();
++ emissive.setHSVValue(h, s, v);
++ if ( emissive != me->material->emissiveColor[0] )
++ me->material->emissiveColor.set1Value(0, emissive);
++}
++
++void
++MaterialEditor::shininess_slider_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ assert(me->material);
++ assert(me->slider5);
++ float shininess = me->slider5->value.getValue();
++ if ( shininess != me->material->shininess[0] )
++ me->material->shininess.set1Value(0, shininess);
++}
++
++void
++MaterialEditor::transparency_slider_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ assert(me->material);
++ assert(me->slider6);
++ float transparency = me->slider6->value.getValue();
++ if ( transparency != me->material->transparency[0] )
++ me->material->transparency.set1Value(0, transparency);
++}
++
++void
++MaterialEditor::checkColorEditorOpenStatus(void)
++{
++ if ( this->button1->on.getValue() ||
++ this->button2->on.getValue() ||
++ this->button3->on.getValue() ||
++ this->button4->on.getValue() ) {
++ if ( !this->coloreditoropen && this->openeditorcb ) {
++ this->coloreditor = this->openeditorcb(this->cbclosure);
++ this->coloreditoropen = TRUE;
++ if ( this->coloreditor_sensor == NULL )
++ this->coloreditor_sensor = new SoFieldSensor(MaterialEditor::coloreditor_cb, this);
++ if ( this->coloreditor )
++ this->coloreditor_sensor->attach(&(this->coloreditor->color));
++ }
++ } else {
++ if ( this->coloreditoropen && this->closeeditorcb ) {
++ if ( this->coloreditor_sensor ) this->coloreditor_sensor->detach();
++ this->closeeditorcb(this->cbclosure, this->coloreditor);
++ this->coloreditor = NULL;
++ this->coloreditoropen = FALSE;
++ }
++ }
++}
++
++void
++MaterialEditor::button1_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ SbBool down = me->button1->on.getValue();
++ if ( !down ) {
++ if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++
++ if ( me->button2->on.getValue() &&
++ !me->button3->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
++ if ( !me->button2->on.getValue() &&
++ me->button3->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++ if ( !me->button2->on.getValue() &&
++ !me->button3->on.getValue() &&
++ me->button4->on.getValue() &&
++ !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++ } else {
++ if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++ if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++ if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++ if ( !me->button2->on.getValue() &&
++ !me->button3->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++ }
++ me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::button2_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ SbBool down = me->button2->on.getValue();
++ if ( !down ) {
++ if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++ if ( me->button1->on.getValue() &&
++ !me->button3->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++ if ( !me->button1->on.getValue() &&
++ me->button3->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++ if ( !me->button1->on.getValue() &&
++ !me->button3->on.getValue() &&
++ me->button4->on.getValue() &&
++ !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++ } else {
++ if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++ if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++ if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++ if ( !me->button1->on.getValue() &&
++ !me->button3->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
++ }
++ me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::button3_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ SbBool down = me->button3->on.getValue();
++ if ( !down ) {
++ if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++ if ( me->button1->on.getValue() &&
++ !me->button2->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++ if ( !me->button1->on.getValue() &&
++ me->button2->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
++ if ( !me->button1->on.getValue() &&
++ !me->button2->on.getValue() &&
++ me->button4->on.getValue() &&
++ !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++ } else {
++ if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++ if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++ if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++ if ( !me->button1->on.getValue() &&
++ !me->button2->on.getValue() &&
++ !me->button4->on.getValue() &&
++ !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++ }
++ me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::button4_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ SbBool down = me->button4->on.getValue();
++ if ( !down ) {
++ if ( me->radio4->on.getValue() ) me->radio4->on.setValue(FALSE);
++ if ( me->button1->on.getValue() &&
++ !me->button2->on.getValue() &&
++ !me->button3->on.getValue() &&
++ !me->radio1->on.getValue() ) me->radio1->on.setValue(TRUE);
++ if ( !me->button1->on.getValue() &&
++ me->button2->on.getValue() &&
++ !me->button3->on.getValue() &&
++ !me->radio2->on.getValue() ) me->radio2->on.setValue(TRUE);
++ if ( !me->button1->on.getValue() &&
++ !me->button2->on.getValue() &&
++ me->button3->on.getValue() &&
++ !me->radio3->on.getValue() ) me->radio3->on.setValue(TRUE);
++ } else {
++ if ( me->radio1->on.getValue() ) me->radio1->on.setValue(FALSE);
++ if ( me->radio2->on.getValue() ) me->radio2->on.setValue(FALSE);
++ if ( me->radio3->on.getValue() ) me->radio3->on.setValue(FALSE);
++ if ( !me->button1->on.getValue() &&
++ !me->button2->on.getValue() &&
++ !me->button3->on.getValue() &&
++ !me->radio4->on.getValue() ) me->radio4->on.setValue(TRUE);
++ }
++ me->checkColorEditorOpenStatus();
++}
++
++void
++MaterialEditor::coloreditor_cb(void * closure, SoSensor * sensor)
++{
++ // coloreditor is being interacted with - so update material editor sliders
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ if ( me->button1->on.getValue() )
++ me->material->ambientColor.setValue(me->coloreditor->color.getValue());
++ if ( me->button2->on.getValue() )
++ me->material->diffuseColor.setValue(me->coloreditor->color.getValue());
++ if ( me->button3->on.getValue() )
++ me->material->specularColor.setValue(me->coloreditor->color.getValue());
++ if ( me->button4->on.getValue() )
++ me->material->emissiveColor.setValue(me->coloreditor->color.getValue());
++}
++
++void
++MaterialEditor::material_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ SoMaterial * mat = me->material;
++ if ( !mat ) return;
++ float h, s, v;
++ SbColor color = mat->ambientColor[0];
++ color.getHSVValue(h, s, v);
++ if ( v != me->slider1->value.getValue() ) me->slider1->value.setValue(v);
++ color = mat->diffuseColor[0];
++ color.getHSVValue(h, s, v);
++ if ( v != me->slider2->value.getValue() ) me->slider2->value.setValue(v);
++ color = mat->specularColor[0];
++ color.getHSVValue(h, s, v);
++ if ( v != me->slider3->value.getValue() ) me->slider3->value.setValue(v);
++ color = mat->emissiveColor[0];
++ color.getHSVValue(h, s, v);
++ if ( v != me->slider4->value.getValue() ) me->slider4->value.setValue(v);
++ v = mat->shininess[0];
++ if ( v != me->slider5->value.getValue() ) me->slider5->value.setValue(v);
++ v = mat->transparency[0];
++ if ( v != me->slider6->value.getValue() ) me->slider6->value.setValue(v);
++ SoNode * attachment = PUBLIC(me)->material.getValue();
++ if ( attachment ) {
++ if ( attachment->isOfType(SoMaterial::getClassTypeId()) ) {
++ SoMaterial * material = (SoMaterial *) attachment;
++ int index = PUBLIC(me)->index.getValue();
++ material->ambientColor.set1Value(index, mat->ambientColor[0]);
++ material->diffuseColor.set1Value(index, mat->diffuseColor[0]);
++ material->specularColor.set1Value(index, mat->specularColor[0]);
++ material->emissiveColor.set1Value(index, mat->emissiveColor[0]);
++ material->shininess.set1Value(index, mat->shininess[0]);
++ material->transparency.set1Value(index, mat->transparency[0]);
++#ifdef HAVE_SOVRMLMATERIAL
++ } else if ( attachment->isOfType(SoVRMLMaterial::getClassTypeId()) ) {
++ SoVRMLMaterial * material = (SoVRMLMaterial *) attachment;
++ SbColor ambient = mat->ambientColor[0];
++ float h, s, v;
++ ambient.getHSVValue(h, s, v);
++ material->ambientIntensity.setValue(v);
++ material->diffuseColor.setValue(mat->diffuseColor[0]);
++ material->specularColor.setValue(mat->specularColor[0]);
++ material->emissiveColor.setValue(mat->emissiveColor[0]);
++ material->shininess.setValue(mat->shininess[0]);
++ material->transparency.setValue(mat->transparency[0]);
++#endif // HAVE_SOVRMLMATERIAL
++ } else {
++ }
++ }
++}
++
++void
++MaterialEditor::material_field_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ MaterialEditor * me = (MaterialEditor *) closure;
++ SoNode * node = PUBLIC(me)->material.getValue();
++ if ( !node ) return;
++ SoMaterial * mat1 = (SoMaterial *) node;
++ SoMaterial * mat2 = me->material;
++
++ if ( mat1->ambientColor[0] != mat2->ambientColor[0] )
++ mat2->ambientColor.set1Value(0, mat1->ambientColor[0]);
++ if ( mat1->diffuseColor[0] != mat2->diffuseColor[0] )
++ mat2->diffuseColor.set1Value(0, mat1->diffuseColor[0]);
++ if ( mat1->specularColor[0] != mat2->specularColor[0] )
++ mat2->specularColor.set1Value(0, mat1->specularColor[0]);
++ if ( mat1->emissiveColor[0] != mat2->emissiveColor[0] )
++ mat2->emissiveColor.set1Value(0, mat1->emissiveColor[0]);
++ if ( mat1->shininess[0] != mat2->shininess[0] )
++ mat2->shininess.set1Value(0, mat1->shininess[0]);
++ if ( mat1->transparency[0] != mat2->transparency[0] )
++ mat2->transparency.set1Value(0, mat1->transparency[0]);
++}
++
++SoGuiColorEditor *
++MaterialEditor::coloreditoropen_cb(void * closure)
++{
++ SoDebugError::postInfo("MaterialEditor::coloreditoropen_cb", "default callback invoked - not implemented yet");
++ return NULL;
++}
++
++void
++MaterialEditor::coloreditorclose_cb(void * closure, SoGuiColorEditor * editor)
++{
++ SoDebugError::postInfo("MaterialEditor::coloreditorclose_cb", "default callback invoked - not implemented yet");
++}
++
++#undef PRIVATE
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/MaterialEditor.h.in
+@@ -0,0 +1,78 @@
++#ifndef COIN_SOGUIMATERIALEDITOR_H
++#define COIN_SOGUIMATERIALEDITOR_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFShort.h>
++#include <Inventor/fields/SoSFNode.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoMaterial;
++class SoGuiColorEditor;
++
++typedef SoGuiColorEditor * SoGuiColorEditorOpenCB(void * closure);
++typedef void SoGuiColorEditorCloseCB(void * closure, SoGuiColorEditor * editor);
++
++class SoGuiMaterialEditor : public SoBaseKit {
++ typedef SoBaseKit inherited;
++ SO_KIT_HEADER(SoGuiMaterialEditor);
++ SO_KIT_CATALOG_ENTRY_HEADER(root);
++
++public:
++ static void initClass(void);
++ SoGuiMaterialEditor(void);
++
++ enum UpdateFrequency {
++ CONTINUOUS,
++ AFTER_ACCEPT
++ };
++
++ SoSFNode material;
++ SoSFShort index;
++ SoSFEnum update;
++
++ void setColorEditorCallbacks(SoGuiColorEditorOpenCB * open, SoGuiColorEditorCloseCB * close, void * closure);
++ SoMaterial * getSphereMaterialNode(void) const;
++
++protected:
++ ~SoGuiMaterialEditor(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIMATERIALEDITOR_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Nodes.cpp.in
+@@ -0,0 +1,60 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiNodes.h>
++
++// *************************************************************************
++
++void
++SoGuiNodes::initClasses(void)
++{
++ SoGuiSceneTexture2::initClass();
++ SoGuiViewportFix::initClass();
++ SoGuiPane::initClass();
++ SoGuiPosition::initClass();
++ SoGuiTranslation::initClass();
++ SoGuiFrame::initClass();
++ SoGuiImage::initClass();
++ SoGuiLabel::initClass();
++ SoGuiToggleButton::initClass();
++ SoGuiRadioButton::initClass();
++ SoGuiClickCounter::initClass();
++ SoGuiSlider1::initClass();
++ SoGuiSlider2::initClass();
++ SoGuiColorEditor::initClass();
++ SoGuiMaterialEditor::initClass();
++ SoGuiViewpointWrapper::initClass();
++}
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Nodes.h.in
+@@ -0,0 +1,65 @@
++#ifndef COIN_SOGUINODES_H
++#define COIN_SOGUINODES_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/@Gui@/nodes/SoGuiSceneTexture2.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiPosition.h>
++#include <Inventor/@Gui@/nodes/SoGuiTranslation.h>
++#include <Inventor/@Gui@/nodes/SoGuiFrame.h>
++#include <Inventor/@Gui@/nodes/SoGuiImage.h>
++#include <Inventor/@Gui@/nodes/SoGuiLabel.h>
++#include <Inventor/@Gui@/nodes/SoGuiToggleButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiRadioButton.h>
++#include <Inventor/@Gui@/nodes/SoGuiClickCounter.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++#include <Inventor/@Gui@/nodes/SoGuiColorEditor.h>
++#include <Inventor/@Gui@/nodes/SoGuiMaterialEditor.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h>
++
++class SoGuiNodes {
++public:
++ static void initClasses(void);
++
++};
++
++#endif // !COIN_SOGUINODES_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Pane.cpp.in
+@@ -0,0 +1,371 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/bundles/SoMaterialBundle.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++#include <Inventor/elements/SoViewVolumeElement.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/misc/SoChildList.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++
++#define ZSCALE (1.0f)
++
++// *************************************************************************
++
++// FIXME: can't cache model matrix like this - use in multiple scene
++// graphs doesn't work then...
++
++class Pane {
++public:
++ SbMatrix modelmatrix;
++ SbVec3f position;
++ SbVec2f raypickpos;
++
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Pane *) obj->internals)
++
++SO_NODE_SOURCE(SoGuiPane);
++
++void
++SoGuiPane::initClass(void)
++{
++ SO_NODE_INIT_CLASS(SoGuiPane, SoSeparator, "Separator");
++}
++
++SoGuiPane::SoGuiPane(void)
++{
++ this->internals = (void *) new Pane;
++ SO_NODE_CONSTRUCTOR(SoGuiPane);
++ SO_NODE_ADD_FIELD(worldSize, (SbVec3f(1.0f, 1.0f, 0.0f)));
++ SO_NODE_ADD_FIELD(objectSize, (SbVec3f(100.0f, 100.0f, 0.0f)));
++}
++
++SoGuiPane::~SoGuiPane(void)
++{
++ Pane * obj = PRIVATE(this);
++ delete obj;
++ this->internals = NULL;
++}
++
++void
++SoGuiPane::doAction(SoAction * action)
++{
++ SoState * state = action->getState();
++
++ state->push();
++
++ if ( state->isElementEnabled(SoModelMatrixElement::getClassStackIndex()) ) {
++ SbVec3f world = this->worldSize.getValue();
++ SbVec3f object = this->objectSize.getValue();
++ SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++ SoModelMatrixElement::scaleBy(state, this, scalefactor);
++ PRIVATE(this)->modelmatrix = SoModelMatrixElement::get(state);
++ }
++
++ SbBool backface = FALSE;
++ if ( state->isElementEnabled(SoViewVolumeElement::getClassStackIndex()) ) {
++ SbVec3f normal(0.0f, 0.0f, 1.0f);
++ PRIVATE(this)->modelmatrix.multDirMatrix(normal, normal);
++ normal.normalize();
++ SbVec3f campos = SoViewVolumeElement::get(state).getProjectionPoint();
++ SbVec3f center = (SbVec3f(0.0f, 0.0f, 0.0f) + this->objectSize.getValue()) / 2.0f;
++ PRIVATE(this)->modelmatrix.multVecMatrix(center, center);
++ SbVec3f camdir = center - campos;
++ camdir.normalize();
++ backface = (normal.dot(camdir) >= 0.0f) ? TRUE : FALSE;
++ }
++
++ if ( action->isOfType(SoHandleEventAction::getClassTypeId()) ) {
++ if ( backface ) {
++ // we don't react to events when facing away
++ goto culled;
++ }
++ }
++
++ if ( action->isOfType(SoRayPickAction::getClassTypeId()) ) {
++ SoRayPickAction * rpaction = (SoRayPickAction *) action;
++ rpaction->setObjectSpace();
++
++ SbPlane plane(SbVec3f(0.0f, 0.0f, 1.0f), 0.0f);
++ SbLine line(rpaction->getLine());
++ // find intersection with SbPlane
++ SbVec3f point;
++ PRIVATE(this)->raypickpos.setValue(-1.0f, -1.0f);
++ if ( plane.intersect(line, point) ) {
++ SbVec3f object = this->objectSize.getValue();
++ SbVec2f pos(point[0], point[1]);
++ if ( pos[0] < 0.0f || pos[1] < 0.0f || pos[0] > object[0] || pos[1] > object[1] ) {
++ goto culled;
++ } else {
++ PRIVATE(this)->raypickpos = pos;
++ }
++ }
++ else goto culled;
++ }
++ inherited::doAction(action);
++culled:
++ state->pop();
++}
++
++void
++SoGuiPane::GLRenderBelowPath(SoGLRenderAction * action)
++{
++ SoState * state = action->getState();
++ state->push();
++
++ SbVec3f world = this->worldSize.getValue();
++ SbVec3f object = this->objectSize.getValue();
++
++ // adjust scale for new object space
++ SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++ SoModelMatrixElement::scaleBy(state, this, scalefactor);
++
++ // store current model matrix
++ PRIVATE(this)->modelmatrix = SoModelMatrixElement::get(state);
++ PRIVATE(this)->position = SbVec3f(0.0f, 0.0f, 0.0f);
++
++
++ SbVec3f normal(0.0f, 0.0f, 1.0f);
++ PRIVATE(this)->modelmatrix.multDirMatrix(normal, normal);
++ normal.normalize();
++
++ SbVec3f campos = SoViewVolumeElement::get(state).getProjectionPoint();
++ SbVec3f center = (SbVec3f(0.0f, 0.0f, 0.0f) + this->objectSize.getValue()) / 2.0f;
++ PRIVATE(this)->modelmatrix.multVecMatrix(center, center);
++
++ SbVec3f camdir = SoViewVolumeElement::get(state).getProjectionDirection();
++ camdir = center - campos;
++ camdir.normalize();
++
++ const float dot = normal.dot(camdir);
++
++ const SbBool backface = (dot >= 0.0f) ? TRUE : FALSE;
++
++ SoMaterialBundle mb(action);
++ mb.sendFirst();
++
++ if ( object[0] != 0.0f && object[1] != 0.0f ) { // draw pane
++ if ( backface ) glNormal3f(0.0f, 0.0f, -1.0f);
++ else glNormal3f(0.0f, 0.0f, 1.0f);
++ glBegin(GL_QUADS);
++ glVertex3f(0.0f, 0.0f, 0.0f);
++ glVertex3f(0.0f, object[1], 0.0f);
++ glVertex3f(object[0], object[1], 0.0f);
++ glVertex3f(object[0], 0.0f, 0.0f);
++ glEnd(); // GL_QUADS
++ }
++
++ if ( backface ) goto finish;
++
++ glDisable(GL_DEPTH_TEST);
++ glDepthMask(FALSE);
++
++ // TODO: it would probably be a good idea to set up clipping around the pane
++ inherited::GLRenderBelowPath(action);
++
++ glDepthMask(TRUE);
++ glEnable(GL_DEPTH_TEST);
++
++finish:
++ state->pop();
++}
++
++void
++SoGuiPane::GLRenderInPath(SoGLRenderAction * action)
++{
++ SoDebugError::postInfo("SoGuiPane::GLRenderInPath", "implementation is out of date");
++ SoState * state = action->getState();
++ state->push();
++
++ SbVec3f world = this->worldSize.getValue();
++ SbVec3f object = this->objectSize.getValue();
++
++ SoMaterialBundle mb(action);
++ mb.sendFirst();
++
++ // draw pane
++ glBegin(GL_QUADS);
++ glVertex3f(0.0f, 0.0f, 0.0f);
++ glVertex3f(0.0f, world[1], 0.0f);
++ glVertex3f(world[0], world[1], 0.0f);
++ glVertex3f(world[0], 0.0f, 0.0f);
++ glEnd(); // GL_QUADS
++
++ // adjust scale for new object space
++ SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++ SoModelMatrixElement::scaleBy(state, this, scalefactor);
++
++ // store current model matrix
++ PRIVATE(this)->modelmatrix = SoModelMatrixElement::get(state);
++ PRIVATE(this)->position = SbVec3f(0.0f, 0.0f, 0.0f);
++
++ GLint olddepthfunc = 0;
++ glGetIntegerv(GL_DEPTH_FUNC, &olddepthfunc);
++ glDepthFunc(GL_LEQUAL);
++
++ // FIXME: set up clipping around pane
++ inherited::GLRenderInPath(action);
++
++ glDepthFunc((GLenum) olddepthfunc);
++ state->pop();
++}
++
++void
++SoGuiPane::GLRenderOffPath(SoGLRenderAction * action)
++{
++ // is this one ever invoked?
++ SoDebugError::postInfo("SoGuiPane::GLRenderOffPath", "no implementation yet");
++ inherited::GLRenderOffPath(action);
++}
++
++void
++SoGuiPane::pick(SoPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiPane::rayPick(SoRayPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiPane::getMatrix(SoGetMatrixAction * action)
++{
++ SoDebugError::postInfo("SoGuiPane::getMatrix", "invoked");
++ SbVec3f world = this->worldSize.getValue();
++ SbVec3f object = this->objectSize.getValue();
++ SbVec3f scalefactor(world[0] / object[0], world[1] / object[1], ZSCALE);
++ SbMatrix matrix = SbMatrix::identity();
++ matrix.setScale(scalefactor);
++ action->getMatrix().multLeft(matrix);
++ // FIXME: update inverse matrix
++ inherited::getMatrix(action);
++}
++
++void
++SoGuiPane::handleEvent(SoHandleEventAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiPane::getBoundingBox(SoGetBoundingBoxAction * action)
++{
++ SbVec3f min = SbVec3f(0.0f, 0.0f, 0.0f);
++ SbVec3f max = this->worldSize.getValue();
++ min[2] = 0.0f; // -0.001f;
++ max[2] = 0.0f; // 0.001f;
++ SbBox3f box(min, max);
++ action->extendBy(box);
++}
++
++SbVec2f
++SoGuiPane::getRayPickIntersectionPoint(void) const
++{
++ return PRIVATE(this)->raypickpos;
++}
++
++void
++SoGuiPane::moveTo(SoState * state, SbVec3f position)
++{
++ SbVec3f object = this->objectSize.getValue();
++ if ( position[0] < 0.0f ) position[0] = object[0] + position[0];
++ if ( position[1] < 0.0f ) position[1] = object[1] + position[1];
++ PRIVATE(this)->position = position;
++ SbVec3f translation(0.0f, 0.0f, 0.0f);
++ translation[0] = PRIVATE(this)->position[0];
++ translation[1] = PRIVATE(this)->position[1];
++ SoModelMatrixElement::set(state, this, PRIVATE(this)->modelmatrix);
++ // SoDebugError::postInfo("SoGuiPane::moveTo", "origo in %g %g", translation[0], translation[1]);
++ SoModelMatrixElement::translateBy(state, this, translation);
++}
++
++void
++SoGuiPane::applyMoveTo(SoGetMatrixAction * action, SbVec3f position)
++{
++ // FIXME: support negative coordinates
++ SoDebugError::postInfo("SoGuiPane::applyMoveTo", "target %g %g", position[0], position[1]);
++ action->getMatrix() = PRIVATE(this)->modelmatrix;
++ SbMatrix matrix = SbMatrix::identity();
++ matrix.setTranslate(position);
++ action->getMatrix().multLeft(matrix);
++ // FIXME: update inverse matrix
++}
++
++void
++SoGuiPane::moveBy(SoState * state, SbVec3f offset)
++{
++ PRIVATE(this)->position += offset;
++ SbVec3f translation(0.0f, 0.0f, 0.0f);
++ translation[0] = PRIVATE(this)->position[0];
++ translation[1] = PRIVATE(this)->position[1];
++ SoModelMatrixElement::set(state, this, PRIVATE(this)->modelmatrix);
++ // SoDebugError::postInfo("SoGuiPane::moveBy", "origo in %g %g", translation[0], translation[1]);
++ SoModelMatrixElement::translateBy(state, this, translation);
++}
++
++void
++SoGuiPane::applyMoveBy(SoGetMatrixAction * action, SbVec3f offset)
++{
++ SoDebugError::postInfo("SoGuiPane::applyMoveBy", "offset %g %g", offset[0], offset[1]);
++ action->getMatrix() = PRIVATE(this)->modelmatrix;
++ SbMatrix matrix = SbMatrix::identity();
++ SbVec3f position = PRIVATE(this)->position + offset;
++ matrix.setTranslate(position);
++ action->getMatrix().multLeft(matrix);
++ // FIXME: update inverse matrix
++}
++
++#undef ZSCALE
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Pane.h.in
+@@ -0,0 +1,89 @@
++#ifndef COIN_SOGUIPANE_H
++#define COIN_SOGUIPANE_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoSeparator.h>
++
++class SoState;
++
++class SoGuiPane : public SoSeparator {
++ typedef SoSeparator inherited;
++ SO_NODE_HEADER(SoGuiPane);
++
++public:
++ static void initClass(void);
++
++ SoGuiPane(void);
++
++ SoSFVec3f worldSize;
++ SoSFVec3f objectSize;
++
++ virtual void doAction(SoAction * action);
++
++ virtual void GLRenderBelowPath(SoGLRenderAction * action);
++ virtual void GLRenderInPath(SoGLRenderAction * action);
++ virtual void GLRenderOffPath(SoGLRenderAction * action);
++ virtual void pick(SoPickAction * action);
++ virtual void rayPick(SoRayPickAction * action);
++ virtual void getMatrix(SoGetMatrixAction * action);
++ virtual void getBoundingBox(SoGetBoundingBoxAction * action);
++ virtual void handleEvent(SoHandleEventAction * action);
++
++ SbVec2f getRayPickIntersectionPoint(void) const;
++
++protected:
++ friend class SoGuiPosition;
++ friend class SoGuiTranslation;
++
++ virtual ~SoGuiPane(void);
++
++ void moveTo(SoState * state, SbVec3f position);
++ void applyMoveTo(SoGetMatrixAction * action, SbVec3f position);
++ void moveBy(SoState * state, SbVec3f translation);
++ void applyMoveBy(SoGetMatrixAction * action, SbVec3f translation);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIPANE_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Position.cpp.in
+@@ -0,0 +1,123 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoPickAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++#include <Inventor/SoPath.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiPosition.h>
++
++// *************************************************************************
++
++SO_NODE_SOURCE(SoGuiPosition);
++
++void
++SoGuiPosition::initClass(void)
++{
++ SO_NODE_INIT_CLASS(SoGuiPosition, SoTransformation, "Transformation");
++}
++
++SoGuiPosition::SoGuiPosition(void)
++{
++ SO_NODE_CONSTRUCTOR(SoGuiPosition);
++ SO_NODE_ADD_FIELD(position, (SbVec3f(0.0f, 0.0f, 0.0f)));
++}
++
++SoGuiPosition::~SoGuiPosition(void)
++{
++}
++
++void
++SoGuiPosition::doAction(SoAction * action)
++{
++ int i;
++ // SoDebugError::postInfo("SoGuiPosition::doAction", "invoked by %s", action->getTypeId().getName().getString());
++ SoGuiPane * pane = NULL;
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++ SoNode * node = path->getNode(i);
++ assert(node);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++ }
++ if ( pane == NULL ) {
++ SoDebugError::postInfo("SoGuiPosition::GLRender", "SoGuiPosition only works below an SoGuiPane node");
++ return;
++ }
++ pane->moveTo(action->getState(), this->position.getValue());
++}
++
++void
++SoGuiPosition::GLRender(SoGLRenderAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiPosition::pick(SoPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiPosition::rayPick(SoRayPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiPosition::getMatrix(SoGetMatrixAction * action)
++{
++ SoDebugError::postInfo("SoGuiPosition::getMatrix", "invoked");
++ int i;
++ SoGuiPane * pane = NULL;
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++ SoNode * node = path->getNode(i);
++ assert(node);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++ }
++ if ( pane == NULL ) {
++ SoDebugError::postInfo("SoGuiPosition::getMatrix", "SoGuiPosition only works below an SoGuiPane node");
++ return;
++ }
++ pane->applyMoveTo(action, this->position.getValue());
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Position.h.in
+@@ -0,0 +1,70 @@
++#ifndef COIN_SOGUIPOSITION_H
++#define COIN_SOGUIPOSITION_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoTransformation.h>
++
++class SoGuiPosition : public SoTransformation {
++ typedef SoTransformation inherited;
++ SO_NODE_HEADER(SoGuiPosition);
++
++public:
++ static void initClass(void);
++
++ SoGuiPosition(void);
++
++ SoSFVec3f position;
++
++ virtual void doAction(SoAction * action);
++ virtual void GLRender(SoGLRenderAction * action);
++ virtual void pick(SoPickAction * action);
++ virtual void rayPick(SoRayPickAction * action);
++ virtual void getMatrix(SoGetMatrixAction * action);
++
++protected:
++ virtual ~SoGuiPosition(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIPOSITION_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/README
+@@ -0,0 +1,40 @@
++NODES
++
++ SoGuiViewportFix - fix origo to a corner of the viewport
++
++ SoGuiPosition - set 2D position on pane
++
++ SoGuiTranslation - accumulate 2D translation on pane
++
++ SoGuiPane - group node for containing a 2D interface
++ - for enabling special translation/position nodes
++ - for enabling special scaling nodes
++
++NODEKITS
++
++ SoGuiFrame - a 2d-rect emboss / frame renderer
++
++ SoGuiClickCounter - a button-like widget that reacts to mouse presses
++
++ SoGuiToggleButton - a button-like widget that can be turned on/off with the mouse
++
++ SoGuiRadioButton - a button-like widget that can be turned on with the mouse
++
++ SoGuiSlider1 - an interactive slider for a one-dimensional value space
++
++ SoGuiSlider2 - an interactive slider for a two-dimensional value space
++
++ SoGuiColorEditor - the machinery of the color editor component
++
++ SoGuiMaterialEditor - the machinery of the material editor component
++
++ENGINES
++
++ SoGuiRadioGroup - an engine that will make sure only one SoSFBool is enabled
++
++ SoGuiFormat - a string formatting engine (very ad-hoc design for now)
++
++DRAGGERS
++
++ [SoGuiWindowDragger]
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/RadioButton.cpp.in
+@@ -0,0 +1,204 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/SoPickedPoint.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiRadioButton.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class RadioButton {
++public:
++ RadioButton(void);
++
++ SoGuiRadioButton * api;
++
++ SoCoordinate3 * coords;
++ SoNode * faceset;
++ SoFieldSensor * size_sensor;
++ static void size_updated_cb(void * closure, SoSensor * sensor);
++
++ static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((RadioButton *)obj->internals)
++
++void
++SoGuiRadioButton::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiRadioButton, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiRadioButton);
++
++SoGuiRadioButton::SoGuiRadioButton(void)
++{
++ this->internals = new RadioButton;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiRadioButton);
++
++ SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++ SO_KIT_ADD_FIELD(on, (FALSE));
++
++ SO_KIT_ADD_CATALOG_ENTRY(root, SoSeparator, FALSE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ SoNode * scene = SoAny::loadSceneGraph(RadioButton::scene);
++ assert(scene);
++ assert(scene->isOfType(SoSeparator::getClassTypeId()));
++ scene->ref();
++
++ PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(scene, "coords");
++ assert(PRIVATE(this)->coords);
++ assert(PRIVATE(this)->coords->isOfType(SoCoordinate3::getClassTypeId()));
++ PRIVATE(this)->faceset = SoAny::scanSceneForName(scene, "faceset");
++ assert(PRIVATE(this)->faceset);
++
++ scene->unrefNoDelete();
++ this->setAnyPart("root", scene);
++
++ PRIVATE(this)->size_sensor = new SoFieldSensor(RadioButton::size_updated_cb, PRIVATE(this));
++ PRIVATE(this)->size_sensor->attach(&(this->size));
++}
++
++
++SoGuiRadioButton::~SoGuiRadioButton(void)
++{
++ delete PRIVATE(this)->size_sensor;
++ RadioButton * obj = PRIVATE(this);
++ delete obj;
++}
++
++void
++SoGuiRadioButton::handleEvent(SoHandleEventAction * action)
++{
++ const SoEvent * ev = action->getEvent();
++ if ( ev->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++ SbBool hit = FALSE;
++ const SoPickedPointList & ppoints = action->getPickedPointList();
++ assert(PRIVATE(this)->faceset);
++ int i = 0;
++ for ( i = 0; !hit && i < ppoints.getLength(); i++ ) {
++ const SoPickedPoint * point = ppoints[i];
++ const SoFullPath * path = (const SoFullPath *) point->getPath();
++ assert(path);
++ SoNode * node = path->getTail();
++ if ( node == PRIVATE(this)->faceset ) hit = TRUE;
++ }
++ if ( hit ) {
++ const SoMouseButtonEvent * event = (SoMouseButtonEvent *) ev;
++ if ( event->getState() == SoButtonEvent::DOWN ) {
++ this->on.setValue(TRUE);
++ action->setHandled();
++ }
++ }
++ }
++ if ( !action->isHandled() ) {
++ inherited::handleEvent(action);
++ }
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++// RadioButton
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++RadioButton::scene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " DEF coords Coordinate3 {",
++ " point [",
++ " 0 0 0,",
++ " 1 0 0,",
++ " 1 1 0,",
++ " 0 1 0",
++ " ]",
++ " }",
++ " DEF faceset IndexedFaceSet {",
++ " coordIndex [",
++ " 0 1 2 -1",
++ " 0 2 3 -1",
++ " ]",
++ " }",
++ "}",
++ NULL
++};
++
++RadioButton::RadioButton(void)
++{
++ this->api = NULL;
++ this->coords = NULL;
++ this->size_sensor = NULL;
++}
++
++void
++RadioButton::size_updated_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ RadioButton * me = (RadioButton *) closure;
++ assert(PUBLIC(me));
++ SbVec3f size = PUBLIC(me)->size.getValue();
++ assert(me->size_sensor);
++ me->size_sensor->detach();
++ assert(me->coords);
++ SbBool save = me->coords->point.enableNotify(FALSE);
++ me->coords->point.set1Value(0, SbVec3f(0.0f, 0.0f, 0.0f));
++ me->coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++ me->coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++ me->coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++ me->coords->enableNotify(save);
++ if ( save ) me->coords->point.touch();
++ me->size_sensor->attach(&(PUBLIC(me)->size));
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/RadioButton.h.in
+@@ -0,0 +1,68 @@
++#ifndef COIN_SOGUIRADIOBUTTON_H
++#define COIN_SOGUIRADIOBUTTON_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiRadioButton : public SoBaseKit {
++ typedef SoBaseKit inherited;
++ SO_KIT_HEADER(SoGuiRadioButton);
++ SO_KIT_CATALOG_ENTRY_HEADER(root);
++public:
++ static void initClass(void);
++
++ SoGuiRadioButton(void);
++
++ SoSFVec3f size;
++ SoSFBool on;
++
++ virtual void handleEvent(SoHandleEventAction * action);
++
++protected:
++ virtual ~SoGuiRadioButton(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIRADIOBUTTON_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/SceneTexture2.cpp.in
+@@ -0,0 +1,205 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*
++ * TODO
++ * - field "SoSFFloat delay" for making node wait a certain time after
++ * last scene change before re-rendering the texture
++ * - field "SoSFBool dirty" for making texture show itself as dirty
++ * (stippled?) until it has been rerendered (in case it takes time to
++ * rerender scene).
++ */
++
++#include <assert.h>
++#include <string.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/sensors/SoOneShotSensor.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/SoOffscreenRenderer.h>
++#include <Inventor/misc/SoNotification.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiSceneTexture2.h>
++
++// *************************************************************************
++
++class SceneTexture2 {
++public:
++ SceneTexture2(void);
++
++ SoGuiSceneTexture2 * api;
++
++ SbVec2s prevsize;
++ SoOffscreenRenderer * renderer;
++
++ SoFieldSensor * size_sensor;
++ static void size_updated_cb(void * closure, SoSensor * sensor);
++
++ SoOneShotSensor * render_sensor;
++ static void render_cb(void * closure, SoSensor * sensor);
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((SceneTexture2 *) obj->internals)
++
++void
++SoGuiSceneTexture2::initClass(void)
++{
++ SO_NODE_INIT_CLASS(SoGuiSceneTexture2, SoTexture2, "Texture2");
++}
++
++SO_NODE_SOURCE(SoGuiSceneTexture2);
++
++SoGuiSceneTexture2::SoGuiSceneTexture2(void)
++{
++ this->internals = new SceneTexture2;
++ PRIVATE(this)->api = this;
++
++ SO_NODE_CONSTRUCTOR(SoGuiSceneTexture2);
++ SO_NODE_ADD_FIELD(size, (SbVec2f(256.0f, 256.0f)));
++ SO_NODE_ADD_FIELD(scene, (NULL));
++
++ PRIVATE(this)->size_sensor = new SoFieldSensor(SceneTexture2::size_updated_cb, PRIVATE(this));
++ PRIVATE(this)->size_sensor->attach(&(this->size));
++ PRIVATE(this)->render_sensor = new SoOneShotSensor(SceneTexture2::render_cb, PRIVATE(this));
++}
++
++SoGuiSceneTexture2::~SoGuiSceneTexture2(void)
++{
++ delete PRIVATE(this)->size_sensor;
++ delete PRIVATE(this)->render_sensor;
++ if ( PRIVATE(this)->renderer != NULL ) {
++ delete PRIVATE(this)->renderer;
++ }
++}
++
++// We overload notify() because we need to know when the scene graph has
++// been updated, but want to stop that notification from propagating
++// through the external scene graph. We only want the texture update to
++// trigger re-rendering.
++void
++SoGuiSceneTexture2::notify(SoNotList * list)
++{
++ if ( list->getLastField() == &(this->scene) ) {
++ PRIVATE(this)->render_sensor->schedule();
++ return;
++ }
++ inherited::notify(list);
++}
++
++//
++// we don't want to write out the image and filename fields.
++//
++void
++SoGuiSceneTexture2::write(SoWriteAction * action)
++{
++ this->image.setDefault(TRUE);
++ this->filename.setDefault(TRUE);
++ inherited::write(action);
++}
++
++
++#undef PRIVATE
++
++// *************************************************************************
++
++#define PUBLIC(obj) (((SceneTexture2 *) obj)->api)
++
++SceneTexture2::SceneTexture2(void)
++{
++ this->api = NULL;
++ this->prevsize = SbVec2s(-1, -1);
++ this->renderer = NULL;
++ this->size_sensor = NULL;
++ this->render_sensor = NULL;
++}
++
++void
++SceneTexture2::size_updated_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ SceneTexture2 * me = (SceneTexture2 *) closure;
++ SbVec2f tempsize = PUBLIC(me)->size.getValue();
++ SbVec2s size;
++ size[0] = (short) tempsize[0];
++ size[1] = (short) tempsize[1];
++ if ( size != me->prevsize ) {
++ if ( me->renderer != NULL ) {
++ me->renderer->setViewportRegion(SbViewportRegion(size));
++ PUBLIC(me)->image.setValue(size, 3, NULL);
++ me->render_sensor->schedule();
++ }
++ me->prevsize = size;
++ }
++}
++
++void
++SceneTexture2::render_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ SceneTexture2 * me = (SceneTexture2 *) closure;
++ SbVec2f tempsize = PUBLIC(me)->size.getValue();
++ SbVec2s size;
++ size[0] = (short) tempsize[0];
++ size[1] = (short) tempsize[1];
++ int nc = 3;
++ SoNode * scene = PUBLIC(me)->scene.getValue();
++ SbBool save = PUBLIC(me)->image.enableNotify(FALSE);
++ if ( scene != NULL ) {
++ if ( me->renderer == NULL ) {
++ me->renderer = new SoOffscreenRenderer(SbViewportRegion(size));
++ me->renderer->setComponents(SoOffscreenRenderer::RGB);
++ me->renderer->getGLRenderAction()->setTransparencyType(SoGLRenderAction::BLEND);
++ me->prevsize = size;
++ PUBLIC(me)->image.setValue(size, nc, NULL);
++ }
++ me->renderer->render(scene);
++ unsigned char * renderbuffer = me->renderer->getBuffer();
++ unsigned char * imagebytes = PUBLIC(me)->image.startEditing(size, nc);
++ memcpy(imagebytes, renderbuffer, size[0] * size[1] * nc);
++ PUBLIC(me)->image.finishEditing();
++ } else {
++ unsigned char * imagebytes = PUBLIC(me)->image.startEditing(size, nc);
++ memset(imagebytes, 0, size[0] * size[1] * nc);
++ PUBLIC(me)->image.finishEditing();
++ }
++ PUBLIC(me)->image.enableNotify(save);
++ if ( save ) PUBLIC(me)->image.touch();
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/SceneTexture2.h.in
+@@ -0,0 +1,67 @@
++#ifndef COIN_SOGUISCENETEXTURE2_H
++#define COIN_SOGUISCENETEXTURE2_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif // !SO at GUI@_INTERNAL
++
++#include <Inventor/fields/SoSFVec2f.h>
++#include <Inventor/fields/SoSFNode.h>
++#include <Inventor/nodes/SoTexture2.h>
++
++class SoGuiSceneTexture2 : public SoTexture2 {
++ typedef SoTexture2 inherited;
++ SO_NODE_HEADER(SoGuiSceneTexture2);
++public:
++ static void initClass(void);
++ SoGuiSceneTexture2(void);
++
++ SoSFVec2f size;
++ SoSFNode scene;
++
++ virtual void notify(SoNotList * list);
++ virtual void write(SoWriteAction * action);
++
++protected:
++ virtual ~SoGuiSceneTexture2(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUISCENETEXTURE2_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider1.cpp.in
+@@ -0,0 +1,558 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/elements/SoLazyElement.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoLists.h>
++
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoTextureCoordinate2.h>
++#include <Inventor/nodes/SoIndexedFaceSet.h>
++#include <Inventor/nodes/SoIndexedLineSet.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider1.h>
++#include <assert.h>
++
++// *************************************************************************
++
++/*!
++ \class SoGuiSlider1 Inventor/@Gui@/nodes/SoGuiSlider1.h
++ \brief A GUI component for a 1-dimensional slider.
++
++ The SoGuiSlider1 node is for creating 2D user interfaces with
++ sliders.
++
++ fields:
++ min
++ max
++ value
++ orientation - not supported yet
++ size
++*/
++
++// *************************************************************************
++
++class Slider1 {
++public:
++ SoGuiSlider1 * kit;
++ SoFieldSensor * sizeSensor;
++ SoFieldSensor * valueSensor;
++ SoFieldSensor * minSensor;
++ SoFieldSensor * maxSensor;
++
++ SbBool grabbing;
++ float grabpos;
++ float grabval;
++ float graboffset;
++ float pickpos;
++ SoGuiPane * pane;
++
++ Slider1(void);
++ ~Slider1(void);
++
++ SbColor mincolor, maxcolor;
++
++ // sensors callbacks
++ static void sizeChangeCB(void * closure, SoSensor * sensor);
++ static void valueChangeCB(void * closure, SoSensor * sensor);
++ static void minChangeCB(void * closure, SoSensor * sensor);
++ static void maxChangeCB(void * closure, SoSensor * sensor);
++};
++
++Slider1::Slider1(void)
++{
++ this->kit = NULL;
++ this->sizeSensor = NULL;
++ this->valueSensor = NULL;
++ this->minSensor = NULL;
++ this->maxSensor = NULL;
++ this->grabbing = FALSE;
++ this->pane = NULL;
++}
++
++#define DELETE_SENSOR(sensor) \
++ if ( (sensor) != NULL ) { \
++ (sensor)->detach(); \
++ delete (sensor); \
++ (sensor) = NULL; \
++ }
++
++Slider1::~Slider1(void)
++{
++ DELETE_SENSOR(this->sizeSensor);
++ DELETE_SENSOR(this->valueSensor);
++ DELETE_SENSOR(this->minSensor);
++ DELETE_SENSOR(this->maxSensor);
++ this->kit = NULL;
++}
++
++#undef DELETE_SENSOR
++
++void
++Slider1::sizeChangeCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Slider1 * internals = (Slider1 *) closure;
++ assert(internals->kit);
++ internals->kit->sizeUpdate();
++}
++
++void
++Slider1::valueChangeCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Slider1 * internals = (Slider1 *) closure;
++ assert(internals->kit);
++ internals->kit->valueUpdate();
++}
++
++void
++Slider1::minChangeCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Slider1 * internals = (Slider1 *) closure;
++ assert(internals->kit);
++ internals->kit->minUpdate();
++}
++
++void
++Slider1::maxChangeCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Slider1 * internals = (Slider1 *) closure;
++ assert(internals->kit);
++ internals->kit->maxUpdate();
++}
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Slider1 *) obj->internals)
++
++void
++SoGuiSlider1::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiSlider1, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiSlider1);
++
++SoGuiSlider1::SoGuiSlider1(void)
++{
++ this->internals = (void *) new Slider1;
++ PRIVATE(this)->kit = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiSlider1);
++
++ SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++ SO_KIT_ADD_FIELD(orientation, (SoGuiSlider1::X));
++ SO_KIT_ADD_FIELD(min, (0.0f));
++ SO_KIT_ADD_FIELD(max, (1.0f));
++ SO_KIT_ADD_FIELD(value, (0.0f));
++ SO_KIT_ADD_FIELD(alwaysHook, (TRUE));
++
++ SO_KIT_DEFINE_ENUM_VALUE(Orientation, X);
++ SO_KIT_DEFINE_ENUM_VALUE(Orientation, Y);
++
++ SO_KIT_SET_SF_ENUM_TYPE(orientation, Orientation);
++
++ SO_KIT_ADD_CATALOG_ENTRY(knobLightLineSet, SoIndexedLineSet, FALSE, knobGeometry, "", FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(knobLightMaterial, SoMaterial, FALSE, knobGeometry, knobLightLineSet, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(knobShadeLineSet, SoIndexedLineSet, FALSE, knobGeometry, knobLightMaterial, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(knobShadeMaterial, SoMaterial, FALSE, knobGeometry, knobShadeLineSet, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(knobFaceSet, SoIndexedFaceSet, FALSE, knobGeometry, knobShadeMaterial, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(knobMaterial, SoMaterial, FALSE, knobGeometry, knobFaceSet, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(knobCoords, SoCoordinate3, FALSE, knobGeometry, knobMaterial, FALSE);
++
++ SO_KIT_ADD_CATALOG_ENTRY(knobGeometry, SoSeparator, FALSE, topSeparator, "", FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceFaceSet, SoIndexedFaceSet, FALSE, surfaceGeometry, "", FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceCoords, SoCoordinate3, FALSE, surfaceGeometry, surfaceFaceSet, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceTexCoords, SoTextureCoordinate2, FALSE, surfaceGeometry, surfaceCoords, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceTexture, SoTexture2, TRUE, surfaceGeometry, surfaceTexCoords, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceMaterial, SoMaterial, TRUE, surfaceGeometry, surfaceTexture, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceGeometry, SoSeparator, FALSE, topSeparator, knobGeometry, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ static float surfacetexturecoordinates[][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 0.0f}, {0.0f, 0.0f} };
++ SoTextureCoordinate2 * surfacetexcoords = SO_GET_ANY_PART(this, "surfaceTexCoords", SoTextureCoordinate2);
++ assert(surfacetexcoords);
++ surfacetexcoords->point.setValues(0, 4, surfacetexturecoordinates);
++
++ static int32_t surfaceindices[] = { 0, 1, 2, -1, 0, 2, 3, -1 };
++ SoIndexedFaceSet * surfacefaceset = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++ assert(surfacefaceset);
++ surfacefaceset->textureCoordIndex.setValues(0, 8, surfaceindices);
++ surfacefaceset->coordIndex.setValues(0, 8, surfaceindices);
++
++ static int32_t knobindices[] = {
++ 0, 1, 2, -1, 0, 2, 3, -1,
++ 4, 5, 6, -1, 4, 6, 7, -1,
++ 8, 2, 5, -1, 8, 5, 9, -1,
++ 3, 11, 10, -1, 3, 10, 4, -1
++ };
++ SoIndexedFaceSet * knobfaceset = SO_GET_ANY_PART(this, "knobFaceSet", SoIndexedFaceSet);
++ assert(knobfaceset);
++ knobfaceset->coordIndex.setValues(0, sizeof(knobindices)/sizeof(knobindices[0]), knobindices);
++
++ this->sizeUpdate();
++
++ SoMaterial * knobmaterial = SO_GET_ANY_PART(this, "knobMaterial", SoMaterial);
++ assert(knobmaterial);
++ knobmaterial->ambientColor.setValue(0.6f, 0.6f, 0.6f);
++ knobmaterial->diffuseColor.setValue(0.6f, 0.6f, 0.6f);
++ knobmaterial->emissiveColor.setValue(0.6f, 0.6f, 0.6f);
++
++ SoMaterial * knoblightmaterial = SO_GET_ANY_PART(this, "knobLightMaterial", SoMaterial);
++ assert(knoblightmaterial);
++ knoblightmaterial->ambientColor.setValue(0.75f, 0.75f, 0.75f);
++ knoblightmaterial->diffuseColor.setValue(0.75f, 0.75f, 0.75f);
++ knoblightmaterial->emissiveColor.setValue(0.75f, 0.75f, 0.75f);
++
++ SoMaterial * knobshadowmaterial = SO_GET_ANY_PART(this, "knobShadeMaterial", SoMaterial);
++ assert(knobshadowmaterial);
++ knobshadowmaterial->ambientColor.setValue(0.4f, 0.4f, 0.4f);
++ knobshadowmaterial->diffuseColor.setValue(0.4f, 0.4f, 0.4f);
++ knobshadowmaterial->emissiveColor.setValue(0.4f, 0.4f, 0.4f);
++
++ // FIXME: move these to correct coordinates
++ SoIndexedLineSet * lightlineset = SO_GET_ANY_PART(this, "knobLightLineSet", SoIndexedLineSet);
++ assert(lightlineset);
++ static int32_t lightindices[] = { 16, 17, 18, -1, 12, 15, 14, -1 };
++ lightlineset->coordIndex.setValues(0, sizeof(lightindices) / sizeof(lightindices[0]), lightindices);
++
++ SoIndexedLineSet * shadelineset = SO_GET_ANY_PART(this, "knobShadeLineSet", SoIndexedLineSet);
++ assert(shadelineset);
++ static int32_t shadeindices[] = { 12, 13, 14, -1, 16, 19, 18, -1 };
++ shadelineset->coordIndex.setValues(0, sizeof(shadeindices) / sizeof(shadeindices[0]), shadeindices);
++
++ // set up sensors
++ PRIVATE(this)->sizeSensor = new SoFieldSensor(Slider1::sizeChangeCB, PRIVATE(this));
++ PRIVATE(this)->sizeSensor->attach(&(this->size));
++ PRIVATE(this)->valueSensor = new SoFieldSensor(Slider1::valueChangeCB, PRIVATE(this));
++ PRIVATE(this)->valueSensor->attach(&(this->value));
++ PRIVATE(this)->minSensor = new SoFieldSensor(Slider1::minChangeCB, PRIVATE(this));
++ PRIVATE(this)->minSensor->attach(&(this->min));
++ PRIVATE(this)->maxSensor = new SoFieldSensor(Slider1::maxChangeCB, PRIVATE(this));
++ PRIVATE(this)->maxSensor->attach(&(this->max));
++}
++
++SoGuiSlider1::~SoGuiSlider1(void)
++{
++ Slider1 * obj = PRIVATE(this);
++ delete obj;
++ this->internals = NULL;
++}
++
++void
++SoGuiSlider1::setSurfaceColor(const SbColor & valuearg)
++{
++ // FIXME: use Material or basecolor instead of texture
++ this->setSurfaceColor(valuearg, valuearg);
++#if 0
++ PRIVATE(this)->mincolor = valuearg;
++ PRIVATE(this)->maxcolor = valuearg;
++ this->setPart("surfaceTexture", NULL);
++#endif
++}
++
++void
++SoGuiSlider1::setSurfaceColor(const SbColor & minvalue, const SbColor & maxvalue)
++{
++ PRIVATE(this)->mincolor = minvalue;
++ PRIVATE(this)->maxcolor = maxvalue;
++
++ this->setPart("surfaceMaterial", NULL);
++ SoTexture2 * texturenode = SO_GET_ANY_PART(this, "surfaceTexture", SoTexture2);
++ assert(texturenode);
++
++ texturenode->image.setValue(SbVec2s(256, 1), 3, NULL);
++ texturenode->model.setValue(SoTexture2::DECAL);
++
++ SbVec2s sizeval;
++ int nc;
++ unsigned char * buf = texturenode->image.startEditing(sizeval, nc);
++ float rmin = minvalue[0];
++ float gmin = minvalue[1];
++ float bmin = minvalue[2];
++ float rmax = maxvalue[0];
++ float gmax = maxvalue[1];
++ float bmax = maxvalue[2];
++ for ( int x = 0; x < sizeval[0]; x += 1 ) {
++ buf[x*nc+0] = (unsigned char) ((rmin + ((float) x / (float) (sizeval[0]-1)) * (rmax - rmin)) * 255.0f);
++ buf[x*nc+1] = (unsigned char) ((gmin + ((float) x / (float) (sizeval[0]-1)) * (gmax - gmin)) * 255.0f);
++ buf[x*nc+2] = (unsigned char) ((bmin + ((float) x / (float) (sizeval[0]-1)) * (bmax - bmin)) * 255.0f);
++ for ( int y = 1; y < sizeval[1]; y += 1 ) {
++ buf[(y*sizeval[0]+x)*nc+0] = buf[x*nc+0];
++ buf[(y*sizeval[0]+x)*nc+1] = buf[x*nc+1];
++ buf[(y*sizeval[0]+x)*nc+2] = buf[x*nc+2];
++ }
++ }
++ texturenode->image.finishEditing();
++}
++
++SbColor
++SoGuiSlider1::getValueAsColor(void) const
++{
++ // FIXME: support custom textures
++ float val = this->value.getValue();
++ float minval = this->min.getValue();
++ float maxval = this->max.getValue();
++ float factor = (maxval - minval) / (val - minval);
++ float r = So at Gui@Clamp(PRIVATE(this)->mincolor[0] + (PRIVATE(this)->maxcolor[0] - PRIVATE(this)->mincolor[0]) * factor, 0.0f, 1.0f);
++ float g = So at Gui@Clamp(PRIVATE(this)->mincolor[1] + (PRIVATE(this)->maxcolor[1] - PRIVATE(this)->mincolor[1]) * factor, 0.0f, 1.0f);
++ float b = So at Gui@Clamp(PRIVATE(this)->mincolor[2] + (PRIVATE(this)->maxcolor[2] - PRIVATE(this)->mincolor[2]) * factor, 0.0f, 1.0f);
++ return SbColor(r, g, b);
++}
++
++void
++SoGuiSlider1::sizeUpdate(void)
++{
++ SbVec3f sizeval = this->size.getValue();
++ if ( sizeval[0] != 0.0f && sizeval[1] != 0.0f ) {
++ float coordinates[][3] = { {0.0f, 0.0f, 0.0f}, {sizeval[0], 0.0f, 0.0f}, {sizeval[0], sizeval[1], 0.0f}, {0.0f, sizeval[1], 0.0f} };
++ SoCoordinate3 * coords = SO_GET_ANY_PART(this, "surfaceCoords", SoCoordinate3);
++ assert(coords);
++ coords->point.setValues(0, sizeof(coordinates) / sizeof(coordinates[0]), coordinates);
++ this->valueUpdate();
++ }
++}
++
++void
++SoGuiSlider1::valueUpdate(void)
++{
++ SbVec3f sizeval = this->size.getValue();
++ float val = this->value.getValue();
++ float minval = this->min.getValue();
++ float maxval = this->max.getValue();
++ if ( minval < maxval ) {
++ if ( val < minval ) {
++ this->value.setValue(minval);
++ val = minval;
++ } else if ( val > maxval ) {
++ this->value.setValue(maxval);
++ val = maxval;
++ }
++ } else {
++ // we also support inverse sliders where min > max
++ if ( val > minval ) {
++ this->value.setValue(minval);
++ val = minval;
++ } else if ( val < maxval ) {
++ this->value.setValue(maxval);
++ val = maxval;
++ }
++ }
++ // store previous height & value to avoid redundant updates
++ float voff = (float) floor(((val - minval) / (maxval - minval)) * sizeval[0]);
++ float knobcoordinates[][3] = {
++ // faces
++ {-7.0f+voff, -4.0f, 0.0f}, {8.0f+voff, -4.0f, 0.0f}, {8.0f+voff, -1.0f, 0.0f}, {-7.0f+voff, -1.0f, 0.0f},
++ {-7.0f+voff, sizeval[1]+1.0f, 0.0f}, {8.0f+voff, sizeval[1]+1.0f, 0.0f}, {8.0f+voff, sizeval[1]+4.0f, 0.0f}, {-7.0f+voff, sizeval[1]+4.0f, 0.0f},
++ {3.0f+voff, -1.0f, 0.0f}, {3.0f+voff, sizeval[1]+1.0f, 0.0f}, {-2.0f+voff, sizeval[1]+1.0f, 0.0f}, {-2.0f+voff, -1.0f, 0.0f},
++ // outside lines
++ // also used in handleEvent() so don't change their significance based on index
++ {-8.0f+voff, -5.0f, 0.0f}, {8.0f+voff, -5.0f, 0.0f}, {8.0f+voff, sizeval[1]+4.0f, 0.0f}, {-8.0f+voff, sizeval[1]+4.0f, 0.0f},
++ // inside lines
++ {-2.0f+voff, -1.0f, 0.0f}, {2.0f+voff, -1.0f, 0.0f}, {2.0f+voff, sizeval[1], 0.0f}, {-2.0f+voff, sizeval[1], 0.0f}
++ };
++ SoCoordinate3 * knobcoords = SO_GET_ANY_PART(this, "knobCoords", SoCoordinate3);
++ assert(knobcoords);
++ knobcoords->point.setValues(0, sizeof(knobcoordinates) / sizeof(knobcoordinates[0]), knobcoordinates);
++}
++
++void
++SoGuiSlider1::minUpdate(void)
++{
++ float minval = this->min.getValue();
++ float maxval = this->max.getValue();
++ float val = this->value.getValue();
++ if ( minval < maxval ) {
++ if ( val < minval ) this->value.setValue(minval);
++ } else {
++ if ( val > minval ) this->value.setValue(minval);
++ }
++}
++
++void
++SoGuiSlider1::maxUpdate(void)
++{
++ float minval = this->min.getValue();
++ float maxval = this->max.getValue();
++ float val = this->value.getValue();
++ if ( minval < maxval ) {
++ if ( val > maxval ) this->value.setValue(maxval);
++ } else {
++ if ( val < maxval ) this->value.setValue(maxval);
++ }
++}
++
++void
++SoGuiSlider1::handleEvent(SoHandleEventAction * action)
++{
++ if ( action->isHandled() ) return;
++ const SoEvent * event = action->getEvent();
++
++ if ( PRIVATE(this)->grabbing ) { // click-and-drag
++ if ( event->isOfType(SoLocation2Event::getClassTypeId()) ) {
++ assert(PRIVATE(this)->pane != NULL);
++ // although the return value is discarded, we need to make this call to make
++ // sure the raypick action is run over the scene graph so the pane can return
++ // a useful value...
++ action->getPickedPoint();
++ SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++ if ( raypos[0] != -1.0f ) {
++ float imagpos = raypos[0] + PRIVATE(this)->graboffset;
++ float minval = this->min.getValue();
++ float maxval = this->max.getValue();
++ float imagval;
++ if ( minval < maxval ) imagval = So at Gui@Clamp(imagpos / this->size.getValue()[0], minval, maxval);
++ else imagval = So at Gui@Clamp(imagpos / this->size.getValue()[0], maxval, minval);
++ this->value.setValue(imagval);
++ }
++ action->setHandled();
++ }
++ else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++ SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++ if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++ (mbevent->getState() == SoButtonEvent::UP) ) {
++ PRIVATE(this)->grabbing = FALSE;
++ PRIVATE(this)->pane = NULL;
++ action->setHandled();
++ }
++ }
++ }
++ else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++ SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++ if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++ (mbevent->getState() == SoButtonEvent::DOWN) ) {
++ action->setPickRadius(0);
++ const SoPickedPointList & pplist = action->getPickedPointList();
++ if ( pplist.getLength() > 0 ) {
++ int i;
++ for ( i = 0; i < pplist.getLength(); i++ ) {
++ if ( action->isHandled() ) break;
++ const SoPickedPoint * pp = pplist[i];
++ const SoPath * path = pp->getPath();
++ SoNode * node = ((SoFullPath *) path)->getTail();
++ if ( node == ((SoNode *) SO_GET_ANY_PART(this, "knobFaceSet", SoIndexedFaceSet)) ) {
++ SbVec3f point = pp->getObjectPoint();
++ SbVec3f sizeval = this->size.getValue();
++ SoCoordinate3 * knobcoords = SO_GET_ANY_PART(this, "knobCoords", SoCoordinate3);
++ assert(knobcoords);
++ SbVec3f knobmin = knobcoords->point[12];
++ SbVec3f knobmax = knobcoords->point[14];
++ if ( point[0] >= knobmin[0] && point[0] <= knobmax[0] &&
++ point[1] >= knobmin[1] && point[1] <= knobmax[1] ) {
++ PRIVATE(this)->grabbing = TRUE;
++ action->setHandled();
++
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ int i = path->getLength() - 1;
++ SoNode * node = NULL;
++ for ( ; i >= 0; i-- ) {
++ node = path->getNode(i);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++ node = NULL;
++ }
++ assert(node != NULL);
++ PRIVATE(this)->pane = (SoGuiPane *) node;
++ PRIVATE(this)->grabval = this->value.getValue();
++ PRIVATE(this)->pickpos = point[0];
++
++ SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++ PRIVATE(this)->grabpos = raypos[0];
++ float realval = ((this->value.getValue() - this->min.getValue()) /
++ (this->max.getValue() - this->min.getValue())) * this->size.getValue()[0];
++ PRIVATE(this)->graboffset = realval - raypos[0];
++ }
++ }
++ }
++ for ( i = 0; i < pplist.getLength(); i++ ) {
++ if ( action->isHandled() ) break;
++ const SoPickedPoint * pp = pplist[i];
++ const SoPath * path = pp->getPath();
++ SoNode * node = ((SoFullPath *) path)->getTail();
++ if ( node == ((SoNode *) SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet)) ) {
++ SbVec3f point = pp->getObjectPoint();
++ SbVec3f sizeval = this->size.getValue();
++ this->value = this->min.getValue() + ((point[0] / sizeval[0]) * (this->max.getValue() - this->min.getValue()));
++ action->setHandled();
++ if ( this->alwaysHook.getValue() ) {
++ PRIVATE(this)->grabbing = TRUE;
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ int i = path->getLength() - 1;
++ SoNode * node = NULL;
++ for ( ; i >= 0; i-- ) {
++ node = path->getNode(i);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++ node = NULL;
++ }
++ assert(node != NULL);
++ PRIVATE(this)->pane = (SoGuiPane *) node;
++ PRIVATE(this)->grabval = this->value.getValue();
++ PRIVATE(this)->pickpos = point[0];
++ SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++ PRIVATE(this)->grabpos = raypos[0];
++ float realval = ((this->value.getValue() - this->min.getValue()) /
++ (this->max.getValue() - this->min.getValue())) * this->size.getValue()[0];
++ PRIVATE(this)->graboffset = realval - raypos[0];
++ }
++ }
++ }
++ }
++ }
++ }
++}
++
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider1.h.in
+@@ -0,0 +1,108 @@
++#ifndef COIN_SOGUISLIDER1_H
++#define COIN_SOGUISLIDER1_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFFloat.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiSlider1 : public SoBaseKit {
++ typedef SoBaseKit inherited;
++
++ SO_KIT_HEADER(SoGuiSlider1);
++
++ SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceGeometry);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobGeometry);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobMaterial);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobCoords);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobFaceSet);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobShadeMaterial);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobShadeLineSet);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobLightMaterial);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobLightLineSet);
++
++public:
++ static void initClass(void);
++
++ SoGuiSlider1(void);
++
++ enum Orientation {
++ X, Y
++ };
++
++ SoSFVec3f size;
++ SoSFEnum orientation; // not implemented
++
++ SoSFFloat min;
++ SoSFFloat max;
++ SoSFFloat value;
++
++ SoSFBool alwaysHook;
++
++ virtual void handleEvent(SoHandleEventAction * action);
++
++ virtual void setSurfaceColor(const SbColor & value);
++ virtual void setSurfaceColor(const SbColor & minvalue, const SbColor & maxvalue);
++ virtual SbColor getValueAsColor(void) const;
++
++ // FIXME: move to something non-public
++ void sizeUpdate(void);
++ void valueUpdate(void);
++ void minUpdate(void);
++ void maxUpdate(void);
++
++protected:
++ virtual ~SoGuiSlider1(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUISLIDER1_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider2.cpp.in
+@@ -0,0 +1,483 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <math.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/misc/SoState.h>
++#include <Inventor/elements/SoLazyElement.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoLists.h>
++
++#include <Inventor/SbColor.h>
++
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoMaterial.h>
++#include <Inventor/nodes/SoTexture2.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoTextureCoordinate2.h>
++#include <Inventor/nodes/SoIndexedFaceSet.h>
++#include <Inventor/nodes/SoTranslation.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/SoAny.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiSlider2.h>
++#include <assert.h>
++
++// *************************************************************************
++
++/*!
++ \class SoGuiSlider2 Inventor/@Gui@/nodes/SoGuiSlider2.h
++ \brief A GUI component for a 2-dimensional slider.
++
++ The SoGuiSlider2 node is for creating 2D user interfaces with
++ sliders.
++
++*/
++
++// *************************************************************************
++
++class Slider2 {
++public:
++ SoGuiSlider2 * kit;
++ SoFieldSensor * sizeSensor;
++ SoFieldSensor * valueSensor;
++
++ Slider2(void);
++ ~Slider2(void);
++
++ // sensors callbacks
++ static void sizeChangeCB(void * closure, SoSensor * sensor);
++ static void valueChangeCB(void * closure, SoSensor * sensor);
++
++ static const char * knobgeometry[];
++ SoTranslation * knobtranslation;
++
++ SoGuiPane * pane;
++
++ SbBool grabbing;
++
++ SbVec2f graboffset;
++ SbVec2f grabval;
++
++ SbVec2f pickpos;
++ SbVec2f grabpos;
++};
++
++Slider2::Slider2(void)
++{
++ this->kit = NULL;
++ this->sizeSensor = NULL;
++ this->valueSensor = NULL;
++ this->grabbing = FALSE;
++ this->pane = NULL;
++}
++
++Slider2::~Slider2(void)
++{
++ if ( this->sizeSensor ) {
++ this->sizeSensor->detach();
++ delete this->sizeSensor;
++ this->sizeSensor = NULL;
++ }
++ if ( this->valueSensor ) {
++ this->valueSensor->detach();
++ delete this->valueSensor;
++ this->valueSensor = NULL;
++ }
++ this->kit = NULL;
++}
++
++void
++Slider2::sizeChangeCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Slider2 * internals = (Slider2 *) closure;
++ assert(internals->kit);
++ internals->kit->sizeUpdate();
++}
++
++void
++Slider2::valueChangeCB(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ Slider2 * internals = (Slider2 *) closure;
++ assert(internals->kit);
++ internals->kit->valueUpdate();
++}
++
++const char *
++Slider2::knobgeometry[] =
++{
++ "# Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " DEF knobtranslation Translation {}",
++ " Coordinate3 {",
++ " point [",
++ // inner loop
++ " 0 0 0,",
++ " 1 0 0,",
++ " 1 1 0,",
++ " 0 1 0,",
++ // middle inner
++ " -1 -1 0,",
++ " 2 -1 0,",
++ " 2 2 0,",
++ " -1 2 0,",
++ // middle outer
++ " -2 -2 0,",
++ " 3 -2 0,",
++ " 3 3 0,",
++ " -2 3 0,",
++ // outer loop
++ " -3 -3 0,",
++ " 4 -3 0,",
++ " 4 4 0,",
++ " -3 4 0",
++ " ]",
++ " }",
++ " Material {",
++ " diffuseColor 0.7 0.7 0.7",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [",
++ // middle
++ " 8 9 5 8 -1",
++ " 8 5 4 8 -1",
++ " 9 10 6 9 -1",
++ " 9 6 5 9 -1",
++ " 10 11 7 10 -1",
++ " 10 7 6 10 -1",
++ " 11 8 4 11 -1",
++ " 11 4 7 11 -1",
++ " ]",
++ " }",
++ " Material {",
++ " diffuseColor 0.5 0.5 0.5",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [",
++ // inner shade
++ " 6 7 3 6 -1",
++ " 6 3 2 6 -1",
++ " 7 4 0 7 -1",
++ " 7 0 3 7 -1",
++ // outer shade
++ " 12 13 9 12 -1",
++ " 12 9 8 12 -1",
++ " 13 14 10 13 -1",
++ " 13 10 9 13 -1",
++ " ]",
++ " }",
++ " Material {",
++ " diffuseColor 0.9 0.9 0.9",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [",
++ // inner light
++ " 4 5 1 4 -1",
++ " 4 1 0 4 -1",
++ " 5 6 2 5 -1",
++ " 5 2 1 5 -1",
++ // outer light
++ " 14 15 11 14 -1",
++ " 14 11 10 14 -1",
++ " 15 12 8 15 -1",
++ " 15 8 11 15 -1",
++ " ]",
++ " }",
++ "}",
++ NULL
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((Slider2 *) obj->internals)
++
++void
++SoGuiSlider2::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiSlider2, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiSlider2);
++
++SoGuiSlider2::SoGuiSlider2(void)
++{
++ this->internals = (void *) new Slider2;
++ PRIVATE(this)->kit = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiSlider2);
++
++ SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++
++ SO_KIT_ADD_FIELD(min, (SbVec2f(0.0f, 0.0f)));
++ SO_KIT_ADD_FIELD(max, (SbVec2f(1.0f, 1.0f)));
++ SO_KIT_ADD_FIELD(value, (SbVec2f(0.0f, 0.0f)));
++
++ SO_KIT_ADD_FIELD(alwaysHook, (TRUE));
++
++ SO_KIT_ADD_CATALOG_ENTRY(knobGeometry, SoSeparator, FALSE, topSeparator, "", TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceFaceSet, SoIndexedFaceSet, FALSE, surfaceGeometry, "", FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceCoords, SoCoordinate3, FALSE, surfaceGeometry, surfaceFaceSet, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceTexCoords, SoTextureCoordinate2, FALSE, surfaceGeometry, surfaceCoords, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceTexture, SoTexture2, TRUE, surfaceGeometry, surfaceTexCoords, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceMaterial, SoMaterial, TRUE, surfaceGeometry, surfaceTexture, TRUE);
++ SO_KIT_ADD_CATALOG_ENTRY(surfaceGeometry, SoSeparator, FALSE, topSeparator, knobGeometry, FALSE);
++ SO_KIT_ADD_CATALOG_ENTRY(topSeparator, SoSeparator, FALSE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ static float surfacetexturecoordinates[][2] = { {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} };
++ SoTextureCoordinate2 * surfacetexcoords = SO_GET_ANY_PART(this, "surfaceTexCoords", SoTextureCoordinate2);
++ assert(surfacetexcoords);
++ surfacetexcoords->point.setValues(0, 4, surfacetexturecoordinates);
++
++ static int32_t surfaceindices[] = { 0, 1, 2, -1, 0, 2, 3, -1 };
++ SoIndexedFaceSet * surfacefaceset = SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet);
++ assert(surfacefaceset);
++ surfacefaceset->textureCoordIndex.setValues(0, 8, surfaceindices);
++ surfacefaceset->coordIndex.setValues(0, 8, surfaceindices);
++
++ SoNode * knob = (SoSeparator *) SoAny::loadSceneGraph(Slider2::knobgeometry);
++ assert(knob != NULL && knob->isOfType(SoSeparator::getClassTypeId()));
++ this->setPart("knobGeometry", knob);
++
++ SoNode * node = SoAny::scanSceneForName(knob, "knobtranslation", FALSE);
++ assert(node != NULL && node->isOfType(SoTranslation::getClassTypeId()));
++ PRIVATE(this)->knobtranslation = (SoTranslation *) node;
++
++ this->sizeUpdate();
++
++ // set up sensors
++ PRIVATE(this)->sizeSensor = new SoFieldSensor(Slider2::sizeChangeCB, PRIVATE(this));
++ PRIVATE(this)->sizeSensor->attach(&(this->size));
++ PRIVATE(this)->valueSensor = new SoFieldSensor(Slider2::valueChangeCB, PRIVATE(this));
++ PRIVATE(this)->valueSensor->attach(&(this->value));
++}
++
++SoGuiSlider2::~SoGuiSlider2(void)
++{
++ Slider2 * obj = PRIVATE(this);
++ delete obj;
++ this->internals = NULL;
++}
++
++void
++SoGuiSlider2::sizeUpdate(void)
++{
++ SbVec3f sizeval = this->size.getValue();
++ if ( sizeval[0] != 0.0f && sizeval[1] != 0.0f ) {
++ float coordinates[][3] = { {0.0f, 0.0f, 0.0f}, {sizeval[0], 0.0f, 0.0f}, {sizeval[0], sizeval[1], 0.0f}, {0.0f, sizeval[1], 0.0f} };
++ SoCoordinate3 * coords = SO_GET_ANY_PART(this, "surfaceCoords", SoCoordinate3);
++ assert(coords);
++ coords->point.setValues(0, sizeof(coordinates) / sizeof(coordinates[0]), coordinates);
++ this->valueUpdate();
++ }
++}
++
++void
++SoGuiSlider2::valueUpdate(void)
++{
++ assert(PRIVATE(this)->knobtranslation != NULL);
++ SbVec2f val = this->value.getValue();
++ SbVec2f minval = this->min.getValue();
++ SbVec2f maxval = this->max.getValue();
++ SbVec3f sizeval = this->size.getValue();
++
++ SbVec2f nval;
++ nval[0] = (val[0] - minval[0]) / (maxval[0] - minval[0]);
++ nval[1] = (val[1] - minval[1]) / (maxval[1] - minval[1]);
++
++ SbVec3f translation;
++ translation[0] = nval[0] * sizeval[0];
++ translation[1] = nval[1] * sizeval[1];
++ translation[2] = 0.0f;
++
++ PRIVATE(this)->knobtranslation->translation.setValue(translation);
++}
++
++void
++SoGuiSlider2::handleEvent(SoHandleEventAction * action)
++{
++ if ( action->isHandled() ) return;
++
++ const SoEvent * event = action->getEvent();
++
++ if ( PRIVATE(this)->grabbing ) { // click-and-drag
++ if ( event->isOfType(SoLocation2Event::getClassTypeId()) ) {
++ assert(PRIVATE(this)->pane != NULL);
++
++ // although the return value is discarded, we need to make this call to make
++ // sure the raypick action is run over the scene graph so the pane can return
++ // a useful value...
++ action->getPickedPoint();
++
++ SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++ if ( raypos[0] != -1.0f ) {
++ SbVec2f imagpos = SbVec2f(raypos[0], raypos[1]) + PRIVATE(this)->graboffset;
++ SbVec2f minval = this->min.getValue();
++ SbVec2f maxval = this->max.getValue();
++ SbVec3f sizeval = this->size.getValue();
++ SbVec2f imagval;
++ imagval[0] = minval[0] + (maxval[0] - minval[0]) * So at Gui@Clamp(imagpos[0] / sizeval[0], 0.0f, 1.0f);
++ imagval[1] = minval[1] + (maxval[1] - minval[1]) * So at Gui@Clamp(imagpos[1] / sizeval[1], 0.0f, 1.0f);
++ this->value.setValue(imagval);
++ }
++ action->setHandled();
++ }
++ else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++ SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++ if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++ (mbevent->getState() == SoButtonEvent::UP) ) {
++ PRIVATE(this)->grabbing = FALSE;
++ PRIVATE(this)->pane = NULL;
++ action->setHandled();
++ }
++ }
++ }
++ else if ( event->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++ SoMouseButtonEvent * mbevent = (SoMouseButtonEvent *) event;
++ if ( (mbevent->getButton() == SoMouseButtonEvent::BUTTON1) &&
++ (mbevent->getState() == SoButtonEvent::DOWN) ) {
++ action->setPickRadius(0);
++ const SoPickedPointList & pplist = action->getPickedPointList();
++ if ( pplist.getLength() > 0 ) {
++ int i;
++ for ( i = 0; i < pplist.getLength(); i++ ) {
++ if ( action->isHandled() ) break;
++ const SoPickedPoint * pp = pplist[i];
++ const SoFullPath * path = (const SoFullPath *) pp->getPath();
++ SoNode * node = NULL;
++ SoNode * knob = SO_GET_ANY_PART(this, "knobGeometry", SoSeparator);
++ int j = path->getLength() - 1;
++ for ( ; j >= 0; j-- ) {
++ SoNode * node = path->getNode(j);
++ if ( node == knob ) break;
++ node = NULL;
++ }
++
++ if ( node != NULL ) {
++ PRIVATE(this)->grabbing = TRUE;
++ action->setHandled();
++
++ SbVec3f point = pp->getObjectPoint();
++ SbVec2f sizeval = SbVec2f(this->size.getValue()[0], this->size.getValue()[1]);
++
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ int i = path->getLength() - 1;
++ SoNode * node = NULL;
++ for ( ; i >= 0; i-- ) {
++ node = path->getNode(i);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++ node = NULL;
++ }
++ assert(node != NULL);
++ PRIVATE(this)->pane = (SoGuiPane *) node;
++ PRIVATE(this)->grabval = this->value.getValue();
++ PRIVATE(this)->pickpos = SbVec2f(point[0], point[1]);
++
++ SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++ PRIVATE(this)->grabpos = raypos;
++ SbVec2f upper = this->value.getValue() - this->min.getValue();
++ SbVec2f lower = this->max.getValue() - this->min.getValue();
++
++ SbVec2f realval;
++ realval[0] = (upper[0] / lower[0]) * sizeval[0];
++ realval[1] = (upper[1] / lower[1]) * sizeval[1];
++ PRIVATE(this)->graboffset = realval - raypos;
++ }
++ }
++ for ( i = 0; i < pplist.getLength(); i++ ) {
++ if ( action->isHandled() ) break;
++ const SoPickedPoint * pp = pplist[i];
++ const SoPath * path = pp->getPath();
++ SoNode * node = ((SoFullPath *) path)->getTail();
++ if ( node == ((SoNode *) SO_GET_ANY_PART(this, "surfaceFaceSet", SoIndexedFaceSet)) ) {
++ SbVec3f point = pp->getObjectPoint();
++ SbVec3f sizeval = this->size.getValue();
++ SbVec2f minval = this->min.getValue();
++ SbVec2f maxval = this->max.getValue();
++ SbVec2f val;
++ val[0] = minval[0] + (point[0] / sizeval[0]) * (maxval[0] - minval[0]);
++ val[1] = minval[1] + (point[1] / sizeval[1]) * (maxval[1] - minval[1]);
++ this->value.setValue(val);
++ action->setHandled();
++ if ( this->alwaysHook.getValue() ) {
++ PRIVATE(this)->grabbing = TRUE;
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ SoNode * node = NULL;
++ int j = path->getLength() - 1;
++ for ( ; j >= 0; j-- ) {
++ node = path->getNode(j);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) break;
++ node = NULL;
++ }
++ assert(node != NULL);
++ PRIVATE(this)->pane = (SoGuiPane *) node;
++ PRIVATE(this)->grabval = this->value.getValue();
++ PRIVATE(this)->pickpos = SbVec2f(point[0], point[1]);
++
++ SbVec2f raypos = PRIVATE(this)->pane->getRayPickIntersectionPoint();
++ PRIVATE(this)->grabpos = raypos;
++ SbVec2f upper = this->value.getValue() - this->min.getValue();
++ SbVec2f lower = this->max.getValue() - this->min.getValue();
++ SbVec2f sizeval = SbVec2f(this->size.getValue()[0], this->size.getValue()[1]);
++
++ SbVec2f realval;
++ realval[0] = (upper[0] / lower[0]) * sizeval[0];
++ realval[1] = (upper[1] / lower[1]) * sizeval[1];
++ PRIVATE(this)->graboffset = realval - raypos;
++ }
++ }
++ }
++ }
++ }
++ }
++}
++
++#undef PRIVATE
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Slider2.h.in
+@@ -0,0 +1,88 @@
++#ifndef COIN_SOGUISLIDER2_H
++#define COIN_SOGUISLIDER2_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFVec2f.h>
++#include <Inventor/fields/SoSFVec3f.h>
++
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiSlider2 : public SoBaseKit {
++ typedef SoBaseKit inherited;
++
++ SO_KIT_HEADER(SoGuiSlider2);
++
++ SO_KIT_CATALOG_ENTRY_HEADER(topSeparator);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceGeometry);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexture);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceMaterial);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceTexCoords);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceCoords);
++ SO_KIT_CATALOG_ENTRY_HEADER(surfaceFaceSet);
++ SO_KIT_CATALOG_ENTRY_HEADER(knobGeometry);
++
++public:
++ static void initClass(void);
++
++ SoGuiSlider2(void);
++
++ SoSFVec3f size;
++
++ SoSFVec2f min;
++ SoSFVec2f max;
++ SoSFVec2f value;
++
++ SoSFBool alwaysHook;
++
++ virtual void handleEvent(SoHandleEventAction * action);
++
++ void sizeUpdate(void);
++ void valueUpdate(void);
++
++protected:
++ virtual ~SoGuiSlider2(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUISLIDER2_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ToggleButton.cpp.in
+@@ -0,0 +1,208 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/SoPickedPoint.h>
++
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/nodes/SoGuiToggleButton.h>
++#include <assert.h>
++
++// *************************************************************************
++
++class ToggleButton {
++public:
++ ToggleButton(void);
++
++ SoGuiToggleButton * api;
++
++ SoCoordinate3 * coords;
++ SoNode * faceset;
++ SoFieldSensor * size_sensor;
++ static void size_updated_cb(void * closure, SoSensor * sensor);
++
++ static const char * scene[];
++};
++
++// *************************************************************************
++
++#define PRIVATE(obj) ((ToggleButton *)obj->internals)
++
++void
++SoGuiToggleButton::initClass(void)
++{
++ SO_KIT_INIT_CLASS(SoGuiToggleButton, SoBaseKit, "BaseKit");
++}
++
++SO_KIT_SOURCE(SoGuiToggleButton);
++
++SoGuiToggleButton::SoGuiToggleButton(void)
++{
++ this->internals = new ToggleButton;
++ PRIVATE(this)->api = this;
++
++ SO_KIT_CONSTRUCTOR(SoGuiToggleButton);
++
++ SO_KIT_ADD_FIELD(size, (SbVec3f(1.0f, 1.0f, 0.0f)));
++ SO_KIT_ADD_FIELD(on, (FALSE));
++
++ SO_KIT_ADD_CATALOG_ENTRY(root, SoSeparator, FALSE, this, "", FALSE);
++
++ SO_KIT_INIT_INSTANCE();
++
++ SoNode * scene = SoAny::loadSceneGraph(ToggleButton::scene);
++ assert(scene);
++ assert(scene->isOfType(SoSeparator::getClassTypeId()));
++ scene->ref();
++
++ PRIVATE(this)->coords = (SoCoordinate3 *) SoAny::scanSceneForName(scene, "coords");
++ assert(PRIVATE(this)->coords);
++ assert(PRIVATE(this)->coords->isOfType(SoCoordinate3::getClassTypeId()));
++ PRIVATE(this)->faceset = SoAny::scanSceneForName(scene, "faceset");
++ assert(PRIVATE(this)->faceset);
++
++ scene->unrefNoDelete();
++ this->setAnyPart("root", scene);
++
++ PRIVATE(this)->size_sensor = new SoFieldSensor(ToggleButton::size_updated_cb, PRIVATE(this));
++ PRIVATE(this)->size_sensor->attach(&(this->size));
++}
++
++
++SoGuiToggleButton::~SoGuiToggleButton(void)
++{
++ delete PRIVATE(this)->size_sensor;
++ ToggleButton * obj = PRIVATE(this);
++ delete obj;
++}
++
++void
++SoGuiToggleButton::handleEvent(SoHandleEventAction * action)
++{
++ const SoEvent * ev = action->getEvent();
++ if ( ev->isOfType(SoMouseButtonEvent::getClassTypeId()) ) {
++ SbBool hit = FALSE;
++ const SoPickedPointList & ppoints = action->getPickedPointList();
++ assert(PRIVATE(this)->faceset);
++ int i = 0;
++ for ( i = 0; !hit && i < ppoints.getLength(); i++ ) {
++ const SoPickedPoint * point = ppoints[i];
++ const SoFullPath * path = (const SoFullPath *) point->getPath();
++ assert(path);
++ SoNode * node = path->getTail();
++ if ( node == PRIVATE(this)->faceset ) hit = TRUE;
++ }
++ if ( hit ) {
++ const SoMouseButtonEvent * event = (SoMouseButtonEvent *) ev;
++ if ( event->getState() == SoButtonEvent::DOWN ) {
++ if ( this->on.getValue() ) {
++ this->on.setValue(FALSE);
++ } else {
++ this->on.setValue(TRUE);
++ }
++ action->setHandled();
++ }
++ }
++ }
++ if ( !action->isHandled() ) {
++ inherited::handleEvent(action);
++ }
++}
++
++#undef PRIVATE
++
++// *************************************************************************
++// ToggleButton
++// *************************************************************************
++
++#define PUBLIC(obj) (obj->api)
++
++const char *
++ToggleButton::scene[] =
++{
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " DEF coords Coordinate3 {",
++ " point [",
++ " 0 0 0,",
++ " 1 0 0,",
++ " 1 1 0,",
++ " 0 1 0",
++ " ]",
++ " }",
++ " DEF faceset IndexedFaceSet {",
++ " coordIndex [",
++ " 0 1 2 -1",
++ " 0 2 3 -1",
++ " ]",
++ " }",
++ "}",
++ NULL
++};
++
++ToggleButton::ToggleButton(void)
++{
++ this->api = NULL;
++ this->coords = NULL;
++ this->size_sensor = NULL;
++}
++
++void
++ToggleButton::size_updated_cb(void * closure, SoSensor * sensor)
++{
++ assert(closure);
++ ToggleButton * me = (ToggleButton *) closure;
++ assert(PUBLIC(me));
++ SbVec3f size = PUBLIC(me)->size.getValue();
++ assert(me->size_sensor);
++ me->size_sensor->detach();
++ assert(me->coords);
++ SbBool save = me->coords->point.enableNotify(FALSE);
++ me->coords->point.set1Value(0, SbVec3f(0.0f, 0.0f, 0.0f));
++ me->coords->point.set1Value(1, SbVec3f(size[0], 0.0f, 0.0f));
++ me->coords->point.set1Value(2, SbVec3f(size[0], size[1], 0.0f));
++ me->coords->point.set1Value(3, SbVec3f(0.0f, size[1], 0.0f));
++ me->coords->enableNotify(save);
++ if ( save ) me->coords->point.touch();
++ me->size_sensor->attach(&(PUBLIC(me)->size));
++}
++
++#undef PUBLIC
++
++// *************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ToggleButton.h.in
+@@ -0,0 +1,68 @@
++#ifndef COIN_SOGUITOGGLEBUTTON_H
++#define COIN_SOGUITOGGLEBUTTON_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++
++class SoGuiToggleButton : public SoBaseKit {
++ typedef SoBaseKit inherited;
++ SO_KIT_HEADER(SoGuiToggleButton);
++ SO_KIT_CATALOG_ENTRY_HEADER(root);
++public:
++ static void initClass(void);
++
++ SoGuiToggleButton(void);
++
++ SoSFVec3f size;
++ SoSFBool on;
++
++ virtual void handleEvent(SoHandleEventAction * action);
++
++protected:
++ virtual ~SoGuiToggleButton(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUITOGGLEBUTTON_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Translation.cpp.in
+@@ -0,0 +1,126 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoPickAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++#include <Inventor/SoPath.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiPane.h>
++#include <Inventor/@Gui@/nodes/SoGuiTranslation.h>
++
++// *************************************************************************
++
++SO_NODE_SOURCE(SoGuiTranslation);
++
++void
++SoGuiTranslation::initClass(void)
++{
++ SO_NODE_INIT_CLASS(SoGuiTranslation, SoTransformation, "Transformation");
++}
++
++SoGuiTranslation::SoGuiTranslation(void)
++{
++ SO_NODE_CONSTRUCTOR(SoGuiTranslation);
++ SO_NODE_ADD_FIELD(translation, (SbVec3f(0.0f, 0.0f, 0.0f)));
++}
++
++SoGuiTranslation::~SoGuiTranslation(void)
++{
++}
++
++void
++SoGuiTranslation::doAction(SoAction * action)
++{
++ // SoDebugError::postInfo("SoGuiTranslation::doAction", "invoked by %s", action->getTypeId().getName().getString());
++ int i;
++ SoGuiPane * pane = NULL;
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++ SoNode * node = path->getNode(i);
++ assert(node);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++ }
++ if ( pane == NULL ) {
++ SoDebugError::postInfo("SoGuiTranslation::doAction", "SoGuiTranslation only works below an SoGuiPane node");
++ return;
++ }
++ SoModelMatrixElement::translateBy(action->getState(), this,
++ this->translation.getValue());
++
++// pane->moveBy(action->getState(), this->translation.getValue());
++}
++
++void
++SoGuiTranslation::GLRender(SoGLRenderAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiTranslation::pick(SoPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiTranslation::rayPick(SoRayPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiTranslation::getMatrix(SoGetMatrixAction * action)
++{
++ SoDebugError::postInfo("SoGuiTranslation::getMatrix", "invoked");
++ int i;
++ SoGuiPane * pane = NULL;
++ const SoFullPath * path = (const SoFullPath *) action->getCurPath();
++ for ( i = path->getLength() - 1; (i >= 0) && (pane == NULL); i-- ) {
++ SoNode * node = path->getNode(i);
++ assert(node);
++ if ( node->isOfType(SoGuiPane::getClassTypeId()) ) pane = (SoGuiPane *) node;
++ }
++ if ( pane == NULL ) {
++ SoDebugError::postInfo("SoGuiTranslation::getMatrix", "SoGuiTranslation only works below an SoGuiPane node");
++ return;
++ }
++ pane->applyMoveBy(action, this->translation.getValue());
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/Translation.h.in
+@@ -0,0 +1,70 @@
++#ifndef COIN_SOGUITRANSLATION_H
++#define COIN_SOGUITRANSLATION_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoTransformation.h>
++
++class SoGuiTranslation : public SoTransformation {
++ typedef SoTransformation inherited;
++ SO_NODE_HEADER(SoGuiTranslation);
++
++public:
++ static void initClass(void);
++
++ SoGuiTranslation(void);
++
++ SoSFVec3f translation;
++
++ virtual void doAction(SoAction * action);
++ virtual void GLRender(SoGLRenderAction * action);
++ virtual void pick(SoPickAction * action);
++ virtual void rayPick(SoRayPickAction * action);
++ virtual void getMatrix(SoGetMatrixAction * action);
++
++protected:
++ virtual ~SoGuiTranslation(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUITRANSLATION_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewpointWrapper.cpp.in
+@@ -0,0 +1,347 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h>
++#include <Inventor/SoPath.h>
++#include <Inventor/sensors/SoPathSensor.h>
++#include <Inventor/sensors/SoFieldSensor.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/fields/SoSFBool.h>
++#include <Inventor/fields/SoSFTime.h>
++#include <assert.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++#ifdef HAVE_SOVRMLVIEWPOINT
++#include <Inventor/VRMLnodes/SoVRMLViewpoint.h>
++#endif // HAVE_SOVRMLVIEWPOINT
++
++// FIXME: make a generic class to handle bindable nodes, pederb 2003-08-29
++
++void
++SoGuiViewpointWrapper::initClass(void)
++{
++ SO_NODE_INIT_CLASS(SoGuiViewpointWrapper, SoPerspectiveCamera, "PerspectiveCamera");
++}
++
++SO_NODE_SOURCE(SoGuiViewpointWrapper);
++
++SoGuiViewpointWrapper::SoGuiViewpointWrapper(void)
++{
++ SO_NODE_CONSTRUCTOR(SoGuiViewpointWrapper);
++ this->scenegraph = NULL;
++ this->pathtoviewpoint = NULL;
++ this->positionsensor = new SoFieldSensor(fieldsensor_cb, this);
++ this->orientationsensor = new SoFieldSensor(fieldsensor_cb, this);
++ this->heightanglesensor = new SoFieldSensor(fieldsensor_cb, this);
++ this->pathsensor = new SoPathSensor(pathsensor_cb, this);
++ this->attachFieldSensors();
++ this->gmaction = new SoGetMatrixAction(SbViewportRegion(100, 100));
++}
++
++SoGuiViewpointWrapper::~SoGuiViewpointWrapper(void)
++{
++ this->pathsensor->detach();
++ delete this->pathsensor;
++ if (this->pathtoviewpoint) this->pathtoviewpoint->unref();
++ this->detachFieldSensors();
++ delete this->positionsensor;
++ delete this->orientationsensor;
++ delete this->heightanglesensor;
++ delete this->gmaction;
++ if (this->scenegraph) this->scenegraph->unref();
++}
++
++void
++SoGuiViewpointWrapper::sendBindEvents(SoNode * node, const SbBool onoff)
++{
++ SoSFBool * isBound = (SoSFBool*) node->getField("isBound");
++ SoSFTime * bindTime = (SoSFTime*) node->getField("bindTime");
++ if (isBound && bindTime) {
++ isBound->setValue(onoff);
++ bindTime->setValue(SbTime::getTimeOfDay());
++ }
++}
++
++void
++SoGuiViewpointWrapper::setViewpoint(SoPath * path)
++{
++ if (this->pathtoviewpoint) {
++ this->sendBindEvents(this->pathtoviewpoint->getTail(), FALSE);
++ this->pathtoviewpoint->unref();
++ this->pathsensor->detach();
++ }
++ this->pathtoviewpoint = (SoFullPath*) path;
++ if (path) {
++ path->ref();
++ this->pathsensor->attach(path);
++ this->updateCamera();
++ this->sendBindEvents(this->pathtoviewpoint->getTail(), TRUE);
++
++ // calculate a focal distance. It's not possible to specify a
++ // focal point in VRML97. We just set it to the center of the
++ // scene.
++ SbViewportRegion vp(640, 480);
++ SoGetBoundingBoxAction bboxaction(vp);
++ bboxaction.apply(path->getHead());
++ SbVec3f center = bboxaction.getCenter();
++
++ float dist = (this->position.getValue() - center).length();
++ // avoid focalDistance ~= 0
++ if (dist < 0.1f) dist = 0.1f;
++ this->focalDistance = dist;
++ }
++}
++
++void
++SoGuiViewpointWrapper::updateCamera(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++ if (this->pathtoviewpoint == NULL) return;
++
++ this->detachFieldSensors();
++
++ SoVRMLViewpoint * vp = (SoVRMLViewpoint*)
++ this->pathtoviewpoint->getTail();
++ assert(vp->getTypeId() == SoVRMLViewpoint::getClassTypeId());
++
++ this->gmaction->apply(this->pathtoviewpoint);
++ SbVec3f pos = vp->position.getValue();
++ float angle = vp->fieldOfView.getValue();
++
++ SbRotation rot = vp->orientation.getValue();
++ SbMatrix m;
++ m.setRotate(rot);
++ this->gmaction->getMatrix().multVecMatrix(pos, pos);
++ m.multRight(this->gmaction->getInverse());
++ m.multLeft(this->gmaction->getMatrix());
++ rot.setValue(m);
++
++ this->position = pos;
++ this->orientation = rot;
++ this->heightAngle = angle;
++
++ this->attachFieldSensors();
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void
++SoGuiViewpointWrapper::updateViewpoint(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++ if (this->pathtoviewpoint == NULL) return;
++ this->pathsensor->detach();
++
++ SoVRMLViewpoint * vp = (SoVRMLViewpoint*)
++ this->pathtoviewpoint->getTail();
++ assert(vp->getTypeId() == SoVRMLViewpoint::getClassTypeId());
++
++ this->gmaction->apply(this->pathtoviewpoint);
++ SbVec3f pos = this->position.getValue();
++ float angle = this->heightAngle.getValue();
++
++ SbRotation rot = this->orientation.getValue();
++ SbMatrix m;
++ m.setRotate(rot);
++ this->gmaction->getInverse().multVecMatrix(pos, pos);
++ m.multRight(this->gmaction->getMatrix());
++ m.multLeft(this->gmaction->getInverse());
++ rot.setValue(m);
++
++ vp->position = pos;
++ vp->orientation = rot;
++ vp->fieldOfView = angle;
++
++ this->pathsensor->attach(this->pathtoviewpoint);
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void
++SoGuiViewpointWrapper::attachFieldSensors(void)
++{
++ this->positionsensor->attach(&this->position);
++ this->orientationsensor->attach(&this->orientation);
++ this->heightanglesensor->attach(&this->heightAngle);
++}
++
++void
++SoGuiViewpointWrapper::detachFieldSensors(void)
++{
++ this->positionsensor->detach();
++ this->orientationsensor->detach();
++ this->heightanglesensor->detach();
++}
++
++void
++SoGuiViewpointWrapper::fieldsensor_cb(void * data, SoSensor * sensor)
++{
++ SoGuiViewpointWrapper * thisp = (SoGuiViewpointWrapper *) data;
++ thisp->updateViewpoint();
++}
++
++void
++SoGuiViewpointWrapper::pathsensor_cb(void * data, SoSensor * sensor)
++{
++ SoGuiViewpointWrapper * thisp = (SoGuiViewpointWrapper *) data;
++ thisp->updateCamera();
++}
++
++void
++SoGuiViewpointWrapper::set_bind_cb(void * data, SoSensor * sensor)
++{
++ SoGuiViewpointWrapper * thisp = (SoGuiViewpointWrapper *) data;
++ int idx = thisp->set_bind_sensorlist.find(sensor);
++
++ if (idx >= 0) {
++ SoNode * node = thisp->nodelist[idx];
++ node->ref();
++ SoSFBool * set_bind = (SoSFBool*) node->getField(SbName("set_bind"));
++ assert(set_bind);
++ if (set_bind->getValue()) { // TRUE event
++ // check if node is already bound
++ if (thisp->pathtoviewpoint && thisp->pathtoviewpoint->getTail() == node) return;
++ thisp->nodelist.remove(idx);
++ thisp->nodelist.insert(node, 0);
++
++ thisp->bindTopOfStack();
++ }
++ else if (idx == 0) { // FALSE event to top-of-stack
++ thisp->nodelist.remove(0);
++ thisp->nodelist.append(node); // place the node at the bottom of the stack
++
++ thisp->bindTopOfStack();
++ }
++ node->unrefNoDelete();
++ }
++}
++
++void
++SoGuiViewpointWrapper::bindTopOfStack(void)
++{
++ if (this->nodelist.getLength()) {
++ this->sa.setNode(this->nodelist[0]);
++ this->sa.setInterest(SoSearchAction::FIRST);
++ this->sa.apply(this->scenegraph);
++ if (this->sa.getPath()) {
++ this->setViewpoint(this->sa.getPath());
++ }
++ this->sa.reset();
++ }
++}
++
++SbBool
++SoGuiViewpointWrapper::hasViewpoints(SoNode * root)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++ SoSearchAction sa;
++ sa.setInterest(SoSearchAction::ALL);
++ sa.setType(SoVRMLViewpoint::getClassTypeId());
++ sa.apply(root);
++ return sa.getPaths().getLength() > 0;
++#else // HAVE_SOVRMLVIEWPOINT
++ return FALSE;
++#endif // ! HAVE_SOVRMLVIEWPOINT
++}
++
++void
++SoGuiViewpointWrapper::setSceneGraph(SoNode * root)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++ this->truncateLists();
++ this->setViewpoint(NULL);
++ if (this->scenegraph) this->scenegraph->unref();
++ this->scenegraph = root;
++ if (this->scenegraph) {
++ this->scenegraph->ref();
++ this->sa.setInterest(SoSearchAction::ALL);
++ this->sa.setType(SoVRMLViewpoint::getClassTypeId());
++ this->sa.apply(root);
++ SoPathList & pl = this->sa.getPaths();
++ if (pl.getLength()) {
++ for (int i = 0; i < pl.getLength(); i++) {
++ SoFullPath * p = (SoFullPath*) pl[i];
++ if (p->getTail()->isOfType(SoVRMLViewpoint::getClassTypeId())) {
++ this->nodelist.append(p->getTail());
++ this->set_bind_sensorlist.append(new SoFieldSensor(set_bind_cb, this));
++ }
++ }
++ this->attachSetBindSensors();
++ // bind the first Viewpoint
++ SoSFBool * set_bind = (SoSFBool*) this->nodelist[0]->getField(SbName("set_bind"));
++ assert(set_bind);
++ set_bind->setValue(TRUE);
++ }
++ this->sa.reset();
++ }
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void
++SoGuiViewpointWrapper::truncateLists(void)
++{
++ this->detachSetBindSensors();
++ this->nodelist.truncate(0);
++ for (int i = 0; i < this->set_bind_sensorlist.getLength(); i++) {
++ SoFieldSensor * fs = (SoFieldSensor*) this->set_bind_sensorlist[i];
++ delete fs;
++ }
++}
++
++void
++SoGuiViewpointWrapper::attachSetBindSensors(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++ assert(this->nodelist.getLength() == this->set_bind_sensorlist.getLength());
++ for (int i = 0; i < this->nodelist.getLength(); i++) {
++ SoVRMLViewpoint * vp = (SoVRMLViewpoint*) this->nodelist[i];
++ SoFieldSensor * fs = (SoFieldSensor*) this->set_bind_sensorlist[i];
++ fs->attach(vp->getField(SbName("set_bind")));
++ }
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
++void
++SoGuiViewpointWrapper::detachSetBindSensors(void)
++{
++#ifdef HAVE_SOVRMLVIEWPOINT
++ for (int i = 0; i < this->set_bind_sensorlist.getLength(); i++) {
++ SoFieldSensor * fs = (SoFieldSensor*) this->set_bind_sensorlist[i];
++ fs->detach();
++ }
++#endif // HAVE_SOVRMLVIEWPOINT
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewpointWrapper.h.in
+@@ -0,0 +1,103 @@
++#ifndef COIN_SOGUIVIEWPOINTWRAPPER_H
++#define COIN_SOGUIVIEWPOINTWRAPPER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/nodes/SoSubNode.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/SoLists.h>
++
++class SoPath;
++class SoFullPath;
++class SoPathSensor;
++class SoSensor;
++class SoFieldSensor;
++class SoGetMatrixAction;
++
++class SoGuiViewpointWrapper : public SoPerspectiveCamera {
++ typedef SoPerspectiveCamera inherited;
++ SO_NODE_HEADER(SoGuiViewpointWrapper);
++public:
++ static void initClass(void);
++ SoGuiViewpointWrapper(void);
++
++ void setSceneGraph(SoNode * root);
++
++ static SbBool hasViewpoints(SoNode * root);
++
++protected:
++ ~SoGuiViewpointWrapper();
++
++private:
++ void setViewpoint(SoPath * path);
++
++ static void fieldsensor_cb(void * data, SoSensor * sensor);
++ static void pathsensor_cb(void * data, SoSensor * sensor);
++ static void set_bind_cb(void * data, SoSensor * sensor);
++
++ void updateCamera(void);
++ void updateViewpoint(void);
++
++ void attachFieldSensors(void);
++ void detachFieldSensors(void);
++
++ SoFullPath * pathtoviewpoint;
++ SoPathSensor * pathsensor;
++ SoFieldSensor * positionsensor;
++ SoFieldSensor * orientationsensor;
++ SoFieldSensor * heightanglesensor;
++ SoGetMatrixAction * gmaction;
++
++ void truncateLists(void);
++
++ SoNodeList nodelist;
++ SbPList set_bind_sensorlist;
++ SoSearchAction sa;
++ SoNode * scenegraph;
++
++ void attachSetBindSensors(void);
++ void detachSetBindSensors(void);
++
++ void sendBindEvents(SoNode * node, const SbBool onoff);
++ void bindTopOfStack(void);
++
++};
++
++#endif // COIN_SOGUIVIEWPOINTWRAPPER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewportFix.cpp.in
+@@ -0,0 +1,178 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <assert.h>
++
++#include <Inventor/SbViewportRegion.h>
++#include <Inventor/SbLinear.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoGLRenderAction.h>
++#include <Inventor/actions/SoPickAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/elements/SoModelMatrixElement.h>
++
++#include <Inventor/@Gui@/nodes/SoGuiViewportFix.h>
++
++// *************************************************************************
++
++SO_NODE_SOURCE(SoGuiViewportFix);
++
++void
++SoGuiViewportFix::initClass(void)
++{
++ SO_NODE_INIT_CLASS(SoGuiViewportFix, SoTransformation, "Transformation");
++}
++
++SoGuiViewportFix::SoGuiViewportFix(void)
++{
++ this->internals = NULL;
++
++ SO_NODE_CONSTRUCTOR(SoGuiViewportFix);
++
++ SO_NODE_ADD_FIELD(corner, (SoGuiViewportFix::LEFT_BOTTOM));
++ SO_NODE_ADD_FIELD(viewportSize, (SbVec3f(0.0f, 0.0f, 0.0f)));
++
++ SO_NODE_DEFINE_ENUM_VALUE(Corner, LEFT_TOP);
++ SO_NODE_DEFINE_ENUM_VALUE(Corner, RIGHT_TOP);
++ SO_NODE_DEFINE_ENUM_VALUE(Corner, LEFT_BOTTOM);
++ SO_NODE_DEFINE_ENUM_VALUE(Corner, RIGHT_BOTTOM);
++
++ SO_NODE_SET_SF_ENUM_TYPE(corner, Corner);
++}
++
++SoGuiViewportFix::~SoGuiViewportFix(void)
++{
++}
++
++void
++SoGuiViewportFix::doAction(SoAction * action)
++{
++ SoState * state = action->getState();
++ if ( ! state->isElementEnabled(SoModelMatrixElement::getClassStackIndex()) ) return;
++
++ SbVec3f vpsize = this->viewportSize.getValue();
++ if ( vpsize[0] <= 0.0f || vpsize[1] <= 0.0f ) return;
++
++ SoModelMatrixElement::makeIdentity(state, this);
++
++ switch ( this->corner.getValue() ) {
++ case SoGuiViewportFix::LEFT_BOTTOM:
++ do {
++ SbVec3f translation(-1.0f, -1.0f, 0.0f);
++ SbVec3f scale(2.0f, 2.0f, 1.0f);
++ if ( vpsize[0] > vpsize[1] ) {
++ translation[0] = translation[0] * (vpsize[0] / vpsize[1]);
++ scale[0] = scale[0] * (vpsize[0] / vpsize[1]);
++ } else {
++ translation[1] = translation[1] * (vpsize[1] / vpsize[0]);
++ scale[1] = scale[1] * (vpsize[1] / vpsize[0]);
++ }
++ SoModelMatrixElement::translateBy(state, this, translation);
++ SoModelMatrixElement::scaleBy(state, this, scale);
++ // FIXME: scale
++ } while ( FALSE );
++ break;
++ default:
++ do {
++ SoDebugError::postInfo("SoGuiViewportFix::GLRender", "unimplemented corner");
++ } while ( FALSE );
++ break;
++ }
++}
++
++void
++SoGuiViewportFix::GLRender(SoGLRenderAction * action)
++{
++ const SbViewportRegion & vp = action->getViewportRegion();
++ SbVec2s vpsize = vp.getViewportSizePixels();
++
++ SbVec3f viewport(vpsize[0], vpsize[1], 0.0f);
++ if ( viewport != this->viewportSize.getValue() )
++ this->viewportSize.setValue(vpsize[0], vpsize[1], 0.0f);
++
++ this->doAction(action);
++}
++
++void
++SoGuiViewportFix::pick(SoPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiViewportFix::rayPick(SoRayPickAction * action)
++{
++ this->doAction(action);
++}
++
++void
++SoGuiViewportFix::getMatrix(SoGetMatrixAction * action)
++{
++ SoDebugError::postInfo("SoGuiViewportFix::getMatrix", "not implemented yet");
++
++ SbVec3f vpsize = this->viewportSize.getValue();
++ if ( vpsize[0] <= 0.0f || vpsize[1] <= 0.0f ) return;
++
++ action->getMatrix() = SbMatrix::identity();
++
++ switch ( this->corner.getValue() ) {
++ case SoGuiViewportFix::LEFT_BOTTOM:
++ do {
++ SbVec3f translation(-1.0f, -1.0f, 0.0f);
++ SbVec3f scale(2.0f, 2.0f, 1.0f);
++ if ( vpsize[0] > vpsize[1] ) {
++ translation[0] = translation[0] * (vpsize[0] / vpsize[1]);
++ scale[0] = scale[0] * (vpsize[0] / vpsize[1]);
++ } else {
++ translation[1] = translation[1] * (vpsize[1] / vpsize[0]);
++ scale[1] = scale[1] * (vpsize[1] / vpsize[0]);
++ }
++ SbMatrix matrix = SbMatrix::identity();
++ matrix.setTranslate(translation);
++ action->getMatrix().multLeft(matrix);
++
++ matrix = SbMatrix::identity();
++ matrix.setScale(scale);
++ action->getMatrix().multLeft(matrix);
++ } while ( FALSE );
++ break;
++ default:
++ do {
++ SoDebugError::postInfo("SoGuiViewportFix::GLRender", "unimplemented corner");
++ } while ( FALSE );
++ break;
++ }
++}
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/nodes/ViewportFix.h.in
+@@ -0,0 +1,82 @@
++#ifndef COIN_SOGUIVIEWPORTFIX_H
++#define COIN_SOGUIVIEWPORTFIX_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/fields/SoSFEnum.h>
++#include <Inventor/fields/SoSFVec3f.h>
++#include <Inventor/nodes/SoTransformation.h>
++
++// might go abstract to separate between ortho and perspective views
++
++class SoGuiViewportFix : public SoTransformation {
++ typedef SoTransformation inherited;
++ SO_NODE_HEADER(SoGuiViewportFix);
++
++public:
++ static void initClass(void);
++
++ SoGuiViewportFix(void);
++
++ enum Corner {
++ LEFT_TOP,
++ RIGHT_TOP,
++ LEFT_BOTTOM,
++ RIGHT_BOTTOM
++ };
++
++ SoSFEnum corner;
++
++ SoSFVec3f viewportSize; // output field: updated internally
++
++ virtual void doAction(SoAction * action);
++ virtual void GLRender(SoGLRenderAction * action);
++ virtual void pick(SoPickAction * action);
++ virtual void rayPick(SoRayPickAction * action);
++ virtual void getMatrix(SoGetMatrixAction * action);
++
++protected:
++ virtual ~SoGuiViewportFix(void);
++
++private:
++ void * internals;
++
++};
++
++#endif // !COIN_SOGUIVIEWPORTFIX_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/help.xpm
+@@ -0,0 +1,266 @@
++#ifndef COIN_PIXMAP_HELP_XPM
++#define COIN_PIXMAP_HELP_XPM
++
++/* XPM */
++static const char * help_xpm[] = {
++"24 24 234 2",
++" c None",
++". c #020204",
++"+ c #0282FC",
++"@ c #828A94",
++"# c #96CAFC",
++"$ c #26A6FC",
++"% c #7A828C",
++"& c #BAE6FC",
++"* c #0296FC",
++"= c #024284",
++"- c #0262C4",
++"; c #8AAED4",
++"> c #C6C6CC",
++", c #2682E4",
++"' c #4AB6FC",
++") c #DEEAF4",
++"! c #727A8C",
++"~ c #0272E4",
++"{ c #2696FC",
++"] c #AAB2C4",
++"^ c #CED6E4",
++"/ c #EAF6FC",
++"( c #028EFC",
++"_ c #3AA6FC",
++": c #0252A4",
++"< c #8E9AA4",
++"[ c #EEEAEC",
++"} c #227AD4",
++"| c #DEDADC",
++"1 c #1E82E4",
++"2 c #96BAE4",
++"3 c #268EF4",
++"4 c #027AF4",
++"5 c #269EFC",
++"6 c #AED6FC",
++"7 c #1E96FC",
++"8 c #026AD4",
++"9 c #4ABAFC",
++"0 c #BEBEC4",
++"a c #4296EC",
++"b c #3AB2FC",
++"c c #DEEEFC",
++"d c #969EAC",
++"e c #028AFC",
++"f c #024A94",
++"g c #9EAABC",
++"h c #C2CEDC",
++"i c #D6DEEC",
++"j c #FAF6F4",
++"k c #025AB4",
++"l c #7A96B4",
++"m c #BAC6D4",
++"n c #328EEC",
++"o c #0A7AEC",
++"p c #026ADC",
++"q c #5AA2EC",
++"r c #0A82FC",
++"s c #36AEFC",
++"t c #0E9EFC",
++"u c #3A96F4",
++"v c #B6B6BC",
++"w c #D6D6D4",
++"x c #1E8EFC",
++"y c #3AAEFC",
++"z c #E2E2E4",
++"A c #3A9EFC",
++"B c #62BAFC",
++"C c #429EF4",
++"D c #8A929C",
++"E c #2EAEFC",
++"F c #DAE6EC",
++"G c #0A96FC",
++"H c #92B6DC",
++"I c #368ADC",
++"J c #62AAF4",
++"K c #E6E6E4",
++"L c #1272DC",
++"M c #F2F2F4",
++"N c #1E8AF4",
++"O c #2692FC",
++"P c #16A2FC",
++"Q c #C2BEC4",
++"R c #9AA6B4",
++"S c #CECED4",
++"T c #0A7EF4",
++"U c #0A6EDC",
++"V c #A2C6EC",
++"W c #26AAFC",
++"X c #02468C",
++"Y c #0266CC",
++"Z c #268AEC",
++"` c #0276EC",
++" . c #269AFC",
++".. c #F2FAFC",
++"+. c #0A8EFC",
++"@. c #42A6FC",
++"#. c #0256AC",
++"$. c #86A6CC",
++"%. c #DEDEDC",
++"&. c #9EC2E4",
++"*. c #26A2FC",
++"=. c #BEDEFC",
++"-. c #42B2FC",
++";. c #E6EEFC",
++">. c #024E9C",
++",. c #FEFEFC",
++"'. c #025EBC",
++"). c #026EDC",
++"!. c #0A86FC",
++"~. c #DADADC",
++"{. c #5EC2FC",
++"]. c #0A9AFC",
++"^. c #62B2FC",
++"/. c #C2EAFC",
++"(. c #92B2D4",
++"_. c #CECACC",
++":. c #AEBACC",
++"<. c #EEFAFC",
++"[. c #929EAC",
++"}. c #EEEEEC",
++"|. c #1E86EC",
++"1. c #9ABEE4",
++"2. c #B2DEFC",
++"3. c #4A96E4",
++"4. c #96A2AC",
++"5. c #A6B2BC",
++"6. c #F6FAFC",
++"7. c #AACEFC",
++"8. c #0E7AE4",
++"9. c #0E82F4",
++"0. c #023E84",
++"a. c #A6CEF4",
++"b. c #52BEFC",
++"c. c #3A92EC",
++"d. c #BEBABC",
++"e. c #1E9EFC",
++"f. c #D6D2D4",
++"g. c #1E7EE4",
++"h. c #BAC2D4",
++"i. c #868E9C",
++"j. c #7E8694",
++"k. c #8E96A4",
++"l. c #EAEAEC",
++"m. c #A6CAF4",
++"n. c #BEEAFC",
++"o. c #8EB2D4",
++"p. c #767E8C",
++"q. c #B2DAFC",
++"r. c #A2AEBC",
++"s. c #C6D2DC",
++"t. c #C2C2C4",
++"u. c #D2D2D4",
++"v. c #46B6FC",
++"w. c #027EFC",
++"x. c #429AF4",
++"y. c #42A2FC",
++"z. c #62AEFC",
++"A. c #0A8AFC",
++"B. c #42AEFC",
++"C. c #66C2FC",
++"D. c #0286FC",
++"E. c #AAB6C4",
++"F. c #CEDAE4",
++"G. c #0292FC",
++"H. c #3AAAFC",
++"I. c #1E9AFC",
++"J. c #D6E2EC",
++"K. c #3A9AF4",
++"L. c #1E92FC",
++"M. c #3AA2FC",
++"N. c #62BEFC",
++"O. c #0A92FC",
++"P. c #42AAFC",
++"Q. c #E6F2FC",
++"R. c #62B6FC",
++"S. c #AAD2FC",
++"T. c #1EA2FC",
++"U. c #0672DC",
++"V. c #929AAC",
++"W. c #066ACC",
++"X. c #DAD6DC",
++"Y. c #EAE6EC",
++"Z. c #2A92F4",
++"`. c #0E7EEC",
++" + c #2A8AEC",
++".+ c #E2DEE4",
++"++ c #066EDC",
++"@+ c #F2EEF4",
++"#+ c #9AA2B4",
++"$+ c #2AA6FC",
++"%+ c #CAC6CC",
++"&+ c #E2EAF4",
++"*+ c #2A96FC",
++"=+ c #EEF6FC",
++"-+ c #9ABAE4",
++";+ c #2A8EF4",
++">+ c #2A9EFC",
++",+ c #3EB2FC",
++"'+ c #E2EEFC",
++")+ c #BAB6BC",
++"!+ c #E6E2E4",
++"~+ c #0E96FC",
++"{+ c #96B6DC",
++"]+ c #F6F2F4",
++"^+ c #9EA6B4",
++"/+ c #2AAAFC",
++"(+ c #2A9AFC",
++"_+ c #2AA2FC",
++":+ c #0E9AFC",
++"<+ c #FAFAFC",
++"[+ c #C6C2C4",
++"}+ c #02428C",
++"|+ c #0262CC",
++"1+ c #0252AC",
++"2+ c #1E82EC",
++"3+ c #024A9C",
++"4+ c #025ABC",
++"5+ c #D6D6DC",
++"6+ c #429EFC",
++"7+ c #8A92A4",
++"8+ c #DAE6F4",
++"9+ c #1E8AFC",
++"0+ c #024694",
++"a+ c #0266D4",
++"b+ c #268AF4",
++"c+ c #0276F4",
++"d+ c #0256B4",
++"e+ c #DEDEE4",
++"f+ c #024EA4",
++"g+ c #025EC4",
++"h+ c #026EE4",
++"i+ c #0E7AEC",
++"j+ c #0E82FC",
++"k+ c #2A92FC",
++". . . . . . . . . . . . . . . . . . . . . . . . ",
++". W.} I 3.q J J z.z.^.^.R.R.B B N.N.C.# # =.c . ",
++". - h.h ^ i F ) '+Q.=+..6.6.6.6.6.6.6.6.6.6.=.. ",
++". '.:.U g.n c.u K.A A M._ _ H.y y b v.b.{.6.# . ",
++". k ] a+U.1 Z b+3 O { { .5 *.*.$ $ E ,+9 6.# . ",
++". #.r.- 8 ~ i+`.9.j+q.c c /.~+~+:+t P W s 6.' . ",
++". 1+^+g+Y ).~ ` 4 7.,.,.,.,.n.G.G.* ].T./+6.-.. ",
++". 1+^+g+Y ).~ ` c+c ,.,.,.,.c ( G.G.].T.$+6.-.. ",
++". 1+R '.Y p ~ ~ ` m.<+,.,.,.& e ( G.G e.$+6.B.. ",
++". : R '.|+8 h+~ ` c+a.c c 2.D.e e ( O.I._+6.B.. ",
++". : #+'.- 8 ).~ ~ ` 4 4 w.+ + D.e e O.I.>+6.P.. ",
++". : 4.4+- a+).).1.c c c c c c q.D.D.+.7 >+.. at .. ",
++". : d 4+- Y 8 ).h+1.l.}.]+j c 6 + + A.L.(+<. at .. ",
++". f+[.k g+Y 8 p ).2 K l.}.M c S.w.w.!.x *+/ y.. ",
++". >.V.k '.|+a+8 p {+.+!+Y.[ @+m.4 w.r 9+k+;.6+. ",
++". >.< d+'.- Y a+8 H | .+!+K l.V c+4 T N Z.&+C . ",
++". >.k.#.4+- |+Y a+o.5+~.%.z !+&.` ` o |.;+8+x.. ",
++". 3+k.#.k g+- |+Y ; u.w X.| e+-+~ ~ o 2+ +J.a . ",
++". f i.: d+4+'.- - $.%+_.S u.f.(.p ).).8.1 F.c.. ",
++". X @ >.: #.d+l v )+d.0 Q t.[+> $.|+Y 8 ++s., . ",
++". }+% f >.f+1+1+#.#.d+d+k k 4+4+'.'.'.- Y m L . ",
++". = ! p.j.@ i.i.D 7+k.k.< V.V.[.d d #+g 5.E.Y . ",
++". 0.0.= }+X 0+0+0+f f 3+3+>.>.>.>.>.: 1+#.k '.. ",
++". . . . . . . . . . . . . . . . . . . . . . . . "};
++
++#endif /* !COIN_PIXMAP_HELP_XPM /
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/home.xpm
+@@ -0,0 +1,43 @@
++#ifndef COIN_PIXMAP_HOME_XPM
++#define COIN_PIXMAP_HOME_XPM
++
++/* XPM */
++static const char * home_xpm[] = {
++"24 24 11 1",
++" c None",
++". c #000000",
++"+ c #808080",
++"@ c #898989",
++"# c #C0C0C0",
++"$ c #F9F9F9",
++"% c #424242",
++"& c #A4A4A4",
++"* c #5D5D5D",
++"= c #C1C1C1",
++"- c #DFDFDF",
++" ",
++" ",
++" ",
++" .. ",
++" .. ",
++" ............. ",
++" ..+............ ",
++" ..+ at +............ ",
++" ..+###+............ ",
++" ..+#$$$#+............ ",
++" ...#$$$$$#+.......%% ",
++" .$+&$$$+++....%**% ",
++" .$&#$$$+#$.*%**%+% ",
++" .$##$$$=#$$**++++% ",
++" .$$$$$$--$$++++%+% ",
++" .$$$$$$$$$$+%++*+% ",
++" .$$$@@#-$$$+*++++% ",
++" .$$$@##-$$$+%+++%% ",
++" .$$$###-$$$+++%% ",
++" .%+####-$$$+%% ",
++" %%%%%%%..% ",
++" ",
++" ",
++" "};
++
++#endif /* !COIN_PIXMAP_HOME_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/ortho.xpm
+@@ -0,0 +1,47 @@
++#ifndef COIN_PIXMAP_ORTHO_XPM
++#define COIN_PIXMAP_ORTHO_XPM
++
++/* XPM */
++static const char * ortho_xpm[] = {
++"24 24 15 1",
++" c None",
++". c #000000",
++"+ c #F5680A",
++"@ c #D00000",
++"# c #A80000",
++"$ c #806840",
++"% c #D9D900",
++"& c #FF0000",
++"* c #808000",
++"= c #FFFF00",
++"- c #600000",
++"; c #800000",
++"> c #EAEA00",
++", c #FCB803",
++"' c #4F4F00",
++" ",
++" ",
++" ",
++" ",
++" ...................... ",
++" .+@@@@@@@@@####$$$$$$. ",
++" .%+&&&&&&&&&&&#$****$. ",
++" .%=+&&&&&&&&&&#$****$. ",
++" .%==+&&&&&&&&&#$****-. ",
++" .%===+&&&&&&&&@$****-. ",
++" .%====+&&&&&&&@$****-. ",
++" .%=====+&&&&&&@$***$-. ",
++" .%======+&&&&&@$***;-. ",
++" .%>======+&&&&@$***;-. ",
++" .%>=======+&&&#$**$;-. ",
++" .%>=======,+&&#$**;;-. ",
++" .%>>=======,+&#$*$;;-. ",
++" .%>>>=======,+#$*;;;-. ",
++" .%>>>>>>=====,#$$;;;-. ",
++" .%%%%%%%%%%%%%**'----. ",
++" ...................... ",
++" ",
++" ",
++" "};
++
++#endif /* !COIN_PIXMAP_ORTHO_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/perspective.xpm
+@@ -0,0 +1,49 @@
++#ifndef COIN_PIXMAP_PERSPECTIVE_XPM
++#define COIN_PIXMAP_PERSPECTIVE_XPM
++
++/* XPM */
++static const char * perspective_xpm[] = {
++"24 24 17 1",
++" c None",
++". c #000000",
++"+ c #D20000",
++"@ c #ECEC00",
++"# c #FC4203",
++"$ c #AC0000",
++"% c #FFFF00",
++"& c #FF0000",
++"* c #C4C400",
++"= c #FFB862",
++"- c #840000",
++"; c #FFA940",
++"> c #666600",
++", c #7D7D00",
++"' c #804000",
++") c #FE8263",
++"! c #737300",
++" ",
++" . ",
++" .+.. ",
++" .@#+$.. ",
++" .@%#&&+$.. ",
++" .@%%#&&&&+$.. ",
++" .@@%%#&&&&&&+$.. ",
++" .*@%%=#&&&&&&&&&. ",
++" .*@%%%=#&&&&&&&&-. ",
++" .*@%%%%;&&&&&&&&>-. ",
++" .@%%%%%%=&&&&&&&>,-. ",
++" .*@%%%%%=&&&&&#>,'-. ",
++" .*@%%%%;&&&&#>,,'-. ",
++" .*@%%%;&&&&>,,,--. ",
++" .*@%%;&&&>,,,'--. ",
++" .*@%;&+>,,,,'--. ",
++" .*%;+',,,,'---. ",
++" .*)'!,,,,'--. ",
++" .'!,,,,,--. ",
++" ...,,,'-. ",
++" ..,-. ",
++" .. ",
++" ",
++" "};
++
++#endif /* !COIN_PIXMAP_PERSPECTIVE_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/pick.xpm
+@@ -0,0 +1,45 @@
++#ifndef COIN_PIXMAP_PICK_XPM
++#define COIN_PIXMAP_PICK_XPM
++
++/* XPM */
++static const char * pick_xpm[] = {
++"24 24 13 1",
++" c None",
++". c #000000",
++"+ c #646464",
++"@ c #EC0000",
++"# c #FF7171",
++"$ c #800000",
++"% c #BB0000",
++"& c #FF4D4D",
++"* c #FF8C8C",
++"= c #FFA2A2",
++"- c #FFBFBF",
++"; c #FFD0D0",
++"> c #D00000",
++" ",
++" ",
++" ",
++" .+ ",
++" + at .+ ",
++" .@#.+ ",
++" +$@##.+ ",
++" .%@&##.+ ",
++" +$@&&*##.+ ",
++" .%@&&*=##.+ ",
++" +$@&&&&=-##.+ ",
++" .%@&&&&&-;#&+ ",
++" +$@&&&&&&=#. ",
++" .%@&&&&*#. ",
++" +$@&&&&#. ",
++" .%@&@%@#. ",
++" +$%@%.$@#. ",
++" .%%. .$@#. ",
++" +$. .$>#. ",
++" + .$. ",
++" . ",
++" ",
++" ",
++" "};
++
++#endif /* !COIN_PIXMAP_PICK_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/seek.xpm
+@@ -0,0 +1,44 @@
++#ifndef COIN_PIXMAP_SEEK_XPM
++#define COIN_PIXMAP_SEEK_XPM
++
++/* XPM */
++static const char * seek_xpm[] = {
++"24 24 12 1",
++" c None",
++". c #000000",
++"+ c #005FBD",
++"@ c #5EAEFF",
++"# c #7DBEFF",
++"$ c #0080FF",
++"% c #FFFFFF",
++"& c #004080",
++"* c #FFFF00",
++"= c #A8A800",
++"- c #6D6D36",
++"; c #FFFF80",
++" ",
++" ",
++" ... ",
++" .+ at +. ",
++" .+#$$+. ",
++" .+%$$$+. ",
++" .+#$$$+&. ",
++" .+@#@$+&. ",
++" .+@%&$+&. ",
++" .....+@@+.$+&. ",
++" .$$$@@@&&$$+&. ",
++" .$@#%@@$$+&+&. ",
++" .&&+@#@$$$&&. ",
++" .**=&+@$$$$&. ",
++" -**;*&+@$$+. ",
++" -**%%++ at ++. ",
++" =%%%*&+ at +. ",
++" =%%**&+&. ",
++" =***=+&. ",
++" =-*=&. ",
++" -.. ",
++" ",
++" ",
++" "};
++
++#endif /* !COIN_PIXMAP_SEEK_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/set_home.xpm
+@@ -0,0 +1,41 @@
++#ifndef COIN_PIXMAP_SET_HOME_XPM
++#define COIN_PIXMAP_SET_HOME_XPM
++
++/* XPM */
++static const char * set_home_xpm[] = {
++"24 24 9 1",
++" c None",
++". c #000000",
++"+ c #2894FF",
++"@ c #4FA7FF",
++"# c #62B0FF",
++"$ c #0077EE",
++"% c #BDDEFF",
++"& c #97CBFF",
++"* c #399CFF",
++" .....................",
++" .++.@@@@@@@@@@@@@@@@@.",
++" .+++.################@.",
++".++++.################@.",
++"......################@.",
++".$$$$$################@.",
++".$$$$@#####%%#########@.",
++".+@@@######%&#########@.",
++".*######%%%%&&%%######@.",
++".*#####%#%######%#####@.",
++".+####%###%######&####@.",
++".+*##&&####%######%###@.",
++".+*#%#######%######%##@.",
++".+*%%%######%%%&&%%%%#@.",
++".++*#%######%#####&###@.",
++".++*#&######%#####%###@.",
++".$++*%*#####%#####%###@.",
++".+++*%**####%#####%###@.",
++".$+$+%%%%%&&%%%&&%%###@.",
++".+$+++++*#############@.",
++".$+$+$+++**###########@.",
++".+$+$++++++***########@.",
++".$+$+$+$+++++++++++****.",
++"........................"};
++
++#endif /* !COIN_PIXMAP_SET_HOME_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/view.xpm
+@@ -0,0 +1,43 @@
++#ifndef COIN_PIXMAP_VIEW_XPM
++#define COIN_PIXMAP_VIEW_XPM
++
++/* XPM */
++static const char * view_xpm[] = {
++"24 24 11 1",
++" c None",
++". c #000000",
++"+ c #A0A0A0",
++"@ c #C0C0C0",
++"# c #464646",
++"$ c #E2E2E2",
++"% c #5E5E5E",
++"& c #FFFFFF",
++"* c #808080",
++"= c #939393",
++"- c #9B9B9B",
++" ",
++" .. ",
++" .+ at ... ",
++" ..#+$#+ at . ",
++" .+@%@&%+$#. ",
++" .+$%@&%@&%+. ",
++" .+&*@&*@&%+ at . ",
++" .+&*@&*@&*+$. ",
++" .@$=@$=@$*@$. ",
++" .@$-@$-@$=@$. ",
++" .@$+@$+@$-@$. ",
++" .@&@&@@&@+&$. ",
++" .. .@&&&&&&&&&&. ",
++" .@$. .@&$&&$&&$&&. ",
++" .+&$..@&+$&+&$+&&. ",
++" .@&$*@$$+&+&+$&&. ",
++" .@&$@$&+&+&+&&&. ",
++" .@$$$$$&$&$&&&. ",
++" .@@$$$&&&&&$$. ",
++" *++@@@@@&&$@* ",
++" .*+++@@@@*. ",
++" .@$$$@.@$$$@. ",
++" .....# #..... ",
++" "};
++
++#endif /* !COIN_PIXMAP_VIEW_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/view_all.xpm
+@@ -0,0 +1,58 @@
++#ifndef COIN_PIXMAP_VIEW_ALL_XPM
++#define COIN_PIXMAP_VIEW_ALL_XPM
++
++/* XPM */
++static const char * view_all_xpm[] = {
++"24 24 26 1",
++" c None",
++". c #000000",
++"+ c #ACAC00",
++"@ c #D9D900",
++"# c #FFFF73",
++"$ c #EAEA00",
++"% c #6A6A35",
++"& c #004080",
++"* c #808080",
++"= c #C0C0C0",
++"- c #0067CE",
++"; c #4B4B4B",
++"> c #FFFFFF",
++", c #B8B8B8",
++"' c #CCCCCC",
++") c #1188FF",
++"! c #D9D9D9",
++"~ c #0077EE",
++"{ c #7DBEFF",
++"] c #399CFF",
++"^ c #158AFF",
++"/ c #B5DAFF",
++"( c #E7E7E7",
++"_ c #808040",
++": c #95954A",
++"< c #919100",
++" ",
++" ................... ",
++" .+.@@@@@@@@@@@@@@@@. ",
++" .++.###############@. ",
++" .....###############@. ",
++" .++++#$@+++++@@#####@. ",
++" .++#$@%........%+###@. ",
++" .@$@%.&&&&.*......%+ at . ",
++" .+%.*&&&&.*=*..=.&&%+. ",
++" ..**&--&;*=>=*....&&.. ",
++" .*,,&---;.*=*.**..--&. ",
++" .,''&---;..*.**==.)--. ",
++" *'!!~---;....*=>>.{]^* ",
++" ,'!>~--~-.....=>>>/{], ",
++" ,'(>{&~)]-......>>>>!' ",
++" *'!(>&-)]]-;..;-{>>>(, ",
++" ._''!{&-)]]]]]]]]/>('* ",
++" .+_'''{&~-))]]])/(('_. ",
++" .++__'''{~~~---/(',_ at . ",
++" .++++:_,'''!!''':_:@@. ",
++" . at +++++<::____::@@##@. ",
++" .@@@++++++++++@@@@@@@. ",
++" ...................... ",
++" "};
++
++#endif /* !COIN_PIXMAP_VIEW_ALL_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/x.xpm
+@@ -0,0 +1,177 @@
++#ifndef COIN_PIXMAP_X_XPM
++#define COIN_PIXMAP_X_XPM
++
++/* XPM */
++static const char * x_xpm[] = {
++"24 24 145 2",
++" c None",
++". c #000000",
++"+ c #C50000",
++"@ c #ED0000",
++"# c #F53636",
++"$ c #F76969",
++"% c #F98B8B",
++"& c #FAA2A2",
++"* c #F54242",
++"= c #F76767",
++"- c #F98D8D",
++"; c #FBABAB",
++"> c #FCBDBD",
++", c #FCBEBE",
++"' c #9F0000",
++") c #CA0000",
++"! c #F30D0D",
++"~ c #F65454",
++"{ c #F98585",
++"] c #FBAFAF",
++"^ c #F42525",
++"/ c #F64949",
++"( c #F87575",
++"_ c #FA9F9F",
++": c #FBBABA",
++"< c #FBB1B1",
++"[ c #7B0000",
++"} c #9E0000",
++"| c #D20000",
++"1 c #F42A2A",
++"2 c #F87272",
++"3 c #FA9A9A",
++"4 c #FBACAC",
++"5 c #F43131",
++"6 c #F75A5A",
++"7 c #F98A8A",
++"8 c #FCBBBB",
++"9 c #FA9696",
++"0 c #9C0000",
++"a c #DB0000",
++"b c #F64545",
++"c c #F98888",
++"d c #FAA6A6",
++"e c #F53F3F",
++"f c #F64646",
++"g c #F87373",
++"h c #FAA0A0",
++"i c #F86D6D",
++"j c #9B0000",
++"k c #E40000",
++"l c #F65757",
++"m c #F99393",
++"n c #FAA3A3",
++"o c #FA9797",
++"p c #F75D5D",
++"q c #F64F4F",
++"r c #F64B4B",
++"s c #F76161",
++"t c #F98E8E",
++"u c #F86C6C",
++"v c #F65151",
++"w c #F54040",
++"x c #E90000",
++"y c #FA9494",
++"z c #F99191",
++"A c #F98787",
++"B c #F87676",
++"C c #F76363",
++"D c #F76666",
++"E c #F87C7C",
++"F c #F87979",
++"G c #F65252",
++"H c #F53333",
++"I c #F41F1F",
++"J c #F31515",
++"K c #F98181",
++"L c #F87F7F",
++"M c #F87B7B",
++"N c #F87E7E",
++"O c #F31C1C",
++"P c #F20404",
++"Q c #EB0000",
++"R c #AC0000",
++"S c #F53D3D",
++"T c #F86F6F",
++"U c #F87878",
++"V c #F76A6A",
++"W c #F42424",
++"X c #F20909",
++"Y c #840000",
++"Z c #BD0000",
++"` c #EE0000",
++" . c #F87070",
++".. c #F75B5B",
++"+. c #F42727",
++"@. c #F31313",
++"#. c #F10000",
++"$. c #F42D2D",
++"%. c #F64C4C",
++"&. c #F76060",
++"*. c #F76464",
++"=. c #8E0000",
++"-. c #B20000",
++";. c #D60000",
++">. c #F20303",
++",. c #F65555",
++"'. c #8A0000",
++"). c #A50000",
++"!. c #BE0000",
++"~. c #8C0000",
++"{. c #9D0000",
++"]. c #AB0000",
++"^. c #B90000",
++"/. c #CD0000",
++"(. c #E60000",
++"_. c #F64848",
++":. c #8D0000",
++"<. c #930000",
++"[. c #960000",
++"}. c #A70000",
++"|. c #DF0000",
++"1. c #7E0000",
++"2. c #860000",
++"3. c #7F0000",
++"4. c #AD0000",
++"5. c #DE0000",
++"6. c #F53939",
++"7. c #810000",
++"8. c #880000",
++"9. c #8B0000",
++"0. c #830000",
++"a. c #DD0000",
++"b. c #F54343",
++"c. c #F99090",
++"d. c #D80000",
++"e. c #890000",
++"f. c #CF0000",
++"g. c #F42121",
++"h. c #C30000",
++"i. c #F20101",
++"j. c #F42B2B",
++"k. c #B50000",
++"l. c #F30A0A",
++"m. c #800000",
++"n. c #D00000",
++". . . . . . . . . . . . . . ",
++". + @ # $ % & . . * = - ; > , . ",
++". ' ) ! ~ { & ] . . ^ / ( _ : , < . ",
++". [ } | 1 2 3 4 ] . . ^ 5 6 7 < 8 4 9 . ",
++". [ [ 0 a b c d 4 d . . e # f g h < h { i . ",
++". [ [ [ j k l m n & o . . p q r s - h t u v w . ",
++". [ [ [ [ 0 x p % y z A B $ C D E - F G H I J . ",
++" . [ [ [ [ } @ v ( K L F g ( M N $ w O P Q . ",
++" . [ [ [ [ R @ S s T g U N E V f W X Q . ",
++" . [ [ [ Y Z ` H G D 2 U ...w +. at .. ",
++" . [ [ [ } ) #.$.%.&.= *.l b # . ",
++" . [ [ =.-.;.>.1 b ,.p ..,.. ",
++" . [ [ '.).!.;.` I e l C = . ",
++" . [ [ [ ~.{.].^./.(.O _.D ( E . ",
++" . [ [ [ Y :.<.[.j }.Z |.^ ..M c t . ",
++" . [ [ 1.2.:.:.2.3.[ 1.:.4.5.6.g - o 3 . ",
++" . [ [ [ 7.8.9.0.[ [ [ [ [ [ } a.b.M c.o 3 . ",
++". [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ =.d.6.u L A c . ",
++". [ [ [ [ [ [ [ [ [ [ . . [ [ [ [ e.f.g.q *.u . ",
++". [ [ [ [ [ [ [ [ [ . . [ [ [ [ Y h.i.j.* . ",
++". [ [ [ [ [ [ [ [ . . [ [ [ [ 7.k.a.l.. ",
++". [ [ [ [ [ [ [ . . [ [ [ [ m.R n.. ",
++". [ [ [ [ [ [ . . [ [ [ [ 7.}.. ",
++". . . . . . . . . . . . . . "};
++
++#endif /* !COIN_PIXMAP_X_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/y.xpm
+@@ -0,0 +1,167 @@
++#ifndef COIN_PIXMAP_Y_XPM
++#define COIN_PIXMAP_Y_XPM
++
++/* XPM */
++static const char * y_xpm[] = {
++"24 24 135 2",
++" c None",
++". c #000000",
++"+ c #FFFFFF",
++"@ c #006AD3",
++"# c #007DFA",
++"$ c #369BFF",
++"% c #69B4FF",
++"& c #8BC5FF",
++"* c #A2D1FF",
++"= c #42A1FF",
++"- c #67B3FF",
++"; c #8DC6FF",
++"> c #ABD5FF",
++", c #BDDEFF",
++"' c #BEDFFF",
++") c #0057AD",
++"! c #006CD8",
++"~ c #0D86FF",
++"{ c #54AAFF",
++"] c #85C2FF",
++"^ c #AFD7FF",
++"/ c #2592FF",
++"( c #49A4FF",
++"_ c #75BAFF",
++": c #9FCFFF",
++"< c #BADDFF",
++"[ c #B1D8FF",
++"} c #00458A",
++"| c #0056AB",
++"1 c #0070DF",
++"2 c #2A95FF",
++"3 c #72B9FF",
++"4 c #9ACDFF",
++"5 c #ACD6FF",
++"6 c #3198FF",
++"7 c #5AADFF",
++"8 c #8AC5FF",
++"9 c #BBDDFF",
++"0 c #96CBFF",
++"a c #0054A8",
++"b c #0074E8",
++"c c #43A1FF",
++"d c #87C3FF",
++"e c #A6D3FF",
++"f c #3F9FFF",
++"g c #46A3FF",
++"h c #73B9FF",
++"i c #A0D0FF",
++"j c #84C2FF",
++"k c #6CB6FF",
++"l c #0050A0",
++"m c #0075E9",
++"n c #4EA7FF",
++"o c #90C8FF",
++"p c #A3D1FF",
++"q c #99CCFF",
++"r c #5DAEFF",
++"s c #4FA7FF",
++"t c #4BA5FF",
++"u c #61B0FF",
++"v c #97CBFF",
++"w c #82C1FF",
++"x c #3A9DFF",
++"y c #004890",
++"z c #006FDE",
++"A c #81C0FF",
++"B c #76BBFF",
++"C c #6AB5FF",
++"D c #64B2FF",
++"E c #52A9FF",
++"F c #2D96FF",
++"G c #158AFF",
++"H c #0783FF",
++"I c #0482FF",
++"J c #0066CC",
++"K c #2291FF",
++"L c #7BBDFF",
++"M c #2492FF",
++"N c #007DF9",
++"O c #0071E2",
++"P c #0070E0",
++"Q c #005EBC",
++"R c #168BFF",
++"S c #0078EF",
++"T c #006EDB",
++"U c #0068D0",
++"V c #0059B2",
++"W c #0077ED",
++"X c #2793FF",
++"Y c #4CA6FF",
++"Z c #58ACFF",
++"` c #48A4FF",
++" . c #1F8FFF",
++".. c #007BF6",
++"+. c #0071E1",
++"@. c #0069D1",
++"#. c #0064C8",
++"$. c #005BB6",
++"%. c #1E8FFF",
++"&. c #3098FF",
++"*. c #2190FF",
++"=. c #007FFE",
++"-. c #0076EB",
++";. c #006DDA",
++">. c #0067CE",
++",. c #00468B",
++"'. c #0064C7",
++"). c #007BF5",
++"!. c #0F87FF",
++"~. c #0058AF",
++"{. c #0073E5",
++"]. c #007FFD",
++"^. c #0180FF",
++"/. c #0076EC",
++"(. c #0055AA",
++"_. c #0073E6",
++":. c #0683FF",
++"<. c #0C86FF",
++"[. c #0057AE",
++"}. c #0078F0",
++"|. c #188CFF",
++"1. c #1C8EFF",
++"2. c #1389FF",
++"3. c #005AB3",
++"4. c #2B95FF",
++"5. c #0052A4",
++"6. c #198CFF",
++"7. c #0065C9",
++"8. c #007AF3",
++"9. c #0A85FF",
++"0. c #0381FF",
++"a. c #0079F2",
++"b. c #0056AC",
++"c. c #0065CA",
++"d. c #0058B0",
++". . . . . . . . . . . . . . ",
++". @ # $ % & * . . = - ; > , ' . ",
++". ) ! ~ { ] * ^ . . / ( _ : < ' [ . ",
++". } | 1 2 3 4 5 ^ . . / 6 7 8 [ 9 5 0 . ",
++". } } a b c d e 5 e . . f $ g h i ^ : j k . ",
++". } } } l m n o p * q . . r s t u 8 v w u ( x . ",
++". } } } } y z g A o o ] B C D D h h E F G H I . ",
++" . } } } } } J K r _ L B _ _ k E M N m O P . ",
++" . } } } } } Q N x r C 3 k t R S T U J . ",
++" . } } } } } V W X Y Z ` ...+. at .#.. ",
++" . } } } } } $.W %.&.*.=.-.;.>.. ",
++" . } } } } ,.'.).!.H ..b T . ",
++" . } } } } ~.{.].^.../.. ",
++" . } } } (._.:.<.^.. ",
++" . } } } [.}.|.1.2.. ",
++" . } } } 3.N X 4.M . ",
++" . } } } 5./.6./ M . ",
++" . } } } } 7.8.9.G . ",
++" . } } } } a ! 8.0.. ",
++" . } } } } ,.Q z a.. ",
++" . } } } } } l '.+.. ",
++" . } } } } } } b.c.. ",
++" . } } } } } } y d.. ",
++" . . . . . . . . . . "};
++
++#endif /* !COIN_PIXMAP_Y_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/pixmaps/z.xpm
+@@ -0,0 +1,163 @@
++#ifndef COIN_PIXMAP_Z_XPM
++#define COIN_PIXMAP_Z_XPM
++
++/* XPM */
++static const char * z_xpm[] = {
++"24 24 131 2",
++" c None",
++". c #020204",
++"+ c #82820C",
++"@ c #C2C214",
++"# c #E2E21C",
++"$ c #EEEE94",
++"% c #F2F25C",
++"& c #E2E25C",
++"* c #EAEA1C",
++"= c #D2D214",
++"- c #A2A214",
++"; c #FEFEFC",
++"> c #DADA14",
++", c #FAFA9C",
++"' c #EAEA5C",
++") c #E2E23C",
++"! c #DADA34",
++"~ c #EAEA3C",
++"{ c #929214",
++"] c #B2B214",
++"^ c #6E6E0C",
++"/ c #F2F27C",
++"( c #F6F694",
++"_ c #E6E674",
++": c #FAFAB4",
++"< c #EAEA7C",
++"[ c #EAEA4C",
++"} c #7A7A0C",
++"| c #DADA24",
++"1 c #E2E22C",
++"2 c #EAE65C",
++"3 c #E2E254",
++"4 c #8A8A0C",
++"5 c #CACA14",
++"6 c #F2F2AC",
++"7 c #E6E65C",
++"8 c #E2DE3C",
++"9 c #BABA14",
++"0 c #FEFEBC",
++"a c #F2EE54",
++"b c #F2F26C",
++"c c #D6D614",
++"d c #AAAA14",
++"e c #EAEA74",
++"f c #DEDE34",
++"g c #9A9A14",
++"h c #76760C",
++"i c #FAFA8C",
++"j c #EEEE4C",
++"k c #E2E26C",
++"l c #DEDE1C",
++"m c #F2EE5C",
++"n c #EAE644",
++"o c #FAF68C",
++"p c #FAFAC4",
++"q c #EEEE8C",
++"r c #827E0C",
++"s c #E2DE2C",
++"t c #E6E62C",
++"u c #928E14",
++"v c #C6C614",
++"w c #E6E61C",
++"x c #F2EEA4",
++"y c #F6F664",
++"z c #E6E25C",
++"A c #EAEA34",
++"B c #D2D224",
++"C c #DEDA14",
++"D c #FAFAAC",
++"E c #EEEE5C",
++"F c #E6E63C",
++"G c #DADA44",
++"H c #F2EE3C",
++"I c #969614",
++"J c #BAB614",
++"K c #76720C",
++"L c #F6F67C",
++"M c #F6F6BC",
++"N c #FEFABC",
++"O c #EAEA8C",
++"P c #EEEA4C",
++"Q c #7E7E0C",
++"R c #DEDE2C",
++"S c #E6E64C",
++"T c #8E8E14",
++"U c #CECE14",
++"V c #F6F2B4",
++"W c #C2BE14",
++"X c #AEAE14",
++"Y c #86860C",
++"Z c #C6C214",
++"` c #EEEE9C",
++" . c #F2F264",
++".. c #E2E264",
++"+. c #D2D21C",
++"@. c #A6A614",
++"#. c #FAFAA4",
++"$. c #DADA3C",
++"%. c #EAEA44",
++"&. c #969214",
++"*. c #B6B614",
++"=. c #72720C",
++"-. c #F6F69C",
++";. c #E6E67C",
++">. c #FAFABC",
++",. c #EAEA84",
++"'. c #7E7A0C",
++"). c #DADA2C",
++"!. c #E6E234",
++"~. c #8A8A14",
++"{. c #CECA14",
++"]. c #F2F2B4",
++"^. c #E6E66C",
++"/. c #BEBE14",
++"(. c #FEFEC4",
++"_. c #F2F274",
++":. c #D6D61C",
++"<. c #AEAA14",
++"[. c #DEDE44",
++"}. c #9E9E14",
++"|. c #7A760C",
++"1. c #EEEE54",
++"2. c #E6E634",
++"3. c #E6E624",
++"4. c #EEEE34",
++"5. c #DEDA1C",
++"6. c #EEEE64",
++"7. c #E6E644",
++"8. c #F6F68C",
++"9. c #EEEA54",
++"0. c #E6E654",
++". . . . . . . . . . . . . . . . . . . . . . . . ",
++". T }.] v c R 7.S [ [ [ 9.1.a % .L o #.: 0 ; . ",
++". } Y I d W c s ) F 7.%.[ j 1.% b 8., : >.(.(.. ",
++". } } '.T - 9 U l # 1 2.~ [ 1.m _.( D >.p >.N . ",
++". } } } Q r I <./.v c l t ~ P 6./ -.D : : D #.. ",
++". } } } '.Q Q Y g @.J 5 > 3.%.E / ( -.-.( o i . ",
++". . . . . . . . . . . . v > t %.E b b b .y y . ",
++" . g ] v C 3.A A A 4.4.H . ",
++" . + I X @ = C # # w w * . ",
++" . Q 4 - 9 U l # # w w w . ",
++" . Q Y g ] {.l 1 !.2.t t . ",
++" . } + { d Z 5.) 7.7.7.n . ",
++" . } + T - 9 :.8 0.7 2 ' . ",
++" . Q + T }.] U f z ^.e e . ",
++" . Q Y T }.X v ).3 _ < q . ",
++" . Q + ~.I @./.+.[.k < $ . ",
++" . =.h } Y I d @ B G ..;.. ",
++". =.=.K h } ~.- *.v +.$.. . . . . . . . . . . . ",
++". =.=.=.K h } u - <.9 v :.$.& _ O x ].V M M ; . ",
++". =.=.=.=.K h Q T I }.d *.v :.! 3 _ q ` 6 6 V . ",
++". =.=.=.=.=.K h Q + 4 { g @.] 9 U ! 3 ^.,.q $ . ",
++". ^ =.=.=.=.=.h h h h '.+ 4 { g @.9 {.| [.z ^.. ",
++". ^ ^ =.=.=.=.=.h h h h h |.} } Y &. at .*.v :.f . ",
++". . . . . . . . . . . . . . . . . . . . . . . . "};
++
++#endif /* !COIN_PIXMAP_Z_XPM */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui-config.1.in
+@@ -0,0 +1,37 @@
++.\" Process this file with
++.\" groff -man -Tascii so at gui@-config.1
++.\"
++.TH so at gui@-config 1 "AUGUST 2001" "Library Configuration" "User Manuals"
++.SH NAME
++so at gui@-config \- Display So at Gui@ Library Configuration
++.SH SYNOPSIS
++.B so at gui@-config
++.I OPTION
++.B [
++.I OPTION
++.B ... ]
++.SH DESCRIPTION
++.B so at gui@-config
++is a script that is used to display what compiler flags and libraries were
++used when So at Gui@ was built.
++.SH OPTIONS
++.IP --version
++Return So at Gui@ version string
++.IP --help
++Display so at gui@-config usage information
++.IP --cppflags
++Return C pre-processor flags for use when compiling with So at Gui@
++.IP --cxxflags
++Return C++ compiler flags for use when compiling with So at Gui@
++.IP --ldflags
++Return linker flags needed when linking against So at Gui@
++.IP --libs
++Return libraries one must link with when using So at Gui@
++.IP --alternate=<config-name>
++Set So at Gui@ configuration to something other than default (when using
++multiple So at Gui@ configurations).
++.SH AUTHORS
++Steve Robbins <smr at debian.org>, and
++.br
++Lars J. Aas <larsa at coin3d.org>
++.
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui-config.in
+@@ -0,0 +1,377 @@
++#! /bin/sh
++# **************************************************************************
++# so at gui@-config -- a utility for retrieving configuration information about
++# the installed So at Gui@ library.
++#
++# Authors:
++# Lars J. Aas <larsa at coin3d.org>
++# Morten Eriksen <mortene at coin3d.org>
++
++program="$0"
++me=`echo "$0" | sed 's,^.*[/\\],,g'`
++wd=`echo "$0" | sed 's,/[^/]*$,,'`
++prefix=`cd "$wd"/..; pwd`
++
++hello=`echo hello | fmt -t -w70 2>&1`
++if test x"$hello" = x"hello"; then
++ # 'fmt -t' works
++ preformat="fmt -t -w76"
++ sedformat='$ q; s/$/ \\/'
++else
++ # sed script replacing "fmt -w76 | sed '2,$ s/^/ /g; $ q; 1,$ s/$/ \\/'"
++ preformat="cat"
++ sedformat='/^............................................................................./ {
++ G
++ s/^\([^\
++]\{1,76\}\) \(.*\)\(\
++\)/\1 \\\3 \2/
++ P
++ D
++}'
++ if test xhello != x"`echo hello | sed -e $sedformat 2>&1`"; then
++ sedformat="s/a/a/"
++ fi
++fi
++
++
++usage="\
++Usage: $me [OPTIONS]
++Options:
++ --alternate=<string>
++ --prefix
++ --cppflags
++ --cflags
++ --cxxflags
++ --ldflags
++ --libs
++ --msvcrt
++ --datadir
++ --includedir
++ --frameworkdir
++ --ac-subst <string> | <sourcefile.in>
++ --ac-desubst <sourcefile>
++ --compile <sourcefile> [<sourcefile>]...
++ --link <program> <object> [<object>]...
++ --build <program> <sourcefile> [<sourcefile>]...
++ --setup | --setup-front
++ --header <classname>
++ --version
++ --usage | --help"
++
++alternate=default
++for arg
++do
++ case $arg in
++ --usage | --help)
++ echo "$usage"
++ exit 0
++ ;;
++ --alternate=*)
++ alternate=`echo $arg | cut -d= -f2-`
++ ;;
++ --debug)
++ alternate=debug
++ ;;
++ esac
++done
++
++if test -f "$prefix/share/Coin/conf/so at gui@-$alternate.cfg"; then
++ configfile="$prefix/share/Coin/conf/so at gui@-$alternate.cfg"
++ . "$configfile"
++elif test -f "$prefix/share/Coin/conf/so at gui@-default.cfg"; then
++ configfile="$prefix/share/Coin/conf/so at gui@-default.cfg"
++ . "$configfile"
++else
++ echo >&2 "$me: no default So at Gui@ config available in \"$prefix/share/Coin/conf/\""
++ exit 1
++fi
++
++# Remove gcc system directories includes from the include path
++if test x"$compiler_is_gcc" = x"yes"; then
++ sim_ac_save_cpp=$CPP
++ CPP="cpp"
++ case `uname -s` in
++ Darwin) CPP="cpp3"
++ ;;
++ esac
++ cpp_sys_dirs=`$CPP -v <<EOF 2>&1 | sed -n -e \
++ '/#include <...> search starts here:/,/End of search list./{
++ /#include <...> search starts here:/b
++ /End of search list./b
++ s/ /-I/
++ p
++ }'
++EOF`
++ result=
++ for inc_path in $cppflags; do
++ additem=true
++ for sys_dir in $cpp_sys_dirs; do
++ if test x$inc_path = x$sys_dir; then
++ additem=false
++ break
++ fi
++ done
++ $additem && result="$result $inc_path"
++ done
++ cppflags=$result
++ CPP=$sim_ac_save_cpp
++fi
++
++while test $# -gt 0
++do
++ case $1 in
++ --version) echo "$version" ;;
++ --prefix) echo "$prefix" ;;
++ --cppflags) echo "$cppflags" ;;
++ --cflags) echo "$cflags" ;;
++ --cxxflags) echo "$cxxflags" ;;
++ --ldflags) echo "$ldflags" ;;
++ --libs) echo "$libs" ;;
++ --msvcrt) echo "$msvcrt" ;;
++ --datadir) echo "$datadir" ;;
++ --includedir) echo "$includedir" ;;
++ --frameworkdir) echo "$frameworkdir" ;;
++ --ac-subst)
++ shift
++ if test $# -eq 1; then
++ case $1 in
++ *\.in)
++ echo $me --ac-subst $1
++ outfile=`echo $1 | sed -e 's/\.in$//'`
++ sedscript=/tmp/ac_subst_$$.sed
++ grep "^AC_SUBST_" $configfile \
++ | sed -e 's/^AC_SUBST_\([^=]*\)="\([^"]*\)"$/s\/@\1@\/\2\/g;/g' \
++ >$sedscript
++ rm -f $outfile
++ case `echo "$compiler" | sed 's/ .*//g'` in
++ gcc | g++)
++ echo "# 1 \"$1\"" >$outfile
++ ;;
++ wrapmsvc | wrapmsvc.exe | msvccc)
++ echo "#line 1 \"$1\"" >$outfile
++ ;;
++ esac
++ sed -f $sedscript <$1 >>$outfile
++ rm -f $sedscript
++ ;;
++ *)
++ eval "VAL=\${AC_SUBST_$1}"
++ echo "$VAL"
++ ;;
++ esac
++ else
++ for arg in $@; do
++ $program --alternate="$alternate" --ac-subst $arg
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ done
++ fi
++ exit 0
++ ;;
++ --ac-desubst)
++ shift
++ echo $me --ac-desubst $1
++ outfile="$1.in"
++ sedscript=/tmp/ac_subst_$$.sed
++ grep "^AC_SUBST_" $configfile \
++ | sed -e 's/^AC_SUBST_\([^=]*\)="\([^"]*\)"$/s\/\2\/@\1@\/g;/g' \
++ >$sedscript
++ sed -f $sedscript <$1 >$outfile
++ rm -f $sedscript
++ ;;
++ --compile)
++ shift
++ if test $# -eq 1; then
++ case $1 in
++ *\.in)
++ outfile=`echo $1 | sed -e 's/\.in$//'`
++ $program --alternate="$alternate" --ac-subst $1
++ $program --alternate="$alternate" --compile $outfile
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ ;;
++ *)
++ basename=`echo "$1" | sed -e 's/\.[^\.]*$//'` # strip off extension
++ echo $compiler $CPPFLAGS $cppflags $CXXFLAGS $cxxflags -c $1 -o $basename. at OBJEXT@ \
++ | $preformat | sed "$sedformat"
++ $compiler \
++ $CPPFLAGS $cppflags \
++ $CXXFLAGS $cxxflags \
++ -c $1 -o $basename. at OBJEXT@
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ ;;
++ esac
++ else
++ for arg in $@; do
++ $program --alternate="$alternate" --compile $arg
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ done
++ fi
++ exit 0
++ ;;
++ --link)
++ shift
++ progname=$1
++ shift
++ echo $compiler $LDFLAGS $ldflags -o $progname $@ $libs $LIBS \
++ | $preformat | sed "$sedformat"
++ $compiler \
++ $LDFLAGS $ldflags \
++ -o $progname $@ \
++ $libs $LIBS
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ case $host in
++ *-darwin*)
++ echo "$me: making Mac OS X application \"$progname.app\""
++ mkdir $progname.app 2>/dev/null
++ mkdir $progname.app/Contents 2>/dev/null
++ mkdir $progname.app/Contents/MacOS 2>/dev/null
++ if test -d $progname.app/Contents/MacOS &&
++ mv -f $progname $progname.app/Contents/MacOS/ &&
++ echo "APPL????" >$progname.app/Contents/PkgInfo; then
++ :
++ else
++ echo >&2 "$me: failed to make Mac OS X application"
++ echo >&2 " - problem is probably user permission or disk space related"
++ exit 1
++ fi
++ ;;
++ esac
++ exit 0
++ ;;
++ --build)
++ shift
++ progname=$1
++ objs=
++ extraldflags=
++ extralibs=
++ shift
++ for arg in $@; do
++ case $arg in
++ *.h.in)
++ $program --alternate="$alternate" --ac-subst $arg
++ ;;
++ *.c.in | *.cpp.in | *.cxx.in | *.cc.in)
++ outfile=`echo "$arg" | sed -e 's/\.in$//'`
++ basename=`echo "$outfile" | sed -e 's/\.[^\.]*$//'` # strip off extension
++ $program --alternate="$alternate" --ac-subst $arg
++ $program --alternate="$alternate" --compile $outfile
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ objs="$objs $basename. at OBJEXT@"
++ ;;
++ *.c | *.cpp | *.cxx | *.cc)
++ basename=`echo "$arg" | sed -e 's/\.[^\.]*$//'` # strip off extension
++ $program --alternate="$alternate" --compile $arg
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ objs="$objs $basename. at OBJEXT@"
++ ;;
++ -L*)
++ extraldflags="$extraldflags $arg"
++ ;;
++ -l*)
++ extralibs="$extralibs $arg"
++ ;;
++ esac
++ done
++ if test -z "$objs"; then
++ echo >&2 "$usage"
++ echo >&2 ""
++ echo >&2 "$me: no object files"
++ exit 1
++ fi
++ echo $compiler $CPPFLAGS $cppflags $CXXFLAGS $cxxflags \
++ $LDFLAGS $ldflags $extraldflags \
++ -o $progname $objs $extralibs $libs $LIBS \
++ | $preformat | sed "$sedformat"
++ $compiler \
++ $CPPFLAGS $cppflags \
++ $CXXFLAGS $cxxflags \
++ $LDFLAGS $ldflags $extraldflags \
++ -o $progname $objs \
++ $extralibs $libs $LIBS
++ retval=$?
++ test $retval -ne 0 && exit $retval
++ exit 0
++ ;;
++ --build-app)
++ case $host in
++ *-darwin*)
++ shift
++ progname=$1
++ shift
++ if test $@; then
++ $program --alternate="$alternate" --build $progname $@ || exit $?
++ fi
++ echo "$me: making Mac OS X application \"$progname.app\""
++ mkdir $progname.app 2>/dev/null
++ mkdir $progname.app/Contents 2>/dev/null
++ mkdir $progname.app/Contents/MacOS 2>/dev/null
++ if test -d $progname.app/Contents/MacOS &&
++ mv -f $progname $progname.app/Contents/MacOS/ &&
++ echo "APPL????" >$progname.app/Contents/PkgInfo &&
++ cat > $progname.app/Contents/Info.plist <<EOF ; then
++<?xml version="1.0" encoding="UTF-8"?>
++<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1
++.0.dtd">
++<plist version="1.0">
++<dict>
++ <key>CFBundleExecutable</key>
++ <string>$progname</string>
++ <key>CFBundlePackageType</key>
++ <string>APPL</string>
++</dict>
++</plist>
++EOF
++ :
++ else
++ echo >&2 "$me: failed to make Mac OS X application"
++ echo >&2 " - problem is probably user permission or disk space related"
++ exit 1
++ fi
++ ;;
++ esac
++ exit 0
++ ;;
++ --setup)
++ # FIXME: scan variables and only modify variables that need modification
++ echo "PATH=\$PATH:$prefix/bin"
++ echo "LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:$prefix/lib"
++ echo "export PATH LD_LIBRARY_PATH"
++ exit 0
++ ;;
++ --setup-front)
++ # FIXME: scan variables and only modify variables that need modification
++ echo "PATH=$prefix/bin:\$PATH"
++ echo "LD_LIBRARY_PATH=$prefix/lib:\$LD_LIBRARY_PATH"
++ echo "export PATH LD_LIBRARY_PATH"
++ exit 0
++ ;;
++ --header)
++ shift
++ classname=$1
++ for header in `find ${prefix}/include/Inventor/@Gui@ -type f | xargs grep -n "^class SO at GUI@_DLL_API ${classname}\>" | cut -d: -f1`; do
++ echo "FILE: ${header}"
++ cat "${header}"
++ done
++ exit 0
++ ;;
++ # ignore some options
++ --alternate=*) ;;
++ --debug) ;;
++ # args not catched until now are invalid
++ *)
++ echo >&2 "$me: Invalid option: \"$1\""
++ echo >&2 "$usage"
++ exit 1
++ ;;
++ esac
++ shift
++done
++
++exit 0
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui.cfg.in
+@@ -0,0 +1,23 @@
++# prefix is determined in so at gui@-config, making the package "movable"
++# prefix="@prefix@"
++host="@host@"
++exec_prefix="@exec_prefix@"
++version="@VERSION@"
++cppflags="@SOGUI_EXTRA_CPPFLAGS@"
++cflags="@SOGUI_EXTRA_CFLAGS@"
++cxxflags="@SOGUI_EXTRA_CXXFLAGS@"
++ldflags="@SOGUI_EXTRA_LDFLAGS@"
++libs="@SOGUI_EXTRA_LIBS@"
++msvcrt="@SOGUI_MSVC_LIBC@"
++datadir="@datarootdir@"
++includedir="@soguiincludedir@"
++frameworkdir="@frameworkdir@"
++compiler="@COIN_COMPILER@"
++AC_SUBST_GUI="@GUI@"
++AC_SUBST_Gui="@Gui@"
++AC_SUBST_gui="@gui@"
++AC_SUBST_WIDGET="@WIDGET@"
++AC_SUBST_EVENT="@EVENT@"
++AC_SUBST_COMPONENTHEADER="@COMPONENTHEADER@"
++compiler_is_gcc=@ac_compiler_gnu@
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/sogui.doxygen.in
+@@ -0,0 +1,1268 @@
++# Doxyfile 1.4.3
++
++# This file describes the settings to be used by the documentation system
++# doxygen (www.doxygen.org) for a project
++#
++# All text after a hash (#) is considered a comment and will be ignored
++# The format is:
++# TAG = value [value, ...]
++# For lists items can also be appended using:
++# TAG += value [value, ...]
++# Values that contain spaces should be placed between quotes (" ")
++
++#---------------------------------------------------------------------------
++# Project related configuration options
++#---------------------------------------------------------------------------
++
++# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
++# by quotes) that should identify the project.
++
++PROJECT_NAME = @PACKAGE@
++
++# The PROJECT_NUMBER tag can be used to enter a project or revision number.
++# This could be handy for archiving the generated documentation or
++# if some version control system is used.
++
++PROJECT_NUMBER = @VERSION@
++
++# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
++# base path where the generated documentation will be put.
++# If a relative path is entered, it will be relative to the location
++# where doxygen was started. If left blank the current directory will be used.
++
++OUTPUT_DIRECTORY =
++
++# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
++# 4096 sub-directories (in 2 levels) under the output directory of each output
++# format and will distribute the generated files over these directories.
++# Enabling this option can be useful when feeding doxygen a huge amount of
++# source files, where putting all generated files in the same directory would
++# otherwise cause performance problems for the file system.
++
++CREATE_SUBDIRS = NO
++
++# The OUTPUT_LANGUAGE tag is used to specify the language in which all
++# documentation generated by doxygen is written. Doxygen will use this
++# information to generate all constant output in the proper language.
++# The default language is English, other supported languages are:
++# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish,
++# Dutch, Finnish, French, German, Greek, Hungarian, Italian, Japanese,
++# Japanese-en (Japanese with English messages), Korean, Korean-en, Norwegian,
++# Polish, Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish,
++# Swedish, and Ukrainian.
++
++OUTPUT_LANGUAGE = English
++
++# This tag can be used to specify the encoding used in the generated output.
++# The encoding is not always determined by the language that is chosen,
++# but also whether or not the output is meant for Windows or non-Windows users.
++# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
++# forces the Windows encoding (this is the default for the Windows binary),
++# whereas setting the tag to NO uses a Unix-style encoding (the default for
++# all platforms other than Windows).
++
++USE_WINDOWS_ENCODING = NO
++
++# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
++# include brief member descriptions after the members that are listed in
++# the file and class documentation (similar to JavaDoc).
++# Set to NO to disable this.
++
++BRIEF_MEMBER_DESC = YES
++
++# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
++# the brief description of a member or function before the detailed description.
++# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
++# brief descriptions will be completely suppressed.
++
++REPEAT_BRIEF = YES
++
++# This tag implements a quasi-intelligent brief description abbreviator
++# that is used to form the text in various listings. Each string
++# in this list, if found as the leading text of the brief description, will be
++# stripped from the text and the result after processing the whole list, is
++# used as the annotated text. Otherwise, the brief description is used as-is.
++# If left blank, the following values are used ("$name" is automatically
++# replaced with the name of the entity): "The $name class" "The $name widget"
++# "The $name file" "is" "provides" "specifies" "contains"
++# "represents" "a" "an" "the"
++
++ABBREVIATE_BRIEF =
++
++# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
++# Doxygen will generate a detailed section even if there is only a brief
++# description.
++
++ALWAYS_DETAILED_SEC = NO
++
++# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
++# inherited members of a class in the documentation of that class as if those
++# members were ordinary class members. Constructors, destructors and assignment
++# operators of the base classes will not be shown.
++
++INLINE_INHERITED_MEMB = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
++# path before files name in the file list and in the header files. If set
++# to NO the shortest path that makes the file name unique will be used.
++
++FULL_PATH_NAMES = NO
++
++# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
++# can be used to strip a user-defined part of the path. Stripping is
++# only done if one of the specified strings matches the left-hand part of
++# the path. The tag can be used to show relative paths in the file list.
++# If left blank the directory from which doxygen is run is used as the
++# path to strip.
++
++STRIP_FROM_PATH =
++
++# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
++# the path mentioned in the documentation of a class, which tells
++# the reader which header file to include in order to use a class.
++# If left blank only the name of the header file containing the class
++# definition is used. Otherwise one should specify the include paths that
++# are normally passed to the compiler using the -I flag.
++
++STRIP_FROM_INC_PATH =
++
++# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
++# (but less readable) file names. This can be useful is your file systems
++# doesn't support long names like on DOS, Mac, or CD-ROM.
++
++SHORT_NAMES = NO
++
++# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
++# will interpret the first line (until the first dot) of a JavaDoc-style
++# comment as the brief description. If set to NO, the JavaDoc
++# comments will behave just like the Qt-style comments (thus requiring an
++# explicit @brief command for a brief description.
++
++JAVADOC_AUTOBRIEF = YES
++
++# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
++# treat a multi-line C++ special comment block (i.e. a block of //! or ///
++# comments) as a brief description. This used to be the default behaviour.
++# The new default is to treat a multi-line C++ comment block as a detailed
++# description. Set this tag to YES if you prefer the old behaviour instead.
++
++MULTILINE_CPP_IS_BRIEF = NO
++
++# If the DETAILS_AT_TOP tag is set to YES then Doxygen
++# will output the detailed description near the top, like JavaDoc.
++# If set to NO, the detailed description appears after the member
++# documentation.
++
++DETAILS_AT_TOP = YES
++
++# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
++# member inherits the documentation from any documented member that it
++# re-implements.
++
++INHERIT_DOCS = YES
++
++# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
++# tag is set to YES, then doxygen will reuse the documentation of the first
++# member in the group (if any) for the other members of the group. By default
++# all members of a group must be documented explicitly.
++
++DISTRIBUTE_GROUP_DOC = NO
++
++# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
++# a new page for each member. If set to NO, the documentation of a member will
++# be part of the file/class/namespace that contains it.
++
++SEPARATE_MEMBER_PAGES = NO
++
++# The TAB_SIZE tag can be used to set the number of spaces in a tab.
++# Doxygen uses this value to replace tabs by spaces in code fragments.
++
++TAB_SIZE = 8
++
++# This tag can be used to specify a number of aliases that acts
++# as commands in the documentation. An alias has the form "name=value".
++# For example adding "sideeffect=\par Side Effects:\n" will allow you to
++# put the command \sideeffect (or @sideeffect) in the documentation, which
++# will result in a user-defined paragraph with heading "Side Effects:".
++# You can put \n's in the value part of an alias to insert newlines.
++
++ALIASES = "COIN=<a href=http://www.coin3d.org><b>Coin</b></a>" \
++ "QT=<a href=http://www.trolltech.com><b>Qt</b></a>"
++
++# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
++# sources only. Doxygen will then generate output that is more tailored for C.
++# For instance, some of the names that are used will be different. The list
++# of all members will be omitted, etc.
++
++OPTIMIZE_OUTPUT_FOR_C = NO
++
++# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
++# only. Doxygen will then generate output that is more tailored for Java.
++# For instance, namespaces will be presented as packages, qualified scopes
++# will look different, etc.
++
++OPTIMIZE_OUTPUT_JAVA = NO
++
++# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
++# the same type (for instance a group of public functions) to be put as a
++# subgroup of that type (e.g. under the Public Functions section). Set it to
++# NO to prevent subgrouping. Alternatively, this can be done per class using
++# the \nosubgrouping command.
++
++SUBGROUPING = YES
++
++#---------------------------------------------------------------------------
++# Build related configuration options
++#---------------------------------------------------------------------------
++
++# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
++# documentation are documented, even if no documentation was available.
++# Private class members and static file members will be hidden unless
++# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
++
++EXTRACT_ALL = NO
++
++# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
++# will be included in the documentation.
++
++EXTRACT_PRIVATE = NO
++
++# If the EXTRACT_STATIC tag is set to YES all static members of a file
++# will be included in the documentation.
++
++EXTRACT_STATIC = NO
++
++# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
++# defined locally in source files will be included in the documentation.
++# If set to NO only classes defined in header files are included.
++
++EXTRACT_LOCAL_CLASSES = NO
++
++# This flag is only useful for Objective-C code. When set to YES local
++# methods, which are defined in the implementation section but not in
++# the interface are included in the documentation.
++# If set to NO (the default) only methods in the interface are included.
++
++EXTRACT_LOCAL_METHODS = NO
++
++# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
++# undocumented members of documented classes, files or namespaces.
++# If set to NO (the default) these members will be included in the
++# various overviews, but no documentation section is generated.
++# This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_MEMBERS = NO
++
++# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
++# undocumented classes that are normally visible in the class hierarchy.
++# If set to NO (the default) these classes will be included in the various
++# overviews. This option has no effect if EXTRACT_ALL is enabled.
++
++HIDE_UNDOC_CLASSES = YES
++
++# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
++# friend (class|struct|union) declarations.
++# If set to NO (the default) these declarations will be included in the
++# documentation.
++
++HIDE_FRIEND_COMPOUNDS = NO
++
++# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
++# documentation blocks found inside the body of a function.
++# If set to NO (the default) these blocks will be appended to the
++# function's detailed documentation block.
++
++HIDE_IN_BODY_DOCS = NO
++
++# The INTERNAL_DOCS tag determines if documentation
++# that is typed after a \internal command is included. If the tag is set
++# to NO (the default) then the documentation will be excluded.
++# Set it to YES to include the internal documentation.
++
++INTERNAL_DOCS = NO
++
++# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
++# file names in lower-case letters. If set to YES upper-case letters are also
++# allowed. This is useful if you have classes or files whose names only differ
++# in case and if your file system supports case sensitive file names. Windows
++# and Mac users are advised to set this option to NO.
++
++CASE_SENSE_NAMES = YES
++
++# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
++# will show members with their full class and namespace scopes in the
++# documentation. If set to YES the scope will be hidden.
++
++HIDE_SCOPE_NAMES = NO
++
++# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
++# will put a list of the files that are included by a file in the documentation
++# of that file.
++
++SHOW_INCLUDE_FILES = YES
++
++# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
++# is inserted in the documentation for inline members.
++
++INLINE_INFO = YES
++
++# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
++# will sort the (detailed) documentation of file and class members
++# alphabetically by member name. If set to NO the members will appear in
++# declaration order.
++
++SORT_MEMBER_DOCS = NO
++
++# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
++# brief documentation of file, namespace and class members alphabetically
++# by member name. If set to NO (the default) the members will appear in
++# declaration order.
++
++SORT_BRIEF_DOCS = NO
++
++# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
++# sorted by fully-qualified names, including namespaces. If set to
++# NO (the default), the class list will be sorted only by class name,
++# not including the namespace part.
++# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
++# Note: This option applies only to the class list, not to the
++# alphabetical list.
++
++SORT_BY_SCOPE_NAME = NO
++
++# The GENERATE_TODOLIST tag can be used to enable (YES) or
++# disable (NO) the todo list. This list is created by putting \todo
++# commands in the documentation.
++
++GENERATE_TODOLIST = YES
++
++# The GENERATE_TESTLIST tag can be used to enable (YES) or
++# disable (NO) the test list. This list is created by putting \test
++# commands in the documentation.
++
++GENERATE_TESTLIST = YES
++
++# The GENERATE_BUGLIST tag can be used to enable (YES) or
++# disable (NO) the bug list. This list is created by putting \bug
++# commands in the documentation.
++
++GENERATE_BUGLIST = YES
++
++# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
++# disable (NO) the deprecated list. This list is created by putting
++# \deprecated commands in the documentation.
++
++GENERATE_DEPRECATEDLIST= YES
++
++# The ENABLED_SECTIONS tag can be used to enable conditional
++# documentation sections, marked by \if sectionname ... \endif.
++
++ENABLED_SECTIONS = SO at GUI@_DOC
++
++# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
++# the initial value of a variable or define consists of for it to appear in
++# the documentation. If the initializer consists of more lines than specified
++# here it will be hidden. Use a value of 0 to hide initializers completely.
++# The appearance of the initializer of individual variables and defines in the
++# documentation can be controlled using \showinitializer or \hideinitializer
++# command in the documentation regardless of this setting.
++
++MAX_INITIALIZER_LINES = 30
++
++# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
++# at the bottom of the documentation of classes and structs. If set to YES the
++# list will mention the files that were used to generate the documentation.
++
++SHOW_USED_FILES = YES
++
++# If the sources in your project are distributed over multiple directories
++# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
++# in the documentation.
++
++SHOW_DIRECTORIES = YES
++
++# The FILE_VERSION_FILTER tag can be used to specify a program or script that
++# doxygen should invoke to get the current version for each file (typically from the
++# version control system). Doxygen will invoke the program by executing (via
++# popen()) the command <command> <input-file>, where <command> is the value of
++# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
++# provided by doxygen. Whatever the progam writes to standard output
++# is used as the file version. See the manual for examples.
++
++FILE_VERSION_FILTER =
++
++#---------------------------------------------------------------------------
++# configuration options related to warning and progress messages
++#---------------------------------------------------------------------------
++
++# The QUIET tag can be used to turn on/off the messages that are generated
++# by doxygen. Possible values are YES and NO. If left blank NO is used.
++
++QUIET = YES
++
++# The WARNINGS tag can be used to turn on/off the warning messages that are
++# generated by doxygen. Possible values are YES and NO. If left blank
++# NO is used.
++
++WARNINGS = YES
++
++# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
++# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
++# automatically be disabled.
++
++WARN_IF_UNDOCUMENTED = YES
++
++# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
++# potential errors in the documentation, such as not documenting some
++# parameters in a documented function, or documenting parameters that
++# don't exist or using markup commands wrongly.
++
++WARN_IF_DOC_ERROR = YES
++
++# This WARN_NO_PARAMDOC option can be abled to get warnings for
++# functions that are documented, but have no documentation for their parameters
++# or return value. If set to NO (the default) doxygen will only warn about
++# wrong or incomplete parameter documentation, but not about the absence of
++# documentation.
++
++WARN_NO_PARAMDOC = NO
++
++# The WARN_FORMAT tag determines the format of the warning messages that
++# doxygen can produce. The string should contain the $file, $line, and $text
++# tags, which will be replaced by the file and line number from which the
++# warning originated and the warning text. Optionally the format may contain
++# $version, which will be replaced by the version of the file (if it could
++# be obtained via FILE_VERSION_FILTER)
++
++WARN_FORMAT = "$file:$line: $text"
++
++# The WARN_LOGFILE tag can be used to specify a file to which warning
++# and error messages should be written. If left blank the output is written
++# to stderr.
++
++WARN_LOGFILE =
++
++#---------------------------------------------------------------------------
++# configuration options related to the input files
++#---------------------------------------------------------------------------
++
++# The INPUT tag can be used to specify the files and/or directories that contain
++# documented source files. You may enter file names like "myfile.cpp" or
++# directories like "/usr/src/myproject". Separate the files or directories
++# with spaces.
++
++INPUT = \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Basic.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Common.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Component.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@ComponentCommon.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Cursor.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Cursor.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@GLWidget.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@GLWidgetCommon.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Object.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@Object.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@RenderArea.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/So at Gui@RenderArea.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@Device.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@DeviceCommon.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@Keyboard.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@KeyboardCommon.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@Mouse.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/devices/So at Gui@MouseCommon.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FlyViewer.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@FullViewer.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@Viewer.cpp \
++ @path_tag@@sogui_build_dir@/src/Inventor/@Gui@/viewers/So at Gui@Viewer.h \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/So at Gui@.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/So at Gui@Component.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/So at Gui@GLWidget.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/devices/So at Gui@Device.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/devices/So at Gui@Keyboard.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/devices/So at Gui@Mouse.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/viewers/ExaminerViewer.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/viewers/FullViewer.cpp \
++ @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/viewers/PlaneViewer.cpp
++
++# If the value of the INPUT tag contains directories, you can use the
++# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
++# and *.h) to filter out the source-files in the directories. If left
++# blank the following patterns are tested:
++# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
++# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm
++
++FILE_PATTERNS =
++
++# The RECURSIVE tag can be used to turn specify whether or not subdirectories
++# should be searched for input files as well. Possible values are YES and NO.
++# If left blank NO is used.
++
++RECURSIVE = NO
++
++# The EXCLUDE tag can be used to specify files and/or directories that should
++# excluded from the INPUT source files. This way you can easily exclude a
++# subdirectory from a directory tree whose root is specified with the INPUT tag.
++
++EXCLUDE =
++
++# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
++# directories that are symbolic links (a Unix filesystem feature) are excluded
++# from the input.
++
++EXCLUDE_SYMLINKS = NO
++
++# If the value of the INPUT tag contains directories, you can use the
++# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
++# certain files from those directories.
++
++EXCLUDE_PATTERNS =
++
++# The EXAMPLE_PATH tag can be used to specify one or more files or
++# directories that contain example code fragments that are included (see
++# the \include command).
++
++EXAMPLE_PATH =
++
++# If the value of the EXAMPLE_PATH tag contains directories, you can use the
++# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
++# and *.h) to filter out the source-files in the directories. If left
++# blank all files are included.
++
++EXAMPLE_PATTERNS =
++
++# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
++# searched for input files to be used with the \include or \dontinclude
++# commands irrespective of the value of the RECURSIVE tag.
++# Possible values are YES and NO. If left blank NO is used.
++
++EXAMPLE_RECURSIVE = NO
++
++# The IMAGE_PATH tag can be used to specify one or more files or
++# directories that contain image that are included in the documentation (see
++# the \image command).
++
++IMAGE_PATH =
++
++# The INPUT_FILTER tag can be used to specify a program that doxygen should
++# invoke to filter for each input file. Doxygen will invoke the filter program
++# by executing (via popen()) the command <filter> <input-file>, where <filter>
++# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
++# input file. Doxygen will then use the output that the filter program writes
++# to standard output. If FILTER_PATTERNS is specified, this tag will be
++# ignored.
++
++INPUT_FILTER =
++
++# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
++# basis. Doxygen will compare the file name with each pattern and apply the
++# filter if there is a match. The filters are a list of the form:
++# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
++# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
++# is applied to all files.
++
++FILTER_PATTERNS =
++
++# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
++# INPUT_FILTER) will be used to filter the input files when producing source
++# files to browse (i.e. when SOURCE_BROWSER is set to YES).
++
++FILTER_SOURCE_FILES = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to source browsing
++#---------------------------------------------------------------------------
++
++# If the SOURCE_BROWSER tag is set to YES then a list of source files will
++# be generated. Documented entities will be cross-referenced with these sources.
++# Note: To get rid of all source code in the generated output, make sure also
++# VERBATIM_HEADERS is set to NO.
++
++SOURCE_BROWSER = NO
++
++# Setting the INLINE_SOURCES tag to YES will include the body
++# of functions and classes directly in the documentation.
++
++INLINE_SOURCES = NO
++
++# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
++# doxygen to hide any special comment blocks from generated source code
++# fragments. Normal C and C++ comments will always remain visible.
++
++STRIP_CODE_COMMENTS = YES
++
++# If the REFERENCED_BY_RELATION tag is set to YES (the default)
++# then for each documented function all documented
++# functions referencing it will be listed.
++
++REFERENCED_BY_RELATION = YES
++
++# If the REFERENCES_RELATION tag is set to YES (the default)
++# then for each documented function all documented entities
++# called/used by that function will be listed.
++
++REFERENCES_RELATION = YES
++
++# If the USE_HTAGS tag is set to YES then the references to source code
++# will point to the HTML generated by the htags(1) tool instead of doxygen
++# built-in source browser. The htags tool is part of GNU's global source
++# tagging system (see http://www.gnu.org/software/global/global.html). You
++# will need version 4.8.6 or higher.
++
++USE_HTAGS = NO
++
++# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
++# will generate a verbatim copy of the header file for each class for
++# which an include is specified. Set to NO to disable this.
++
++VERBATIM_HEADERS = YES
++
++#---------------------------------------------------------------------------
++# configuration options related to the alphabetical class index
++#---------------------------------------------------------------------------
++
++# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
++# of all compounds will be generated. Enable this if the project
++# contains a lot of classes, structs, unions or interfaces.
++
++ALPHABETICAL_INDEX = NO
++
++# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
++# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
++# in which this list will be split (can be a number in the range [1..20])
++
++COLS_IN_ALPHA_INDEX = 5
++
++# In case all classes in a project start with a common prefix, all
++# classes will be put under the same header in the alphabetical index.
++# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
++# should be ignored while generating the index headers.
++
++IGNORE_PREFIX =
++
++#---------------------------------------------------------------------------
++# configuration options related to the HTML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
++# generate HTML output.
++
++GENERATE_HTML = @SOGUI_DOC_HTML@
++
++# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `html' will be used as the default path.
++
++HTML_OUTPUT = @sogui_html_dir@
++
++# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
++# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
++# doxygen will generate files with .html extension.
++
++HTML_FILE_EXTENSION = .html
++
++# The HTML_HEADER tag can be used to specify a personal HTML header for
++# each generated HTML page. If it is left blank doxygen will generate a
++# standard header.
++
++HTML_HEADER = @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/common/docs/doxygen/header.html
++
++# The HTML_FOOTER tag can be used to specify a personal HTML footer for
++# each generated HTML page. If it is left blank doxygen will generate a
++# standard footer.
++
++HTML_FOOTER = @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/common/docs/doxygen/footer.html
++
++# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
++# style sheet that is used by each HTML page. It can be used to
++# fine-tune the look of the HTML output. If the tag is left blank doxygen
++# will generate a default style sheet. Note that doxygen will try to copy
++# the style sheet file to the HTML output directory, so don't put your own
++# stylesheet in the HTML output directory as well, or it will be erased!
++
++HTML_STYLESHEET = @path_tag@@sogui_src_dir@/src/Inventor/@Gui@/common/docs/doxygen/stylesheet.css
++
++# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
++# files or namespaces will be aligned in HTML using tables. If set to
++# NO a bullet list will be used.
++
++HTML_ALIGN_MEMBERS = YES
++
++# If the GENERATE_HTMLHELP tag is set to YES, additional index files
++# will be generated that can be used as input for tools like the
++# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
++# of the generated HTML documentation.
++
++GENERATE_HTMLHELP = @SOGUI_DOC_HTML_HELP@
++
++# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
++# be used to specify the file name of the resulting .chm file. You
++# can add a path in front of the file if the result should not be
++# written to the html output directory.
++
++CHM_FILE = @path_tag@@sogui_html_help_dir@/So at Gui@- at SOGUI_MAJOR_VERSION@.chm
++
++# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
++# be used to specify the location (absolute path including file name) of
++# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
++# the HTML help compiler on the generated index.hhp.
++
++HHC_LOCATION = @path_tag@@sim_ac_hhc_exe@
++
++# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
++# controls if a separate .chi index file is generated (YES) or that
++# it should be included in the master .chm file (NO).
++
++GENERATE_CHI = NO
++
++# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
++# controls whether a binary table of contents is generated (YES) or a
++# normal table of contents (NO) in the .chm file.
++
++BINARY_TOC = NO
++
++# The TOC_EXPAND flag can be set to YES to add extra items for group members
++# to the contents of the HTML help documentation and to the tree view.
++
++TOC_EXPAND = NO
++
++# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
++# top of each HTML page. The value NO (the default) enables the index and
++# the value YES disables it.
++
++DISABLE_INDEX = NO
++
++# This tag can be used to set the number of enum values (range [1..20])
++# that doxygen will group on one line in the generated HTML documentation.
++
++ENUM_VALUES_PER_LINE = 4
++
++# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
++# generated containing a tree-like index structure (just like the one that
++# is generated for HTML Help). For this to work a browser that supports
++# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
++# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
++# probably better off using the HTML help feature.
++
++GENERATE_TREEVIEW = NO
++
++# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
++# used to set the initial width (in pixels) of the frame in which the tree
++# is shown.
++
++TREEVIEW_WIDTH = 250
++
++#---------------------------------------------------------------------------
++# configuration options related to the LaTeX output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
++# generate Latex output.
++
++GENERATE_LATEX = NO
++
++# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `latex' will be used as the default path.
++
++LATEX_OUTPUT =
++
++# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
++# invoked. If left blank `latex' will be used as the default command name.
++
++LATEX_CMD_NAME = latex
++
++# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
++# generate index for LaTeX. If left blank `makeindex' will be used as the
++# default command name.
++
++MAKEINDEX_CMD_NAME = makeindex
++
++# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
++# LaTeX documents. This may be useful for small projects and may help to
++# save some trees in general.
++
++COMPACT_LATEX = NO
++
++# The PAPER_TYPE tag can be used to set the paper type that is used
++# by the printer. Possible values are: a4, a4wide, letter, legal and
++# executive. If left blank a4wide will be used.
++
++PAPER_TYPE = a4wide
++
++# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
++# packages that should be included in the LaTeX output.
++
++EXTRA_PACKAGES =
++
++# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
++# the generated latex document. The header should contain everything until
++# the first chapter. If it is left blank doxygen will generate a
++# standard header. Notice: only use this tag if you know what you are doing!
++
++LATEX_HEADER =
++
++# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
++# is prepared for conversion to pdf (using ps2pdf). The pdf file will
++# contain links (just like the HTML output) instead of page references
++# This makes the output suitable for online browsing using a pdf viewer.
++
++PDF_HYPERLINKS = NO
++
++# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
++# plain latex in the generated Makefile. Set this option to YES to get a
++# higher quality PDF documentation.
++
++USE_PDFLATEX = NO
++
++# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
++# command to the generated LaTeX files. This will instruct LaTeX to keep
++# running if errors occur, instead of asking the user for help.
++# This option is also used when generating formulas in HTML.
++
++LATEX_BATCHMODE = NO
++
++# If LATEX_HIDE_INDICES is set to YES then doxygen will not
++# include the index chapters (such as File Index, Compound Index, etc.)
++# in the output.
++
++LATEX_HIDE_INDICES = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the RTF output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
++# The RTF output is optimized for Word 97 and may not look very pretty with
++# other RTF readers or editors.
++
++GENERATE_RTF = NO
++
++# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `rtf' will be used as the default path.
++
++RTF_OUTPUT = rtf
++
++# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
++# RTF documents. This may be useful for small projects and may help to
++# save some trees in general.
++
++COMPACT_RTF = NO
++
++# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
++# will contain hyperlink fields. The RTF file will
++# contain links (just like the HTML output) instead of page references.
++# This makes the output suitable for online browsing using WORD or other
++# programs which support those fields.
++# Note: wordpad (write) and others do not support links.
++
++RTF_HYPERLINKS = NO
++
++# Load stylesheet definitions from file. Syntax is similar to doxygen's
++# config file, i.e. a series of assignments. You only have to provide
++# replacements, missing definitions are set to their default value.
++
++RTF_STYLESHEET_FILE =
++
++# Set optional variables used in the generation of an rtf document.
++# Syntax is similar to doxygen's config file.
++
++RTF_EXTENSIONS_FILE =
++
++#---------------------------------------------------------------------------
++# configuration options related to the man page output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
++# generate man pages
++
++GENERATE_MAN = @SOGUI_DOC_MAN@
++
++# The MAN_OUTPUT tag is used to specify where the man pages will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `man' will be used as the default path.
++
++MAN_OUTPUT = @sogui_man_dir@
++
++# The MAN_EXTENSION tag determines the extension that is added to
++# the generated man pages (default is the subroutine's section .3)
++
++MAN_EXTENSION = .3
++
++# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
++# then it will generate one additional man file for each entity
++# documented in the real man page(s). These additional files
++# only source the real man page, but without them the man command
++# would be unable to find the correct page. The default is NO.
++
++MAN_LINKS = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the XML output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_XML tag is set to YES Doxygen will
++# generate an XML file that captures the structure of
++# the code including all documentation.
++
++GENERATE_XML = NO
++
++# The XML_OUTPUT tag is used to specify where the XML pages will be put.
++# If a relative path is entered the value of OUTPUT_DIRECTORY will be
++# put in front of it. If left blank `xml' will be used as the default path.
++
++XML_OUTPUT = xml
++
++# The XML_SCHEMA tag can be used to specify an XML schema,
++# which can be used by a validating XML parser to check the
++# syntax of the XML files.
++
++XML_SCHEMA =
++
++# The XML_DTD tag can be used to specify an XML DTD,
++# which can be used by a validating XML parser to check the
++# syntax of the XML files.
++
++XML_DTD =
++
++# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
++# dump the program listings (including syntax highlighting
++# and cross-referencing information) to the XML output. Note that
++# enabling this will significantly increase the size of the XML output.
++
++XML_PROGRAMLISTING = YES
++
++#---------------------------------------------------------------------------
++# configuration options for the AutoGen Definitions output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
++# generate an AutoGen Definitions (see autogen.sf.net) file
++# that captures the structure of the code including all
++# documentation. Note that this feature is still experimental
++# and incomplete at the moment.
++
++GENERATE_AUTOGEN_DEF = NO
++
++#---------------------------------------------------------------------------
++# configuration options related to the Perl module output
++#---------------------------------------------------------------------------
++
++# If the GENERATE_PERLMOD tag is set to YES Doxygen will
++# generate a Perl module file that captures the structure of
++# the code including all documentation. Note that this
++# feature is still experimental and incomplete at the
++# moment.
++
++GENERATE_PERLMOD = NO
++
++# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
++# the necessary Makefile rules, Perl scripts and LaTeX code to be able
++# to generate PDF and DVI output from the Perl module output.
++
++PERLMOD_LATEX = NO
++
++# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
++# nicely formatted so it can be parsed by a human reader. This is useful
++# if you want to understand what is going on. On the other hand, if this
++# tag is set to NO the size of the Perl module output will be much smaller
++# and Perl will parse it just the same.
++
++PERLMOD_PRETTY = YES
++
++# The names of the make variables in the generated doxyrules.make file
++# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
++# This is useful so different doxyrules.make files included by the same
++# Makefile don't overwrite each other's variables.
++
++PERLMOD_MAKEVAR_PREFIX =
++
++#---------------------------------------------------------------------------
++# Configuration options related to the preprocessor
++#---------------------------------------------------------------------------
++
++# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
++# evaluate all C-preprocessor directives found in the sources and include
++# files.
++
++ENABLE_PREPROCESSING = YES
++
++# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
++# names in the source code. If set to NO (the default) only conditional
++# compilation will be performed. Macro expansion can be done in a controlled
++# way by setting EXPAND_ONLY_PREDEF to YES.
++
++MACRO_EXPANSION = YES
++
++# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
++# then the macro expansion is limited to the macros specified with the
++# PREDEFINED and EXPAND_AS_PREDEFINED tags.
++
++EXPAND_ONLY_PREDEF = NO
++
++# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
++# in the INCLUDE_PATH (see below) will be search if a #include is found.
++
++SEARCH_INCLUDES = YES
++
++# The INCLUDE_PATH tag can be used to specify one or more directories that
++# contain include files that are not input files but should be processed by
++# the preprocessor.
++
++INCLUDE_PATH =
++
++# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
++# patterns (like *.h and *.hpp) to filter out the header-files in the
++# directories. If left blank, the patterns specified with FILE_PATTERNS will
++# be used.
++
++INCLUDE_FILE_PATTERNS =
++
++# The PREDEFINED tag can be used to specify one or more macro names that
++# are defined before the preprocessor is started (similar to the -D option of
++# gcc). The argument of the tag is a list of macros of the form: name
++# or name=definition (no spaces). If the definition and the = are
++# omitted =1 is assumed. To prevent a macro definition from being
++# undefined via #undef or recursively expanded use the := operator
++# instead of the = operator.
++
++PREDEFINED = DOXYGEN_SKIP_THIS \
++ __COIN_SO at GUI@__
++
++# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
++# this tag can be used to specify a list of macro names that should be expanded.
++# The macro definition that is found in the sources will be used.
++# Use the PREDEFINED tag if you want to use a different macro definition.
++
++EXPAND_AS_DEFINED =
++
++# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
++# doxygen's preprocessor will remove all function-like macros that are alone
++# on a line, have an all uppercase name, and do not end with a semicolon. Such
++# function macros are typically used for boiler-plate code, and will confuse
++# the parser if not removed.
++
++SKIP_FUNCTION_MACROS = YES
++
++#---------------------------------------------------------------------------
++# Configuration::additions related to external references
++#---------------------------------------------------------------------------
++
++# The TAGFILES option can be used to specify one or more tagfiles.
++# Optionally an initial location of the external documentation
++# can be added for each tagfile. The format of a tag file without
++# this location is as follows:
++# TAGFILES = file1 file2 ...
++# Adding location for the tag files is done as follows:
++# TAGFILES = file1=loc1 "file2 = loc2" ...
++# where "loc1" and "loc2" can be relative or absolute paths or
++# URLs. If a location is present for each tag, the installdox tool
++# does not have to be run to correct the links.
++# Note that each tag file must have a unique name
++# (where the name does NOT include the path)
++# If a tag file is not located in the directory in which doxygen
++# is run, you must also specify the path to the tagfile here.
++
++TAGFILES =
++
++# When a file name is specified after GENERATE_TAGFILE, doxygen will create
++# a tag file that is based on the input files it reads.
++
++GENERATE_TAGFILE =
++
++# If the ALLEXTERNALS tag is set to YES all external classes will be listed
++# in the class index. If set to NO only the inherited external classes
++# will be listed.
++
++ALLEXTERNALS = NO
++
++# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
++# in the modules index. If set to NO, only the current project's groups will
++# be listed.
++
++EXTERNAL_GROUPS = YES
++
++# The PERL_PATH should be the absolute path and name of the perl script
++# interpreter (i.e. the result of `which perl').
++
++PERL_PATH = @sim_ac_perl_exe@
++
++#---------------------------------------------------------------------------
++# Configuration options related to the dot tool
++#---------------------------------------------------------------------------
++
++# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
++# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
++# or super classes. Setting the tag to NO turns the diagrams off. Note that
++# this option is superseded by the HAVE_DOT option below. This is only a
++# fallback. It is recommended to install and use dot, since it yields more
++# powerful graphs.
++
++CLASS_DIAGRAMS = YES
++
++# If set to YES, the inheritance and collaboration graphs will hide
++# inheritance and usage relations if the target is undocumented
++# or is not a class.
++
++HIDE_UNDOC_RELATIONS = NO
++
++# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
++# available from the path. This tool is part of Graphviz, a graph visualization
++# toolkit from AT&T and Lucent Bell Labs. The other options in this section
++# have no effect if this option is set to NO (the default)
++
++HAVE_DOT = NO
++
++# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for each documented class showing the direct and
++# indirect inheritance relations. Setting this tag to YES will force the
++# the CLASS_DIAGRAMS tag to NO.
++
++CLASS_GRAPH = YES
++
++# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for each documented class showing the direct and
++# indirect implementation dependencies (inheritance, containment, and
++# class references variables) of the class with other documented classes.
++
++COLLABORATION_GRAPH = YES
++
++# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
++# will generate a graph for groups, showing the direct groups dependencies
++
++GROUP_GRAPHS = YES
++
++# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
++# collaboration diagrams in a style similar to the OMG's Unified Modeling
++# Language.
++
++UML_LOOK = NO
++
++# If set to YES, the inheritance and collaboration graphs will show the
++# relations between templates and their instances.
++
++TEMPLATE_RELATIONS = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
++# tags are set to YES then doxygen will generate a graph for each documented
++# file showing the direct and indirect include dependencies of the file with
++# other documented files.
++
++INCLUDE_GRAPH = YES
++
++# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
++# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
++# documented header file showing the documented files that directly or
++# indirectly include this file.
++
++INCLUDED_BY_GRAPH = YES
++
++# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
++# generate a call dependency graph for every global function or class method.
++# Note that enabling this option will significantly increase the time of a run.
++# So in most cases it will be better to enable call graphs for selected
++# functions only using the \callgraph command.
++
++CALL_GRAPH = NO
++
++# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
++# will graphical hierarchy of all classes instead of a textual one.
++
++GRAPHICAL_HIERARCHY = YES
++
++# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
++# then doxygen will show the dependencies a directory has on other directories
++# in a graphical way. The dependency relations are determined by the #include
++# relations between the files in the directories.
++
++DIRECTORY_GRAPH = YES
++
++# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
++# generated by dot. Possible values are png, jpg, or gif
++# If left blank png will be used.
++
++DOT_IMAGE_FORMAT = png
++
++# The tag DOT_PATH can be used to specify the path where the dot tool can be
++# found. If left blank, it is assumed the dot tool can be found in the path.
++
++DOT_PATH =
++
++# The DOTFILE_DIRS tag can be used to specify one or more directories that
++# contain dot files that are included in the documentation (see the
++# \dotfile command).
++
++DOTFILE_DIRS =
++
++# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
++# (in pixels) of the graphs generated by dot. If a graph becomes larger than
++# this value, doxygen will try to truncate the graph, so that it fits within
++# the specified constraint. Beware that most browsers cannot cope with very
++# large images.
++
++MAX_DOT_GRAPH_WIDTH = 1024
++
++# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
++# (in pixels) of the graphs generated by dot. If a graph becomes larger than
++# this value, doxygen will try to truncate the graph, so that it fits within
++# the specified constraint. Beware that most browsers cannot cope with very
++# large images.
++
++MAX_DOT_GRAPH_HEIGHT = 1024
++
++# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
++# graphs generated by dot. A depth value of 3 means that only nodes reachable
++# from the root by following a path via at most 3 edges will be shown. Nodes
++# that lay further from the root node will be omitted. Note that setting this
++# option to 1 or 2 may greatly reduce the computation time needed for large
++# code bases. Also note that a graph may be further truncated if the graph's
++# image dimensions are not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH
++# and MAX_DOT_GRAPH_HEIGHT). If 0 is used for the depth value (the default),
++# the graph is not depth-constrained.
++
++MAX_DOT_GRAPH_DEPTH = 0
++
++# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
++# background. This is disabled by default, which results in a white background.
++# Warning: Depending on the platform used, enabling this option may lead to
++# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
++# read).
++
++DOT_TRANSPARENT = NO
++
++# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
++# files in one run (i.e. multiple -o and -T options on the command line). This
++# makes dot run faster, but since only newer versions of dot (>1.8.10)
++# support this, this feature is disabled by default.
++
++DOT_MULTI_TARGETS = NO
++
++# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
++# generate a legend page explaining the meaning of the various boxes and
++# arrows in the dot generated graphs.
++
++GENERATE_LEGEND = YES
++
++# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
++# remove the intermediate dot files that are used to generate
++# the various graphs.
++
++DOT_CLEANUP = YES
++
++#---------------------------------------------------------------------------
++# Configuration::additions related to the search engine
++#---------------------------------------------------------------------------
++
++# The SEARCHENGINE tag specifies whether or not a search engine should be
++# used. If set to NO the values of all tags below this one will be ignored.
++
++SEARCHENGINE = NO
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/soguidefs.h.in
+@@ -0,0 +1,165 @@
++#ifndef SO at GUI@_INTERNALDEFS_H
++#define SO at GUI@_INTERNALDEFS_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/* ********************************************************************** */
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++/* ********************************************************************** */
++
++#ifdef __FILE__
++#define SO at GUI@_STUB_FILE __FILE__
++#else
++/* FIXME: avoid this case by redefining the compilation rules to define the
++ current filename in some variable. [20010919 larsa] */
++#define SO at GUI@_STUB_FILE ((char *)0L)
++#endif
++
++#ifdef __LINE__
++#define SO at GUI@_STUB_LINE __LINE__
++#else
++#define SO at GUI@_STUB_LINE 0
++#endif
++
++#ifdef __cplusplus
++#ifdef HAVE_CPP_COMPILER_FUNCTION_NAME_VAR
++#define SO at GUI@_STUB_FUNC HAVE_CPP_COMPILER_FUNCTION_NAME_VAR
++#else
++#define SO at GUI@_STUB_FUNC ((const char *)0L)
++#endif
++#else /* !__cplusplus */
++#ifdef HAVE_C_COMPILER_FUNCTION_NAME_VAR
++#define SO at GUI@_STUB_FUNC HAVE_C_COMPILER_FUNCTION_NAME_VAR
++#else
++#define SO at GUI@_STUB_FUNC ((const char *)0L)
++#endif
++#endif /* !__cplusplus */
++
++#if SO at GUI@_DEBUG
++
++#include <Inventor/errors/SoDebugError.h>
++
++/*
++ This stupid thing is here to silence some compilers that complain on
++ constant if-expressions.
++*/
++
++inline int so at gui@_not_null(const void * arg) { return (arg != NULL) ? 1 : 0; }
++
++
++/* Collects common code from SO at GUI@_STUB(), SO at GUI@_STUB()_ONCE and
++ SO at GUI@_OBSOLETED(). */
++
++#define SO at GUI@_FUNCTIONIDENTIFIER(SO at GUI@STR) \
++ SbString SO at GUI@STR(so at gui@_not_null(SO at GUI@_STUB_FILE) ? SO at GUI@_STUB_FILE : ""); \
++ if (SO at GUI@STR.getLength() > 0) { SO at GUI@STR += ':'; } \
++ SO at GUI@STR += SbString((int)SO at GUI@_STUB_LINE); SO at GUI@STR += ':'; \
++ SO at GUI@STR += so at gui@_not_null(SO at GUI@_STUB_FUNC) ? SO at GUI@_STUB_FUNC : ""
++
++/*
++ SO at GUI@_STUB(): a macro that prints out stub information.
++ Used where there is functionality missing.
++*/
++
++#define SO at GUI@_STUB() \
++ do { \
++ SO at GUI@_FUNCTIONIDENTIFIER(s); \
++ SoDebugError::postWarning(s.getString(), \
++ "STUB: functionality not yet completed"); \
++ } while (0)
++
++/*
++ SO at GUI@_STUB_ONCE(): a macro that prints out stub information, but only on
++ the first pass. Used where there is functionality missing that may be
++ called hundreds of times.
++*/
++
++#define SO at GUI@_STUB_ONCE() \
++ do { \
++ static int first = 1; \
++ if (first) { \
++ SO at GUI@_FUNCTIONIDENTIFIER(s); \
++ SoDebugError::postWarning(s.getString(), \
++ "STUB: functionality not yet completed " \
++ "(first and last warning)"); \
++ first = 0; \
++ } \
++ } while (0)
++
++/*
++ SO at GUI@_OBSOLETED(): a macro that prints out information about an obsoleted
++ function still being in use.
++*/
++
++#define SO at GUI@_OBSOLETED() \
++ do { \
++ SO at GUI@_FUNCTIONIDENTIFIER(s); \
++ SoDebugError::post(s.getString(), \
++ "OBSOLETED: functionality no longer supported"); \
++ } while (0)
++
++#else /* !SO at GUI@_DEBUG */
++
++/* snub the stubs */
++#define SO at GUI@_STUB() do { } while (0)
++#define SO at GUI@_STUB_ONCE() do { } while (0)
++#define SO at GUI@_OBSOLETED() do { } while (0)
++
++#endif /* !SO at GUI@_DEBUG */
++
++/*
++ GETTEXT support
++*/
++
++#if defined(ENABLE_NLS) && defined(HAVE_GETTEXT)
++#include <libintl.h>
++#define _(String) dgettext (PACKAGE, String)
++#define N_(String) (String)
++#else
++#define _(String) (String)
++#define N_(String) (String)
++#endif /* HAVE_GETTEXT && ENABLE_NLS */
++
++/* ********************************************************************** */
++
++#endif /* ! SO at GUI@_INTERNALDEFS_H */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput.h.in
+@@ -0,0 +1,53 @@
++#ifndef COIN_SPWINPUT_H
++#define COIN_SPWINPUT_H
++
++/* @configure_input@ */
++
++/*----------------------------------------------------------------------
++ * (C) 1999 Spacetec IMC Corporation ("Spacetec").
++ *
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby granted provided that this copyright
++ * notice appears in all copies. Permission to modify this software is granted
++ * and Spacetec will support such modifications only if said modifications are
++ * approved by Spacetec.
++ *
++ */
++
++#define SPW_INPUT_MAJOR 7
++#define SPW_INPUT_MINOR 6
++#define SPW_INPUT_UPDATE 0
++#define SPW_INPUT_BUILD 1
++#define SPW_INPUT_VERSION "7.6.0.1"
++#define SPW_INPUT_DATE _T("January 18, 1999")
++
++#define SPW_MAXBUF 80
++
++typedef enum {
++ SPW_InputMotionEvent=1, /* Event type is a motion event */
++ SPW_InputButtonPressEvent=2, /* Event type is a button press event */
++ SPW_InputButtonReleaseEvent=3 /* Event type is a button release event */
++} SPW_InputEventType;
++
++typedef struct {
++ unsigned int old; /* The last state of the buttons */
++ unsigned int current; /* The current state of the buttons */
++ unsigned int pressed; /* Which buttons were pressed */
++ unsigned int released; /* Which buttons were released */
++} SPW_InputButtonTable;
++
++typedef struct {
++ short int type; /* The type of event */
++ float fData[7]; /* The float Spaceball data */
++ short int sData[7]; /* The integer Spaceball data */
++ int buttonNumber; /* The button number for this event */
++ SPW_InputButtonTable buttonState; /* The state of the buttons */
++ char string[SPW_MAXBUF]; /* Extra data area */
++} SPW_InputEvent;
++
++/* These two methods should only be used under X */
++int SPW_CheckForSpaceballX11(void * display, int winid, char * product);
++int SPW_TranslateEventX11(void * display, void * xevent, SPW_InputEvent * sbEvent);
++/* FIXME: add two similar methods for WIN32. pederb, 20001114 */
++
++#endif /* COIN_SPWINPUT_H */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput_win32.c.in
+@@ -0,0 +1,1418 @@
++/* @configure_input@ */
++
++/*----------------------------------------------------------------------
++ * (C) 1998-2009 3Dconnexion. All rights reserved.
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby grated provided that this copyright
++ * notice appears in all copies. Permission to modify this software is granted
++ * and 3Dconnexion will support such modifications only is said modifications are
++ * approved by 3Dconnexion.
++ *
++ */
++/*
++ * The module contains interface routines to the Si library routines contained
++ * in the associated Dynamic Link Library. The DLL is loaded explicitly when
++ * Si is initialized. When the DLL is loaded, the initialization routine finds
++ * the addresses of the routines that it exposes to the world. Once this is
++ * done the library routines are used as if they were part of the original
++ * source code.
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#ifdef HAVE_WIN32_API /* Only compile this file when the Win32 API is available */
++
++#define SPW_DEFINE_COPYRIGHT
++#define SPW_DEFINE_GLOBALS
++
++#include <windows.h>
++#include <Inventor/@Gui@/devices/spwinput_win32.h>
++
++
++/* DLL library name */
++
++static LPCTSTR DllLibrary = "siappdll";
++
++
++/* names of DLL variables used in DLL */
++
++static LPCSTR strDLLRetVal = "SpwErrorVal";
++
++/*typedef enum SpwRetVal SpwReturnValue;*/
++/* Names of functions contained in DLL; used to find their addresses at load
++ time */
++
++static LPCSTR fnSiBeep = "SiBeep";
++static LPCSTR fnSiInitialize = "SiInitialize";
++static LPCSTR fnSiTerminate = "SiTerminate";
++static LPCSTR fnSiGetDeviceID = "SiGetDeviceID";
++static LPCSTR fnSiGetNumDevices = "SiGetNumDevices";
++static LPCSTR fnSiDeviceIndex = "SiDeviceIndex";
++static LPCSTR fnSiDispatch = "SiDispatch";
++static LPCSTR fnSiIsSpaceWareEvent = "SiIsSpaceWareEvent";
++static LPCSTR fnSiOpenWinInit = "SiOpenWinInit";
++static LPCSTR fnSiOpen = "SiOpen";
++static LPCSTR fnSiClose = "SiClose";
++static LPCSTR fnSiGetEventWinInit = "SiGetEventWinInit";
++static LPCSTR fnSiGetEvent = "SiGetEvent";
++static LPCSTR fnSiRezero = "SiRezero";
++static LPCSTR fnSiGrabDevice = "SiGrabDevice";
++static LPCSTR fnSiReleaseDevice = "SiReleaseDevice";
++static LPCSTR fnSiButtonPressed = "SiButtonPressed";
++static LPCSTR fnSiButtonReleased = "SiButtonReleased";
++static LPCSTR fnSiSetUIMode = "SiSetUiMode";
++static LPCSTR fnSiGetDevicePort = "SiGetDevicePort";
++static LPCSTR fnSiGetDriverInfo = "SiGetDriverInfo";
++static LPCSTR fnSiGetLibraryInfo = "SiGetLibraryInfo";
++static LPCSTR fnSiGetDeviceInfo = "SiGetDeviceInfo";
++static LPCSTR fnSpwErrorString = "SpwErrorString";
++
++/* DLL initialization status */
++static enum InitResult gInitStatus = NOT_LOADED;
++
++/* DLL handle */
++HINSTANCE ghDll;
++enum SpwRetVal SpwErrorVal;
++
++/* Device handle */
++SiHdl Spw_DeviceHandle = SI_NO_HANDLE;
++
++/* Check to see if we can open a device handle to the spaceball */
++int SPW_SpaceBallExistsWin32(void)
++{
++ SiOpenData oData;
++ SiOpenWinInit(&oData,NULL);
++ return (SiOpen("", SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData) != SI_NO_HANDLE) ? TRUE : FALSE;
++}
++
++/* check if can open a handle to the spaceball, load the driver functions
++ and start receiving input from the spaceball */
++int SPW_CheckForSpaceballWin32(void * win)
++{
++ char classname[25];
++ SiOpenData oData;
++
++ if (Spw_DeviceHandle == SI_NO_HANDLE) {
++ if (SiInitialize() != SPW_DLL_LOAD_ERROR) {
++ GetClassName((HWND)win, classname, sizeof(classname));
++ SiOpenWinInit(&oData, (HWND)win);
++
++ Spw_DeviceHandle = SiOpen(classname, SI_ANY_DEVICE, SI_NO_MASK, SI_EVENT, &oData);
++
++ if (Spw_DeviceHandle != SI_NO_HANDLE) {
++ SiSetUiMode(Spw_DeviceHandle, SI_UI_ALL_CONTROLS);
++ return TRUE;
++ }
++ else {
++ SiTerminate();
++ return FALSE;
++ }
++ }
++ else return FALSE;
++ }
++ else return TRUE;
++}
++
++/* translates a Win32 event to a SPW_InputEvent. */
++int SPW_TranslateEventWin32(MSG * msg, SPW_InputEvent * sbEvent)
++{
++ SiSpwEvent spwEvent;
++ SiGetEventData eventdata;
++
++ if (Spw_DeviceHandle != SI_NO_HANDLE) {
++
++ SiGetEventWinInit (&eventdata, msg->message, msg->wParam, msg->lParam);
++ if (SiGetEvent (Spw_DeviceHandle, 0, &eventdata, &spwEvent) == SI_IS_EVENT) {
++
++ int i;
++ switch(spwEvent.type) {
++ case SI_MOTION_EVENT:
++ sbEvent->type = SPW_InputMotionEvent;
++ for(i=0; i<6; i++) {
++ sbEvent->sData[i] = (short)spwEvent.u.spwData.mData[i];
++ }
++ break;
++ case SI_BUTTON_EVENT:
++ sbEvent->type = SPW_InputButtonPressEvent;
++ sbEvent->buttonState.pressed = (SiButtonPressed(&spwEvent) != SI_NO_BUTTON);
++ sbEvent->buttonState.released = (SiButtonReleased(&spwEvent) != SI_NO_BUTTON);
++ break;
++ }
++ return TRUE;
++ }
++ }
++ return FALSE;
++}
++
++/* Stop receiving input from the spaceball */
++void SPW_disableSpaceBallWin32(void)
++{
++ SiClose(Spw_DeviceHandle);
++ SiTerminate();
++ Spw_DeviceHandle = SI_NO_HANDLE;
++}
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * void __SiAppInitialize(void)
++ *
++ * Args:
++ * None
++ *
++ * Return Value:
++ * None
++ *
++ * Description:
++ * This function opens up the DLL library and, if successful, loads a
++ * function pointer table with exported UAPI functions contained in the DLL.
++ *
++ *---------------------------------------------------------------------------*/
++int __SiAppInitialize(void)
++{
++ enum InitResult nResult; /* intialization result code */
++ enum ErrorCode nErrorCode; /* function return code */
++
++ /* attempt to load the DLL */
++ if ((ghDll = LoadLibrary (DllLibrary)) != NULL)
++ {
++ /* preset variables and hope for success */
++ nResult = LOADED;
++ nErrorCode = NO_DLL_ERROR;
++
++ /* load up the global variable used by the DLL to return error info */
++
++ if ((pDllSpwRetVal = (enum SpwRetVal *)
++ GetProcAddress(ghDll, strDLLRetVal)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_VAR_LOAD_FAILURE;
++ }
++
++ /* load up function pointer table */
++ if ((pfnSiBeep = (PFNSI_BEEP)
++ GetProcAddress(ghDll, fnSiBeep)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiInit = (PFNSI_INIT)
++ GetProcAddress(ghDll, fnSiInitialize)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiTerminate = (PFNSI_TERMINATE)
++ GetProcAddress(ghDll, fnSiTerminate)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetNumDevices = (PFNSI_GETNUMDEVICES)
++ GetProcAddress(ghDll, fnSiGetNumDevices)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetDeviceID = (PFNSI_GETDEVICEID)
++ GetProcAddress(ghDll, fnSiGetDeviceID)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiDeviceIndex = (PFNSI_DEVICEINDEX)
++ GetProcAddress(ghDll, fnSiDeviceIndex)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiDispatch = (PFNSI_DISPATCH)
++ GetProcAddress(ghDll, fnSiDispatch)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiOpenWinInit = (PFNSI_OPENWININIT)
++ GetProcAddress(ghDll, fnSiOpenWinInit)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiOpen = (PFNSI_OPEN)
++ GetProcAddress(ghDll, fnSiOpen)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiClose = (PFNSI_CLOSE)
++ GetProcAddress(ghDll, fnSiClose)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetEventWinInit = (PFNSI_GETEVENTWININIT)
++ GetProcAddress(ghDll, fnSiGetEventWinInit)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiIsSpaceWareEvent = (PFNSI_ISSPACEWAREEVENT)
++ GetProcAddress(ghDll, fnSiIsSpaceWareEvent)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetEvent = (PFNSI_GETEVENT)
++ GetProcAddress(ghDll, fnSiGetEvent)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiRezero = (PFNSI_REZERO)
++ GetProcAddress(ghDll, fnSiRezero)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGrabDevice = (PFNSI_GRABDEVICE)
++ GetProcAddress(ghDll, fnSiGrabDevice)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiReleaseDevice = (PFNSI_RELEASEDEVICE)
++ GetProcAddress(ghDll, fnSiReleaseDevice)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiButtonPressed = (PFNSI_BUTTONPRESSED)
++ GetProcAddress(ghDll, fnSiButtonPressed)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiButtonReleased = (PFNSI_BUTTONRELEASED)
++ GetProcAddress(ghDll, fnSiButtonReleased)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiSetUiMode = (PFNSI_SETUIMODE)
++ GetProcAddress(ghDll, fnSiSetUIMode)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetDevicePort = (PFNSI_GETDEVICEPORT)
++ GetProcAddress(ghDll, fnSiGetDevicePort)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetDriverInfo = (PFNSI_GETDRIVERINFO)
++ GetProcAddress(ghDll, fnSiGetDriverInfo)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetLibraryInfo = (PFNSI_GETLIBRARYINFO)
++ GetProcAddress(ghDll, fnSiGetLibraryInfo)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSiGetDeviceInfo = (PFNSI_GETDEVICEINFO)
++ GetProcAddress(ghDll, fnSiGetDeviceInfo)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++
++ if ((pfnSpwErrorString = (PFNSPW_ERRORSTRING)
++ GetProcAddress(ghDll, fnSpwErrorString)) == NULL)
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_FUNCTION_LOAD_FAILURE;
++ }
++ }
++ else /* couldn't load DLL */
++ {
++ nResult = FAILED;
++ nErrorCode = DLL_LOAD_FAILURE;
++ }
++
++ /* set the global variable */
++
++ gInitStatus = nResult;
++
++ return nErrorCode;
++}
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiInitialize (void)
++ *
++ * Args:
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SPW_ERROR Initialization error
++ *
++ * Description:
++ * This function initializes the SpaceWare input library. Since most input
++ * functions require that the library be initialized, this function should
++ * be called before any other input functions are called.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiInitialize(void)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ __SiAppInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiInit();
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiTerminate (void)
++ *
++ * Args:
++ * None
++ *
++ * Return Value:
++ * None
++ *
++ * Description:
++ * This function must be called to properly shut down the SpaceWare input
++ * library. No other input functions (except SiInit) should be called
++ * afterwards.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiTerminate(void)
++{
++ /* It is unlikely that the function table will not have been loaded by the
++ time this is called, but we'll cover the bases anyhow */
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ SpwErrorVal = SPW_DLL_LOAD_ERROR; /* global variable */
++ return;
++ }
++
++ /* if we weren't returning void, we'd do error handling here */
++ }
++
++ pfnSiTerminate();
++ SpwErrorVal = *pDllSpwRetVal;
++
++ /* Unload the DLL to prevent memory leaks */
++ FreeLibrary(ghDll);
++
++ /* change status in case someone reinitializes */
++ gInitStatus = NOT_LOADED;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiGetNumDevices (void)
++ *
++ * Args:
++ *
++ * Return Value:
++ * If the SpaceWare input library is initialized, the number of devices is
++ * returned and SpwErrorVal is set to SPW_NO_ERROR. Otherwise, the return
++ * code is -1 and SpwErrorVal is set to either SI_UNINITIALIZED or one of
++ * the other standard error codes.
++ *
++ * Description:
++ * This function returns the number of input devices detected by the
++ * driver.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiGetNumDevices (void)
++{
++ int tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ SpwErrorVal = SPW_DLL_LOAD_ERROR; /* global variable */
++ return -1;
++ }
++ }
++
++ tmpRetVal = pfnSiGetNumDevices();
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SiDevID SiGetDeviceID (SiHdl hdl)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ *
++ * Return Value:
++ * If there is no error, the device ID is returned and SpwErrorVal is set
++ * to SPW_NO_ERROR. Otherwise, the return value is SI_NO_DEVICE and
++ * SpwErrorVal is set to either SI_BAD_HANDLE (if the SpaceWare handle is
++ * invalid) or one of the other standard error codes.
++ *
++ * Description:
++ * Given a SpaceWare handle, this function returns the ID of the
++ * associated device.
++ *
++ *---------------------------------------------------------------------------*/
++
++SiDevID
++SiGetDeviceID (SiHdl hdl)
++{
++ SiDevID tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ SpwErrorVal = SPW_DLL_LOAD_ERROR; /* global variable */
++ return SI_NO_DEVICE;
++ }
++ }
++
++ tmpRetVal = pfnSiGetDeviceID(hdl);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SiDevID SiDeviceIndex (int idx)
++ *
++ * Args:
++ * idx (r/o) Device index (zero relative)
++ *
++ * Return Value:
++ * If there is no error, the device ID is returned and SpwErrorVal is set
++ * to SPW_NO_ERROR. Otherwise, the return value is SI_NO_DEVICE and
++ * SpwErrorVal is set to either SPW_ERROR (if the device index is invalid),
++ * SI_UNINITIALIZED, or SI_NO_DRIVER.
++ *
++ * Description:
++ * Given a device index, SiDeviceIndex returns the associated device ID.
++ * This routine is particularly useful with the function SiGetDevicePort.
++ *
++ *---------------------------------------------------------------------------*/
++
++SiDevID
++SiDeviceIndex (int idx)
++{
++ SiDevID tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ SpwErrorVal = SPW_DLL_LOAD_ERROR; /* global variable */
++ return SI_NO_DEVICE;
++ }
++ }
++
++ tmpRetVal = pfnSiDeviceIndex(idx);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiDispatch (SiHdl hdl, SiGetEventData *pData, SiSpwEvent *pEvent,
++ * SiSpwHandlers *pHandlers)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ * pData (r/o) Pntr to platform specific data (as passed to SiGetEvent)
++ * pEvent (r/o) Pntr to SpaceWare event (as returned by SiGetEvent)
++ * pHandlers (r/o) Pntr to SpaceWare event handlers
++ *
++ * Return Value:
++ * Value returned by called event handler or zero if handler not defined.
++ *
++ * Description:
++ * Provided as a companion to SiGetEvent, this function calls the appro-
++ * priate handler to process the SpaceWare event returned by SiGetEvent.
++ * The SiSpwHandlers structure contains one handler for each event type.
++ * An event type can be ignored by setting the func member of the appro-
++ * priate SiEventHandler structure to NULL. Unlike the handler for
++ * SiGetEvent, there is no specific use for the function return value of
++ * these handlers -- the interpretation is entirely the caller's.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiDispatch (SiHdl hdl, SiGetEventData *pData,
++ SiSpwEvent *pEvent, SiSpwHandlers *pDHandlers)
++{
++ int tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return 0;
++ }
++ }
++
++ tmpRetVal = pfnSiDispatch(hdl, pData, pEvent, pDHandlers);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiOpenWinInit (SiOpenData *pData, HWND hWnd)
++ *
++ * Args:
++ * pData (w/o) Pointer to storage for returned platform specific data
++ * hWnd (r/o) Window handle
++ *
++ * Return Value:
++ * Nothing
++ *
++ * Description:
++ * This function initializes the Windows platform specific data for a
++ * subsequent call to SiOpen.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiOpenWinInit (SiOpenData *pData, HWND hWnd)
++{
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ pData = NULL;
++ hWnd = NULL;
++ return;
++ }
++ }
++
++ pfnSiOpenWinInit(pData, hWnd);
++ SpwErrorVal = *pDllSpwRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SiHdl SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
++ * SiOpenData *pData)
++ *
++ * Args:
++ * pAppName (r/o) Pointer to application name
++ * devID (r/o) Device ID or SI_ANY_DEVICE
++ * pTMask (r/o) Pointer to device type mask or SI_NO_MASK
++ * mode (r/o) SpaceWare event retrieval method: SI_EVENT or SI_POLL
++ * pData (r/o) Pointer to platform specific data if mode is SI_EVENT
++ *
++ * Return Value:
++ * SpaceWare handle or SI_NO_HANDLE if error. SpwErrorVal is set to one
++ * of the following:
++ *
++ * SPW_NO_ERROR No error
++ * SPW_ERROR Device could not be opened
++ * SI_BAD_ID Invalid device ID
++ * SI_BAD_VALUE Invalid argument
++ * SI_UNSUPPORTED Specified retrieval method is unsupported
++ *
++ * Description:
++ * SiOpen is called to open a device for input and (sometimes) output
++ * access. The device in which to open is indicated via the device ID
++ * (devID) and a device type mask (pTMask). If the ID of a particular
++ * device is known, it is passed in devID. If the ID is not known or the
++ * application simply doesn't care which device is selected, devID is passed
++ * as SI_ANY_DEVICE.
++ *
++ * Irrespective of the device ID, the device type mask indicates which
++ * device types are permitted. The type may be constrained to particular
++ * devices, classes, or any combination thereof. The mask is created via
++ * the function SiSetTypeMask (see the definition of that function for more
++ * information). If the application doesn't wish to constrain the selection
++ * to any particular types or classes, pTMask may be passed as SI_NO_MASK.
++ * This is the equivalent of passing a mask set to SI_ALL_TYPES.
++ *
++ * The following table shows how a device is selected based on the device ID
++ * and type mask. In those cases where SI_ANY_DEVICE is specified, the
++ * order in which the devices are searched is the same order as indexed by
++ * the function SiDevIndex.
++ *
++ * devID pTMask Device selected
++ *
++ * SI_ANY_DEVICE SI_NO_MASK The first available device in the list.
++ *
++ * A device ID SI_NO_MASK The device matching the specified ID if
++ * it's available.
++ *
++ * SI_ANY_DEVICE A type mask The first available device in the list
++ * with a type or class that is specified
++ * in the mask.
++ *
++ * A device ID A type mask The device matching the specified ID if
++ * its type or class matches one specified
++ * in the mask and it's available.
++ *
++ * Note that some SpaceWare implementations will run only if all of the
++ * configured devices are attached and working properly. Thus, all of the
++ * devices are available. Other implementations may run with some devices
++ * not working. These constitute unavailable devices.
++ *
++ * The mode argument specifies how the application intends to retrieve
++ * data from the device. SI_EVENT indicates that the application should
++ * be informed, via a system event message, whenever device data is
++ * pending. The message is acknowledged by a call to SiGetEvent. When
++ * this mode is selected, pData points to the platform specific informa-
++ * tion necessary for the API to generate system event messages. The mode
++ * SI_POLL indicates that the application will check for data from the
++ * device by calling SiGetEvent regularly. For this mode, pData is passed
++ * as NULL.
++ *
++ *---------------------------------------------------------------------------*/
++
++SiHdl
++SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
++ SiOpenData *pData)
++{
++ SiHdl tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ SpwErrorVal = SPW_DLL_LOAD_ERROR;
++ return NULL;
++ }
++ }
++
++ tmpRetVal = pfnSiOpen(pAppName, devID, pTMask, mode, pData);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiClose (SiHdl hdl)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SPW_ERROR Close error
++ * SI_BAD_HANDL Invalid SpaceWare handle
++ *
++ * Description:
++ * This function closes a device. Once closed, the SpaceWare handle is
++ * no longer valid.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum
++SpwRetVal SiClose (SiHdl hdl)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiClose(hdl);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * SPWbool SiIsSpaceWareEvent (SiGetEventData *pData, SiHdl *pHdl)
++ *
++ * Args:
++ * pData (r/o) Pointer to platform specific data
++ * pHdl (w/o) Pointer to storage for returned SpaceWare handle
++ *
++ * Return Value:
++ * SPW_TRUE if pData refers to a SpaceWare event, otherwise SPW_FALSE.
++ *
++ * Description:
++ * This function determines whether or not the data addressed by pData per-
++ * tains to a SpaceWare event. If so, the handle for which the event is
++ * intended is returned.
++ *
++ * Notes:
++ * NULL may be passed for pHdl if the return of the intended handle is not
++ * required.
++ *
++ *---------------------------------------------------------------------------*/
++
++SPWbool
++SiIsSpaceWareEvent(SiGetEventData *pData, SiHdl *pHdl)
++{
++ SPWbool tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_FALSE;
++ }
++ }
++
++ tmpRetVal = pfnSiIsSpaceWareEvent(pData, pHdl);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiGetEventWinInit (SiGetEventData *pData,
++ * UINT msg, WPARAM wParam, LPARAM lParam)
++ *
++ * Args:
++ * pData (w/o) Pointer to storage for returned platform specific data
++ * msg (r/o) Windows message
++ * wParam (r/o) Parameter #1
++ * lParam (r/o) Parameter #2
++ *
++ * Return Value:
++ * Nothing
++ *
++ * Description:
++ * This function initializes the Windows platform specific data for a
++ * subsequent call to SiGetEvent.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiGetEventWinInit (SiGetEventData *pData, UINT msg, WPARAM wParam,
++ LPARAM lParam)
++{
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return;
++ }
++ }
++
++ pfnSiGetEventWinInit(pData, msg, wParam, lParam);
++ SpwErrorVal = *pDllSpwRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetEvent (SiHdl hdl, int flags,
++ * SiGetEventData *pData, SiSpwEvent *pEvent)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ * flags (r/o) Processing flags
++ * pData (r/o) Pointer to platform specific data
++ * pEvent (w/o) Pointer to storage for returned SpaceWare event
++ *
++ * Return Value:
++ * SI_BAD_HANDLE Invalid SpaceWare handle
++ * SI_NOT_EVENT The event is not a SpaceWare event or no event pending
++ * SI_IS_EVENT The event is a SpaceWare event
++ * SI_SKIP_EVENT The event is a SpaceWare event but it should be skipped
++ *
++ * Description:
++ * This function determines if device data is pending and if so, returns
++ * the data as a SpaceWare event. See the "SpaceWare Universal API"
++ * specification for a complete description of this function.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetEvent (SiHdl hdl, int flags, SiGetEventData *pData,
++ SiSpwEvent *pEvent)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiGetEvent(hdl, flags, pData, pEvent);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiBeep (SiHdl hdl, char *pString)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ * pString (r/o) Pointer to beep description string
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SI_BAD_HANDLE Invalid SpaceWare handle
++ * SI_BAD_VALUE Bad string
++ *
++ * Description:
++ * If supported, this function causes the input device to emit a sequence
++ * of tones and pauses. Each character of the string represents either a
++ * tone or a delay. Lowercase letters [a-z] represent a tone, uppercase
++ * letters [A-Z] represent a pause. The closer the letter is to the
++ * beginning of the alphabet the shorter the pause or tone ('a' or 'A' is
++ * 1/32 second, 'b' or 'B' is 2/32 second, etc). Up to 14 characters in
++ * a string are processed, additional characters are ignored.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiBeep(SiHdl hdl, char *pString)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiBeep(hdl, pString);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiRezero (SiHdl hdl)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SI_BAD_HANDLE Invalid SpaceWare handle
++ *
++ * Description:
++ * This function causes the input device's current setting to be defined
++ * as the rest position. Movement away from this position will cause
++ * motion events. This can be used to eliminate drift or to set up a
++ * constant motion.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiRezero (SiHdl hdl)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiRezero(hdl);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGrabDevice (SiHdl hdl, SPWbool exclusive)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ * exclusive (r/o) Exclusive grab flag
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SPW_ERROR Grab failed
++ * SI_BAD_HANDLE Invalid SpaceWare handle
++ *
++ * Description:
++ * This function is used to "grab" or capture a device in multi-tasking
++ * environments. For an exclusive capture, the application retains control
++ * of the device regardless of which window has the focus. For a non-
++ * exclusive capture, the application retains control of the device only if
++ * no other application, sharing the same device, has the focus. Some
++ * SpaceWare implementations only allow one non-exclusive grab. Others
++ * allow multiple non-exclusive grabs and provide an interface for inter-
++ * actively selecting the current non-exclusive grab application. An exclu-
++ * sive grab fails if another application has already exclusively captured
++ * the device. A non-exclusive grab fails if the SpaceWare implementation
++ * only allows one non-exclusive grab and another application has already
++ * non-exclusively captured the device. Note that an exclusive grab should
++ * be used sparingly if at all.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGrabDevice (SiHdl hdl, SPWbool exclusive)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiGrabDevice(hdl, exclusive);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiReleaseDevice (SiHdl hdl)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SPW_ERROR Device not captured
++ * SI_BAD_HANDLE Invalid SpaceWare handle
++ *
++ * Description:
++ * This function releases a device that has been captured via the routine
++ * SiGrabDevice. A captured device is automatically released when closed.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiReleaseDevice (SiHdl hdl)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiReleaseDevice(hdl);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiButtonPressed (SiSpwEvent *pEvent)
++ *
++ * Args:
++ * pEvent (r/o) Pointer to SpaceWare event
++ *
++ * Return Value:
++ * Button number or SI_NO_BUTTON if not a button or combo event or no
++ * button was pressed. If it's not a button or combo event, SpwErrorVal
++ * is set to SPW_ERROR otherwise SpwErrorVal is SPW_NO_ERROR.
++ *
++ * Description:
++ * Given a button or combo event, this function returns the number of the
++ * button pressed. In the event that multiple buttons are pressed, the
++ * lowest button number is returned.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiButtonPressed (SiSpwEvent *pEvent)
++{
++ int tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ SpwErrorVal = SPW_DLL_LOAD_ERROR;
++ return SI_NO_BUTTON;
++ }
++ }
++
++ tmpRetVal = pfnSiButtonPressed(pEvent);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SiButtonReleased (SiSpwEvent *pEvent)
++ *
++ * Args:
++ * pEvent (r/o) Pointer to SpaceWare event
++ *
++ * Return Value:
++ * Button number or SI_NO_BUTTON if not a button or combo event or no
++ * button was released. If it's not a button or combo event, SpwErrorVal
++ * is set to SPW_ERROR otherwise SpwErrorVal is SPW_NO_ERROR.
++ *
++ * Description:
++ * Given a button or combo event, this function returns the number of the
++ * button released. In the event that multiple buttons are released, the
++ * lowest button number is returned.
++ *
++ *---------------------------------------------------------------------------*/
++
++int
++SiButtonReleased (SiSpwEvent *pEvent)
++{
++ int tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ SpwErrorVal = SPW_DLL_LOAD_ERROR;
++ return SI_NO_BUTTON;
++ }
++ }
++
++ tmpRetVal = pfnSiButtonReleased(pEvent);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiSetUiMode (SiHdl hdl, SPWuint32 mode)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle or SI_ALL_HANDLES
++ * mode (r/o) UI mode
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SI_BAD_HANDLE Invalid SpaceWare handle
++ *
++ * Description:
++ * This function sets the current User Interface (UI) mode bit mask for a
++ * specified device. If hdl is SI_ALL_HANDLES, the mask for each open
++ * device is set. This option is useful if an app uses the same UI mode
++ * for more than one device. Each set bit in the mask indicates that a
++ * particular feature is enabled. The bits are defined as follows.
++ *
++ * SI_UI_ALL_CONTROLS All controls
++ * SI_UI_NO_CONTROLS No controls
++ * SI_UI_FILTERS Filter controls
++ * SI_UI_FUNC_BUTTONS Function buttons
++ * SI_UI_RESET_BUTTONS Reset buttons
++ * SI_UI_SENSITIVITY Sensitivity control
++ * SI_UI_TUNING Tuning control
++ * SI_UI_DIALOG_POPUP Dialog popup button (on device)
++ *
++ * Note that for SI_UI_ALL_CONTROLS, all bits are set; for SI_UI_NO_CONTROLS,
++ * no bits are set.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiSetUiMode (SiHdl hdl, SPWuint32 mode)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiSetUiMode(hdl, mode);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiSetTypeMask (SiTypeMask *pTMask, int type1, ...,
++ * SI_END_ARGS)
++ *
++ * Args:
++ * pTMask (w/o) Pointer to storage for returned device type mask
++ * type1 (r/o) First device type
++ * ... (r/o) Additional device types
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ *
++ * Description:
++ * This function provides compatibility with older software.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiSetTypeMask (SiTypeMask *pTMask, int type1, ...)
++{
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ /* stub function -> return a happy value */
++ return SPW_NO_ERROR;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetDevicePort (SiDevID devID, SiDevPort *pPort)
++ *
++ * Args:
++ * devID (r/o) Device ID
++ * pPort (w/o) Pointer to storage for returned device port info
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SI_BAD_ID Invalid device ID
++ *
++ * Description:
++ * The purpose of this function is to provide a correlation between the
++ * devices and the system ports to which they are connected. Each call
++ * to SiGetDevicePort returns information for one device.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetDevicePort (SiDevID devID, SiDevPort *pPort)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiGetDevicePort(devID, pPort);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetDriverInfo (SiVerInfo *pInfo)
++ *
++ * Args:
++ * pInfo (w/o) Pointer to storage for returned driver version info
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SPW_ERROR This version of the SpaceWare library does not use a driver
++ *
++ * Description:
++ * SiGetDriverInfo returns driver version information.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetDriverInfo (SiVerInfo *pInfo)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiGetDriverInfo(pInfo);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SiGetLibraryInfo (SiVerInfo *pInfo)
++ *
++ * Args:
++ * pInfo (w/o) Pointer to storage for returned library version info
++ *
++ * Return Value:
++ * Nothing. SpwErrorVal is always set to SPW_NO_ERROR by this function.
++ *
++ * Description:
++ * SiGetLibraryInfo returns library version information.
++ *
++ *---------------------------------------------------------------------------*/
++
++void
++SiGetLibraryInfo (SiVerInfo *pInfo)
++{
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ pInfo = NULL;
++ return;
++ }
++
++ }
++
++ pfnSiGetLibraryInfo(pInfo);
++ SpwErrorVal = *pDllSpwRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * enum SpwRetVal SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo)
++ *
++ * Args:
++ * hdl (r/o) SpaceWare handle
++ * pInfo (w/o) Pointer to storage for returned device information
++ *
++ * Return Value:
++ * SPW_NO_ERROR No error
++ * SI_BAD_HANDLE Invalid SpaceWare handle
++ *
++ * Description:
++ * This function returns all sorts of information on the specified device.
++ *
++ *---------------------------------------------------------------------------*/
++
++enum SpwRetVal
++SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo)
++{
++ enum SpwRetVal tmpRetVal; /* temporary return value */
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return SPW_DLL_LOAD_ERROR;
++ }
++ }
++
++ tmpRetVal = pfnSiGetDeviceInfo(hdl, pInfo);
++ SpwErrorVal = *pDllSpwRetVal;
++ return tmpRetVal;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * char *SpwErrorString (enum SpwRetVal val)
++ *
++ * Parameters:
++ * val (r/o) Error value
++ *
++ * Return:
++ * Pointer to string containing error message.
++ *
++ * Description:
++ * This function returns a pointer to the error message string associated
++ * with the given error value. Note that the returned pointer points to
++ * static memory that is overridden each time SpwErrorString is called.
++ *
++ *---------------------------------------------------------------------------*/
++
++char *
++SpwErrorString (enum SpwRetVal val)
++{
++
++ if (gInitStatus != LOADED)
++ {
++ SiInitialize();
++ if (gInitStatus == FAILED)
++ {
++ return NULL;
++ }
++ }
++
++ return (char *) pfnSpwErrorString(val);
++}
++
++#endif /* HAVE_WIN32_API */
++
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput_win32.h.in
+@@ -0,0 +1,511 @@
++#ifndef SPWINPUT_WIN32_H
++#define SPWINPUT_WIN32_H
++
++/* @configure_input@ */
++
++/*----------------------------------------------------------------------
++ * (C) 1998-2009 3Dconnexion. All rights reserved.
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby grated provided that this copyright
++ * notice appears in all copies. Permission to modify this software is granted
++ * and 3Dconnexion will support such modifications only is said modifications are
++ * approved by 3Dconnexion.
++ *
++ */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#include <Inventor/@Gui@/devices/spwinput.h>
++
++#ifndef HAVE_WIN32_API
++#error "Do not include this file unless HAVE_WIN32_API is set."
++#endif /* !HAVE_WIN32_API */
++
++#include <tchar.h>
++
++/* some enumerated types used in spwinput_win32.cpp */
++enum InitResult
++ {
++ NOT_LOADED,
++ FAILED,
++ LOADED
++ };
++
++enum ErrorCode
++ {
++ NO_DLL_ERROR=0,
++ DLL_LOAD_FAILURE,
++ DLL_FUNCTION_LOAD_FAILURE,
++ DLL_VAR_LOAD_FAILURE
++ };
++
++enum SpwRetVal /* Error return values. */
++ {
++ SPW_NO_ERROR, /* No error. */
++ SPW_ERROR, /* Error -- function failed. */
++ SI_BAD_HANDLE, /* Invalid SpaceWare handle. */
++ SI_BAD_ID, /* Invalid device ID. */
++ SI_BAD_VALUE, /* Invalid argument value. */
++ SI_IS_EVENT, /* Event is a SpaceWare event. */
++ SI_SKIP_EVENT, /* Skip this SpaceWare event. */
++ SI_NOT_EVENT, /* Event is not a SpaceWare event. */
++ SI_NO_DRIVER, /* SpaceWare driver is not running. */
++ SI_NO_RESPONSE, /* SpaceWare driver is not responding. */
++ SI_UNSUPPORTED, /* The function is unsupported by this version. */
++ SI_UNINITIALIZED, /* SpaceWare input library is uninitialized. */
++ SI_WRONG_DRIVER, /* Driver is incorrect for this SpaceWare version.*/
++ SI_INTERNAL_ERROR, /* Internal SpaceWare error. */
++ SI_BAD_PROTOCOL, /* The transport protocol is unknown. */
++ SI_OUT_OF_MEMORY, /* Unable to malloc space required. */
++ SPW_DLL_LOAD_ERROR, /* Could not load siapp dlls */
++ SI_NOT_OPEN, /* Spaceball device not open */
++ SI_ITEM_NOT_FOUND /* Item not found */
++ };
++
++static enum SpwRetVal *pDllSpwRetVal;
++
++/* some macros */
++#define SPW_FALSE (0)
++#define SPW_TRUE (!SPW_FALSE)
++
++#define SPW_MAX(a,b) (((a)>(b))?(a):(b))
++#define SPW_MIN(a,b) (((a)<(b))?(a):(b))
++
++#define SPW_ABS(a) (((a)<0)?(-(a)):(a))
++
++#define SPW_SIGN(a) ((a)>=0?1:-1)
++
++#define SPW_BIND(min,n,max) (SPW_MIN((max),SPW_MAX((min),(n))))
++
++#define SPW_NUM_ELEMENTS_IN(a) (sizeof(a)/sizeof((a)[0]))
++
++#define SPW_PI 3.14159265358979324f
++
++#define SPW_DEG_TO_RAD(d) ((d)*SPW_PI/180.0f)
++#define SPW_RAD_TO_DEG(r) ((r)*180.0f/SPW_PI)
++
++#define SPW_LENGTH_OF(a) (sizeof(a)/sizeof((a)[0]))
++
++#define SPW_END_OF(a) (&(a)[SPW_LENGTH_OF(a)-1])
++
++#define SPW_SQ(a) ((a)*(a))
++
++#define SPW_ABSDIFF(a, b) (fabs((double) (a) - (b)))
++
++/* the accepted datatypes for spacetec products */
++
++#define tchar_t _TCHAR
++#define char_t char
++#define uint32_t unsigned long
++#define sint32_t long
++#define boolean_t unsigned char
++#define void_t void
++#define window_handle_t HWND
++
++
++typedef long SPWint32;
++typedef short SPWint16;
++typedef char SPWint8;
++typedef int SPWbool;
++typedef unsigned long SPWuint32;
++typedef unsigned short SPWuint16;
++typedef unsigned char SPWuint8;
++typedef _TCHAR SPWchar;
++typedef _TCHAR* SPWstring;
++typedef float SPWfloat32;
++typedef double SPWfloat64;
++
++/*
++ * UI modes
++ */
++#define SI_UI_ALL_CONTROLS 0xffffffffL
++#define SI_UI_NO_CONTROLS 0x00000000L
++
++/*
++ * These UI modes are left here for legacy applications.
++ */
++#define SI_UI_FILTERS 0x00000001L
++#define SI_UI_FUNC_BUTTONS 0x00000002L
++#define SI_UI_RESET_BUTTONS 0x00000004L
++#define SI_UI_SENSITIVITY 0x00000008L
++#define SI_UI_TUNING 0x00000010L
++#define SI_UI_DIALOG_POPUP 0x00000020L
++
++/*
++ * Device types and classes
++ */
++typedef enum
++ {
++ SI_ALL_TYPES = -1,
++ SI_UNKNOWN_DEVICE = 0,
++ SI_SPACEBALL_2003 = 1,
++ SI_SPACEBALL_3003 = 2,
++ SI_SPACE_CONTROLLER = 3,
++ SI_AVENGER = 4,
++ SI_SPACEORB_360 = 5,
++ SI_NAVIGATOR = 6,
++ SI_SPACEBALL_2003A = 7,
++ SI_SPACEBALL_2003B = 8,
++ SI_SPACEBALL_2003C = 9,
++ SI_SPACEBALL_3003A = 10,
++ SI_SPACEBALL_3003B = 11,
++ SI_SPACEBALL_3003C = 12,
++ SI_SPACEBALL_4000 = 13,
++ SI_SPACEMOUSE_CLASSIC = 14,
++ SI_SPACEMOUSE_PLUS = 15,
++ SI_SPACEMOUSE_XT = 16,
++ SI_PUCKMAN = 17,
++ SI_CADMAN = 18,
++ SI_NUM_DEV_TYPES /* Leave this last, add before it */
++ } SiDevType;
++
++/*
++ * These defintions of device classes are left in for legacy applications.
++ */
++#define SI_HIGH_END 63
++#define SI_MED_END 62
++#define SI_LOW_END 61
++
++/*
++ * Data retrieval mode, only SI_EVENT is currently supported.
++ */
++#define SI_EVENT 0x0001
++#define SI_POLL 0x0002
++
++/*
++ * Get event flags
++ */
++#define SI_AVERAGE_EVENTS 0x0001
++
++/*
++ * This is an INTERNAL flag used by the polling mechanism, user applications
++ * should NOT send this flag.
++ */
++#define SI_POLLED_REQUEST 0x0100
++
++/*
++ * SpaceWare event types
++ */
++typedef enum
++ {
++ SI_BUTTON_EVENT = 1,
++ SI_MOTION_EVENT,
++ SI_COMBO_EVENT, /* Not implemented */
++ SI_ZERO_EVENT,
++ SI_EXCEPTION_EVENT,
++ SI_OUT_OF_BAND,
++ SI_ORIENTATION_EVENT,
++ SI_KEYBOARD_EVENT,
++ SI_LPFK_EVENT
++ } SiEventType;
++
++/*
++ * Data modes
++ */
++#define SI_MODE_NORMALIZE 0x0001
++#define SI_MODE_COMPRESS 0x0002
++#define SI_MODE_SENSITIVITY 0x0004
++#define SI_MODE_TUNING 0x0008
++
++/*
++ * Motion data offsets
++ */
++#define SI_TX 0 /* Translation X value */
++#define SI_TY 1 /* Translation Y value */
++#define SI_TZ 2 /* Translation Z value */
++#define SI_RX 3 /* Rotation X value */
++#define SI_RY 4 /* Rotation Y value */
++#define SI_RZ 5 /* Rotation Z value */
++
++/*
++ * Reserved buttons
++ */
++
++#define SI_RESET_BIT 0x00000001L
++#define SI_PICK_BIT 0x80000000L
++#define SI_DIALOG_BIT 0x40000000L
++
++#define SI_RESET_BUTTON 0
++#define SI_PICK_BUTTON 31
++#define SI_DIALOG_BUTTON 30
++
++/*
++ * Miscellaneous
++ */
++#define SI_END_ARGS 0
++#define SI_NO_HANDLE ((SiHdl) NULL)
++#define SI_ALL_HANDLES ((SiHdl) NULL)
++#define SI_ANY_HANDLE ((SiHdl) NULL)
++#define SI_NO_TRANSCTL ((SiTransCtl) NULL)
++#define SI_NO_MASK ((SiTypeMask *) NULL)
++#define SI_ANY_DEVICE -1
++#define SI_NO_DEVICE -1
++#define SI_NO_TYPE -1
++#define SI_NO_LIST -1
++#define SI_NO_BUTTON -1
++#define SI_STRSIZE 128
++#define SI_MAXBUF 128
++#define SI_KEY_MAXBUF 5120
++
++typedef int SiDevID; /* Device ID */
++typedef void *SiHdl; /* SpaceWare handle */
++typedef void *SiTransCtl; /* SpaceWare transport control handle */
++
++typedef struct /* Open data */
++ {
++
++ HWND hWnd; /* Window handle for SpaceWare messages. */
++ SiTransCtl transCtl; /* SpaceWare transport control handle. Reserved */
++ /* for the s80 transport mechanism. */
++ DWORD processID; /* The process ID for this application. */
++ char exeFile[MAX_PATH]; /* The executable name of the process. */
++ SPWint32 libFlag; /* Library version flag. */
++ } SiOpenData;
++
++typedef struct /* Get event Data */
++ {
++
++ UINT msg;
++ WPARAM wParam;
++ LPARAM lParam;
++ } SiGetEventData;
++
++typedef struct /* Device type mask */
++ {
++ unsigned char mask[8];
++ } SiTypeMask;
++
++typedef struct /* Device port information */
++ {
++ SiDevID devID; /* Device ID */
++ int devType; /* Device type */
++ int devClass; /* Device class */
++ char devName[SI_STRSIZE]; /* Device name */
++ char portName[SI_STRSIZE]; /* Port name */
++ } SiDevPort;
++
++typedef struct /* Device information */
++ {
++ char firmware[SI_STRSIZE]; /* Firmware version */
++ int devType; /* Device type */
++ int numButtons; /* Number of buttons */
++ int numDegrees; /* Number of degrees of freedom */
++ SPWbool canBeep; /* Device beeps */
++ int majorVersion; /* Major version number */
++ int minorVersion; /* Minor version number */
++ } SiDevInfo;
++
++typedef struct /* Version information */
++ {
++ int major; /* Major version number */
++ int minor; /* Minor version number */
++ int build; /* Build number */
++ char version[SI_STRSIZE]; /* Version string */
++ char date[SI_STRSIZE]; /* Date string */
++ } SiVerInfo;
++
++typedef struct /* Sensitivity parameters */
++ {
++ char dummy;
++ } SiSensitivity;
++
++typedef struct /* Tuning parameters */
++ {
++ char dummy;
++ } SiTuning;
++
++typedef struct
++ {
++ SPWuint8 code; /* Out of band message code */
++ SPWuint8 message[SI_MAXBUF-1]; /* The actual message */
++ } SiSpwOOB;
++
++typedef struct
++ {
++ SPWuint8 string[SI_KEY_MAXBUF]; /* String for keyboard data */
++ } SiKeyboardData;
++
++typedef struct
++ {
++ SPWuint32 lpfk; /* LPFK number to send */
++ } SiLpfkData;
++
++typedef enum
++ {
++ SI_LEFT = 0,
++ SI_RIGHT
++ } SiOrientation;
++
++typedef struct /* Bitmasks of button states */
++ {
++ SPWuint32 last; /* Buttons pressed as of last event */
++ SPWuint32 current; /* Buttons pressed as of this event */
++ SPWuint32 pressed; /* Buttons pressed this event */
++ SPWuint32 released; /* Buttons released this event */
++ } SiButtonData;
++
++typedef struct /* SpaceWare data */
++ {
++ SiButtonData bData; /* Button data */
++ long mData[6]; /* Motion data (index via SI_TX, etc) */
++ long period; /* Period (milliseconds) */
++ } SiSpwData;
++
++typedef struct /* SpaceWare event */
++ {
++ int type; /* Event type */
++ union
++ {
++ SiSpwData spwData; /* Button, motion, or combo data */
++ SiSpwOOB spwOOB; /* Out of band message */
++ SiOrientation spwOrientation;/* Which hand orientation is the device */
++ char exData[SI_MAXBUF]; /* Exception data */
++ SiKeyboardData spwKeyData; /* String for keyboard data */
++ SiLpfkData spwLpfkData; /* LPFK data */
++ } u;
++ } SiSpwEvent;
++
++typedef struct /* Event handler (for SiDispatch) */
++ {
++ int (*func) (SiOpenData *, SiGetEventData *, SiSpwEvent *, void *);
++ void *data;
++ } SiEventHandler;
++
++typedef struct /* SpaceWare event handlers */
++ {
++ SiEventHandler button; /* Button event handler */
++ SiEventHandler motion; /* Motion event handler */
++ SiEventHandler combo; /* Combo event handler */
++ SiEventHandler zero; /* Zero event handler */
++ SiEventHandler exception; /* Exception event handler */
++ } SiSpwHandlers;
++
++
++enum SpwRetVal SiAndTypeMask (SiTypeMask *pTMaskA, SiTypeMask *pTMaskB);
++
++
++
++/* interface specifications define parameter passing to DLL functions */
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++typedef enum SpwRetVal (WINAPI *PFNSI_INIT) (void);
++typedef void (WINAPI *PFNSI_TERMINATE) (void);
++typedef void (WINAPI *PFNSI_OPENWININIT) (SiOpenData *pData, HWND hWnd);
++typedef int (WINAPI *PFNSI_GETNUMDEVICES) (void);
++typedef SiDevID (WINAPI *PFNSI_GETDEVICEID) (SiHdl hdl);
++typedef int (WINAPI *PFNSI_DISPATCH) (SiHdl hdl, SiGetEventData *pData,
++ SiSpwEvent *pEvent, SiSpwHandlers *pDHandlers);
++typedef SiHdl (WINAPI *PFNSI_OPEN) (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
++ SiOpenData *pData);
++typedef enum SpwRetVal (WINAPI *PFNSI_CLOSE) (SiHdl hdl);
++typedef SPWbool (WINAPI *PFNSI_ISSPACEWAREEVENT) (SiGetEventData *pData, SiHdl *pHdl);
++typedef void (WINAPI *PFNSI_GETEVENTWININIT) (SiGetEventData *pData, UINT msg, WPARAM wParam, LPARAM lParam);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETEVENT) (SiHdl hdl, int flags, SiGetEventData *pData,
++ SiSpwEvent *pEvent);
++typedef enum SpwRetVal (WINAPI *PFNSI_BEEP) (SiHdl hdl, char *pString);
++typedef enum SpwRetVal (WINAPI *PFNSI_REZERO) (SiHdl hdl);
++typedef enum SpwRetVal (WINAPI *PFNSI_GRABDEVICE) (SiHdl hdl, SPWbool exclusive);
++typedef enum SpwRetVal (WINAPI *PFNSI_RELEASEDEVICE) (SiHdl hdl);
++typedef int (WINAPI *PFNSI_BUTTONPRESSED) (SiSpwEvent *pEvent);
++typedef int (WINAPI *PFNSI_BUTTONRELEASED) (SiSpwEvent *pEvent);
++typedef enum SpwRetVal (WINAPI *PFNSI_SETUIMODE) (SiHdl hdl, SPWuint32 mode);
++typedef enum SpwRetVal (WINAPI *PFNSI_SETTYPEMASK) (SiTypeMask *pTMask, int type1, ...);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETDEVICEPORT) (SiDevID devID, SiDevPort *pPort);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETDRIVERINFO) (SiVerInfo *pInfo);
++typedef void (WINAPI *PFNSI_GETLIBRARYINFO) (SiVerInfo *pInfo);
++typedef enum SpwRetVal (WINAPI *PFNSI_GETDEVICEINFO) (SiHdl hdl, SiDevInfo *pInfo);
++typedef char* (WINAPI *PFNSPW_ERRORSTRING) (enum SpwRetVal val);
++typedef SiDevID (WINAPI *PFNSI_DEVICEINDEX) (int idx);
++
++#ifdef __cplusplus
++}
++#endif
++
++/* function pointers to functions in DLL */
++static PFNSI_INIT pfnSiInit;
++static PFNSI_TERMINATE pfnSiTerminate;
++static PFNSI_OPENWININIT pfnSiOpenWinInit;
++static PFNSI_GETNUMDEVICES pfnSiGetNumDevices;
++static PFNSI_GETDEVICEID pfnSiGetDeviceID;
++static PFNSI_DISPATCH pfnSiDispatch;
++static PFNSI_OPEN pfnSiOpen;
++static PFNSI_CLOSE pfnSiClose;
++static PFNSI_DEVICEINDEX pfnSiDeviceIndex;
++static PFNSI_GETEVENTWININIT pfnSiGetEventWinInit;
++static PFNSI_GETEVENT pfnSiGetEvent;
++static PFNSI_ISSPACEWAREEVENT pfnSiIsSpaceWareEvent;
++static PFNSI_BEEP pfnSiBeep;
++static PFNSI_REZERO pfnSiRezero;
++static PFNSI_GRABDEVICE pfnSiGrabDevice;
++static PFNSI_RELEASEDEVICE pfnSiReleaseDevice;
++static PFNSI_BUTTONPRESSED pfnSiButtonPressed;
++static PFNSI_BUTTONRELEASED pfnSiButtonReleased;
++static PFNSI_SETUIMODE pfnSiSetUiMode;
++static PFNSI_SETTYPEMASK pfnSiSetypeMask;
++static PFNSI_GETDEVICEPORT pfnSiGetDevicePort;
++static PFNSI_GETDRIVERINFO pfnSiGetDriverInfo;
++static PFNSI_GETLIBRARYINFO pfnSiGetLibraryInfo;
++static PFNSI_GETDEVICEINFO pfnSiGetDeviceInfo;
++static PFNSPW_ERRORSTRING pfnSpwErrorString;
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++/* externally used functions */
++int SiGetPortList (SiDevPort **ppPort);
++void SiFreePortList (SiDevPort *pPort);
++void SiTune2003 (SiSpwEvent *pEvent);
++void SiTuneSC (SiSpwEvent *pEvent);
++
++enum SpwRetVal SiInitialize(void);
++void SiTerminate(void);
++int SiGetNumDevices (void);
++SiDevID SiDeviceIndex (int idx);
++int SiDispatch (SiHdl hdl, SiGetEventData *pData,
++ SiSpwEvent *pEvent, SiSpwHandlers *pDHandlers);
++void SiOpenWinInit (SiOpenData *pData, HWND hWnd);
++SiHdl SiOpen (char *pAppName, SiDevID devID, SiTypeMask *pTMask, int mode,
++ SiOpenData *pData);
++enum SpwRetVal SiClose (SiHdl hdl);
++void SiGetEventWinInit (SiGetEventData *pData,
++ UINT msg, WPARAM wParam, LPARAM lParam);
++enum SpwRetVal SiGetEvent (SiHdl hdl, int flags, SiGetEventData *pData,
++ SiSpwEvent *pEvent);
++enum SpwRetVal SiBeep (SiHdl hdl, char *string);
++enum SpwRetVal SiRezero (SiHdl hdl);
++enum SpwRetVal SiGrabDevice (SiHdl hdl, SPWbool exclusive);
++enum SpwRetVal SiReleaseDevice (SiHdl hdl);
++int SiButtonPressed (SiSpwEvent *pEvent);
++int SiButtonReleased (SiSpwEvent *pEvent);
++enum SpwRetVal SiSetUiMode (SiHdl hdl, SPWuint32 mode);
++enum SpwRetVal SiSetTypeMask (SiTypeMask *pTMask, int type1, ...);
++enum SpwRetVal SiGetDevicePort (SiDevID devID, SiDevPort *pPort);
++enum SpwRetVal SiGetDriverInfo (SiVerInfo *pInfo);
++void SiGetLibraryInfo (SiVerInfo *pInfo);
++enum SpwRetVal SiGetDeviceInfo (SiHdl hdl, SiDevInfo *pInfo);
++char * SpwErrorString (enum SpwRetVal val);
++
++#ifdef __cplusplus
++}
++#endif
++
++
++#ifdef __cplusplus
++extern "C" {
++#endif
++
++int SPW_CheckForSpaceballWin32(void * win);
++int SPW_TranslateEventWin32(MSG * msg, SPW_InputEvent * sbEvent);
++void SPW_disableSpaceBallWin32(void);
++int SPW_SpaceBallExistsWin32(void);
++
++#ifdef __cplusplus
++}
++#endif
++
++#endif /* #ifndef SIAPP_H */
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/spwinput_x11.cpp.in
+@@ -0,0 +1,1982 @@
++/* @configure_input@ */
++
++/*-----------------------------------------------------------------------------
++ *
++ * (C) 1998 Spacetec IMC Corporation ("Spacetec").
++ *
++ * Permission to use, copy, modify, and distribute this software for all
++ * purposes and without fees is hereby granted provided that this copyright
++ * notice appears in all copies. Permission to modify this software is granted
++ * and Spacetec will support such modifications only if said modifications are
++ * approved by Spacetec.
++ *
++ */
++
++/* Some code cleanup by the Coin team. Also added configure tests for
++ * header files and added two methods:
++ *
++ * int SPW_CheckForSpaceballX11(void * display, int winid, char * product);
++ * int SPW_TranslateEventX11(void * display, void * xevent, SPW_InputEvent * sbEvent);
++ */
++
++/* FIXME: isn't this really "pure" C code? If so, don't use a C++
++ suffix on the file -- so we don't get tempted to pollute
++ it. 20010821 mortene. */
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif /* HAVE_CONFIG_H */
++
++#if SO at GUI@_DEBUG && 0 // debug
++#define SPW_DEBUG 1
++#endif // debug
++
++#include "spwinput.h"
++
++/* The setting of this define needs to be added manually to
++ configure.in for all relevant projects. */
++#ifndef HAVE_X11_AVAILABLE
++
++/* just provide empty methods if X is not available */
++int
++SPW_CheckForSpaceballX11(void *, int, char *)
++{
++ return 0;
++}
++
++int
++SPW_TranslateEventX11(void *, void *, SPW_InputEvent *)
++{
++ return 0;
++}
++
++#else /* HAVE_X11_AVAILABLE */
++
++#include <ctype.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <time.h>
++
++#ifdef HAVE_UNISTD_H
++#include <unistd.h>
++#endif // HAVE_UNISTD_H
++#ifdef HAVE_NETINET_IN_H
++#include <netinet/in.h>
++#endif /* HAVE_NETINET_IN_H */
++#ifdef HAVE_SYS_TIME_H
++#include <sys/time.h>
++#endif /* HAVE_SYS_TIME_H */
++#ifdef HAVE_SYS_TYPES_H
++#include <sys/types.h>
++#endif /* HAVE_SYS_TYPES_H */
++#ifdef HAVE_SELECT_H
++#include <select.h>
++#endif /* HAVE_SELECT_H */
++
++#define XLIB_ILLEGAL_ACCESS
++#include <X11/Xlib.h>
++#include <X11/Xutil.h>
++
++#ifdef HAVE_X11_EXTENSIONS_SGIMISC_H
++#include <X11/extensions/SGIMisc.h>
++#elif HAVE_X11_XPROTO_H
++#include <X11/Xproto.h>
++#endif /* HAVE_X11_XPROTO */
++
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++#include <X11/extensions/XInput.h>
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++
++/* Callbacks for handling motion and button events */
++typedef void (*SPW_InputMotionEventHandler)(Display *,float *,void *);
++typedef void (*SPW_InputButtonEventHandler)(Display *,int,void *);
++typedef int (*SPW_InputOtherEventHandler)(Display *,XEvent *,void *);
++
++/* Dispatch structure for SPW_InputDispatch */
++typedef struct {
++ Display * display;
++ XEvent * xevent;
++ SPW_InputEvent * spwevent;
++ int delay;
++ SPW_InputMotionEventHandler handle_motion;
++ SPW_InputButtonEventHandler handle_bpress;
++ SPW_InputButtonEventHandler handle_brelease;
++ SPW_InputOtherEventHandler handle_other;
++ void * pMotionAppData;
++ void * pButtonAppData;
++ void * pOtherAppData;
++} SPW_InputDispatchStruct;
++
++/* ------------------------------------------------------------------------ */
++
++static int SPW_InputCheckForSpaceball(Display *, Window, char *);
++static int SPW_InputIsSpaceballEvent (Display *, XEvent *,
++ SPW_InputEvent *);
++static int SPW_InputXPending (Display *, int);
++static void SPW_InputInitDispatchStruct (SPW_InputDispatchStruct *);
++static int SPW_InputDispatch (SPW_InputDispatchStruct *);
++static int SPW_InputDispatchEx (SPW_InputDispatchStruct *);
++
++static void SPW_InputBeep (Display *, char *);
++static void SPW_InputRezero (Display *);
++static int SPW_GrabDevice(Display *display, Window window,
++ int exclusive);
++static int SPW_ReleaseDevice(Display * display);
++
++#define SPW_InputDefaultDelay 0 /* 0 Hz update */
++
++/*
++ Wrapper function which makes it possible to avoid including X11 in the
++ header file.
++*/
++int
++SPW_CheckForSpaceballX11(void * display, int winid, char * product)
++{
++ return SPW_InputCheckForSpaceball((Display*) display, (Window) winid, product);
++}
++
++/*
++ If xevent is a spaceball event, translates xevent to sbEvent and return 1.
++ If xevent is not a spaceball event returns 0. void * pointers are
++ passed to avoid including the X header files in the spwinput.h header file.
++*/
++int
++SPW_TranslateEventX11(void * display, void * xevent, SPW_InputEvent * sbEvent)
++{
++ return SPW_InputIsSpaceballEvent((Display*) display, (XEvent*) xevent, sbEvent);
++}
++
++/*
++ * This is the number of events before we stop asking the
++ * driver for handshaking information.
++ *
++ * 25 events/sec * 60 sec * 1 min = 1500
++ */
++#define SPW_MaxEventCount 1500
++
++/* these are all the Spaceball XCM atom names */
++#define SPW_InputMotionAtomName "SpaceballMotionEventType"
++#define SPW_InputButtonPressAtomName "SpaceballButtonPressEventType"
++#define SPW_InputButtonReleaseAtomName "SpaceballButtonReleaseEventType"
++#define SPW_InputPassThruAtomName "SpaceWarePassThruCommandEventType"
++
++/* found the spaceball */
++static int SpaceballFound = 0;
++
++/* the spaceball is using XIE */
++static int SpaceballInputExtension = 0;
++
++/* the spaceball is using XCM */
++static int SpaceWareAtomsDefined = 0;
++
++/* the magic XCM window used for communication */
++static Window SpaceWareXCMWindowID = 0;
++
++/* the window ID that the spaceball data is sent to */
++static Window ReturnWindowID = 0;
++
++/* XSendEvent uses these types and Atoms to communicate with the driver */
++static int SPW_DevMotionEventType; /* Spaceball motion type */
++static int SPW_DevButtonPressEventType; /* Spaceball button press type */
++static int SPW_DevButtonReleaseEventType; /* Spaceball button release type */
++static Atom SPW_InputMotionAtom; /* Spaceball motion Atom */
++static Atom SPW_InputButtonPressAtom; /* Spaceball button press Atom */
++static Atom SPW_InputButtonReleaseAtom; /* Spaceball button release Atom */
++static Atom SPW_InputPassThruAtom; /* Main daemon communication Atom */
++
++static Atom WM_SAVE_YOURSELF; /* Atoms daemon will use */
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++
++static XID SpaceballDevID = 0; /* XIE ID for the Spaceball device */
++static XDevice *pSpaceballDev = NULL; /* The spaceball XIE structure */
++static XEventClass SPW_SpaceballEventClass[3]; /* XIE Events classes */
++
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++
++static char strData[19]; /* buffer used to store the string that
++ is to be sent to XCM daemon */
++static int SPW_strLength = 0; /* length of the strData string */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * static Window FindXCMWindow (Display *display)
++ *
++ * Args:
++ * display (r/o) The display on which to search for the XCM window
++ *
++ * Return Value:
++ * The window ID of the XCM window.
++ *
++ * Description:
++ * Finds the window named "sballd_XCM" and returns it's window ID
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++static Window
++FindXCMWindow (Display *display)
++{
++ Window root; /* the root window for the display */
++ Window parent; /* parent window in the search tree */
++ Window *children; /* children windows of the parrent window */
++ unsigned int nChildren; /* number of children the parent window has */
++ int i; /* counter */
++
++ /* if we already have the daemon window don't look again */
++ if (SpaceWareXCMWindowID != 0) {
++ return SpaceWareXCMWindowID;
++ }
++
++ XQueryTree(display, RootWindowOfScreen(DefaultScreenOfDisplay(display)),
++ &root, &parent, &children, &nChildren);
++
++ for (i = 0; i < (int) nChildren; i++){
++ char *name;
++ int found = 0;
++
++ XFetchName (display, children[i], &name);
++ if (name) {
++#ifdef SPW_DEBUG
++ fprintf(stderr,"FindXCMWindow: %s\n", name);
++#endif
++ if (strcmp(name, "sballd_XCM") == 0) {
++ found = 1;
++ }
++ XFree(name);
++ }
++
++ if (found == 1) {
++ break;
++ }
++ }
++
++ if (i == (int)nChildren) {
++ SpaceWareXCMWindowID = 0;
++ }
++ else {
++ SpaceWareXCMWindowID = children[i];
++ }
++
++ XFree((char *) children);
++
++ if (SpaceWareXCMWindowID == 0) {
++ return False;
++ }
++ else {
++ return SpaceWareXCMWindowID;
++ }
++} /* end of FindXCMWindow */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * static void StringFlush (Display *display, Window win)
++ *
++ * Args:
++ * display (r/o) The X Display of which the XCM window is a resident
++ * win (r/o) The window that the XCM daemon replies to
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function sends the string that is in the strData buffer to the
++ * XCM window. Once it is send it clears the strData buffer.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++static void StringFlush (Display *display, Window win)
++{
++ XClientMessageEvent event; /* event used to send string to XCM daemon */
++ int i; /* counter used to step through the string */
++
++ /* if we don't already have the XCM window id find it */
++ if (SpaceWareXCMWindowID == 0) {
++ FindXCMWindow (display);
++ }
++ if (SpaceWareXCMWindowID == 0) {
++ return;
++ }
++
++ if (SPW_strLength == 0) { /* if the string is empty do nothing */
++ return;
++ }
++
++ /* set up the event structure for sending */
++ event.type = ClientMessage;
++ event.display = display;
++ event.window = SpaceWareXCMWindowID;
++ event.message_type = SPW_InputPassThruAtom;
++ event.format = 8;
++
++ /* copy the string into the event */
++ for (i = 0; i < 15; i++) {
++ event.data.b[i] = strData[i];
++ }
++ if (SPW_strLength > 15) {
++ SPW_strLength = 15;
++ }
++
++ /* force zero on end of data */
++ event.data.b[SPW_strLength] = 0;
++
++ event.data.l[4] = (long)htonl(win);
++
++#ifdef SPW_DEBUG
++ fprintf (stderr,"StringFlush %s\n", event.data.b);
++#endif
++
++ /* send the string to the XCM daemon */
++ if (XSendEvent (display, SpaceWareXCMWindowID, True, 0,
++ (XEvent *)&event) == 0) {
++#ifdef SPW_DEBUG
++ fprintf (stderr, "SPW_Input: XSendEvent failed!\n");
++#endif
++ }
++ XSync (display,False);
++
++ /* clear the buffer */
++ SPW_strLength = 0;
++} /* end of StringFlush */
++
++/*-----------------------------------------------------------------------------
++ *
++ * static void SendString (Display *display, char *string)
++ *
++ * Args:
++ * display (r/o) The X Display of which the XCM window is a resident
++ * string (r/o) The string that is sent to the XCM daemon
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function sends string to the XCM window and flushs the
++ * internal buffer.
++ *
++ * Notes:
++ * To flush the string call StringFlush.
++ *
++ *---------------------------------------------------------------------------*/
++static void SendString (Display *display, char *string)
++{
++ int i; /* counter used to step through the string */
++
++ /* copy the string into strData and send strData to the XCM driver */
++ for (i = 0; i < (int) strlen (string); i++) {
++ strData[SPW_strLength++] = string[i];
++ }
++ StringFlush (display, ReturnWindowID);
++} /* end of String */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputString (Display *display, char *string)
++ *
++ * Args:
++ * display (r/o) The X Display of which the XCM window is a resident
++ * string (r/o) The string that is sent to the XCM daemon
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function sends string to the XCM window using SendString.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++
++void SPW_InputString (Display *display, char *string)
++{
++ SPW_strLength = 0; /* flush the internal buffer */
++ SendString (display, string); /* setup the string for sending */
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputResetGlobalVars (void)
++ *
++ * Args:
++ * None.
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function resets all the static global variable used in the Spaceball
++ * input function.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputResetGlobalVars (void)
++{
++ SpaceballFound = 0;
++ SpaceballInputExtension = 0;
++ SpaceWareAtomsDefined = 0;
++ SpaceWareXCMWindowID = 0;
++} /* end of SPW_InputResetGlobalVars */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputResetSpaceball (Display *display)
++ *
++ * Args:
++ * display (r/o) The X Display of which the XCM window is a resident
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function resets the Spaceball attached to the display defined in
++ * the display variable. The daemon will reset all internal Spaceball
++ * variables to their default and rezeros the Spaceball itself.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputResetSpaceball (Display *display)
++{
++ SPW_strLength = 0;
++ static char RESET[] = "RESET";
++ SendString (display, RESET);
++} /* end of SPW_InputResetSpaceball */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputCloseXIE (Display *display)
++ *
++ * Args:
++ * display (r/o) The X Display to which the Spaceball is attached
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function closes all comunication with the Spaceball XIE driver.
++ *
++ * Notes:
++ * When the XIE driver is closed the Spaceball may lose power.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputCloseXIE (Display *display)
++{
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++ if (SpaceballInputExtension == 1) {
++ XCloseDevice (display, pSpaceballDev);
++
++ SpaceballInputExtension = 0;
++ SpaceballFound = 0;
++ }
++#endif
++} /* end of SPW_InputCloseXIE */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputIsXIE (void)
++ *
++ * Args:
++ * None.
++ *
++ * Return Value:
++ * 0 if XIE is disabled or 1 if it is enabled.
++ *
++ * Description:
++ * This function determines if the Spaceball XIE driver is enabled.
++ *
++ * Notes:
++ * This is exported from this library so users of this library
++ * can determine the method of communication used.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputIsXIE (void)
++{
++ return SpaceballInputExtension;
++} /* end of SPW_InputIsXIE */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputIsXCM (void)
++ *
++ * Args:
++ * None.
++ *
++ * Return Value:
++ * 0 if XCM is disabled or 1 if it is enabled.
++ *
++ * Description:
++ * This function determines f the Spaceball XCM driver is enabled.
++ *
++ * Notes:
++ * This is exported from this library so users of this library
++ * can determine the method of communication used.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputIsXCM (void)
++{
++ return SpaceWareAtomsDefined;
++} /* end of SPW_InputIsXCM */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputSelectExtensionEvent (Display *display, Window window)
++ *
++ * Args:
++ * display (r/o) The X Display to which the Spaceball is attached
++ * window (r/o) What window to check for extension events
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * Check to see if the Spaceball XInput Extension is enabled.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputSelectExtensionEvent (Display *display, Window window)
++{
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++ XSelectExtensionEvent (display, window, SPW_SpaceballEventClass, 3);
++#endif
++
++} /* end of SPW_InputSelectExtensionEvent */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_SendHandshake(Display *display)
++ *
++ * Args:
++ * display (r/o) The display on which to send the message
++ *
++ * Return Value:
++ * None
++ *
++ * Description:
++ * Sends a handshaking packet to the Xdaemon with what version of
++ * the software we are running. Eventually we may even use this
++ * information. Right now it's mainly to make sure that the soft
++ * button window gets the correct cache values.
++ *
++ * Notes:
++ * This function returns nothing, but sends a message to the Xdaemon.
++ * The message is sent to guaranty the daemon gets the window id
++ * of the application.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_SendHandshake (Display *display)
++{
++ static char pHandshake[20]; /* store some space */
++
++ if (SpaceWareXCMWindowID != 0) /* using daemon */
++ {
++ SPW_strLength = 0;
++ pHandshake[0] = '\0';
++ strcat (pHandshake, "~~SLIM V");
++ strcat (pHandshake, SPW_INPUT_VERSION);
++ strcat (pHandshake, "\r");
++
++ SendString (display, pHandshake);
++ }
++} /* end of SPW_SendHandshake */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_GrabDevice(Display *display, Window window, int exclusive)
++ *
++ * Args:
++ * display (r/o) The current display pointer
++ * window (r/o) The window to send to
++ * exclusive (r/o) Specify if the grab is exclusive
++ *
++ * Return Value:
++ * None
++ *
++ * Description:
++ * This function is used to signal the driver that the application wishes
++ * to "grab" the Spaceball device. This prevents other applications from
++ * getting data from the device. There are two possible grab modes: An
++ * exclusive grab forces the driver to send data to the application window
++ * regardless of what window has focus. A non-exclusive grab forces the
++ * driver to send Spaceball data to the application window when no other
++ * Spaceball enabled window has focus.
++ *
++ * Notes:
++ * This function does not work with XIE.
++ * It is recommended that exclusive grab not be used.
++ * This function will change the ReturnWindowID if the window parameter
++ * is not NULL.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_GrabDevice(Display *display, Window window,
++ int exclusive)
++{
++ if (window != 0) {
++ ReturnWindowID = window;
++ }
++
++ if ((ReturnWindowID == 0) || /* return window not set */
++ (SpaceWareXCMWindowID == 0)) {/* daemon not running */
++ return 0;
++ }
++
++ SPW_strLength = 0;
++
++ if (exclusive == 1)
++ {
++ static char hard[] = "~hard";
++ SendString (display, hard);
++ }
++ else
++ {
++ static char soft[] = "~soft";
++ SendString (display, soft);
++ }
++
++ return 1;
++} /* end of SPW_GrabDevice */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_ReleaseDevice(Display *display)
++ *
++ * Args:
++ * display (r/o) The current display pointer
++ *
++ * Return Value:
++ * None
++ *
++ * Description:
++ * This function is used to release a grabbed device. This frees the
++ * driver to send data to the application with focus regardless if it has
++ * been Spaceball enabled.
++ *
++ * Notes:
++ * This function does not work with XIE.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_ReleaseDevice(Display *display)
++{
++ if ((ReturnWindowID == 0) || /* return window not set */
++ (SpaceWareXCMWindowID == 0)) /* daemon not running */
++ {
++ return 0;
++ }
++
++ SPW_strLength = 0;
++ static char relgrab[] = "~relgrab";
++ SendString (display, relgrab);
++ return 1;
++} /* end of SPW_ReleaseDevice */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * static int FindXCMAtoms (Display *display)
++ *
++ * Args:
++ * display (r/o) The display on which to search for the XCM atoms
++ *
++ * Return Value:
++ * 1 if the XCM atoms were found, 0 if not.
++ *
++ * Description:
++ * Returns True if all the XCM atoms are found.
++ *
++ * Notes:
++ * Has the side effect of looking up the atoms and putting the
++ * values in the SPW_Input...Atom variables
++ *
++ *---------------------------------------------------------------------------*/
++static int FindXCMAtoms (Display *display)
++{
++ /* if we already have the atoms don't look again */
++ if (SpaceWareAtomsDefined == 1)
++ {
++ return 1;
++ }
++
++ /*
++ * Try to find the atoms; if X does not find the atoms it will try to
++ * create them.
++ */
++ SPW_InputMotionAtom = XInternAtom(display, SPW_InputMotionAtomName, True);
++ SPW_InputButtonPressAtom = XInternAtom(display, SPW_InputButtonPressAtomName,
++ True);
++ SPW_InputButtonReleaseAtom = XInternAtom(display,
++ SPW_InputButtonReleaseAtomName,True);
++
++ SPW_InputPassThruAtom = XInternAtom(display,
++ SPW_InputPassThruAtomName, True);
++
++#ifdef SPW_DEBUG
++ fprintf(stderr,"SPW_InputMotionAtom %d\n", SPW_InputMotionAtom);
++ fprintf(stderr,"SPW_InputButtonPressAtom %d\n", SPW_InputButtonPressAtom);
++ fprintf(stderr,"SPW_InputButtonReleaseAtom %d\n",SPW_InputButtonReleaseAtom);
++ fprintf(stderr,"SPW_InputPassThruAtom %d\n", SPW_InputPassThruAtom);
++#endif
++
++ /* if any one of the atoms does not exist return a failure */
++ if ((SPW_InputMotionAtom == None) ||
++ (SPW_InputButtonPressAtom == None) ||
++ (SPW_InputButtonReleaseAtom == None) ||
++ (SPW_InputPassThruAtom == None))
++ {
++ return 0;
++ }
++
++ /* set the global that tells us the atoms are defined and found */
++ SpaceWareAtomsDefined = 1;
++ return 1;
++} /* end of FindXCMAtoms */
++
++/*-----------------------------------------------------------------------------
++ *
++ * static int FindXCM (Display *display)
++ *
++ * Args:
++ * display (r/o) The display on which to search for the XCM window
++ *
++ * Return Value:
++ * Returns 1 if the XCM driver is found, 0 if not.
++ *
++ * Description:
++ * Find the XCM driver (window and atoms). This function is used
++ * to check if the driver is running because if the atoms exist
++ * then the driver is running.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++static int FindXCM (Display *display)
++{
++ unsigned long win; /* the XCM window */
++ int atom; /* boolean that tell us if we found the atoms */
++
++ win = FindXCMWindow (display);
++ atom = FindXCMAtoms (display);
++
++#ifdef SPW_DEBUG
++ fprintf(stderr, "win %d atom %d\n", win, atom);
++#endif
++
++ if ((win != 0) && (atom == 1)) {
++ return 1;
++ }
++
++ return 0;
++} /* end of FindXCM */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_FindXIE (Display *display)
++ *
++ * Args:
++ * display (r/o) The display on which to search for the XCM window
++ *
++ * Return Value:
++ * 1 if the XIE driver was found, 0 if not.
++ *
++ * Description:
++ * Find the XIE Spaceball extension.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++
++int SPW_FindXIE (Display *display)
++{
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++ int ieMajor;
++ int ieFirstEvent;
++ int ieFirstError;
++ int nDev;
++ XDeviceInfo *pDev;
++ int i,j;
++ char *ptr;
++
++ /* if we have already found the XIE driver don't look again */
++ if (SpaceballInputExtension == 1)
++ {
++ return 1;
++ }
++
++ /* See if XIE is configured */
++ if (XQueryExtension (display, "XInputExtension", &ieMajor,
++ &ieFirstEvent, &ieFirstError) == 0)
++ {
++ return 0;
++ }
++
++#ifdef SPW_DEBUG
++ fprintf (stderr, "SPW_FindXIE() Extension found\n");
++#endif
++
++ /* get a list of available XIE devices */
++ pDev = XListInputDevices (display, &nDev);
++
++ /* Make sure there are valid devices */
++ if (pDev == 0) {
++ return 0;
++ }
++
++ /* Try to find the Spaceball device in the list */
++ for (i = 0; i < nDev; i++) {
++#ifdef SPW_DEBUG
++ fprintf (stderr, "SPW_FindXIE() device %s\n", pDev[i].name);
++#endif
++ /* Compare against type name per device */
++ if (strcmp(pDev[i].name, XI_SPACEBALL) == 0) break;
++ }
++
++ /*
++ * if we have gone past the end of the list then no Spaceball XIE
++ * driver was found
++ */
++ if (i == nDev) {
++ XFreeDeviceList (pDev);
++ return 0;
++ }
++
++ /* record all necessary info on the Spaceball XIE driver */
++ SpaceballDevID = pDev[i].id;
++ pSpaceballDev = XOpenDevice (display, SpaceballDevID);
++
++ /* clean up the device list */
++ XFreeDeviceList (pDev);
++
++ /* enable the Spaceball callbacks */
++ DeviceMotionNotify (pSpaceballDev, SPW_DevMotionEventType,
++ SPW_SpaceballEventClass[0]);
++ DeviceButtonPress (pSpaceballDev, SPW_DevButtonPressEventType,
++ SPW_SpaceballEventClass[1]);
++ DeviceButtonRelease (pSpaceballDev, SPW_DevButtonReleaseEventType,
++ SPW_SpaceballEventClass[2]);
++ SpaceballInputExtension = 1;
++
++ return 1;
++#else
++ return 0;
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++} /* end of SPW_FindXIE */
++
++/*-----------------------------------------------------------------------------
++ *
++ * static void InitializeSpaceball (Display *display, char *version)
++ *
++ * Args:
++ * display (r/o) The display on which to search for the XCM window
++ * version (r/o) the XCM driver version.
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * Find the Spaceball via XIE or XCM.
++ *
++ * Notes:
++ * The returnWindow parameter is not set if the Spaceball is configured
++ * using XIE.
++ *
++ *---------------------------------------------------------------------------*/
++static void InitializeSpaceball (Display *display, char *version)
++{
++ /* if we already found the Spaceball don't search again */
++ if (SpaceballFound == 1) {
++ return;
++ }
++
++ /* Create some more Atoms the Daemon uses */
++ (void)XInternAtom (display, "WM_PROTOCOLS", False);
++ (void)XInternAtom (display, "WM_DELETE_WINDOW", False);
++
++ /* search for the XIE driver first */
++ if (SPW_FindXIE (display) == 1) {
++ SpaceballFound = 1;
++#ifdef SPW_DEBUG
++ fprintf(stderr, "\n");
++ fprintf(stderr, "Spaceball (R) device found,");
++ fprintf(stderr, " using SpaceWare (R) XIE interface.\n");
++ fprintf(stderr, "SpaceWare Version %s\n", version);
++ fprintf(stderr, "Copyright (c) 1998 Spacetec IMC Corporation\n");
++ fprintf(stderr, "All Rights Reserved\n");
++#endif
++ }
++ /* if we don't find the XIE driver search for the XCM driver */
++ else if (FindXCM (display) == 1) {
++ SpaceballFound = 1;
++#ifdef SPW_DEBUG
++ fprintf(stderr, "\n");
++ fprintf(stderr, "Spaceball (R) device found,");
++ fprintf(stderr, " using SpaceWare (R) XCM interface.\n");
++ fprintf(stderr, "SpaceWare Version %s\n", version);
++ fprintf(stderr, "Copyright (c) 1998 Spacetec IMC Corporation\n");
++ fprintf(stderr, "All Rights Reserved\n");
++#endif
++ }
++} /* end of InitializeSpaceball */
++
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputCheckForSpaceball (Display *display, Window window,
++ * char *product)
++ *
++ * Args:
++ * display (r/o) The display on which to search for the XCM window
++ * window (r/o) the window on the application side to send messages to.
++ * product (r/o) name of the application that is opening the Spaceball.
++ *
++ * Return Value:
++ * 1 if the Spaceball was opened, 0 if not.
++ *
++ * Description:
++ * Find the Spaceball via XIE or XCM.
++ *
++ * Notes:
++ * The window parameter is not set if the Spaceball is configured
++ * using XIE.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputCheckForSpaceball (Display *display,
++ Window window,
++ char *product)
++{
++ char version[256]; /* The version of SpaceWare */
++ int productlen; /* length of the product string */
++
++#ifdef SPW_DEBUG
++ fprintf(stderr, "SPW_InputCheckForSpaceball window 0x%x product %s\n",
++ window, product);
++#endif
++
++ /* check to make sure the corect parameters were passed */
++ if ((display == NULL) || (window == 0)) {
++ return 0;
++ }
++
++ /* build the SpaceWare version and product info string */
++ strcpy (version, SPW_INPUT_VERSION);
++ if (product != NULL) {
++ productlen = strlen (product);
++ if ((productlen > 0) && (productlen < 200)) {
++ strcat(version, ".");
++ strcat(version, product);
++ }
++ }
++
++ /* save off the application window for future reference */
++ if (ReturnWindowID == 0) {
++ ReturnWindowID = window;
++ }
++
++ /* try to open the Spaceball */
++ InitializeSpaceball (display, version);
++ if (SpaceballFound == 0) {
++ return 0;
++ }
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++
++ /* If we're using XIE, try to enable Spaceball events */
++
++ if (SPW_FindXIE (display) == 1) {
++ XSelectExtensionEvent (display, window, SPW_SpaceballEventClass, 3);
++ }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++ /* Send version info to the daemon */
++ SPW_SendHandshake (display);
++
++ /* we found the Spaceball so return a success message */
++ return 1;
++
++} /* end of SPW_InputCheckForSpaceball */
++
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputIsSpaceballEvent (Display *display, XEvent *event,
++ * SPW_InputEvent *spwev)
++ *
++ * Args:
++ * display (r/o) The display the Spaceball is attached to
++ * event (r/o) The event that we want to check
++ * spwev (w/o) The spaceball return structure contaning the spaceball data
++ *
++ * Return Value:
++ * True if the event is a spaceball event, False if not.
++ *
++ * Description:
++ * Determine if the event is a spaceball event and pack it into
++ * the spwev_ret structure.
++ *
++ * Notes:
++ * This function handles XCM as well as XIE events.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputIsSpaceballEvent (Display *display, XEvent *event,
++ SPW_InputEvent *spwev)
++{
++ static int shake_count = 0; /* how many events have passed without */
++ /* the daemon sending us a handshake */
++ static int last_shake = 0; /* the last time we sent a handshake */
++ static int shake_delay = 7; /* number of events we wait before */
++ /* sending another handshake message */
++ int isSpaceball=0;
++ static int have_handshake = 0; /* did we get a handshake
++ from daemon? */
++ static int have_tune = 0; /* do we have the tune data yet */
++ static float sbtune[6]; /* the tune multipliers */
++ char *scaleVar; /* environment variable containg
++ tune data */
++ int i; /* counter */
++
++ /* if the event, display or spwev variables are not allocated then return */
++ if ((display == NULL) || (event == NULL) || (spwev == NULL)) {
++ return 0;
++ }
++
++#ifdef SPW_DEBUG
++ fprintf(stderr,"SPW_InputIsSpaceballEvent type %d\n", event->type);
++#endif
++
++ /* the event is a spaceball event so deal with it */
++ if (event->type == ClientMessage) {
++ XClientMessageEvent *clientMessage = (XClientMessageEvent *) event;
++#ifdef SPW_DEBUG
++ fprintf(stderr," message_type %d\n", clientMessage->message_type);
++#endif
++
++ /* the event is a motion event */
++ if (clientMessage->message_type == SPW_InputMotionAtom) {
++
++ /* specify we found a spaceball event */
++ isSpaceball = 1;
++
++ /* specify the spaceball event is a motion event */
++ spwev->type = SPW_InputMotionEvent;
++
++ /* copy the spaceball data out of the event into the spwev structure */
++ for (i = 0; i < 7; i++) {
++ spwev->sData[i] = clientMessage->data.s[i + 2];
++ spwev->fData[i] = (float) ((int) clientMessage->data.s[i + 2]);
++ }
++ }
++
++ /* if the event is a button press event process it */
++ else if (clientMessage->message_type == SPW_InputButtonPressAtom) {
++ /* specify we found a spaceball event */
++ isSpaceball = 1;
++
++ /* specify the spaceball event is a button event */
++ spwev->type = SPW_InputButtonPressEvent;
++
++ /* copy the spaceball data out of the event into the spwev structure */
++ spwev->buttonNumber = clientMessage->data.s[2];
++
++ }
++
++ /* if the event is a button release event process it */
++ else if (clientMessage->message_type == SPW_InputButtonReleaseAtom) {
++ /* specify we found a spaceball event */
++ isSpaceball = 1;
++
++ /* specify the spaceball event is a button event */
++ spwev->type = SPW_InputButtonReleaseEvent;
++
++ /* copy the spaceball data out of the event into the spwev structure */
++ spwev->buttonNumber = clientMessage->data.s[2];
++
++ }
++
++ /* the event is a pass through event */
++ else if (clientMessage->message_type == SPW_InputPassThruAtom) {
++ char *str = clientMessage->data.b; /* data in the passthrough event */
++
++ /* check if the pass through event is handshaking from the daemon */
++ if ((str[0] == '~') && (str[1] == '~')) {
++ have_handshake = 1;
++ }
++ }
++
++ /* if we did get a spaceball event save the window ID we got it from */
++ if (isSpaceball == 1) {
++ /* if we don't know what the XCM window is yet save it off */
++ if (SpaceWareXCMWindowID == 0) {
++ SpaceWareXCMWindowID = ntohl(clientMessage->data.l[0]);
++ }
++ }
++ } /* if (event->type == ClientMessage */
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++ /* check to see if the event is a spaceball XIE motion event */
++ else if ((event->type == SPW_DevMotionEventType) &&
++ (((XDeviceMotionEvent *)event)->deviceid == SpaceballDevID)) {
++ /* cast the event to a XIE event */
++ XDeviceMotionEvent *motion = (XDeviceMotionEvent *)event;
++ int i; /* Counter loop index */
++ static float sbData[7]; /* the spaceball data */
++
++ /*
++ * There is not enough room in an SGI X Input Extension event for all
++ * 7 motion values (6 DOF data + period) the Spaceball produces.
++ * Therefore, when we implement the Spaceball XIE we say it has
++ * 7 axes and we send them in two separate XIE events. The
++ * period, axis 6, is sent alone in the first event; the 6 dof data
++ * are sent in the next event. First_axis and axes_count are set
++ * correctly so the client code can figure out when it has a
++ * complete event.
++ *
++ * This function returns 1 to indicate it was a Spaceball event.
++ * In other words, it was not some other type of event the application
++ * should handle. BUT the spwev.type is set to 0 if it is not a
++ * complete Spaceball motion event. This should cause the switch
++ * statement that is suppose to follow a call to this function to
++ * ignore the event.
++ */
++
++ /* specify we found a spaceball event */
++ isSpaceball = 1;
++
++ /* specify the event is a motion event */
++ spwev->type = SPW_InputMotionEvent;
++
++ /* extract the spaceball motion data from the event */
++ for (i = 0; i < (int) (motion->axes_count); i++) {
++ sbData[motion->first_axis+i] = motion->axis_data[i];
++ }
++
++ /* the first axis will always be one, so this will work */
++ if (motion->first_axis != 6) {
++ for (i = 0; i < 7; i++) {
++ spwev->fData[i] = sbData[i];
++ spwev->sData[i] = (short)((int)sbData[i]);
++ }
++ }
++ else {
++ /* Only the period has been received, ignore event */
++ spwev->type = 0;
++ }
++ }
++
++ /* check to see if the event is a spaceball XIE button press event */
++ else if ((event->type == SPW_DevButtonPressEventType) &&
++ (((XDeviceButtonEvent *)event)->deviceid == SpaceballDevID)) {
++ /* cast the event to a XIE event */
++ XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
++
++ /* specify we found a spaceball message */
++ isSpaceball = 1;
++
++ /* specify the message was a button press event */
++ spwev->type = SPW_InputButtonPressEvent;
++
++ /* copy the button data out of the event */
++ spwev->buttonNumber = button->button;
++
++ }
++
++ /* check to see if the event is a spaceball XIE button release event */
++ else if ((event->type==SPW_DevButtonReleaseEventType) &&
++ (((XDeviceButtonEvent *)event)->deviceid == SpaceballDevID)) {
++ /* cast the event to a XIE event */
++ XDeviceButtonEvent *button = (XDeviceButtonEvent *) event;
++
++ /* specify we found a spaceball message */
++ isSpaceball = 1;
++
++ /* specify the message was a button press event */
++ spwev->type = SPW_InputButtonReleaseEvent;
++
++ /* specify the message was a button release event */
++ spwev->buttonNumber = button->button;
++
++ }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++ /*
++ * if after all that we haven't determined the event to be a spaceball
++ * event return a failure
++ */
++ if (isSpaceball == 0) {
++ return 0;
++ }
++
++ /*
++ * If we haven't gotten a handshake packet from the daemon
++ * and it's still early in the process try again, otherwise
++ * say the daemon must be earlier than 7.0. Basically we'll
++ * have sent out SPW_MaxEventCount/shake_delay handshake messages to the
++ * daemon without a response.
++ */
++ if ((have_handshake == 0) && (shake_count < SPW_MaxEventCount)) {
++ if ((last_shake + shake_delay) == shake_count) {
++ SPW_SendHandshake (display);
++ last_shake = shake_count;
++ }
++ shake_count++;
++ }
++
++ /*
++ * Tuning: we want to have the option to tune an application without
++ * having to recompile it each time. We will do this by setting the
++ * SBALL_TUNING variable and scaling the data by it. This should only
++ * be used to get the constants to acutally put into the application.
++ */
++
++ if (spwev->type == SPW_InputMotionEvent) {
++ if (have_tune == 0) {
++ scaleVar = getenv("SBALL_TUNING");
++ if (scaleVar != NULL) {
++ sscanf(scaleVar, "%f %f %f %f %f %f", &sbtune[0],
++ &sbtune[1],
++ &sbtune[2],
++ &sbtune[3],
++ &sbtune[4],
++ &sbtune[5]);
++ }
++ else {
++ sbtune[0] = 1.0f;
++ sbtune[1] = 1.0f;
++ sbtune[2] = 1.0f;
++ sbtune[3] = 1.0f;
++ sbtune[4] = 1.0f;
++ sbtune[5] = 1.0f;
++ }
++ have_tune = 1;
++ }
++
++ spwev->fData[0] *= sbtune[0];
++ spwev->fData[1] *= sbtune[1];
++ spwev->fData[2] *= sbtune[2];
++ spwev->fData[3] *= sbtune[3];
++ spwev->fData[4] *= sbtune[4];
++ spwev->fData[5] *= sbtune[5];
++
++ spwev->sData[0] = (int)(spwev->sData[0] * sbtune[0]);
++ spwev->sData[1] = (int)(spwev->sData[1] * sbtune[1]);
++ spwev->sData[2] = (int)(spwev->sData[2] * sbtune[2]);
++ spwev->sData[3] = (int)(spwev->sData[3] * sbtune[3]);
++ spwev->sData[4] = (int)(spwev->sData[4] * sbtune[4]);
++ spwev->sData[5] = (int)(spwev->sData[5] * sbtune[5]);
++ }
++
++ return 1;
++} /* end of SPW_InputIsSpaceballEvent */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputBeep (Display *display, char *string)
++ *
++ * Args:
++ * display (r/o) The X Display of which the XCM window is a resident
++ * string (r/o) the Spaceball beep string
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function send a string to the XCM driver that will cause
++ * the spaceball to beep. Each lower case character (a-z) results
++ * in a tone, and each upper case character (A-Z) results in a pause
++ * between tones.
++ * Example: cCcC - cause the ball to beep twice.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputBeep (Display *display, char *string)
++{
++ char sndStr[15]; /* the control string to be sent to the driver */
++
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++ /* if we are connected via XIE use that to beep the ball */
++ if (SpaceballInputExtension == 1) {
++#ifdef HAVE_X11_EXTENSIONS_SGIMISC_H
++ /* SGI beep */
++ int slen = strlen (string);
++ static char buf[32];
++ char *cp = buf;
++
++ if (slen > 29) slen = 29;
++ *cp++ = '\r';
++ *cp++ = 'B';
++ strcpy (cp, string);
++ cp += slen;
++ *cp++ = '\r';
++ *cp = NULL;
++ XSGIDeviceControl (display, (int)SpaceballDevID, "sbprivate", buf);
++ XFlush (display);
++
++#elif HAVE_X11_XPROTO_H
++ /* HP beep */
++ int i = 0;
++ int slen = strlen (string);
++ XBellFeedbackControl cntrl;
++
++#if defined(__cplusplus) || defined(c_plusplus)
++ cntrl.c_class = BellFeedbackClass;
++#else /* ! __cplusplus */
++ cntrl.class = BellFeedbackClass;
++#endif /* __cplusplus */
++ cntrl.pitch = 'B';
++ cntrl.percent = 0;
++ while (i < slen) {
++ cntrl.duration = (short) string[i++];
++ XChangeFeedbackControl(display, pSpaceballDev,
++ DvPercent | DvPitch | DvDuration,
++ (XFeedbackControl *)(void *)&cntrl);
++ }
++#endif /* HAVE_XCHANGEFEEDBACKCONTROL */
++ }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++ /* if we are not using XIE use XCM to communicate with the ball */
++ if (SpaceballInputExtension == 0) {
++ /* setup the string to be sent */
++ SPW_strLength = 0;
++ sndStr[0] = '\0';
++ strcat (sndStr, "B");
++ strcat (sndStr, string);
++ strcat (sndStr, "\r");
++
++ /* send the string */
++ SendString (display, sndStr);
++ }
++} /* end of SPW_InputBeep */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputRezero (Display *display)
++ *
++ * Args:
++ * display (r/o) The X Display of which the XCM window is a resident
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function causes the Spaceball to rezero at its current location.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputRezero (Display *display)
++{
++#ifdef HAVE_X11_EXTENSIONS_XINPUT_H
++ /* if we are connected via XIE use that to rezero the ball */
++ if (SpaceballInputExtension == 1)
++ {
++#ifdef HAVE_X11_EXTENSIONS_SGIMISC_H
++ /* SGI rezero */
++ static char *cmd = "\rZ\r";
++
++ XSGIDeviceControl (display, (int)SpaceballDevID, "sbprivate", cmd);
++ XFlush (display);
++
++#elif HAVE_X11_XPROTO_H
++ XBellFeedbackControl cntrl;
++
++#if defined(__cplusplus) || defined(c_plusplus)
++ cntrl.c_class = BellFeedbackClass;
++#else /* ! __cplusplus */
++ cntrl.class = BellFeedbackClass;
++#endif /* __cplusplus */
++ cntrl.pitch = 'Z';
++ cntrl.percent = 0;
++ cntrl.duration = 0;
++ XChangeFeedbackControl (display, pSpaceballDev,
++ DvPercent | DvPitch | DvDuration,
++ (XFeedbackControl *)(void *)&cntrl);
++#endif /* HAVE_X11_XPROTO_H */
++ }
++#endif /* HAVE_X11_EXTENSIONS_XINPUT_H */
++
++ /* if we are not using XIE use XCM to communicate with the ball */
++ if (SpaceballInputExtension == 0) {
++ /* setup the rezero string and send it */
++ SPW_strLength = 0;
++ static char Z[] = "Z\r";
++ SendString (display, Z);
++ }
++} /* end of SPW_InputRezero */
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputSetPulseRate (Display *display, unsigned short rate)
++ *
++ * Args:
++ * display (r/o) The X Display of which the XCM window is a resident
++ * rate (r/o) The rate at which the spaceball data is sent
++ *
++ * Return Value:
++ * None.
++ *
++ * Description:
++ * This function sets the Spaceball transmission rate. Currently
++ * it is just stubed out since we don't want the transmission rate
++ * of the Spaceball to change.
++ *
++ * Notes:
++ * None.
++ *
++ *---------------------------------------------------------------------------*/
++void SPW_InputSetPulseRate (Display *display, unsigned short rate)
++{
++
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputXPending (Display *display, int delay)
++ *
++ * Args:
++ * display (r/o) The X Display on which the queue is resident
++ * delay (r/o) amount of time to wait for the next event in microseconds
++ *
++ * Return Value:
++ * Returns the number of event on the X queue.
++ *
++ * Description:
++ * Wait for another Spaceball event to come in within the time delay.
++ *
++ * Notes:
++ * If delay is less than or equal to zero this just checks the queue
++ * without waiting.
++ *
++ *---------------------------------------------------------------------------*/
++int SPW_InputXPending (Display *display, int delay)
++{
++ int numevents; /* the number of event on the X queue */
++ struct timeval short_wait; /* time struct needed for select call */
++
++ fd_set Xfds;
++
++#ifdef SPW_DEBUG
++ fprintf(stderr,"SPW_InputXPending\n");
++#endif
++
++ /* get the number of event waiting on the event queue */
++ numevents = XPending (display);
++
++#ifdef SPW_DEBUG
++ fprintf(stderr," numevents %d delay %d\n", numevents, delay);
++#endif
++
++ /*
++ * if there are already event waiting or we have exceded the delay
++ * return the number of events on the queue
++ */
++ if ((numevents > 0) || (delay <= 0)) {
++ return numevents;
++ }
++
++ /* use select to wait for the designated delay period */
++ short_wait.tv_sec = 0;
++ short_wait.tv_usec = (long) delay;
++ FD_ZERO (&Xfds);
++ FD_SET (ConnectionNumber (display), &Xfds);
++
++ (void)select (ConnectionNumber (display) + 1, &Xfds, NULL,
++ NULL, &short_wait);
++
++ /* check the event queue again */
++ numevents = XPending (display);
++
++#ifdef SPW_DEBUG
++ fprintf(stderr," numevents %d\n", numevents);
++#endif
++
++ /* return the number of event on the queue */
++ return numevents;
++} /* end of SPW_InputXPending*/
++
++/*-----------------------------------------------------------------------------
++ *
++ * void SPW_InputInitDispatchStruct (SPW_InputDispatchStruct *ds)
++ *
++ * Args:
++ * ds (w/o) - input dispatch structure
++ *
++ * Return Value:
++ * None
++ *
++ * Description:
++ * Zeroizes a new dispatch structure and sets the default delay.
++ *
++ * Notes:
++ *
++ *----------------------------------------------------------------------------*/
++void SPW_InputInitDispatchStruct (SPW_InputDispatchStruct * ds)
++{
++ memset(ds, (unsigned char)0, sizeof(SPW_InputDispatchStruct));
++ ds->delay = SPW_InputDefaultDelay;
++}
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputDispatch (SPW_InputDispatchStruct *ds)
++ *
++ * Args:
++ * ds (r/o) - input dispatch structure
++ *
++ * Return Value:
++ * 1 if a redraw is required, 0 if a redraw is not required.
++ *
++ * Description:
++ * Determines what type of event has been returned by the Spaceball and calls
++ * the appropriate dispatch routine.
++ * SPW_InputMotionEventHandler - called if a motion event occured
++ * SPW_InputButtonEventHandler - called if a button event occured
++ * SPW_InputOtherEventHandler - called if a non-spaceball event occured
++ *
++ * Notes:
++ * if SPW_InputOtherEventHandler return a non-zero SPW_InputDispatch
++ * will dispose of the event and continue processing events.
++ *
++ *----------------------------------------------------------------------------*/
++
++int SPW_InputDispatch (SPW_InputDispatchStruct *ds)
++{
++ float data[7]; /* place to store Spaceball event data */
++ int i; /* loop counter */
++ int motion_events; /* flag tells if we have motion event*/
++ int event_pending; /* flag tells if ther's an event pending */
++ int all_zero_event; /* flag set if there's an all zero event */
++ int redraw; /* redraw flag */
++ int continue_loop; /* flag to keep while loop running */
++
++ /* initialize variable */
++ redraw = 0;
++ motion_events=0;
++ event_pending=1;
++ all_zero_event=0;
++ redraw = 0;
++ continue_loop=1;
++
++#ifdef SPW_DEBUG
++ fprintf(stderr,"SPW_InputDispatch\n"); /* show where we are */
++#endif
++
++ /* if dispatch struct is empty, return to caller */
++ if (ds == NULL)
++ {
++ return 0;
++ }
++
++ /* initialize local event data structure */
++ for (i = 0; i < 7; i++)
++ {
++ data[i] = 0.0f;
++ }
++
++ /* compress event data while it keeps on coming */
++ while (continue_loop == 1)
++ {
++
++#ifdef SPW_DEBUG
++ fprintf(stderr," spwevent type %d\n", ds->spwevent->type);
++#endif
++
++ /* see what type of event we have */
++ switch(ds->spwevent->type)
++ {
++ case SPW_InputMotionEvent:
++ motion_events++;
++
++ /* Check for a no motion event */
++ if ((ds->spwevent->fData[0] == 0.0) &&
++ (ds->spwevent->fData[1] == 0.0) &&
++ (ds->spwevent->fData[2] == 0.0) &&
++ (ds->spwevent->fData[3] == 0.0) &&
++ (ds->spwevent->fData[4] == 0.0) &&
++ (ds->spwevent->fData[5] == 0.0))
++ {
++ all_zero_event++; /* keep track of how many we have */
++ }
++
++ /* add data into local structure */
++ for (i = 0; i < 7; i++)
++ {
++ data[i] += ds->spwevent->fData[i];
++ }
++
++#ifdef SPW_DEBUG
++ fprintf(stderr," %f %f %f %f %f %f %f\n", data[0],data[1],data[2],
++ data[3],data[4],data[5],data[6]);
++#endif
++
++ break;
++ case SPW_InputButtonPressEvent: /* button press event */
++ /* if button press event handler function pointer is present */
++ if (ds->handle_bpress != 0)
++ {
++ (*(ds->handle_bpress)) (ds->display, ds->spwevent->buttonNumber,
++ ds->pButtonAppData);
++ }
++
++ /* check for rezero button */
++ if (ds->spwevent->buttonNumber == 9)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] = 0.0f; /* zero data structure */
++ }
++ motion_events = 0; /* reset number of motion events */
++ }
++ break;
++ case SPW_InputButtonReleaseEvent: /* button release event */
++
++ if (ds->handle_brelease != 0)
++ {
++ (*(ds->handle_brelease)) (ds->display,ds->spwevent->buttonNumber,
++ ds->pButtonAppData);
++ }
++ /* check for rezero button */
++ if (ds->spwevent->buttonNumber == 9)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] = 0.0f; /* clear local data */
++ }
++ motion_events = 0; /* reset number of motion events */
++ redraw = 1;
++ }
++ break;
++ default:
++ break;
++ } /* end of case statement */
++
++ /* check if input is pending */
++ if (SPW_InputXPending (ds->display, ds->delay))
++ {
++ XNextEvent (ds->display, ds->xevent); /* get an event */
++
++ /* if it's not a Spaceball event see if we should continue */
++ if (SPW_InputIsSpaceballEvent (ds->display, ds->xevent,
++ ds->spwevent) == 0)
++ {
++ /* if we have an event handler...*/
++ if (ds->handle_other != 0)
++ {
++ /* handle event and get loop status */
++ continue_loop = (ds->handle_other)
++ (ds->display, ds->xevent, ds->pOtherAppData);
++ }
++ else
++ {
++ continue_loop = 0; /* no event handler -> bail */
++ }
++ }
++ }
++ else /* no more events to compress */
++ {
++ event_pending = 0;
++ continue_loop = 0;
++ }
++ } /* end of while loop */
++
++#ifdef SPW_DEBUG
++ fprintf(stderr," event_pending %d motion_events %d all_zero_event %d\n",
++ event_pending, motion_events, all_zero_event);
++#endif
++
++ /* push unwanted event back onto the stack */
++ if (event_pending == 1)
++ {
++ XPutBackEvent(ds->display, ds->xevent);
++ }
++
++ /* average event data by the period of the Spaceball data */
++ if (data[6] != 0.0)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] /= data[6];
++ }
++ }
++
++#ifdef SPW_DEBUG
++ fprintf(stderr,"ave %f %f %f %f %f %f\n\n", data[0], data[1], data[2],
++ data[3], data[4], data[5]);
++#endif
++
++ /* if we have a motion event handler... */
++ if (ds->handle_motion != 0)
++ {
++ /* if there are motion events, handle them and force a redraw */
++ if (motion_events != 0)
++ {
++ (*(ds->handle_motion)) (ds->display, data, ds->pMotionAppData);
++ redraw = 1;
++ }
++
++ if ((all_zero_event != 0) && (motion_events > 1))
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] = 0.0f; /* reset data */
++ }
++
++ /* handle motion and force a redraw */
++ (ds->handle_motion) (ds->display, data, ds->pMotionAppData);
++ redraw = 1;
++ }
++ }
++
++ return redraw;
++} /* end of SPW_InputDispatch */
++
++/*-----------------------------------------------------------------------------
++ *
++ * int SPW_InputDispatchEx (SPW_InputDispatchStruct *ds)
++ *
++ * Args:
++ * ds (r/o) - input dispatch structure
++ *
++ * Return Value:
++ * 1 if a redraw is required, 0 if a redraw is not required.
++ *
++ * Description:
++ * Determines what type of event has been returned by the Spaceball and calls
++ * the appropriate dispatch routine.
++ * SPW_InputMotionEventHandler - called if a motion event occured
++ * SPW_InputButtonEventHandler - called if a button event occured
++ * SPW_InputOtherEventHandler - called if a non-spaceball event occured
++ *
++ * Notes:
++ * An optimized and more cooperative version of SPW_InputDispatch().
++ * if SPW_InputOtherEventHandler returns non-zero, SPW_InputDispatchEx
++ * will dispose of the event and continue compressing motion events.
++ * If zero is returned, this function will dump all accumalated motion
++ * events (unlike its predecessor) and quickly return control back to
++ * the app. Also, the standard Xlib call XPending() is used instead of
++ * SPW_InputXPending().
++ *
++ *----------------------------------------------------------------------------*/
++
++int SPW_InputDispatchEx (SPW_InputDispatchStruct *ds)
++{
++ float data[7]; /* place to store Spaceball event data */
++ int i; /* loop counter */
++ int motion_events; /* flag tells if we have motion event*/
++ int all_zero_event; /* flag set if there's an all zero event */
++ int redraw; /* redraw flag */
++ int continue_loop; /* flag to keep while loop running */
++
++ /* initialize variable */
++ redraw = 0;
++ motion_events=0;
++ all_zero_event=0;
++ redraw = 0;
++ continue_loop=1;
++
++#ifdef SPW_DEBUG
++ fprintf(stderr,"SPW_InputDispatch\n"); /* show where we are */
++#endif
++
++ /* if dispatch struct is empty, return to caller */
++ if (ds == NULL)
++ {
++ return 0;
++ }
++
++ /* initialize local event data structure */
++ for (i = 0; i < 7; i++)
++ {
++ data[i] = 0.0f;
++ }
++
++ /* compress event data while it keeps on coming */
++ while (continue_loop == 1)
++ {
++
++#ifdef SPW_DEBUG
++ fprintf(stderr," spwevent type %d\n", ds->spwevent->type);
++#endif
++
++ /* make sure we have ball data */
++ SPW_InputIsSpaceballEvent (ds->display, ds->xevent, ds->spwevent);
++
++ /* see what type of event we have */
++ switch(ds->spwevent->type)
++ {
++ case SPW_InputMotionEvent:
++ motion_events++;
++
++ /* Check for a no motion event */
++ if ((ds->spwevent->fData[0] == 0.0) &&
++ (ds->spwevent->fData[1] == 0.0) &&
++ (ds->spwevent->fData[2] == 0.0) &&
++ (ds->spwevent->fData[3] == 0.0) &&
++ (ds->spwevent->fData[4] == 0.0) &&
++ (ds->spwevent->fData[5] == 0.0))
++ {
++ all_zero_event++; /* keep track of how many we have */
++ }
++
++ /* add data into local structure */
++ for (i = 0; i < 7; i++)
++ {
++ data[i] += ds->spwevent->fData[i];
++ }
++
++#ifdef SPW_DEBUG
++ fprintf(stderr," %f %f %f %f %f %f %f\n",
++ data[0],data[1],data[2],
++ data[3],data[4],data[5],data[6]);
++#endif
++
++ break;
++ case SPW_InputButtonPressEvent: /* button press event */
++ /* if button press event handler function pointer is present */
++ if (ds->handle_bpress != 0)
++ {
++ (*(ds->handle_bpress)) (ds->display, ds->spwevent->buttonNumber,
++ ds->pButtonAppData);
++ }
++
++ /* check for rezero button */
++ if (ds->spwevent->buttonNumber == 9)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] = 0.0f; /* zero data structure */
++ }
++ motion_events = 0; /* reset number of motion events */
++ }
++ break;
++ case SPW_InputButtonReleaseEvent: /* button release event */
++
++ if (ds->handle_brelease != 0)
++ {
++ (*(ds->handle_brelease)) (ds->display,ds->spwevent->buttonNumber,
++ ds->pButtonAppData);
++ }
++ /* check for rezero button */
++ if (ds->spwevent->buttonNumber == 9)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] = 0.0f; /* clear local data */
++ }
++ motion_events = 0; /* reset number of motion events */
++ redraw = 1;
++ }
++ break;
++ default:
++ break;
++ } /* end of case statement */
++
++ /* check if input is pending */
++ if (XPending (ds->display) > 0)
++ {
++ XPeekEvent (ds->display, ds->xevent); /* look at an event */
++ if (SPW_InputIsSpaceballEvent (ds->display, ds->xevent,
++ ds->spwevent) == 1)
++ {
++ XEvent throw_away;
++ XNextEvent (ds->display, &throw_away); /* remove the event */
++ }
++ else /* if it's not a Spaceball event see if we should continue */
++ {
++ /* if we have an event handler...*/
++ if (ds->handle_other != NULL)
++ {
++ /* handle event and get loop status */
++ continue_loop = (ds->handle_other)
++ (ds->display, ds->xevent, ds->pOtherAppData);
++ if (continue_loop == 1)
++ {
++ XNextEvent (ds->display, ds->xevent); /* get next event */
++ }
++ else
++ {
++ motion_events = 0; /* app needs control back, fast! */
++ }
++ }
++ else
++ {
++ continue_loop = 0; /* no event handler -> bail */
++ }
++ }
++ }
++ else /* no more events to compress */
++ {
++ continue_loop = 0;
++ }
++ } /* end of while loop */
++
++#if defined(SPW_DEBUG) && 0
++ fprintf(stderr," event_pending %d motion_events %d all_zero_event %d\n",
++ event_pending, motion_events, all_zero_event);
++#endif
++
++ /* average event data by the period of the Spaceball data */
++ if (data[6] != 0.0)
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] /= data[6];
++ }
++ }
++
++#ifdef SPW_DEBUG
++ fprintf(stderr,"ave %f %f %f %f %f %f\n\n", data[0], data[1],
++ data[2],
++ data[3], data[4], data[5]);
++#endif
++
++ /* if we have a motion event handler... */
++ if (ds->handle_motion != 0)
++ {
++ /* if there are motion events, handle them and force a redraw */
++ if (motion_events != 0)
++ {
++ (*(ds->handle_motion)) (ds->display, data, ds->pMotionAppData);
++ redraw = 1;
++ }
++
++ if ((all_zero_event != 0) && (motion_events > 1))
++ {
++ for (i = 0; i < 6; i++)
++ {
++ data[i] = 0.0f; /* reset data */
++ }
++
++ /* handle motion and force a redraw */
++ (ds->handle_motion) (ds->display, data, ds->pMotionAppData);
++ redraw = 1;
++ }
++ }
++
++ return redraw;
++
++} /* end of SPW_InputDispatchEx */
++
++#endif /* HAVE_X11_AVAILABLE */
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiConstrainedViewer.cpp.in
+@@ -0,0 +1,299 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class So at Gui@ConstrainedViewer Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h
++ \brief The So at Gui@ConstrainedViewer class is the superclass for viewers with constrains on the viewpoint.
++ \ingroup components viewers
++
++ This abstract viewer class adds new methods to keep the camera in an
++ upright position according to some arbitrary up-direction. The
++ up-direction can be decided by either the application programmer (by
++ using So at Gui@ConstrainedViewer::setUpDirection()) or the end-user,
++ through interaction mechanisms defined by the subclasses.
++*/
++
++#include <Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <so at gui@defs.h>
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++class So at Gui@ConstrainedViewerP {
++public:
++ So at Gui@ConstrainedViewerP(So at Gui@ConstrainedViewer * owner) {
++ this->publ = owner;
++ }
++
++ void rotateCamera(const float delta) const;
++
++ SbVec3f upvechome;
++ SbVec3f upvector; // The camera's "up" vector is contrained to be in this direction.
++
++private:
++ So at Gui@ConstrainedViewer * publ;
++};
++
++#define PRIVATE(o) (o->pimpl)
++#define PUBLIC(o) (o->publ)
++
++void
++So at Gui@ConstrainedViewerP::rotateCamera(const float delta) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++ camera->orientation = camera->orientation.getValue() *
++ SbRotation(PUBLIC(this)->getUpDirection(), -delta);
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// ************************************************************************
++
++SO at GUI@_OBJECT_ABSTRACT_SOURCE(So at Gui@ConstrainedViewer);
++
++// ************************************************************************
++
++/*!
++ Constructor.
++*/
++So at Gui@ConstrainedViewer::So at Gui@ConstrainedViewer(@WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build)
++ : inherited(parent, name, embed, flag, type, FALSE)
++{
++ PRIVATE(this) = new So at Gui@ConstrainedViewerP(this);
++
++ this->setClassName("So at Gui@ConstrainedViewer");
++ this->setLeftWheelString("Tilt");
++ this->setBottomWheelString("Rotate");
++ this->setRightWheelString("Dolly");
++
++ PRIVATE(this)->upvector = SbVec3f(0.0f, 1.0f, 0.0f);
++ PRIVATE(this)->upvechome = PRIVATE(this)->upvector;
++
++ if (build) {
++ @WIDGET@ viewer = this->buildWidget(this->getParentWidget());
++ this->setBaseWidget(viewer);
++ }
++}
++
++// ************************************************************************
++
++/*!
++ Virtual destructor.
++*/
++So at Gui@ConstrainedViewer::~So at Gui@ConstrainedViewer()
++{
++ delete PRIVATE(this);
++}
++
++// ************************************************************************
++
++/*!
++ Set up-direction vector for the camera viewpoint.
++*/
++void
++So at Gui@ConstrainedViewer::setUpDirection(const SbVec3f & dir)
++{
++ SbRotation change(PRIVATE(this)->upvector, dir);
++ PRIVATE(this)->upvector = dir;
++
++ SoCamera * cam = this->getCamera();
++ if (cam == NULL) { return; } // can happen for empty scene, for instance
++
++ cam->orientation = change * cam->orientation.getValue();
++ this->checkForCameraUpConstrain();
++}
++
++// ************************************************************************
++
++/*!
++ Return up-direction vector for the camera viewpoint.
++*/
++const SbVec3f &
++So at Gui@ConstrainedViewer::getUpDirection(void) const
++{
++ return PRIVATE(this)->upvector;
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::setCamera(SoCamera * newcam)
++{
++ inherited::setCamera(newcam);
++ if (newcam != NULL) { this->checkForCameraUpConstrain(); }
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::saveHomePosition(void)
++{
++ inherited::saveHomePosition();
++ PRIVATE(this)->upvechome = PRIVATE(this)->upvector;
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::resetToHomePosition(void)
++{
++ inherited::resetToHomePosition();
++ PRIVATE(this)->upvector = PRIVATE(this)->upvechome;
++ // should be unnecessary to reset camera position here (camera
++ // should have been in a valid state on the last saveHomePosition()
++ // call)
++}
++
++// ************************************************************************
++
++/*!
++ This method tilts the camera \a delta degrees closer to the up
++ direction.
++*/
++void
++So at Gui@ConstrainedViewer::tiltCamera(float delta)
++{
++ SoCamera * const camera = this->getCamera();
++ if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++ SbVec3f camdir;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), camdir);
++ camera->orientation = camera->orientation.getValue() *
++ SbRotation(this->getUpDirection().cross(camdir), delta);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::bottomWheelMotion(float value)
++{
++ PRIVATE(this)->rotateCamera(value - this->getBottomWheelValue());
++ inherited::bottomWheelMotion(value);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::leftWheelMotion(float value)
++{
++ this->tiltCamera( this->getLeftWheelValue() - value);
++ inherited::leftWheelMotion(value);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@ConstrainedViewer::changeCameraValues(SoCamera * camera)
++{
++ inherited::changeCameraValues(camera);
++ this->checkForCameraUpConstrain();
++}
++
++// ************************************************************************
++
++/*!
++ Executes a raypick at the given mousepointer location and sets the
++ viewer's camera up-vector direction to the normal vector of the
++ picked geometry.
++*/
++void
++So at Gui@ConstrainedViewer::findUpDirection(SbVec2s mouselocation)
++{
++ SoRayPickAction rp(this->getViewportRegion());
++ rp.setPoint(mouselocation);
++
++ // Use the full scenegraph, not just the user-set scenegraph (which
++ // is what So at Gui@ConstrainedViewer::getSceneGraph() would return).
++ SoNode * realroot = this->getSceneManager()->getSceneGraph();
++ rp.apply(realroot);
++
++ SoPickedPoint * point = rp.getPickedPoint();
++ if (point == NULL) { return; } // missed all geometry
++
++ SbVec3f normvec = point->getNormal();
++ // FIXME: need to flip normal if we hit the backside of a
++ // polygon. 20010925 mortene.
++ this->setUpDirection(normvec);
++}
++
++// ************************************************************************
++
++/*!
++ If necessary, "tilts" the camera sideways so the up-direction is
++ heeded.
++*/
++void
++So at Gui@ConstrainedViewer::checkForCameraUpConstrain(void)
++{
++ SoCamera * cam = this->getCamera();
++ assert(cam);
++
++ SbRotation camorient = cam->orientation.getValue();
++
++ SbVec3f campointdir;
++ camorient.multVec(SbVec3f(0, 0, -1), campointdir);
++ SbVec3f camrightdir;
++ camorient.multVec(SbVec3f(1, 0, 0), camrightdir);
++
++ SbVec3f correctrightdir = campointdir.cross(PRIVATE(this)->upvector);
++ if (correctrightdir.length() == 0.0f) { return; } // upvector == pointdir
++
++ SbRotation r(camrightdir, correctrightdir);
++ SbRotation newcamorient = camorient * r;
++ cam->orientation = newcamorient;
++}
++
++// ************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiConstrainedViewer.h.in
+@@ -0,0 +1,77 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_CONSTRAINEDVIEWER_H
++#define SO at GUI@_CONSTRAINEDVIEWER_H
++
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++
++// ************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@ConstrainedViewer : public So at Gui@FullViewer {
++ SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@ConstrainedViewer, So at Gui@FullViewer);
++
++public:
++ void setUpDirection(const SbVec3f & dir);
++ const SbVec3f & getUpDirection(void) const;
++
++ virtual void setCamera(SoCamera * newcam);
++ virtual void saveHomePosition(void);
++ virtual void resetToHomePosition(void);
++
++protected:
++ So at Gui@ConstrainedViewer(@WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build);
++
++ ~So at Gui@ConstrainedViewer();
++
++ virtual void tiltCamera(float delta);
++ virtual void bottomWheelMotion(float value);
++ virtual void leftWheelMotion(float value);
++
++ virtual void changeCameraValues(SoCamera * camera);
++ void findUpDirection(SbVec2s mouselocation);
++ void checkForCameraUpConstrain(void);
++
++private:
++ class So at Gui@ConstrainedViewerP * pimpl;
++};
++
++// ************************************************************************
++
++#endif // ! SO at GUI@_CONSTRAINEDVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiExaminerViewer.cpp.in
+@@ -0,0 +1,1301 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*ExaminerViewer sourcecode.
++
++// *************************************************************************
++
++/*!
++ \class So at Gui@ExaminerViewer So at Gui@ExaminerViewer.h Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h
++ \brief The So at Gui@ExaminerViewer class is a 3D-model examination viewer.
++ \ingroup components viewers
++
++ This class is the viewer considered to be the most "general purpose"
++ viewer, and it is often used in rapid prototyping to examine simple
++ models aswell as complete scenes (although for the latter, you might
++ be better off with one of the other viewer classes).
++
++ <center>
++ <img src="http://doc.coin3d.org/images/SoLibs/viewers/examinerviewer.png">
++ </center>
++
++ Here is a complete, stand-alone example that shows how to set up an
++ So at Gui@ExaminerViewer as a model viewer that loads Inventor and VRML
++ files from disk and places them inside the viewer for the end-user
++ to examine:
++
++ \code
++ #include <Inventor/@Gui@/So at Gui@.h>
++ #include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++ #include <Inventor/nodes/SoBaseColor.h>
++ #include <Inventor/nodes/SoCone.h>
++ #include <Inventor/nodes/SoSeparator.h>
++
++ int
++ main(int argc, char ** argv)
++ {
++ if (argc < 2) {
++ (void)fprintf(stderr, "\n\n\tUsage: %s <modelfilename>\n\n",
++ argc > 0 ? argv[0] : "viewerapp");
++ exit(1);
++ }
++
++ // Initialize So at Gui@ and Inventor API libraries. This returns a main
++ // window to use.
++ @WIDGET@ mainwin = So at Gui@::init(argc, argv, argv[0]);
++
++ // Open the argument file..
++ SoInput in;
++ SbBool ok = in.openFile(argv[1]);
++ if (!ok) { exit(1); }
++
++ // ..and import it.
++ SoSeparator * root = SoDB::readAll(&in);
++ if (root == NULL) { exit(1); }
++ root->ref();
++
++ // Use the ExaminerViewer, for a nice interface for 3D model
++ // inspection.
++ So at Gui@ExaminerViewer * viewer = new So at Gui@ExaminerViewer(mainwin);
++ viewer->setSceneGraph(root);
++ viewer->show();
++
++ // Pop up the main window.
++ So at Gui@::show(mainwin);
++ // Loop until exit.
++ So at Gui@::mainLoop();
++
++ // Clean up resources.
++ delete viewer;
++ root->unref();
++
++ return 0;
++ }
++ \endcode
++
++ So at Gui@ExaminerViewer has a convenient interface for repositioning
++ and reorientation of the camera, by panning, rotating and zooming
++ it's position. The following controls can be used:
++
++ <ul>
++
++ <li>hold down left mousebutton and move mouse pointer to rotate the
++ camera around it's current focal point (the focal point can be
++ changed by doing a seek operation)</li>
++
++ <li>hold middle mousebutton to pan (or a CTRL-key plus left
++ mousebutton, or a SHIFT-key plus left mousebutton)</li>
++
++ <li>hold down left + middle mousebutton to zoom / dolly, or CTRL +
++ middle mousebutton, or CTRL + SHIFT + the left mousebutton</li>
++
++ <li>click 's', then pick with the left mousebutton to seek</li>
++
++ <li>right mousebutton opens the popup menu</li>
++
++ <li>click 'ESC' key to switch to and from 'camera interaction' mode
++ and 'scenegraph interaction' mode (see setViewing()
++ documentation)</li>
++
++ <!--
++ FIXME: This functionality has been disabled. See FIXME comment
++ 20050202 larsa below.
++
++ <li>hold down the 'ALT' key to temporary toggle from
++ camera-interaction mode to scenegraph-interaction mode</li>
++
++ //-->
++
++ <li>'q' quits the application</li>
++
++ </ul>
++
++ The So at Gui@ExaminerViewer provides a user decoration's button for
++ toggling between orthographic or perspective camera view volumes and
++ projection methods. This is the bottom-most click button on the
++ right decoration border.
++
++ It also inherits the decoration buttons from the So at Gui@FullViewer:
++ the arrow for switching to "scenegraph interaction" mode, the hand
++ for setting back to "camera interaction" mode, the house for "reset
++ camera to home position", the blueprint house for "set new camera
++ home position", the eye for "zoom camera out to view full scene" and
++ the flashlight for setting "click to seek" mode.
++
++ Note that a common faulty assumption about all the viewer-classes is
++ that user interaction (in the "examine"-mode, not the
++ scenegraph-interaction mode) influences the model or 3D-scene in the
++ view. This is not correct, as it is always the viewer's \e camera
++ that is translated and rotated.
++
++ The initial position of the camera is placed such that all of the
++ scenegraph's geometry fits within it's view.
++
++ \sa So at Gui@FlyViewer, So at Gui@PlaneViewer
++*/
++
++// *************************************************************************
++
++// Documentation shared between So* toolkits follows below.
++
++/*!
++ \fn So at Gui@ExaminerViewer::So at Gui@ExaminerViewer(@WIDGET@ parent, const char * name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type)
++
++ Constructor. See parent class for explanation of arguments.
++ Calling this constructor will make sure the examiner viewer widget
++ will be built immediately.
++*/
++
++/*!
++ \fn So at Gui@ExaminerViewer::So at Gui@ExaminerViewer(@WIDGET@ parent, const char * name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type, SbBool build)
++
++ Constructor. See parent class for explanation of arguments.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <math.h>
++
++#include <Inventor/SbTime.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/projectors/SbSphereSheetProjector.h>
++#include <Inventor/projectors/SbSpherePlaneProjector.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/events/SoMotion3Event.h>
++
++#include <so at gui@defs.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewer.h>
++#include <Inventor/@Gui@/viewers/So at Gui@ExaminerViewerP.h>
++
++#include <Inventor/@Gui@/So at Gui@Basic.h>
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++#include <Inventor/@Gui@/viewers/SoGuiFullViewerP.h> // for pan() and zoom()
++
++#define PRIVATE(obj) ((obj)->pimpl)
++#define PUBLIC(obj) ((obj)->pub)
++
++static const int MOUSEPOSLOGSIZE = 16;
++
++// Bitmap representations of an "X", a "Y" and a "Z" for the axis cross.
++static GLubyte xbmp[] = { 0x11,0x11,0x0a,0x04,0x0a,0x11,0x11 };
++static GLubyte ybmp[] = { 0x04,0x04,0x04,0x04,0x0a,0x11,0x11 };
++static GLubyte zbmp[] = { 0x1f,0x10,0x08,0x04,0x02,0x01,0x1f };
++
++// ************************************************************************
++
++/*!
++ Decide if it should be possible to start a spin animation of the
++ model in the viewer by releasing the mouse button while dragging.
++
++ If the \a enable flag is \c FALSE and we're currently animating, the
++ spin will be stopped.
++
++ \sa isAnimationEnabled
++*/
++void
++So at Gui@ExaminerViewer::setAnimationEnabled(const SbBool enable)
++{
++ PRIVATE(this)->spinanimatingallowed = enable;
++ if (!enable && this->isAnimating()) { this->stopAnimating(); }
++}
++
++// *************************************************************************
++
++/*!
++ Query whether or not it is possible to start a spinning animation by
++ releasing the left mouse button while dragging the mouse.
++
++ \sa setAnimationEnabled
++*/
++
++SbBool
++So at Gui@ExaminerViewer::isAnimationEnabled(void) const
++{
++ return PRIVATE(this)->spinanimatingallowed;
++}
++
++// *************************************************************************
++
++/*!
++ Stop the model from spinning.
++*/
++
++void
++So at Gui@ExaminerViewer::stopAnimating(void)
++{
++ if (PRIVATE(this)->currentmode != SoGuiExaminerViewerP::SPINNING) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@ExaminerViewer::stopAnimating",
++ "not animating");
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++ PRIVATE(this)->setMode(this->isViewing() ?
++ SoGuiExaminerViewerP::IDLE :
++ SoGuiExaminerViewerP::INTERACT);
++}
++
++// *************************************************************************
++
++/*!
++ Query if the model in the viewer is currently in spinning mode after
++ a user drag.
++*/
++
++SbBool
++So at Gui@ExaminerViewer::isAnimating(void) const
++{
++ return PRIVATE(this)->currentmode == SoGuiExaminerViewerP::SPINNING;
++}
++
++// ************************************************************************
++
++/*!
++ Set the flag deciding whether or not to show the axis cross.
++
++ \sa isFeedbackVisible, getFeedbackSize, setFeedbackSize
++*/
++
++void
++So at Gui@ExaminerViewer::setFeedbackVisibility(const SbBool enable)
++{
++ if (enable == PRIVATE(this)->axiscrossEnabled) {
++#ifdef SO at GUI@_EXTRA_DEBUG
++ SoDebugError::postWarning("So at Gui@ExaminerViewer::setFeedbackVisibility",
++ "feedback visibility already set to %s", enable ? "TRUE" : "FALSE");
++#endif // SO at GUI@_EXTRA_DEBUG
++ return;
++ }
++ PRIVATE(this)->axiscrossEnabled = enable;
++
++ if (this->isViewing()) { this->scheduleRedraw(); }
++}
++
++/*!
++ Check if the feedback axis cross is visible.
++
++ \sa setFeedbackVisibility, getFeedbackSize, setFeedbackSize
++*/
++
++SbBool
++So at Gui@ExaminerViewer::isFeedbackVisible(void) const
++{
++ return PRIVATE(this)->axiscrossEnabled;
++}
++
++// ************************************************************************
++
++/*!
++ Set the size of the feedback axiscross. The value is interpreted as
++ an approximate percentage chunk of the dimensions of the total
++ canvas.
++
++ \sa getFeedbackSize, isFeedbackVisible, setFeedbackVisibility
++*/
++void
++So at Gui@ExaminerViewer::setFeedbackSize(const int size)
++{
++#if SO at GUI@_DEBUG
++ if (size < 1) {
++ SoDebugError::postWarning("So at Gui@ExaminerViewer::setFeedbackSize",
++ "the size setting should be larger than 0");
++ return;
++ }
++#endif // SO at GUI@_DEBUG
++
++ PRIVATE(this)->axiscrossSize = size;
++
++ if (this->isFeedbackVisible() && this->isViewing()) {
++ this->scheduleRedraw();
++ }
++}
++
++/*!
++ Return the size of the feedback axis cross. Default is 25.
++
++ \sa setFeedbackSize, isFeedbackVisible, setFeedbackVisibility
++*/
++
++int
++So at Gui@ExaminerViewer::getFeedbackSize(void) const
++{
++ return PRIVATE(this)->axiscrossSize;
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@ExaminerViewer::processSoEvent(const SoEvent * const ev)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@ExaminerViewer::processSoEvent",
++ "[invoked], event '%s'",
++ ev->getTypeId().getName().getString());
++#endif // debug
++
++ // We're in "interact" mode (ie *not* the camera modification mode),
++ // so don't handle the event here. It should either be forwarded to
++ // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++ // it's an ESC or ALT press (to switch modes).
++ if (!this->isViewing()) { return inherited::processSoEvent(ev); }
++
++ // Events when in "ready-to-seek" mode are ignored, except those
++ // which influence the seek mode itself -- these are handled further
++ // up the inheritance hierarchy.
++ if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
++
++ const SoType type(ev->getTypeId());
++
++ const SbVec2s size(this->getGLSize());
++ const SbVec2f prevnormalized = PRIVATE(this)->lastmouseposition;
++ const SbVec2s pos(ev->getPosition());
++ const SbVec2f posn((float) pos[0] / (float) So at Gui@Max((int)(size[0] - 1), 1),
++ (float) pos[1] / (float) So at Gui@Max((int)(size[1] - 1), 1));
++
++ PRIVATE(this)->lastmouseposition = posn;
++
++ // Set to TRUE if any event processing happened. Note that it is not
++ // necessary to restrict ourselves to only do one "action" for an
++ // event, we only need this flag to see if any processing happened
++ // at all.
++ SbBool processed = FALSE;
++
++ const SoGuiExaminerViewerP::ViewerMode currentmode = PRIVATE(this)->currentmode;
++ SoGuiExaminerViewerP::ViewerMode newmode = currentmode;
++
++ PRIVATE(this)->ctrldown = ev->wasCtrlDown();
++ PRIVATE(this)->shiftdown = ev->wasShiftDown();
++
++ // Mouse Button / Spaceball Button handling
++
++ if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++ processed = TRUE;
++
++ const SoMouseButtonEvent * const event = (const SoMouseButtonEvent *) ev;
++ const int button = event->getButton();
++ const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
++
++ switch (button) {
++ case SoMouseButtonEvent::BUTTON1:
++ PRIVATE(this)->button1down = press;
++ if (press && (currentmode == SoGuiExaminerViewerP::SEEK_WAIT_MODE)) {
++ newmode = SoGuiExaminerViewerP::SEEK_MODE;
++ this->seekToPoint(pos); // implicitly calls interactiveCountInc()
++ }
++ break;
++ case SoMouseButtonEvent::BUTTON2:
++ processed = FALSE; // pass on to superclass, so popup menu is shown
++ break;
++ case SoMouseButtonEvent::BUTTON3:
++ PRIVATE(this)->button3down = press;
++ break;
++#ifdef HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++ case SoMouseButtonEvent::BUTTON4:
++ if (press) SoGuiFullViewerP::zoom(this->getCamera(), 0.1f);
++ break;
++ case SoMouseButtonEvent::BUTTON5:
++ if (press) SoGuiFullViewerP::zoom(this->getCamera(), -0.1f);
++ break;
++#endif // HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++ default:
++ break;
++ }
++ }
++
++ // Keyboard handling
++ if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
++ const SoKeyboardEvent * const event = (const SoKeyboardEvent *) ev;
++ const SbBool press = event->getState() == SoButtonEvent::DOWN ? TRUE : FALSE;
++ switch (event->getKey()) {
++ case SoKeyboardEvent::LEFT_CONTROL:
++ case SoKeyboardEvent::RIGHT_CONTROL:
++ processed = TRUE;
++ PRIVATE(this)->ctrldown = press;
++ break;
++ case SoKeyboardEvent::LEFT_SHIFT:
++ case SoKeyboardEvent::RIGHT_SHIFT:
++ processed = TRUE;
++ PRIVATE(this)->shiftdown = press;
++ break;
++ default:
++ break;
++ }
++ }
++
++ // Mouse Movement handling
++ if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
++ const SoLocation2Event * const event = (const SoLocation2Event *) ev;
++
++ processed = TRUE;
++
++ if (PRIVATE(this)->currentmode == SoGuiExaminerViewerP::ZOOMING) {
++ PRIVATE(this)->zoomByCursor(posn, prevnormalized);
++ }
++ else if (PRIVATE(this)->currentmode == SoGuiExaminerViewerP::PANNING) {
++ SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++ PRIVATE(this)->panningplane, posn, prevnormalized);
++ }
++ else if (PRIVATE(this)->currentmode == SoGuiExaminerViewerP::DRAGGING) {
++ PRIVATE(this)->addToLog(event->getPosition(), event->getTime());
++ PRIVATE(this)->spin(posn);
++ }
++ else {
++ processed = FALSE;
++ }
++ }
++
++ // Spaceball & Joystick handling
++ if (type.isDerivedFrom(SoMotion3Event::getClassTypeId())) {
++ SoMotion3Event * const event = (SoMotion3Event *) ev;
++ SoCamera * const camera = this->getCamera();
++ if (camera) {
++ if (PRIVATE(this)->motion3OnCamera) {
++ SbVec3f dir = event->getTranslation();
++ camera->orientation.getValue().multVec(dir,dir);
++ camera->position = camera->position.getValue() + dir;
++ camera->orientation =
++ event->getRotation() * camera->orientation.getValue();
++ processed = TRUE;
++ }
++ else {
++ // FIXME: move/rotate model
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("So at Gui@ExaminerViewer::processSoEvent",
++ "SoMotion3Event for model movement is not implemented yet");
++#endif // SO at GUI@_DEBUG
++ processed = TRUE;
++ }
++ }
++ }
++
++ enum {
++ BUTTON1DOWN = 1 << 0,
++ BUTTON3DOWN = 1 << 1,
++ CTRLDOWN = 1 << 2,
++ SHIFTDOWN = 1 << 3
++ };
++ unsigned int combo =
++ (PRIVATE(this)->button1down ? BUTTON1DOWN : 0) |
++ (PRIVATE(this)->button3down ? BUTTON3DOWN : 0) |
++ (PRIVATE(this)->ctrldown ? CTRLDOWN : 0) |
++ (PRIVATE(this)->shiftdown ? SHIFTDOWN : 0);
++
++ switch (combo) {
++ case 0:
++ if (currentmode == SoGuiExaminerViewerP::SPINNING) { break; }
++ newmode = SoGuiExaminerViewerP::IDLE;
++ if ((currentmode == SoGuiExaminerViewerP::DRAGGING) &&
++ this->isAnimationEnabled() && (PRIVATE(this)->log.historysize >= 3)) {
++ SbTime stoptime = (ev->getTime() - PRIVATE(this)->log.time[0]);
++ if (stoptime.getValue() < 0.100) {
++ const SbVec2s glsize(this->getGLSize());
++ SbVec3f from = PRIVATE(this)->spinprojector->project(SbVec2f(float(PRIVATE(this)->log.position[2][0]) / float(So at Gui@Max(glsize[0]-1, 1)),
++ float(PRIVATE(this)->log.position[2][1]) / float(So at Gui@Max(glsize[1]-1, 1))));
++ SbVec3f to = PRIVATE(this)->spinprojector->project(posn);
++ SbRotation rot = PRIVATE(this)->spinprojector->getRotation(from, to);
++
++ SbTime delta = (PRIVATE(this)->log.time[0] - PRIVATE(this)->log.time[2]);
++ double deltatime = delta.getValue();
++ rot.invert();
++ rot.scaleAngle(float(0.200 / deltatime));
++
++ SbVec3f axis;
++ float radians;
++ rot.getValue(axis, radians);
++ if ((radians > 0.01f) && (deltatime < 0.300)) {
++ newmode = SoGuiExaminerViewerP::SPINNING;
++ PRIVATE(this)->spinRotation = rot;
++ }
++ }
++ }
++ break;
++ case BUTTON1DOWN:
++ newmode = SoGuiExaminerViewerP::DRAGGING;
++ break;
++ case BUTTON3DOWN:
++ case CTRLDOWN|BUTTON1DOWN:
++ case SHIFTDOWN|BUTTON1DOWN:
++ newmode = SoGuiExaminerViewerP::PANNING;
++ break;
++ case BUTTON1DOWN|BUTTON3DOWN:
++ case CTRLDOWN|BUTTON3DOWN:
++ case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
++ newmode = SoGuiExaminerViewerP::ZOOMING;
++ break;
++
++ // There are many cases we don't handle that just falls through to
++ // the default case, like SHIFTDOWN, CTRLDOWN, CTRLDOWN|SHIFTDOWN,
++ // SHIFTDOWN|BUTTON3DOWN, SHIFTDOWN|CTRLDOWN|BUTTON3DOWN, etc.
++ // This is a feature, not a bug. :-)
++ //
++ // mortene.
++
++ default:
++ // The default will make a spin stop and otherwise not do
++ // anything.
++ if ((currentmode != SoGuiExaminerViewerP::SEEK_WAIT_MODE) &&
++ (currentmode != SoGuiExaminerViewerP::SEEK_MODE)) {
++ newmode = SoGuiExaminerViewerP::IDLE;
++ }
++ break;
++ }
++
++ if (newmode != currentmode) {
++ PRIVATE(this)->setMode(newmode);
++ }
++
++ // If not handled in this class, pass on upwards in the inheritance
++ // hierarchy.
++ return processed || inherited::processSoEvent(ev);
++}
++
++// *************************************************************************
++
++// documented in superclass
++void
++So at Gui@ExaminerViewer::setSeekMode(SbBool on)
++{
++ // Overrides this method to make sure any animations are stopped
++ // before we go into seek mode.
++
++ // Note: this method is almost identical to the setSeekMode() in the
++ // So at Gui@FlyViewer and So at Gui@PlaneViewer, so migrate any changes.
++
++#if SO at GUI@_DEBUG
++ if (on == this->isSeekMode()) {
++ SoDebugError::postWarning("So at Gui@ExaminerViewer::setSeekMode",
++ "seek mode already %sset", on ? "" : "un");
++ return;
++ }
++#endif // SO at GUI@_DEBUG
++
++ if (this->isAnimating()) { this->stopAnimating(); }
++ inherited::setSeekMode(on);
++ PRIVATE(this)->setMode(on ?
++ SoGuiExaminerViewerP::SEEK_WAIT_MODE :
++ (this->isViewing() ?
++ SoGuiExaminerViewerP::IDLE : SoGuiExaminerViewerP::INTERACT));
++}
++
++// *************************************************************************
++
++/*!
++ Decide whether or not the mouse pointer cursor should be visible in
++ the rendering canvas.
++*/
++void
++So at Gui@ExaminerViewer::setCursorEnabled(SbBool enable)
++{
++ inherited::setCursorEnabled(enable);
++ PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->currentmode);
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@ExaminerViewer::getDefaultWidgetName(void) const
++{
++ return "So at Gui@ExaminerViewer";
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@ExaminerViewer::getDefaultTitle(void) const
++{
++ return "Examiner Viewer";
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@ExaminerViewer::getDefaultIconTitle(void) const
++{
++ return "Examiner Viewer";
++}
++
++// *************************************************************************
++
++// Documented in superclass. Overrides this method to be able to draw
++// the axis cross, if selected, and to keep a continuous animation
++// upon spin.
++void
++So at Gui@ExaminerViewer::actualRedraw(void)
++{
++ SbTime now = SbTime::getTimeOfDay();
++ double secs = now.getValue() - PRIVATE(this)->prevRedrawTime.getValue();
++
++ PRIVATE(this)->prevRedrawTime = now;
++
++ if (this->isAnimating()) {
++ SbRotation deltaRotation = PRIVATE(this)->spinRotation;
++ deltaRotation.scaleAngle(float(secs * 5.0));
++ PRIVATE(this)->reorientCamera(deltaRotation);
++ }
++
++ inherited::actualRedraw();
++
++ if (this->isFeedbackVisible()) { PRIVATE(this)->drawAxisCross(); }
++
++ // Immediately reschedule to get continous spin animation.
++ if (this->isAnimating()) { this->scheduleRedraw(); }
++}
++
++// *************************************************************************
++
++// doc in super
++void
++So at Gui@ExaminerViewer::afterRealizeHook(void)
++{
++ inherited::afterRealizeHook();
++ PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->currentmode);
++}
++
++// *************************************************************************
++
++// Documented in superclass. Overridden to provide the examiner viewer
++// functionality on the left thumbwheel (x axis rotation).
++void
++So at Gui@ExaminerViewer::leftWheelMotion(float value)
++{
++ if (this->isAnimating()) this->stopAnimating();
++
++ float newval = PRIVATE(this)->rotXWheelMotion(value, this->getLeftWheelValue());
++ inherited::leftWheelMotion(newval);
++}
++
++// Documented in superclass. Overridden to provide the examiner viewer
++// functionality on the bottom thumbwheel (y axis rotation).
++void
++So at Gui@ExaminerViewer::bottomWheelMotion(float value)
++{
++ if (this->isAnimating()) this->stopAnimating();
++
++ float newval = PRIVATE(this)->rotYWheelMotion(value, this->getBottomWheelValue());
++ inherited::bottomWheelMotion(newval);
++}
++
++// Documented in superclass. Overridden to provide the examiner viewer
++// functionality on the left thumbwheel (dolly/zoom).
++void
++So at Gui@ExaminerViewer::rightWheelMotion(float value)
++{
++ SoGuiFullViewerP::zoom(this->getCamera(), this->getRightWheelValue() - value);
++ inherited::rightWheelMotion(value);
++}
++
++// *************************************************************************
++
++// Documented in superclass. This method overridden from parent class
++// to make sure the mouse pointer cursor is updated.
++void
++So at Gui@ExaminerViewer::setViewing(SbBool enable)
++{
++ if (!!this->isViewing() == !!enable) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@ExaminerViewer::setViewing",
++ "current state already %s", enable ? "TRUE" : "FALSE");
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++
++ PRIVATE(this)->setMode(enable ?
++ SoGuiExaminerViewerP::IDLE :
++ SoGuiExaminerViewerP::INTERACT);
++ inherited::setViewing(enable);
++}
++
++// *************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// Remaining code is for the SoGuiExaminerViewerP "private
++// implementation" class.
++
++SoGuiExaminerViewerP::SoGuiExaminerViewerP(So at Gui@ExaminerViewer * publ)
++{
++ PUBLIC(this) = publ;
++}
++
++SoGuiExaminerViewerP::~SoGuiExaminerViewerP()
++{
++}
++
++void
++SoGuiExaminerViewerP::genericConstructor(void)
++{
++ this->currentmode = SoGuiExaminerViewerP::IDLE;
++
++ this->prevRedrawTime = SbTime::getTimeOfDay();
++ this->spinanimatingallowed = TRUE;
++ this->spinsamplecounter = 0;
++ this->spinincrement = SbRotation::identity();
++
++ // FIXME: use a smaller sphere than the default one to have a larger
++ // area close to the borders that gives us "z-axis rotation"?
++ // 19990425 mortene.
++ this->spinprojector = new SbSphereSheetProjector(SbSphere(SbVec3f(0, 0, 0), 0.8f));
++ SbViewVolume volume;
++ volume.ortho(-1, 1, -1, 1, -1, 1);
++ this->spinprojector->setViewVolume(volume);
++
++ this->axiscrossEnabled = FALSE;
++ this->axiscrossSize = 25;
++
++ this->spinRotation.setValue(SbVec3f(0, 0, -1), 0);
++
++ this->log.size = MOUSEPOSLOGSIZE;
++ this->log.position = new SbVec2s [ MOUSEPOSLOGSIZE ];
++ this->log.time = new SbTime [ MOUSEPOSLOGSIZE ];
++ this->log.historysize = 0;
++ this->button1down = FALSE;
++ this->button3down = FALSE;
++ this->ctrldown = FALSE;
++ this->shiftdown = FALSE;
++ this->pointer.now = SbVec2s(0, 0);
++ this->pointer.then = SbVec2s(0, 0);
++ this->motion3OnCamera = TRUE;
++}
++
++void
++SoGuiExaminerViewerP::genericDestructor(void)
++{
++ delete this->spinprojector;
++ delete[] this->log.position;
++ delete[] this->log.time;
++}
++
++// ************************************************************************
++
++// rotate a camera around its focalpoint, in the direction around the
++// given axis, by the given delta value (in radians)
++void
++SoGuiExaminerViewerP::rotateCamera(SoCamera * cam,
++ const SbVec3f & aroundaxis,
++ const float delta)
++{
++ const SbVec3f DEFAULTDIRECTION(0, 0, -1);
++ const SbRotation currentorientation = cam->orientation.getValue();
++
++ SbVec3f currentdir;
++ currentorientation.multVec(DEFAULTDIRECTION, currentdir);
++
++ const SbVec3f focalpoint = cam->position.getValue() +
++ cam->focalDistance.getValue() * currentdir;
++
++ // set new orientation
++ cam->orientation = SbRotation(aroundaxis, delta) * currentorientation;
++
++ SbVec3f newdir;
++ cam->orientation.getValue().multVec(DEFAULTDIRECTION, newdir);
++ cam->position = focalpoint - cam->focalDistance.getValue() * newdir;
++}
++
++// The "rotX" wheel is the wheel on the left decoration on the
++// examiner viewer. This function translates interaction with the
++// "rotX" wheel into camera movement.
++float
++SoGuiExaminerViewerP::rotXWheelMotion(float value, float oldvalue)
++{
++ SoCamera * cam = PUBLIC(this)->getCamera();
++ if (cam == NULL) return 0.0f; // can happen for empty scenegraph
++
++ SoGuiExaminerViewerP::rotateCamera(cam, SbVec3f(-1, 0, 0), value - oldvalue);
++ return value;
++}
++
++// The "rotY" wheel is the wheel on the bottom decoration on the
++// examiner viewer. This function translates interaction with the
++// "rotX" wheel into camera movement.
++float
++SoGuiExaminerViewerP::rotYWheelMotion(float value, float oldvalue)
++{
++ SoCamera * cam = PUBLIC(this)->getCamera();
++ if (cam == NULL) return 0.0f; // can happen for empty scenegraph
++
++ SoGuiExaminerViewerP::rotateCamera(cam, SbVec3f(0, -1, 0), value - oldvalue);
++ return value;
++}
++
++// ************************************************************************
++
++// The viewer is a state machine, and all changes to the current state
++// are made through this call.
++void
++SoGuiExaminerViewerP::setMode(const ViewerMode newmode)
++{
++ const ViewerMode oldmode = this->currentmode;
++ if (newmode == oldmode) { return; }
++
++ switch (newmode) {
++ case DRAGGING:
++ // Set up initial projection point for the projector object when
++ // first starting a drag operation.
++ this->spinprojector->project(this->lastmouseposition);
++ PUBLIC(this)->interactiveCountInc();
++ this->clearLog();
++ break;
++
++ case SPINNING:
++ PUBLIC(this)->interactiveCountInc();
++ PUBLIC(this)->scheduleRedraw();
++ break;
++
++ case PANNING:
++ {
++ // The plane we're projecting the mouse coordinates to get 3D
++ // coordinates should stay the same during the whole pan
++ // operation, so we should calculate this value here.
++ SoCamera * cam = PUBLIC(this)->getCamera();
++ if (cam == NULL) { // can happen for empty scenegraph
++ this->panningplane = SbPlane(SbVec3f(0, 0, 1), 0);
++ }
++ else {
++ SbViewVolume vv = cam->getViewVolume(PUBLIC(this)->getGLAspectRatio());
++ this->panningplane = vv.getPlane(cam->focalDistance.getValue());
++ }
++ }
++ PUBLIC(this)->interactiveCountInc();
++ break;
++
++ case ZOOMING:
++ PUBLIC(this)->interactiveCountInc();
++ break;
++
++ default: // include default to avoid compiler warnings.
++ break;
++ }
++
++ switch (oldmode) {
++ case SPINNING:
++ case DRAGGING:
++ case PANNING:
++ case ZOOMING:
++ PUBLIC(this)->interactiveCountDec();
++ break;
++
++ default:
++ break;
++ }
++
++#if SO at GUI@_DEBUG && 0 // debug
++ if (oldmode == ZOOMING) {
++ SbVec3f v = PUBLIC(this)->getCamera()->position.getValue();
++ SoDebugError::postInfo("So at Gui@ExaminerViewerP::setMode",
++ "new camera position after zoom: <%e, %e, %e>",
++ v[0], v[1], v[2]);
++ }
++#endif // debug
++
++ this->setCursorRepresentation(newmode);
++ this->currentmode = newmode;
++}
++
++// ************************************************************************
++
++void
++SoGuiExaminerViewerP::drawAxisCross(void)
++{
++ // FIXME: convert this to a superimposition scenegraph instead of
++ // OpenGL calls. 20020603 mortene.
++
++ // Store GL state.
++ glPushAttrib(GL_ALL_ATTRIB_BITS);
++ GLfloat depthrange[2];
++ glGetFloatv(GL_DEPTH_RANGE, depthrange);
++ GLdouble projectionmatrix[16];
++ glGetDoublev(GL_PROJECTION_MATRIX, projectionmatrix);
++
++ glDepthFunc(GL_ALWAYS);
++ glDepthMask(GL_TRUE);
++ glDepthRange(0, 0);
++ glEnable(GL_DEPTH_TEST);
++ glDisable(GL_LIGHTING);
++ glEnable(GL_COLOR_MATERIAL);
++ glDisable(GL_BLEND); // Kills transparency.
++
++ // Set the viewport in the OpenGL canvas. Dimensions are calculated
++ // as a percentage of the total canvas size.
++ SbVec2s view = PUBLIC(this)->getGLSize();
++ const int pixelarea =
++ int(float(this->axiscrossSize)/100.0f * So at Gui@Min(view[0], view[1]));
++#if 0 // middle of canvas
++ SbVec2s origin(view[0]/2 - pixelarea/2, view[1]/2 - pixelarea/2);
++#endif // middle of canvas
++#if 1 // lower right of canvas
++ SbVec2s origin(view[0] - pixelarea, 0);
++#endif // lower right of canvas
++ glViewport(origin[0], origin[1], pixelarea, pixelarea);
++
++
++
++ // Set up the projection matrix.
++ glMatrixMode(GL_PROJECTION);
++ glLoadIdentity();
++
++ const float NEARVAL = 0.1f;
++ const float FARVAL = 10.0f;
++ const float dim = NEARVAL * float(tan(M_PI / 8.0)); // FOV is 45� (45/360 = 1/8)
++ glFrustum(-dim, dim, -dim, dim, NEARVAL, FARVAL);
++
++
++ // Set up the model matrix.
++ glMatrixMode(GL_MODELVIEW);
++ glPushMatrix();
++ SbMatrix mx;
++ SoCamera * cam = PUBLIC(this)->getCamera();
++
++ // If there is no camera (like for an empty scene, for instance),
++ // just use an identity rotation.
++ if (cam) { mx = cam->orientation.getValue(); }
++ else { mx = SbMatrix::identity(); }
++
++ mx = mx.inverse();
++ mx[3][2] = -3.5; // Translate away from the projection point (along z axis).
++ glLoadMatrixf((float *)mx);
++
++
++ // Find unit vector end points.
++ SbMatrix px;
++ glGetFloatv(GL_PROJECTION_MATRIX, (float *)px);
++ SbMatrix comb = mx.multRight(px);
++
++ SbVec3f xpos;
++ comb.multVecMatrix(SbVec3f(1,0,0), xpos);
++ xpos[0] = (1 + xpos[0]) * view[0]/2;
++ xpos[1] = (1 + xpos[1]) * view[1]/2;
++ SbVec3f ypos;
++ comb.multVecMatrix(SbVec3f(0,1,0), ypos);
++ ypos[0] = (1 + ypos[0]) * view[0]/2;
++ ypos[1] = (1 + ypos[1]) * view[1]/2;
++ SbVec3f zpos;
++ comb.multVecMatrix(SbVec3f(0,0,1), zpos);
++ zpos[0] = (1 + zpos[0]) * view[0]/2;
++ zpos[1] = (1 + zpos[1]) * view[1]/2;
++
++
++ // Render the cross.
++ {
++ glLineWidth(2.0);
++
++ enum { XAXIS, YAXIS, ZAXIS };
++ int idx[3] = { XAXIS, YAXIS, ZAXIS };
++ float val[3] = { xpos[2], ypos[2], zpos[2] };
++
++ // Bubble sort.. :-}
++ if (val[0] < val[1]) { So at Gui@Swap(val[0], val[1]); So at Gui@Swap(idx[0], idx[1]); }
++ if (val[1] < val[2]) { So at Gui@Swap(val[1], val[2]); So at Gui@Swap(idx[1], idx[2]); }
++ if (val[0] < val[1]) { So at Gui@Swap(val[0], val[1]); So at Gui@Swap(idx[0], idx[1]); }
++ assert((val[0] >= val[1]) && (val[1] >= val[2])); // Just checking..
++
++ for (int i=0; i < 3; i++) {
++ glPushMatrix();
++ if (idx[i] == XAXIS) { // X axis.
++ glColor3f(0.500f, 0.125f, 0.125f);
++ } else if (idx[i] == YAXIS) { // Y axis.
++ glRotatef(90, 0, 0, 1);
++ glColor3f(0.125f, 0.500f, 0.125f);
++ } else { // Z axis.
++ glRotatef(-90, 0, 1, 0);
++ glColor3f(0.125f, 0.125f, 0.500f);
++ }
++ this->drawArrow();
++ glPopMatrix();
++ }
++ }
++
++ // Render axis notation letters ("X", "Y", "Z").
++ glMatrixMode(GL_PROJECTION);
++ glLoadIdentity();
++ glOrtho(0, view[0], 0, view[1], -1, 1);
++
++ glMatrixMode(GL_MODELVIEW);
++ glLoadIdentity();
++
++ GLint unpack;
++ glGetIntegerv(GL_UNPACK_ALIGNMENT, &unpack);
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++
++ glColor3fv(SbVec3f(0.8f, 0.8f, 0.0f).getValue());
++
++ glRasterPos2d(xpos[0], xpos[1]);
++ glBitmap(8, 7, 0, 0, 0, 0, xbmp);
++ glRasterPos2d(ypos[0], ypos[1]);
++ glBitmap(8, 7, 0, 0, 0, 0, ybmp);
++ glRasterPos2d(zpos[0], zpos[1]);
++ glBitmap(8, 7, 0, 0, 0, 0, zbmp);
++
++ glPixelStorei(GL_UNPACK_ALIGNMENT, unpack);
++ glPopMatrix();
++
++ // Reset original state.
++
++ // FIXME: are these 3 lines really necessary, as we push
++ // GL_ALL_ATTRIB_BITS at the start? 20000604 mortene.
++ glDepthRange(depthrange[0], depthrange[1]);
++ glMatrixMode(GL_PROJECTION);
++ glLoadMatrixd(projectionmatrix);
++
++ glPopAttrib();
++}
++
++// Draw an arrow for the axis representation directly through OpenGL.
++void
++SoGuiExaminerViewerP::drawArrow(void)
++{
++ glBegin(GL_LINES);
++ glVertex3f(0.0f, 0.0f, 0.0f);
++ glVertex3f(1.0f, 0.0f, 0.0f);
++ glEnd();
++ glDisable(GL_CULL_FACE);
++ glBegin(GL_TRIANGLES);
++ glVertex3f(1.0f, 0.0f, 0.0f);
++ glVertex3f(1.0f - 1.0f / 3.0f, +0.5f / 4.0f, 0.0f);
++ glVertex3f(1.0f - 1.0f / 3.0f, -0.5f / 4.0f, 0.0f);
++ glVertex3f(1.0f, 0.0f, 0.0f);
++ glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, +0.5f / 4.0f);
++ glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, -0.5f / 4.0f);
++ glEnd();
++ glBegin(GL_QUADS);
++ glVertex3f(1.0f - 1.0f / 3.0f, +0.5f / 4.0f, 0.0f);
++ glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, +0.5f / 4.0f);
++ glVertex3f(1.0f - 1.0f / 3.0f, -0.5f / 4.0f, 0.0f);
++ glVertex3f(1.0f - 1.0f / 3.0f, 0.0f, -0.5f / 4.0f);
++ glEnd();
++}
++
++// ************************************************************************
++
++// Rotate the camera by the given amount, then reposition it so we're
++// still pointing at the same focal point.
++void
++SoGuiExaminerViewerP::reorientCamera(const SbRotation & rot)
++{
++ SoCamera * cam = PUBLIC(this)->getCamera();
++ if (cam == NULL) return;
++
++ // Find global coordinates of focal point.
++ SbVec3f direction;
++ cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
++ SbVec3f focalpoint = cam->position.getValue() +
++ cam->focalDistance.getValue() * direction;
++
++ // Set new orientation value by accumulating the new rotation.
++ cam->orientation = rot * cam->orientation.getValue();
++
++ // Reposition camera so we are still pointing at the same old focal point.
++ cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
++ cam->position = focalpoint - cam->focalDistance.getValue() * direction;
++}
++
++// ************************************************************************
++
++// Uses the sphere sheet projector to map the mouseposition unto
++// a 3D point and find a rotation from this and the last calculated point.
++void
++SoGuiExaminerViewerP::spin(const SbVec2f & pointerpos)
++{
++ if (this->log.historysize < 2) return;
++ assert(this->spinprojector != NULL);
++
++ SbVec2s glsize(PUBLIC(this)->getGLSize());
++ SbVec2f lastpos;
++ lastpos[0] = float(this->log.position[1][0]) / float(So at Gui@Max((int)(glsize[0]-1), 1));
++ lastpos[1] = float(this->log.position[1][1]) / float(So at Gui@Max((int)(glsize[1]-1), 1));
++
++ this->spinprojector->project(lastpos);
++ SbRotation r;
++ this->spinprojector->projectAndGetRotation(pointerpos, r);
++ r.invert();
++ this->reorientCamera(r);
++
++ // Calculate an average angle magnitude value to make the transition
++ // to a possible spin animation mode appear smooth.
++
++ SbVec3f dummy_axis, newaxis;
++ float acc_angle, newangle;
++ this->spinincrement.getValue(dummy_axis, acc_angle);
++ acc_angle *= this->spinsamplecounter; // weight
++ r.getValue(newaxis, newangle);
++ acc_angle += newangle;
++
++ this->spinsamplecounter++;
++ acc_angle /= this->spinsamplecounter;
++ // FIXME: accumulate and average axis vectors aswell? 19990501 mortene.
++ this->spinincrement.setValue(newaxis, acc_angle);
++
++ // Don't carry too much baggage, as that'll give unwanted results
++ // when the user quickly trigger (as in "click-drag-release") a spin
++ // animation.
++ if (this->spinsamplecounter > 3) this->spinsamplecounter = 3;
++}
++
++// ************************************************************************
++
++// Calculate a zoom/dolly factor from the difference of the current
++// cursor position and the last.
++void
++SoGuiExaminerViewerP::zoomByCursor(const SbVec2f & thispos,
++ const SbVec2f & prevpos)
++{
++ // There is no "geometrically correct" value, 20 just seems to give
++ // about the right "feel".
++ SoGuiFullViewerP::zoom(PUBLIC(this)->getCamera(),
++ (thispos[1] - prevpos[1]) * 20.0f);
++}
++
++// *************************************************************************
++// Methods used for spin animation tracking.
++
++// This method "clears" the mouse location log, used for spin
++// animation calculations.
++void
++SoGuiExaminerViewerP::clearLog(void)
++{
++ this->log.historysize = 0;
++}
++
++// This method adds another point to the mouse location log, used for spin
++// animation calculations.
++void
++SoGuiExaminerViewerP::addToLog(const SbVec2s pos, const SbTime time)
++{
++ // In case someone changes the const size setting at the top of this
++ // file too small.
++ assert (this->log.size > 2 && "mouse log too small!");
++
++ if (this->log.historysize > 0 && pos == this->log.position[0]) {
++#if SO at GUI@_DEBUG && 0 // debug
++ // This can at least happen under SoQt.
++ SoDebugError::postInfo("SoGuiExaminerViewerP::addToLog", "got position already!");
++#endif // debug
++ return;
++ }
++
++ int lastidx = this->log.historysize;
++ // If we've filled up the log, we should throw away the last item:
++ if (lastidx == this->log.size) { lastidx--; }
++
++ assert(lastidx < this->log.size);
++ for (int i = lastidx; i > 0; i--) {
++ this->log.position[i] = this->log.position[i-1];
++ this->log.time[i] = this->log.time[i-1];
++ }
++
++ this->log.position[0] = pos;
++ this->log.time[0] = time;
++ if (this->log.historysize < this->log.size)
++ this->log.historysize += 1;
++}
++
++// *************************************************************************
++
++// This method sets whether Motion3 events should affect the camera or
++// the model.
++void
++SoGuiExaminerViewerP::setMotion3OnCamera(SbBool enable)
++{
++ this->motion3OnCamera = enable;
++}
++
++// This method returns whether Motion3 events affects the camera or
++// the model.
++SbBool
++SoGuiExaminerViewerP::getMotion3OnCamera(void) const
++{
++ return this->motion3OnCamera;
++}
++
++// ************************************************************************
++
++// Set cursor graphics according to mode.
++void
++SoGuiExaminerViewerP::setCursorRepresentation(int modearg)
++{
++ if (!PUBLIC(this)->isCursorEnabled()) {
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getBlankCursor());
++ return;
++ }
++
++ switch (modearg) {
++ case SoGuiExaminerViewerP::INTERACT:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::DEFAULT));
++ break;
++
++ case SoGuiExaminerViewerP::IDLE:
++ case SoGuiExaminerViewerP::DRAGGING:
++ case SoGuiExaminerViewerP::SPINNING:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getRotateCursor());
++ break;
++
++ case SoGuiExaminerViewerP::ZOOMING:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getZoomCursor());
++ break;
++
++ case SoGuiExaminerViewerP::SEEK_MODE:
++ case SoGuiExaminerViewerP::SEEK_WAIT_MODE:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::CROSSHAIR));
++ break;
++
++ case SoGuiExaminerViewerP::PANNING:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getPanCursor());
++ break;
++
++ default: assert(0); break;
++ }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiExaminerViewer.h.in
+@@ -0,0 +1,108 @@
++#ifndef SO at GUI@_EXAMINERVIEWER_H
++#define SO at GUI@_EXAMINERVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++
++class SoSeparator;
++class SoSwitch;
++class SoTranslation;
++class SoScale;
++
++class So at Gui@ThumbWheel;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@ExaminerViewer : public So at Gui@FullViewer {
++ SO at GUI@_OBJECT_HEADER(So at Gui@ExaminerViewer, So at Gui@FullViewer);
++
++public:
++ So at Gui@ExaminerViewer(@WIDGET@ parent = NULL,
++ const char * name = NULL,
++ SbBool embed = TRUE,
++ So at Gui@FullViewer::BuildFlag flag = BUILD_ALL,
++ So at Gui@Viewer::Type type = BROWSER);
++ ~So at Gui@ExaminerViewer();
++
++ void setAnimationEnabled(const SbBool enable);
++ SbBool isAnimationEnabled(void) const;
++
++ void stopAnimating(void);
++ SbBool isAnimating(void) const;
++
++ void setFeedbackVisibility(const SbBool enable);
++ SbBool isFeedbackVisible(void) const;
++
++ void setFeedbackSize(const int size);
++ int getFeedbackSize(void) const;
++
++ virtual void setViewing(SbBool enable);
++ virtual void setCamera(SoCamera * camera);
++ virtual void setCursorEnabled(SbBool enable);
++
++protected:
++ So at Gui@ExaminerViewer(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build);
++
++ virtual void leftWheelMotion(float val);
++ virtual void bottomWheelMotion(float val);
++ virtual void rightWheelMotion(float val);
++
++ virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++ virtual SbBool processSoEvent(const SoEvent * const event);
++ virtual void setSeekMode(SbBool enable);
++ virtual void actualRedraw(void);
++
++ virtual void afterRealizeHook(void);
++
++private:
++ class So at Gui@ExaminerViewerP * pimpl;
++
++ friend class SoGuiExaminerViewerP;
++ friend class So at Gui@ExaminerViewerP;
++};
++
++#endif // ! SO at GUI@_EXAMINERVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiExaminerViewerP.h.in
+@@ -0,0 +1,140 @@
++#ifndef SOGUIEXAMINERVIEWERP_H
++#define SOGUIEXAMINERVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/SbTime.h>
++
++class So at Gui@ExaminerViewer;
++class SoCamera;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiExaminerViewer class.
++
++class SoGuiExaminerViewerP
++{
++public:
++ ~SoGuiExaminerViewerP();
++
++ void genericConstructor(void);
++ void genericDestructor(void);
++
++ void setMotion3OnCamera(SbBool enable);
++ SbBool getMotion3OnCamera(void) const;
++
++ static void rotateCamera(SoCamera * cam, const SbVec3f & aroundaxis, const float delta);
++ float rotXWheelMotion(float value, float old);
++ float rotYWheelMotion(float value, float old);
++
++ void reorientCamera(const SbRotation & rotation);
++ void spin(const SbVec2f & mousepos);
++ void pan(const SbVec2f & mousepos, const SbVec2f & prevpos);
++ void zoom(const float diffvalue);
++ void zoomByCursor(const SbVec2f & mousepos, const SbVec2f & prevpos);
++
++ SbVec2f lastmouseposition;
++ SbPlane panningplane;
++
++ SbBool spinanimatingallowed;
++ SbVec2f lastspinposition;
++ int spinsamplecounter;
++ SbRotation spinincrement;
++ class SbSphereSheetProjector * spinprojector;
++
++ SbRotation spinRotation;
++
++ SbBool axiscrossEnabled;
++ int axiscrossSize;
++
++ void drawAxisCross(void);
++ static void drawArrow(void);
++
++ struct { // tracking mouse movement in a log
++ short size;
++ short historysize;
++ SbVec2s * position;
++ SbTime * time;
++ } log;
++
++ // The Microsoft Visual C++ v6.0 compiler needs a name on this class
++ // to be able to generate a constructor (which it wants to have for
++ // running the the SbVec2s constructors). So don't try to be clever
++ // and make it anonymous.
++ struct Pointer {
++ SbVec2s now, then;
++ } pointer;
++
++ SbBool button1down;
++ SbBool button3down;
++ SbBool ctrldown, shiftdown;
++
++ void clearLog(void);
++ void addToLog(const SbVec2s pos, const SbTime time);
++
++ SbTime prevRedrawTime;
++
++ SbBool motion3OnCamera;
++
++ enum ViewerMode {
++ IDLE,
++ INTERACT,
++ ZOOMING,
++ PANNING,
++ DRAGGING,
++ SPINNING,
++ SEEK_WAIT_MODE,
++ SEEK_MODE
++ } mode;
++
++ ViewerMode currentmode;
++ void setMode(const ViewerMode mode);
++
++ void setCursorRepresentation(int mode);
++
++protected:
++ SoGuiExaminerViewerP(So at Gui@ExaminerViewer * publ);
++ So at Gui@ExaminerViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIEXAMINERVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFlyViewer.cpp.in
+@@ -0,0 +1,1289 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class So at Gui@FlyViewer Inventor/@Gui@/viewers/So at Gui@FlyViewer.h
++ \brief The So at Gui@FlyViewer class implements controls for moving
++ the camera in a "flying" motion.
++ \ingroup viewers
++
++ Controls:
++ <ul>
++
++ <li>Left mouse button increases the speed.</li>
++
++ <li>Middle mouse button decreases the speed.</li>
++
++ <li>Left and middle mouse button together sets the speed to zero.</li>
++
++ <li>"s" puts the viewer in seek mode. Click some geometry with the
++ left mouse button to start the seek zoom animation. (Hitting "s"
++ again before clicking will cancel the seek operation.)</li>
++
++ <li>"u" puts the viewer in up-vector pick mode. Click some geometry
++ with the left mouse button to set the camera's up-vector to the
++ normal vector of the face you pick.
++ (Hitting "u" again before clicking will cancel the pick operation.)</li>
++
++ <li>The control key stops the flying and lets you tilt the camera by moving
++ the pointer.</li>
++
++ </ul>
++*/
++
++/*
++ FIXME:
++ - animate camera when setting up-vector so the scene doesn't just
++ suddenly change.
++*/
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/viewers/So at Gui@FlyViewer.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <Inventor/nodes/SoCallback.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoSwitch.h>
++#include <Inventor/nodes/SoScale.h>
++#include <Inventor/nodes/SoTranslation.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/actions/SoHandleEventAction.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <string.h> // strlen() etc
++#include <stdlib.h> // abs()
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// FIXME: We should probably move this class out of this
++// impl-file. There is code here that could be factored out and reused
++// in other modules, for example camera handling. Now there is a
++// duplication with some of the code in So at Gui@ConstrainedViewerP, for
++// example. 20021017 rolvs
++class So at Gui@FlyViewerP {
++public:
++ So at Gui@FlyViewerP(So at Gui@FlyViewer * owner);
++ ~So at Gui@FlyViewerP();
++
++ enum ViewerMode {
++ FLYING, TILTING, WAITING_FOR_SEEK, WAITING_FOR_UP_PICK
++ };
++
++ void constructor(SbBool build);
++
++ void dolly(const float delta) const;
++ void updateCursorRepresentation(void); // in SoNativeFlyViewer.cpp
++ void setMode(ViewerMode newmode);
++ int getMode(void) { return this->viewermode; }
++
++#define SO at GUI@_MIN_STEP 0.2f
++#define SO at GUI@_INC_FACTOR 1.2f
++#define SO at GUI@_MAX_SPEED 20.0f
++
++ SbTime * lastrender;
++
++ float currentspeed;
++
++ // Maximum speed, target for currentspeed during
++ // acceleration/decceleration.
++ float maxspeed;
++
++ // Scales speed. Calculated in updateSpeedScalingFactor.
++ float speed_scaling_factor;
++
++ // Used to calculate a new max_speed, on the basis on 'where' we are
++ // in the speed landscape, see {increment|decrement}MaxSpeed().
++ int max_speed_factor;
++
++ // Speed
++ void incrementMaxSpeed();
++ void decrementMaxSpeed();
++ void updateMaxSpeed();
++ void updateSpeedScalingFactor();
++ void stopMoving();
++
++ void updateSpeedIndicator(void);
++ void updateCameraPosition( SoCamera * camera, float speed, float dt );
++ void updateCameraOrientation( SoCamera * camera,
++ float d_tilt,
++ float d_pan,
++ float dt );
++ double calculateChangeInTime();
++ void updateCurrentSpeed(double dt);
++
++
++ // Current keyboard state.
++ SbBool button1down;
++ SbBool button3down;
++ int lctrldown;
++ int rctrldown;
++ SbBool lshiftdown;
++ SbBool rshiftdown;
++
++ // View, speed display, renderingstate.
++ SoSearchAction * searcher;
++
++ SoNode * superimposition;
++ SoCoordinate3 * sgeometry;
++
++ SoScale * sscale;
++ SoScale * crossscale;
++
++ SoTranslation * stranslation;
++ SoTranslation * crossposition;
++
++ SoSwitch * smaxspeedswitch;
++ SoSwitch * scurrentspeedswitch;
++ SoSwitch * crossswitch;
++
++ SoNode * getSuperimpositionNode(const char * name);
++
++ void superimpositionevent(SoAction * action);
++ static void superimposition_cb(void * closure, SoAction * action);
++
++
++ //
++ float tilt_increment; // Angle-adjustment between View-up and direction
++ float pan_increment; // Rotation-adjustment around View-up
++
++ SbVec2s mouseloc;
++ SbVec2s lastpos;
++ SbVec2s tiltpos;
++
++ // FIXME: Refactor event handlers and PUBLIC(this)->processSoEvent
++ // in a way similar to that in SoGuiExaminerViewer, where only
++ // internal state is red/set. 20021017 rolvs
++ SbBool processKeyboardEvent(const SoKeyboardEvent * const kevt);
++ SbBool processMouseButtonEvent(const SoMouseButtonEvent * const mevt);
++ SbBool processLocation2Event(const SoLocation2Event * const levt);
++private:
++ So at Gui@FlyViewer * publ;
++ ViewerMode viewermode;
++};
++
++So at Gui@FlyViewerP::So at Gui@FlyViewerP(So at Gui@FlyViewer * owner)
++{
++ this->searcher = NULL;
++ this->publ = owner;
++ this->viewermode = FLYING;
++ this->currentspeed = 0.0f;
++ this->maxspeed = 0.0f;
++ this->speed_scaling_factor = 0.4f;
++ this->max_speed_factor = 0;
++ this->stranslation = NULL;
++ this->sscale = NULL;
++ this->button1down = FALSE;
++ this->button3down = FALSE;
++ this->lctrldown = 0;
++ this->rctrldown = 0;
++ this->lshiftdown = FALSE;
++ this->rshiftdown = FALSE;
++ this->lastrender = new SbTime;
++ this->tilt_increment = 0.0f;
++ this->pan_increment = 0.0f;
++}
++
++So at Gui@FlyViewerP::~So at Gui@FlyViewerP(void)
++{
++ if ( this->searcher != NULL )
++ delete this->searcher;
++ delete this->lastrender;
++
++ // superimposition unrefed in other destructor
++}
++
++#define PRIVATE(o) (o->pimpl)
++#define PUBLIC(o) (o->publ)
++
++
++// Common constructor code.
++void
++So at Gui@FlyViewerP::constructor(SbBool build)
++{
++ PUBLIC(this)->setClassName(PUBLIC(this)->getDefaultWidgetName());
++
++ static const char * superimposed[] = {
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " MaterialBinding {",
++ " value OVERALL",
++ " }",
++ " OrthographicCamera {",
++ " height 1",
++ " nearDistance 0",
++ " farDistance 1",
++ " }",
++ " DEF so at gui@->callback Callback { }",
++ " Separator {",
++ " DEF so at gui@->translation Translation {",
++ " translation 0 0 0",
++ " }",
++ " DEF so at gui@->scale Scale {",
++ " scaleFactor 1 1 1",
++ " }",
++ " DEF so at gui@->geometry Coordinate3 {",
++ " point [",
++ " -0.8 -0.04 0,",
++ " -0.8 0 0,",
++ " -0.8 0.04 0,",
++ " 0 -0.04 0,",
++ " 0 0 0,",
++ " 0 0.04 0,",
++ " 0.8 -0.04 0,",
++ " 0.8 0 0,",
++ " 0.8 0.04 0,",
++ " 0 0.02 0,", // idx 9
++ " 0.8 0.02 0,",
++ " 0.8 -0.02 0,",
++ " 0 -0.02 0,",
++ " 0 0.01 0,", // idx 13
++ " 0.4 0.01 0,",
++ " 0.4 -0.01 0,",
++ " 0 -0.01 0",
++ " ]",
++ " }",
++ " DEF so at gui@->maxspeedswitch Switch {",
++ " whichChild -3",
++ // max speed indicator
++ " Material {",
++ " emissiveColor 1 0 0",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [",
++ " 12, 11, 10, 9, -1",
++ " ]",
++ " }",
++ " }",
++ // the coordinate system
++ " BaseColor {",
++ " rgb 1 1 1",
++ " }",
++ " IndexedLineSet {",
++ " coordIndex [",
++ " 0, 2, -1,",
++ " 3, 5, -1,",
++ " 6, 8, -1,",
++ " 1, 7, -1",
++ " ]",
++ " }",
++ // current speed indicator
++ " DEF so at gui@->currentspeedswitch Switch {",
++ " whichChild -3",
++ " Material {",
++ " emissiveColor 0 0 1",
++ " }",
++ " IndexedFaceSet {",
++ " coordIndex [",
++ " 16, 15, 14, 13, -1",
++ " ]",
++ " }",
++ " }",
++ " }",
++ // cross
++ " DEF so at gui@->crossswitch Switch {",
++ " whichChild -1",
++ " DEF so at gui@->crossposition Translation {",
++ " translation 0 0 0",
++ " }",
++ " DEF so at gui@->crossscale Scale {",
++ " scaleFactor 1 1 1",
++ " }",
++ " BaseColor {",
++ " rgb 1 0 0",
++ " }",
++ " Coordinate3 {",
++ " point [",
++ " 0 -1 0,",
++ " 0 1 0,",
++ " -1 0 0,",
++ " 1 0 0",
++ " ]",
++ " }",
++ " IndexedLineSet {",
++ " coordIndex [",
++ " 0, 1, -1,",
++ " 2, 3, -1",
++ " ]",
++ " }",
++ " }",
++ "}",
++ NULL
++ };
++
++ int i, bufsize;
++ for (i = bufsize = 0; superimposed[i]; i++)
++ bufsize += strlen(superimposed[i]) + 1;
++ char * buf = new char [bufsize + 1];
++ for (i = bufsize = 0; superimposed[i]; i++) {
++ strcpy(buf + bufsize, superimposed[i]);
++ bufsize += strlen(superimposed[i]);
++ buf[bufsize] = '\n';
++ bufsize++;
++ }
++ SoInput * input = new SoInput;
++ input->setBuffer(buf, bufsize);
++ SbBool ok = SoDB::read(input, this->superimposition);
++ assert(ok);
++ delete input;
++ delete [] buf;
++ this->superimposition->ref();
++
++
++ this->sscale = (SoScale *)
++ this->getSuperimpositionNode("so at gui@->scale");
++ this->stranslation = (SoTranslation *)
++ this->getSuperimpositionNode("so at gui@->translation");
++ this->sgeometry = (SoCoordinate3 *)
++ this->getSuperimpositionNode("so at gui@->geometry");
++ this->smaxspeedswitch = (SoSwitch *)
++ this->getSuperimpositionNode("so at gui@->maxspeedswitch");
++ this->scurrentspeedswitch = (SoSwitch *)
++ this->getSuperimpositionNode("so at gui@->currentspeedswitch");
++ this->crossswitch = (SoSwitch *)
++ this->getSuperimpositionNode("so at gui@->crossswitch");
++ this->crossposition = (SoTranslation *)
++ this->getSuperimpositionNode("so at gui@->crossposition");
++ this->crossscale = (SoScale *)
++ this->getSuperimpositionNode("so at gui@->crossscale");
++
++ SoCallback * cb = (SoCallback *)
++ this->getSuperimpositionNode("so at gui@->callback");
++ cb->setCallback(So at Gui@FlyViewerP::superimposition_cb, this);
++
++ this->updateSpeedIndicator();
++
++ PUBLIC(this)->addSuperimposition(this->superimposition);
++ PUBLIC(this)->setSuperimpositionEnabled(this->superimposition,TRUE);
++
++ if (build) {
++ @WIDGET@ viewer = PUBLIC(this)->buildWidget(PUBLIC(this)->getParentWidget());
++ PUBLIC(this)->setBaseWidget(viewer);
++ }
++}
++
++// This method dollies the camera back and forth in the scene.
++void
++So at Gui@FlyViewerP::dolly(const float delta) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++ SbPlane walkplane(PUBLIC(this)->getUpDirection(),
++ camera->position.getValue());
++
++ SbVec3f campos = camera->position.getValue();
++ SbVec3f camvec;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), camvec);
++ SbLine cross(campos + camvec,
++ campos + camvec + PUBLIC(this)->getUpDirection());
++ SbVec3f intersect;
++ walkplane.intersect(cross, intersect);
++ SbVec3f dir = intersect - campos;
++ dir.normalize();
++
++ camera->position = campos - dir * delta;
++}
++
++// The viewer is a state machine, and all changes to the current state
++// are made through this call.
++void
++So at Gui@FlyViewerP::setMode(ViewerMode newmode)
++{
++ this->viewermode = newmode;
++ this->updateCursorRepresentation();
++}
++
++// This method locates a named node in the superimposed scene.
++SoNode *
++So at Gui@FlyViewerP::getSuperimpositionNode(const char * name)
++{
++ if (! this->searcher)
++ this->searcher = new SoSearchAction;
++ searcher->reset();
++ searcher->setName(SbName(name));
++ searcher->setInterest(SoSearchAction::FIRST);
++ searcher->setSearchingAll(TRUE);
++ searcher->apply(this->superimposition);
++ assert(searcher->getPath());
++ return searcher->getPath()->getTail();
++}
++
++SbBool
++So at Gui@FlyViewerP::processKeyboardEvent(const SoKeyboardEvent * const ke)
++{
++ assert( ke != NULL );
++ switch (ke->getState()) {
++ case SoButtonEvent::UP:
++ switch (ke->getKey()) {
++ case SoKeyboardEvent::U:
++ do {
++ // either to switch to up-vector pick mode, or back to fly
++ // mode if pick-mode already activated (ie cancel the
++ // up-vector pick operation)
++ SbBool uppickmode =
++ this->getMode() == So at Gui@FlyViewerP::WAITING_FOR_UP_PICK;
++ this->setMode(uppickmode ? So at Gui@FlyViewerP::FLYING :
++ So at Gui@FlyViewerP::WAITING_FOR_UP_PICK);
++
++ this->stopMoving();
++
++ this->updateSpeedIndicator();
++ PUBLIC(this)->scheduleRedraw();
++ return TRUE;
++ } while (FALSE);
++ break;
++
++ case SoKeyboardEvent::S:
++ this->stopMoving();
++ this->updateSpeedIndicator();
++ PUBLIC(this)->scheduleRedraw();
++ return FALSE;
++
++ case SoKeyboardEvent::LEFT_SHIFT:
++ this->lshiftdown = FALSE;
++ if (this->lshiftdown < 0) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++ "left shift key count < 0");
++#endif
++ this->lshiftdown = 0;
++ }
++ break;
++ case SoKeyboardEvent::RIGHT_SHIFT:
++ this->rshiftdown = FALSE;
++ if (this->rshiftdown < 0) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++ "right shift key count < 0");
++#endif
++ this->rshiftdown = 0;
++ }
++ break;
++ case SoKeyboardEvent::LEFT_CONTROL:
++ this->lctrldown -= 1;
++ if (this->lctrldown < 0) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewerP::processKyeboardEvent",
++ "left control key count < 0");
++#endif
++ this->lctrldown = 0;
++ }
++ break;
++ case SoKeyboardEvent::RIGHT_CONTROL:
++ this->rctrldown -= 1;
++ if (this->rctrldown < 0) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewerP::processKyeboardEvent",
++ "right control key count < 0");
++#endif
++ this->rctrldown = 0;
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ case SoButtonEvent::DOWN:
++ switch (ke->getKey()) {
++ case SoKeyboardEvent::LEFT_SHIFT:
++ this->lshiftdown += 1;
++ if (this->lshiftdown > 2) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++ "left shift key count > 2");
++#endif
++ this->lshiftdown = 2;
++ }
++ break;
++ case SoKeyboardEvent::RIGHT_SHIFT:
++ this->rshiftdown += 1;
++ if (this->rshiftdown > 2) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++ "right shift key count > 2");
++#endif
++ this->rshiftdown = 2;
++ }
++ break;
++ case SoKeyboardEvent::LEFT_CONTROL:
++ this->lctrldown += 1;
++ if (this->lctrldown > 2) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewerP::processKeyboardEvent",
++ "left control key count > 2");
++#endif
++ this->lctrldown = 2;
++ }
++ break;
++ case SoKeyboardEvent::RIGHT_CONTROL:
++ this->rctrldown += 1;
++ if (this->rctrldown > 2) {
++#if SO at GUI@_DEBUG
++ SoDebugError::post("So at Gui@FlyViewer::processSoEvent",
++ "right control key count > 2");
++#endif
++ this->rctrldown = 2;
++ }
++ break;
++ default:
++ break;
++ }
++ break;
++ default:
++ break;
++ }
++
++ if ((this->getMode() == So at Gui@FlyViewerP::FLYING) &&
++ (this->lctrldown || this->rctrldown)) {
++ this->setMode(So at Gui@FlyViewerP::TILTING);
++
++ this->tiltpos = this->mouseloc;
++ this->lastpos = this->mouseloc;
++
++ this->stopMoving();
++ this->updateSpeedIndicator();
++ this->crossswitch->whichChild.setValue(SO_SWITCH_ALL);
++ PUBLIC(this)->scheduleRedraw();
++ // NOTE; this could be optimized to only draw the superimposition in
++ // question if speed is zero.
++ } else if ((this->getMode() == So at Gui@FlyViewerP::TILTING) &&
++ !this->lctrldown && !this->rctrldown) {
++ this->setMode(So at Gui@FlyViewerP::FLYING);
++ assert(this->crossswitch != NULL);
++ this->crossswitch->whichChild.setValue(SO_SWITCH_NONE);
++ PUBLIC(this)->scheduleRedraw();
++ }
++ return FALSE;
++}
++
++
++SbBool
++So at Gui@FlyViewerP::processMouseButtonEvent( const SoMouseButtonEvent * const me )
++{
++ assert( me != NULL );
++
++ // FIXME: only for fly mode
++ switch (this->getMode()) {
++ case So at Gui@FlyViewerP::WAITING_FOR_UP_PICK:
++ if ((me->getButton() == SoMouseButtonEvent::BUTTON1) &&
++ (me->getState() == SoButtonEvent::DOWN)) {
++ PUBLIC(this)->findUpDirection(me->getPosition());
++ this->setMode(So at Gui@FlyViewerP::FLYING);
++ return TRUE;
++ }
++ break;
++ case So at Gui@FlyViewerP::FLYING:
++ switch (me->getButton()) {
++ case SoMouseButtonEvent::BUTTON1:
++
++ switch (me->getState()) {
++
++ case SoButtonEvent::DOWN:
++ // Incrementing speed.
++ this->button1down = TRUE;
++ if (this->button3down) {
++ this->stopMoving();
++ }
++ else {
++ this->incrementMaxSpeed();
++ }
++ this->updateSpeedIndicator();
++ PUBLIC(this)->scheduleRedraw();
++ return TRUE;
++ case SoButtonEvent::UP:
++ this->button1down = FALSE;
++ return TRUE;
++ default:
++ break;
++ }
++ break;
++
++ case SoMouseButtonEvent::BUTTON3:
++
++ switch (me->getState()) {
++ case SoButtonEvent::DOWN:
++ this->button3down = TRUE;
++
++ if (this->button1down) {
++ this->stopMoving();
++ }
++ else
++ this->decrementMaxSpeed();
++
++ this->updateSpeedIndicator();
++ PUBLIC(this)->scheduleRedraw();
++ return TRUE;
++ case SoButtonEvent::UP:
++ this->button3down = FALSE;
++ return TRUE;
++ default:
++ break;
++ }
++ break;
++ default:
++ break;
++ }
++ default:
++ break;
++ }
++ return FALSE;
++}
++
++SbBool
++So at Gui@FlyViewerP::processLocation2Event(const SoLocation2Event * const lev)
++{
++ this->mouseloc = lev->getPosition();
++
++ if (this->getMode() == So at Gui@FlyViewerP::TILTING) {
++
++ float pan = (this->lastpos[0] - this->mouseloc[0])/100.0f;
++ float tilt = (this->lastpos[1] - this->mouseloc[1])/100.0f;
++
++ SoCamera * camera = PUBLIC(this)->getCamera();
++ if (camera == NULL)
++ return TRUE; // probably sceneless
++
++ this->updateCameraOrientation( camera, tilt, pan, 1.0f );
++ this->lastpos = this->mouseloc;
++ }
++
++ // FIXME: The size of the glcanvas only changes when the viewer is
++ // resized. The GLSize should be set from the FlyViewer, to remove
++ // the dependency on the PUBLIC(this) class. 20021021 rolvs
++ SbVec2s glsize( PUBLIC(this)->getGLSize() );
++
++ // NOTE: The values are normalized, so that the FlyViewer behaves
++ // the same way no matter the screen-size. The old way to do it made
++ // the possible range of pan and tilt increment depend on the canvas
++ // size. 20021022 rolvs.
++ this->pan_increment = 0.5f - float(this->mouseloc[0])/glsize[0];
++ this->tilt_increment = 0.5f - float(this->mouseloc[1])/glsize[1];
++
++ return TRUE;
++}
++
++void
++So at Gui@FlyViewerP::superimpositionevent(SoAction * action)
++{
++ if (!action->isOfType(SoGLRenderAction::getClassTypeId())) return;
++ SbViewportRegion vpRegion =
++ ((SoGLRenderAction *) action)->getViewportRegion();
++ SbVec2s viewport = vpRegion.getViewportSizePixels();
++ float aspect = float(viewport[0]) / float(viewport[1]);
++ float factorx = 1.0f/float(viewport[1]) * 220.0f;
++ float factory = factorx;
++ if (aspect > 1.0f) {
++ this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f, 0.0f));
++ } else {
++ this->stranslation->translation.setValue(SbVec3f(0.0f, -0.4f / aspect, 0.0f));
++ factorx /= aspect;
++ factory /= aspect;
++ }
++ if (viewport[0] > 500)
++ factorx *= 500.0f / 400.0f;
++ else
++ factorx *= float(viewport[0]) / 400.0f;
++ this->sscale->scaleFactor.setValue(SbVec3f(factorx, factory, 1.0f));
++
++ if (this->getMode() == TILTING) {
++ assert(this->crossposition != NULL);
++ assert(this->crossscale != NULL);
++ float tx = float(this->tiltpos[0]-float(viewport[0])/2.0f)/(float(viewport[0]));
++ float ty = float(this->tiltpos[1]-float(viewport[1])/2.0f)/(float(viewport[1]));
++ if (aspect > 1.0f) tx *= aspect;
++ else ty /= aspect;
++ this->crossposition->translation.setValue(SbVec3f(tx, ty, 0));
++
++ float sx = (1.0f/float(viewport[0])) * 15.0f;
++ float sy = (1.0f/float(viewport[1])) * 15.0f;
++ if (aspect > 1.0f) sx *= aspect;
++ else sy /= aspect;
++ this->crossscale->scaleFactor.setValue(SbVec3f(sx, sy, 0));
++ }
++}
++
++void
++So at Gui@FlyViewerP::superimposition_cb(void * closure, SoAction * action)
++{
++ assert(closure != NULL);
++ ((So at Gui@FlyViewerP *) closure)->superimpositionevent(action);
++}
++
++void
++So at Gui@FlyViewerP::updateSpeedIndicator(void)
++{
++ assert(this->sgeometry != NULL);
++
++ SbVec3f * points = this->sgeometry->point.startEditing();
++
++ if (points[10][0] == 0.0f)
++ this->smaxspeedswitch->whichChild.setValue(SO_SWITCH_ALL);
++ if (points[14][0] == 0.0f)
++ this->scurrentspeedswitch->whichChild.setValue(SO_SWITCH_ALL);
++ points[10][0] = this->maxspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++ points[11][0] = this->maxspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++ points[14][0] = this->currentspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++ points[15][0] = this->currentspeed / (SO at GUI@_MAX_SPEED / 0.8f);
++ this->sgeometry->point.finishEditing();
++
++ if (this->maxspeed == 0.0f)
++ this->smaxspeedswitch->whichChild.setValue(SO_SWITCH_NONE);
++ if (this->currentspeed == 0.0f)
++ this->scurrentspeedswitch->whichChild.setValue(SO_SWITCH_NONE);
++}
++
++double So at Gui@FlyViewerP::calculateChangeInTime()
++{
++ SbTime thisrender;
++ thisrender.setToTimeOfDay();
++
++ if (this->currentspeed == 0.0f)
++ this->lastrender->setValue(thisrender.getValue() - 0.01);
++
++ // We've had a report on Coin-support that floats may have too low
++ // precision for the subtraction of these two values (ie it becomes
++ // zero), so don't cast to float.
++ //
++ // FIXME: it doesn't sound likely that this was the real cause of
++ // the problem. First of all, it seems improbably that precision
++ // could be so bad for floats, as the time between render frames
++ // should almost be guaranteed to be milliseconds, at least. It is
++ // suspicious that the error only shows up with the Intel C++
++ // compiler, and not when the reported built with MSVC++ instead.
++ //
++ // Second, the fix is not sufficient. What if the
++ // SbTime::getTimeOfDay() resolution is too low on the particular
++ // system, so we often get zero difference here? That case must be
++ // handled, and from the original bug report, it sounds like it
++ // isn't, which is a separate bug in itself.
++ //
++ // Third, what's up with that magic multiplication factor of 10?
++ // That doesn't seem to make sense.
++ //
++ // 20061212 mortene.
++
++ // This is only a problem on release builds which makes it sound
++ // like it's just some value that is not properly
++ // initialized. (20061212 frodo)
++
++ double t = (thisrender.getValue() - this->lastrender->getValue()) * 10.0;
++
++ if (t >= 1.0)
++ t = 1.0;
++
++ return t;
++}
++
++void So at Gui@FlyViewerP::updateCurrentSpeed(double dt)
++{
++ float speedscale =
++ 1.0f - (this->pan_increment * this->pan_increment
++ + this->tilt_increment * this->tilt_increment);
++
++ // NOTE: I don't believe that this boundary condition could ever
++ // happen. 20021022 rolvs
++ if (speedscale < 0.0f)
++ speedscale = 0.0f;
++
++ this->currentspeed +=
++ (((this->currentspeed +
++ this->maxspeed * speedscale) / 2.0f) -
++ this->currentspeed) * dt;
++}
++
++void So at Gui@FlyViewerP::updateCameraPosition(SoCamera * camera,
++ float current_speed,
++ float dt)
++{
++ assert(camera != NULL);
++ SbVec3f dir;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++ dir.normalize();
++ camera->position.setValue(camera->position.getValue() +
++ dir * (current_speed * dt));
++}
++
++void So at Gui@FlyViewerP::updateCameraOrientation(SoCamera * camera,
++ float d_tilt,
++ float d_pan,
++ float dt)
++{
++ assert(camera != NULL);
++ // FIXME: Make sure that the angle between direction and up-vector
++ // stays larger than zero, or else it gets 'locked' in an undefined
++ // state and starts to act weird. This should probably be done in
++ // parent class. 20021017 rolvs
++ PUBLIC(this)->tiltCamera(d_tilt * dt);
++
++ camera->orientation = camera->orientation.getValue() *
++ SbRotation(PUBLIC(this)->getUpDirection(), d_pan * dt);
++}
++
++void
++So at Gui@FlyViewerP::incrementMaxSpeed(void)
++{
++ this->max_speed_factor++;
++ this->updateMaxSpeed();
++}
++
++
++void
++So at Gui@FlyViewerP::decrementMaxSpeed(void)
++{
++ this->max_speed_factor--;
++ this->updateMaxSpeed();
++}
++
++
++void
++So at Gui@FlyViewerP::updateSpeedScalingFactor(void)
++{
++ SoNode * n = PUBLIC(this)->getSceneGraph();
++ if(n == NULL)
++ return; // Scenegraph not set yet?
++
++ SoGetBoundingBoxAction bbact(PUBLIC(this)->getViewportRegion());
++ bbact.apply(n);
++
++ SbBox3f bbox = bbact.getBoundingBox();
++ float bbox_diagonal = (bbox.getMax() - bbox.getMin()).length();
++
++ // FIXME: It should be possible to create a simple scaling function,
++ // based on some logaritmic evaluation. 20021017 rolvs.
++ if (bbox_diagonal > 100)
++ this->speed_scaling_factor = 1.0f; // log(bbox_diagonal);
++ else if (bbox_diagonal > 10 && bbox_diagonal < 100)
++ this->speed_scaling_factor = 0.4f;
++ else if (bbox_diagonal > 1 && bbox_diagonal < 10)
++ this->speed_scaling_factor = 0.3f;
++ else if (bbox_diagonal > 0.1 && bbox_diagonal < 1)
++ this->speed_scaling_factor = 0.1f;
++ else
++ this->speed_scaling_factor = 0.1f * bbox_diagonal;
++}
++
++void So at Gui@FlyViewerP::stopMoving(void)
++{
++ this->maxspeed = 0.0f;
++ this->currentspeed = 0.0f;
++ this->max_speed_factor = 0;
++}
++
++void So at Gui@FlyViewerP::updateMaxSpeed(void)
++{
++ if (this->max_speed_factor == 0) {
++ this->stopMoving();
++ return;
++ }
++
++ // FIXME: Move this methodcall so that it is called only
++ // once. (e.g. when scene graph is set) 20021021 rolvs
++ this->updateSpeedScalingFactor();
++
++ this->maxspeed =
++ this->max_speed_factor
++ * float(pow(SO at GUI@_INC_FACTOR, abs( this->max_speed_factor)))
++ * this->speed_scaling_factor;
++
++ if (this->maxspeed > SO at GUI@_MAX_SPEED)
++ this->maxspeed = SO at GUI@_MAX_SPEED;
++ else if (this->maxspeed < -1*SO at GUI@_MAX_SPEED)
++ this->maxspeed = -1 * SO at GUI@_MAX_SPEED;
++}
++
++
++
++// Set cursor graphics according to mode.
++void
++So at Gui@FlyViewerP::updateCursorRepresentation(void)
++{
++ if (!PUBLIC(this)->isCursorEnabled()) {
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getBlankCursor());
++ return;
++ }
++
++ switch (this->viewermode) {
++ case So at Gui@FlyViewerP::FLYING:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::DEFAULT));
++ break;
++
++ case So at Gui@FlyViewerP::WAITING_FOR_SEEK:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::CROSSHAIR));
++ break;
++
++ case So at Gui@FlyViewerP::WAITING_FOR_UP_PICK:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::UPARROW));
++ break;
++
++ case So at Gui@FlyViewerP::TILTING:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getPanCursor());
++ break;
++
++ default:
++ assert(0 && "unknown mode");
++ break;
++ }
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// ************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@FlyViewer);
++
++// ************************************************************************
++
++/*!
++ Public constructor.
++*/
++So at Gui@FlyViewer::So at Gui@FlyViewer(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type)
++ : inherited(parent, name, embed, flag, type, FALSE)
++{
++ PRIVATE(this) = new So at Gui@FlyViewerP(this);
++ PRIVATE(this)->constructor(TRUE);
++}
++
++// ************************************************************************
++
++/*!
++ Protected constructor, used by viewer components derived from the
++ So at Gui@FlyViewer.
++*/
++So at Gui@FlyViewer::So at Gui@FlyViewer(@WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build)
++ : inherited(parent, name, embed, flag, type, FALSE)
++{
++ PRIVATE(this) = new So at Gui@FlyViewerP(this);
++ PRIVATE(this)->constructor(build);
++}
++
++// ************************************************************************
++
++/*!
++ Virtual constructor.
++*/
++So at Gui@FlyViewer::~So at Gui@FlyViewer()
++{
++ if (PRIVATE(this)->superimposition != NULL) {
++ this->removeSuperimposition(PRIVATE(this)->superimposition);
++ PRIVATE(this)->superimposition->unref();
++ PRIVATE(this)->superimposition = NULL;
++ }
++ delete PRIVATE(this);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setViewing(SbBool enable)
++{
++ if (enable != this->isViewing())
++ PRIVATE(this)->stopMoving();
++
++ inherited::setViewing(enable);
++ this->setSuperimpositionEnabled(PRIVATE(this)->superimposition, enable);
++ this->scheduleRedraw();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::resetToHomePosition(void)
++{
++ PRIVATE(this)->stopMoving();
++ inherited::resetToHomePosition();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::viewAll(void)
++{
++ PRIVATE(this)->stopMoving();
++ inherited::viewAll();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setCamera(SoCamera * camera)
++{
++ PRIVATE(this)->stopMoving();
++
++ inherited::setCamera(camera);
++ // FIXME: do something with up-direction?
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setCursorEnabled(SbBool enable)
++{
++ inherited::setCursorEnabled(enable);
++ PRIVATE(this)->updateCursorRepresentation();
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setCameraType(SoType type)
++{
++ PRIVATE(this)->stopMoving();
++ inherited::setCameraType(type);
++ // FIXME: what else? 20010907 mortene.
++}
++
++// ************************************************************************
++
++// doc in super
++const char *
++So at Gui@FlyViewer::getDefaultWidgetName(void) const
++{
++ static const char defaultWidgetName[] = "So at Gui@FlyViewer";
++ return defaultWidgetName;
++}
++
++// ************************************************************************
++
++// doc in super
++const char *
++So at Gui@FlyViewer::getDefaultTitle(void) const
++{
++ static const char defaultTitle[] = "Fly Viewer";
++ return defaultTitle;
++}
++
++// ************************************************************************
++
++// doc in super
++const char *
++So at Gui@FlyViewer::getDefaultIconTitle(void) const
++{
++ static const char defaultIconTitle[] = "Fly Viewer";
++ return defaultIconTitle;
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@FlyViewer::processSoEvent(const SoEvent * const event)
++{
++ // FIXME: Refactor the event-handling so that it uses the same
++ // strategy as in So at Gui@ExaminerViewer, where the event-handler
++ // only checks the state and the mode from that. 20021016 rolvs.
++
++ // We're in "interact" mode (ie *not* the camera modification mode),
++ // so don't handle the event here. It should either be forwarded to
++ // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++ // it's an ESC and ALT press (to switch modes).
++ if (!this->isViewing()) { return inherited::processSoEvent(event); }
++
++ // Events when in "ready-to-seek" mode are ignored, except those
++ // which influence the seek mode itself -- these are handled further
++ // up the inheritance hierarchy.
++ if (this->isSeekMode()) { return inherited::processSoEvent(event); }
++
++ // FIXME: There is more parts of the code in
++ // So at Gui@*FlyViewer::processEvent that should go in to the
++ // processKeyboardEvent function; to be fixed later.
++ // 20021015 rolvs
++
++ // Keyboard handling
++ if (event->isOfType(SoKeyboardEvent::getClassTypeId())) {
++ SbBool result =
++ PRIVATE(this)->processKeyboardEvent( (SoKeyboardEvent*)event );
++
++ if( result ){
++ return TRUE;
++ }
++ // Else: Do nothing, and proceed as usual
++ }
++
++ // Mousebutton handling
++ // See FIXME and comment for keyboardhandler.
++ else if (event->isOfType(SoMouseButtonEvent::getClassTypeId())) {
++ // FIXME: only for fly mode
++ const SoMouseButtonEvent * const me =
++ (const SoMouseButtonEvent *const) event;
++ SbBool result = PRIVATE( this )->processMouseButtonEvent( me );
++ if( result )
++ return TRUE;
++ }
++
++ else if (event->isOfType(SoLocation2Event::getClassTypeId())) {
++ const SoLocation2Event * const le =
++ (const SoLocation2Event * const) event;
++ SbBool result = PRIVATE( this )->processLocation2Event( le );
++ if( result )
++ return TRUE;
++ }
++
++ return inherited::processSoEvent(event);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::setSeekMode(SbBool enable)
++{
++ // Note: this method is almost identical to the setSeekMode() in the
++ // So at Gui@ExaminerViewer, so migrate any changes.
++
++#if SO at GUI@_DEBUG
++ if (enable == this->isSeekMode()) {
++ SoDebugError::postWarning("So at Gui@FlyViewer::setSeekMode",
++ "seek mode already %sset", enable ? "" : "un");
++ return;
++ }
++#endif // SO at GUI@_DEBUG
++
++ // FIXME: what if we're in the middle of a seek already? 20010910 mortene.
++ // larsa - either stop the seek (on false) or reset timer to two new secs
++
++ inherited::setSeekMode(enable);
++ PRIVATE(this)->setMode(enable ? So at Gui@FlyViewerP::WAITING_FOR_SEEK :
++ So at Gui@FlyViewerP::FLYING);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::actualRedraw(void)
++{
++ if (!this->isViewing()) {
++ inherited::actualRedraw();
++ return;
++ }
++
++ switch (PRIVATE(this)->getMode()) {
++ case So at Gui@FlyViewerP::FLYING:
++ {
++ PRIVATE(this)->updateCurrentSpeed(PRIVATE(this)->calculateChangeInTime());
++ PRIVATE(this)->updateSpeedIndicator();
++
++ SbTime thisrender;
++ thisrender.setToTimeOfDay();
++
++ if (PRIVATE(this)->currentspeed != 0.0f) {
++ // We've had a report on Coin-support that floats may have too
++ // low precision for the subtraction of these two values (ie
++ // it becomes zero), so don't cast to float.
++ //
++ // Note: there's some additional information about this, see
++ // the FIXME comment in the
++ // So at Gui@FlyViewerP::calculateChangeInTime() function.
++ double t = (thisrender.getValue() -
++ PRIVATE(this)->lastrender->getValue()) * 2.0;
++ if (t > 0.0) {
++ SoCamera * camera = this->getCamera();
++
++ if (camera){ // could be a sceneless viewer
++ PRIVATE(this)->updateCameraPosition
++ ( camera,
++ PRIVATE(this)->currentspeed*
++ PRIVATE(this)->speed_scaling_factor,
++ t );
++ PRIVATE(this)->updateCameraOrientation
++ ( camera,
++ PRIVATE(this)->tilt_increment,
++ PRIVATE(this)->pan_increment,
++ t );
++ }
++ }
++ }
++
++ inherited::actualRedraw();
++
++ PRIVATE(this)->lastrender->setValue(thisrender.getValue());
++
++ if (PRIVATE(this)->currentspeed != 0.0f ||
++ PRIVATE(this)->maxspeed != 0.0f)
++ this->scheduleRedraw();
++ }
++ break;
++ default:
++ inherited::actualRedraw();
++ break;
++ }
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::rightWheelMotion(float value)
++{
++ PRIVATE(this)->dolly(value - this->getRightWheelValue());
++ inherited::rightWheelMotion(value);
++}
++
++// ************************************************************************
++
++// doc in super
++void
++So at Gui@FlyViewer::afterRealizeHook(void)
++{
++ PRIVATE(this)->updateCursorRepresentation();
++ inherited::afterRealizeHook();
++}
++
++// ************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFlyViewer.h.in
+@@ -0,0 +1,87 @@
++#ifndef SO at GUI@_FLYVIEWER_H
++#define SO at GUI@_FLYVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h>
++
++// ************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@FlyViewer : public So at Gui@ConstrainedViewer {
++ SO at GUI@_OBJECT_HEADER(So at Gui@FlyViewer, So at Gui@ConstrainedViewer);
++
++public:
++ So at Gui@FlyViewer(@WIDGET@ parent = NULL,
++ const char * name = NULL,
++ SbBool embed = TRUE,
++ So at Gui@FullViewer::BuildFlag flag = BUILD_ALL,
++ So at Gui@Viewer::Type type = BROWSER);
++ ~So at Gui@FlyViewer();
++
++ virtual void setViewing(SbBool enable);
++ virtual void viewAll(void);
++ virtual void resetToHomePosition(void);
++ virtual void setCamera(SoCamera * camera);
++ virtual void setCursorEnabled(SbBool enable);
++ virtual void setCameraType(SoType type);
++
++protected:
++ So at Gui@FlyViewer(@WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++ virtual SbBool processSoEvent(const SoEvent * const event);
++ virtual void setSeekMode(SbBool enable);
++ virtual void actualRedraw(void);
++
++ virtual void rightWheelMotion(float value);
++
++ virtual void afterRealizeHook(void);
++
++private:
++ class So at Gui@FlyViewerP * pimpl;
++ friend class So at Gui@FlyViewerP;
++};
++
++// ************************************************************************
++
++#endif // ! SO at GUI@_FLYVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFullViewer.cpp.in
+@@ -0,0 +1,1648 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*FullViewer sourcecode.
++
++/*!
++ \class So at Gui@FullViewer So at Gui@FullViewer.h Inventor/@Gui@/viewers/So at Gui@FullViewer.h
++ \brief The So at Gui@FullViewer class adds some user interface components to the viewer canvas.
++ \ingroup components viewers
++
++ The So at Gui@FullViewer is an abstract viewer class which extends it's
++ superclass (the basic So at Gui@Viewer class) with two major user
++ interface additions:
++
++ <ul>
++
++ <li>decorations around the render canvas, with buttons and
++ thumbwheels to control camera interaction and various other aspects
++ of model / scene viewing</li>
++
++ <li>a popup menu, invoked with the right mouse button, which
++ controls yet more aspects of the rendering and the viewer</li>
++
++ </ul>
++
++ The user interface features listed above are the common parts of the
++ user interfaces of the So at Gui@FullViewer's non-abstract subclasses.
++
++ For "real" application programs, the viewers / components from this
++ class onwards and further down in the inheritance hierarchy is
++ usually not all that interesting, as they enforces too much extra
++ user interface cruft not compatible with the look and feel of the
++ other parts of the application user interface. So most "real"
++ applications will use either the So at Gui@Viewer or the
++ So at Gui@RenderArea as their base-level component, and then inherit
++ one of these down into one's own "proper" viewer classes.
++
++ The non-abstract subclasses of the So at Gui@FullViewer class are
++ viewer components often used as a test-bed for prototyping / rapid
++ application development when doing quick testing of scenes,
++ stand-alone 3D-models, animation techniques, etc etc.
++
++
++ \sa So at Gui@ConstrainedViewer, So at Gui@ExaminerViewer, So at Gui@PlaneViewer
++*/
++
++
++// *************************************************************************
++
++#include <float.h>
++
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewerP.h>
++#include <Inventor/@Gui@/widgets/So at Gui@PopupMenu.h>
++#include <so at gui@defs.h>
++
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++// ************************************************************************
++
++#define PRIVATE(o) (o->pimpl)
++#define PUBLIC(o) (o->pub)
++
++// ************************************************************************
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++ \fn void So at Gui@FullViewer::createViewerButtons(@WIDGET@ parent, SbPList * buttonlist)
++
++ Set up the viewer buttons with pixmaps and event connections.
++
++
++ One important note if you want to override this method to add your
++ own buttons to the list (in the explanation below, it is assumed
++ that you know how virtual function table pointers are handled by
++ C++):
++
++ createViewerButtons() is called (indirectly) from the constructors
++ of the viewer classes. This means that you need to delay it's
++ invocation until your own subclass's constructor is run, because
++ otherwise your re-implementation won't have been added to the
++ internal virtual function table yet.
++
++ Delaying a superclass viewer from building it's decorations is done
++ by passing build==FALSE as the last argument of the protected
++ constructors. You will then have to explicitly trigger the building
++ in your own constructor.
++
++ Here's a minimal example that shows the steps needed to be able to
++ override createViewerButtons() from So at Gui@ExaminerViewer:
++
++ \code
++ class MyExaminerViewer : public So at Gui@ExaminerViewer {
++
++ public:
++ MyExaminerViewer(@WIDGET@ parent);
++
++ protected:
++ virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++ };
++
++ MyExaminerViewer::MyExaminerViewer(@WIDGET@ parent)
++ : So at Gui@ExaminerViewer(parent, NULL, TRUE,
++ So at Gui@FullViewer::BUILD_ALL, So at Gui@FullViewer::BROWSER,
++ // build == FALSE, to delay creation of decorations
++ FALSE)
++ {
++ // Explicitly trigger the construction of viewer decorations.
++ @WIDGET@ widget = this->buildWidget(this->getParentWidget());
++ this->setBaseWidget(widget);
++ }
++
++ void
++ MyExaminerViewer::createViewerButtons(@WIDGET@ parent, SbPList * buttonlist)
++ {
++ So at Gui@ExaminerViewer::createViewerButtons(parent, buttonlist);
++ // [now add your own button(s) to the buttonlist]
++ }
++ \endcode
++*/
++
++/*!
++ \enum So at Gui@FullViewer::BuildFlag
++
++ Valid values for the constructor argument that decides how much of
++ the user interface features to set up. The enum values are bitflags
++ that can be OR'ed together.
++*/
++/*!
++ \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_NONE
++
++ Do not add any of the user interface components.
++*/
++/*!
++ \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_DECORATION
++
++ Only build and set up the decorations around the OpenGL canvas.
++*/
++/*!
++ \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_POPUP
++
++ Only build the popup menu. (Activated with the right mousebutton.)
++*/
++/*!
++ \var So at Gui@FullViewer::BuildFlag So at Gui@FullViewer::BUILD_ALL
++
++ Build all user interface components of the So at Gui@FullViewer.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::leftDecoration
++ The root widget for the left-side decorations.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::leftWheel
++ The widget representing the thumbwheel left of the render canvas.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::leftWheelLabel
++ Label widget of left wheel.
++*/
++
++/*!
++ \var char * So at Gui@FullViewer::leftWheelStr
++ Text of left thumbwheel's label.
++*/
++
++/*!
++ \var float So at Gui@FullViewer::leftWheelVal
++ Current value of the left thumbwheel.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::bottomDecoration
++ The root widget for the bottom decorations.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::bottomWheel
++ The widget representing the thumbwheel below the render canvas.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::bottomWheelLabel
++ Label widget of bottom wheel.
++*/
++
++/*!
++ \var char * So at Gui@FullViewer::bottomWheelStr
++ Text of bottom thumbwheel's label.
++*/
++
++/*!
++ \var float So at Gui@FullViewer::bottomWheelVal
++ Current value of the bottom thumbwheel.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::rightDecoration
++ The root widget for the right-side decorations.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::rightWheel
++ The widget representing the thumbwheel on the right side of the render canvas.
++*/
++
++/*!
++ \var @WIDGET@ So at Gui@FullViewer::rightWheelLabel
++ Label widget of right wheel.
++*/
++
++/*!
++ \var char * So at Gui@FullViewer::rightWheelStr
++ Text of right thumbwheel's label.
++*/
++
++/*!
++ \var float So at Gui@FullViewer::rightWheelVal
++ Current value of the right-side thumbwheel.
++*/
++
++/*!
++ \var So at Gui@PopupMenu * So at Gui@FullViewer::prefmenu
++ Pointer to the popup menu instance.
++*/
++
++/*!
++ \fn So at Gui@FullViewer::So at Gui@FullViewer(@WIDGET@ parent, const char * name, SbBool embed, So at Gui@FullViewer::BuildFlag buildFlag, So at Gui@Viewer::Type type, SbBool build)
++
++ Constructor. See parent class for explanation of arguments.
++
++ Subclasses will probably usually call with the \a buildNow flag set
++ to \c FALSE to be able to do delayed building of the OpenGL canvas
++ after other setup tasks has been performed.
++*/
++
++/*!
++ \fn So at Gui@FullViewer::~So at Gui@FullViewer()
++
++ Destructor.
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::setDecoration(const SbBool enable)
++
++ Turn the viewer decorations on or off.
++
++ \sa isDecoration()
++*/
++
++/*!
++ \fn SbBool So at Gui@FullViewer::isDecoration(void) const
++
++ Return \c TRUE if the viewer decorations are on, otherwise \c FALSE.
++
++ \sa setDecoration()
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::setPopupMenuEnabled(const SbBool enable)
++
++ Decide whether or not if clicking with the right mouse button on
++ the OpenGL canvas should reveal a preferences popup menu when in
++ viewing mode.
++
++ \sa isPopupMenuEnabled()
++*/
++
++/*!
++ \fn SbBool So at Gui@FullViewer::isPopupMenuEnabled(void) const
++
++ Return \c TRUE if the popup preferences menu is enabled,
++ otherwise \c FALSE.
++
++ \sa setPopupMenuEnabled()
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@FullViewer::getAppPushButtonParent(void) const
++
++ Returns the widget which is used as the parent of application
++ specified buttons. The row of application buttons (if any) will be
++ placed in the upper left corner.
++
++ \sa addAppPushButton(), insertAppPushButton(), removeAppPushButton()
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::addAppPushButton(@WIDGET@ newButton)
++
++ Add an application specific push button to the viewer decorations.
++ Application buttons will be laid out in a vertical row from the
++ upper left corner.
++
++ The button will be added bottom-most.
++
++ \sa insertAppPushButton(), removeAppPushButton(), getAppPushButtonParent()
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::insertAppPushButton(@WIDGET@ newButton, int index)
++
++ Insert an application specific push button to the viewer decorations
++ at the given \c index.
++
++ \sa addAppPushButton(), removeAppPushButton(), getAppPushButtonParent()
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::removeAppPushButton(@WIDGET@ oldButton)
++
++ Remove one of the application specific buttons.
++
++ \sa addAppPushButton(), insertAppPushButton()
++*/
++
++/*!
++ \fn int So at Gui@FullViewer::findAppPushButton(@WIDGET@ oldButton) const
++
++ Return the index of a particular button that has been specified by
++ the application, or -1 of the button has not been added.
++
++ \sa addAppPushButton()
++*/
++
++/*!
++ \fn int So at Gui@FullViewer::lengthAppPushButton(void) const
++
++ Return number of application specific buttons added.
++
++ \sa addAppPushButton(), insertAddAppPushButton()
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@FullViewer::getRenderAreaWidget(void) const
++
++ Returns the render area OpenGL canvas widget.
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::buildDecoration(@WIDGET@ parent)
++
++ Build viewer decorations.
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@FullViewer::buildLeftTrim(@WIDGET@ parent)
++
++ Build decorations on the left of the render canvas. Override this
++ method in subclasses if you want your own decorations on the viewer
++ window.
++
++ The decoration will be 30 pixels wide.
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@FullViewer::buildBottomTrim(@WIDGET@ parent)
++
++ Build decorations on the bottom of the render canvas. Override this
++ method in subclasses if you want your own decorations on the viewer window.
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@FullViewer::buildRightTrim(@WIDGET@ parent)
++
++ Build decorations on the right side of the render canvas. Override this
++ method in subclasses if you want your own decorations on the viewer window.
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@FullViewer::buildAppButtons(@WIDGET@ parent)
++
++ Build the application specified button row (if any buttons were
++ set up).
++*/
++
++/*!
++ \fn @WIDGET@ So at Gui@FullViewer::buildViewerButtons(@WIDGET@ parent)
++
++ Build and layout viewer specified button row.
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::buildPopupMenu(void)
++
++ Make a popup menu with preferences settings.
++
++ One important note as for when you want to override this function in
++ a subclass: be aware that it will usually be invoked (indirectly)
++ from this class's constructor. That is \e before the table of
++ virtual function pointers has been set up for the subclass, and
++ because of this, the function will not be called in the subclass
++ even though it is virtual.
++
++ To make the overriding actually be in effect, you need to delay
++ building the widgets of this class. For information on how to do
++ that, see the documentation of
++ So at Gui@FullViewer::createViewerButtons().
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::openPopupMenu(const SbVec2s position)
++
++ NOTE: This method is not part of the original InventorXt API.
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::setLeftWheelString(const char * const string)
++
++ Set label of the left thumbwheel.
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::setBottomWheelString(const char * const string)
++
++ Set label of the bottom thumbwheel.
++*/
++
++/*!
++ \fn void So at Gui@FullViewer::setRightWheelString(const char * const string)
++
++ Set label of the right thumbwheel.
++*/
++
++// ************************************************************************
++
++// Note: the following function documentation blocks for thumbwheel
++// handling will also be used for all the miscellaneous viewer
++// subclasses, so keep'em general.
++
++/*!
++ Called when the user start to drag the thumbwheel in the left
++ frame. Override this method in subclassed viewers to provide your
++ own functionality on the thumbwheel.
++
++ \sa leftWheelMotion(), leftWheelFinish()
++ \sa bottomWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::leftWheelStart(void)
++{
++ this->interactiveCountInc();
++}
++
++/*!
++ Called repeatedly as the user drags the thumbwheel in the left
++ frame. Override this method in subclassed viewers to provide your
++ own functionality on the thumbwheel.
++
++ \sa leftWheelStart(), leftWheelFinish()
++ \sa bottomWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::leftWheelMotion(float value)
++{
++ this->leftWheelVal = value;
++}
++
++/*!
++ Called as the user let go of the thumbwheel in the left frame
++ after a drag operation. Override this method in subclassed viewers
++ to provide your own functionality on the thumbwheel.
++
++ \sa leftWheelStart(), leftWheelMotion()
++ \sa bottomWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::leftWheelFinish(void)
++{
++ this->interactiveCountDec();
++}
++
++/*!
++ Set a new value for the left thumbwheel.
++*/
++void
++So at Gui@FullViewer::setLeftWheelValue(const float value)
++{
++ this->leftWheelVal = value;
++ // Wheel may not be constructed yet, but we need to be robust, as
++ // set*WheelValue() is used from subclasses.
++ if (this->leftWheel) {
++ So at Gui@FullViewerP::setThumbWheelValue(this->leftWheel, value);
++ }
++}
++
++/*!
++ Get current value of the left thumbwheel.
++
++ \sa leftWheelMotion()
++*/
++float
++So at Gui@FullViewer::getLeftWheelValue(void) const
++{
++ return this->leftWheelVal;
++}
++
++/*!
++ Called when the user start to drag the thumbwheel in the bottom
++ frame. Override this method in subclassed viewers to provide your
++ own functionality on the thumbwheel.
++
++ \sa bottomWheelMotion(), bottomWheelFinish()
++ \sa leftWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::bottomWheelStart(void)
++{
++ this->interactiveCountInc();
++}
++
++/*!
++ Called repeatedly as the user drags the thumbwheel in the bottom
++ frame. Override this method in subclassed viewers to provide your
++ own functionality on the thumbwheel.
++
++ \sa bottomWheelStart(), bottomWheelFinish()
++ \sa leftWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::bottomWheelMotion(float value)
++{
++ this->bottomWheelVal = value;
++}
++
++/*!
++ Called as the user let go of the thumbwheel in the bottom frame
++ after a drag operation. Override this method in subclassed viewers
++ to provide your own functionality on the thumbwheel.
++
++ \sa bottomWheelStart(), bottomWheelMotion()
++ \sa leftWheelStart(), rightWheelStart()
++*/
++void
++So at Gui@FullViewer::bottomWheelFinish(void)
++{
++ this->interactiveCountDec();
++}
++
++/*!
++ Set a new value for the bottom thumbwheel.
++*/
++void
++So at Gui@FullViewer::setBottomWheelValue(const float value)
++{
++ this->bottomWheelVal = value;
++ // Wheel may not be constructed yet, but we need to be robust, as
++ // set*WheelValue() is used from subclasses.
++ if (this->bottomWheel) {
++ So at Gui@FullViewerP::setThumbWheelValue(this->bottomWheel, value);
++ }
++}
++
++/*!
++ Get current value of the bottom thumbwheel.
++
++ \sa bottomWheelMotion()
++*/
++float
++So at Gui@FullViewer::getBottomWheelValue(void) const
++{
++ return this->bottomWheelVal;
++}
++
++/*!
++ Called when the user start to drag the thumbwheel in the right
++ frame. Override this method in subclassed viewers to provide your
++ own functionality on the thumbwheel.
++
++ \sa rightWheelMotion(), rightWheelFinish()
++ \sa leftWheelStart(), bottomWheelStart()
++*/
++void
++So at Gui@FullViewer::rightWheelStart(void)
++{
++ this->interactiveCountInc();
++}
++
++/*!
++ Called repeatedly as the user drags the thumbwheel in the right
++ frame. Override this method in subclassed viewers to provide your
++ own functionality on the thumbwheel.
++
++ \sa rightWheelStart(), rightWheelFinish()
++ \sa leftWheelStart(), bottomWheelStart()
++*/
++void
++So at Gui@FullViewer::rightWheelMotion(float value)
++{
++ this->rightWheelVal = value;
++}
++
++/*!
++ Called as the user let go of the thumbwheel in the right frame
++ after a drag operation. Override this method in subclassed viewers
++ to provide your own functionality on the thumbwheel.
++
++ \sa rightWheelStart(), rightWheelMotion()
++ \sa leftWheelStart(), bottomWheelStart()
++*/
++void
++So at Gui@FullViewer::rightWheelFinish(void)
++{
++ this->interactiveCountDec();
++}
++
++/*!
++ Set a new value for the right thumbwheel.
++*/
++void
++So at Gui@FullViewer::setRightWheelValue(const float value)
++{
++ this->rightWheelVal = value;
++ // Wheel may not be constructed yet, but we need to be robust, as
++ // set*WheelValue() is used from subclasses.
++ if (this->rightWheel) {
++ So at Gui@FullViewerP::setThumbWheelValue(this->rightWheel, value);
++ }
++}
++
++/*!
++ Get current value of the right thumbwheel.
++
++ \sa rightWheelMotion()
++*/
++float
++So at Gui@FullViewer::getRightWheelValue(void) const
++{
++ return this->rightWheelVal;
++}
++
++// *************************************************************************
++
++/*!
++ This method returns the native widget for the label below the left
++ thumb wheel.
++*/
++
++ at WIDGET@
++So at Gui@FullViewer::getLeftWheelLabelWidget(void) const
++{
++ return this->leftWheelLabel;
++}
++
++/*!
++ This method returns the native widget for the label below the right thumb
++ wheel.
++*/
++ at WIDGET@
++So at Gui@FullViewer::getRightWheelLabelWidget(void) const
++{
++ return this->rightWheelLabel;
++}
++
++/*!
++ This method returns the native widget for the label beside the
++ bottom thumb wheel.
++*/
++ at WIDGET@
++So at Gui@FullViewer::getBottomWheelLabelWidget(void) const
++{
++ return this->bottomWheelLabel;
++}
++
++// ************************************************************************
++
++/*!
++ Set title of popup menu.
++*/
++void
++So at Gui@FullViewer::setPopupMenuString(const char * name)
++{
++ PRIVATE(this)->popupmenutitle = name;
++ if (this->prefmenu) { this->prefmenu->setMenuTitle(SoGuiFullViewerP::ROOT_MENU, name); }
++}
++
++
++// Documented in superclass.
++SbBool
++So at Gui@FullViewer::processSoEvent(const SoEvent * const ev)
++{
++ // We're in "interact" mode (ie *not* the camera modification mode),
++ // so don't handle the event here. It should either be forwarded to
++ // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++ // it's an ESC press (to switch modes).
++ if (!this->isViewing()) { return inherited::processSoEvent(ev); }
++
++ // Note: with the original SGI InventorXt, the popup menu is also
++ // activated by RMB clicks in non-viewing mode. We want to allow RMB
++ // clicks to pass through to the scenegraph in non-viewing mode, so
++ // we don't copy that behavior.
++
++ if (ev->getTypeId().isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++ SoMouseButtonEvent * const e = (SoMouseButtonEvent *) ev;
++ if ((e->getButton() == SoMouseButtonEvent::BUTTON2)) {
++ if (this->isPopupMenuEnabled()) {
++ if (e->getState() == SoButtonEvent::DOWN) {
++ this->openPopupMenu(e->getPosition());
++ }
++ // Steal all RMB-events if the viewer uses the popup-menu.
++ return TRUE;
++ }
++ }
++ }
++
++ return inherited::processSoEvent(ev);
++}
++
++// *************************************************************************
++
++// FIXME: get rid of this hack and make this file truly
++// "generic". 20020109 mortene.
++#ifndef __COIN_SOWIN__
++
++// *************************************************************************
++
++// Doc in superclass.
++void
++So at Gui@FullViewer::setComponentCursor(const So at Gui@Cursor & cursor)
++{
++ // Overridden to apply the new cursor only for the rendering canvas
++ // widget. Otherwise, the default So at Gui@Component
++ // setComponentCursor() method will set the cursor for the top-most
++ // parent widget, which makes it affect all sub-widgets, like the
++ // decorations stuff.
++
++ So at Gui@Component::setWidgetCursor(this->getGLWidget(), cursor);
++}
++
++// *************************************************************************
++
++#endif // ! __COIN_SOWIN__
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiFullViewerP::SoGuiFullViewerP(So at Gui@FullViewer * owner)
++{
++ this->pub = owner;
++}
++
++SoGuiFullViewerP::~SoGuiFullViewerP()
++{
++}
++
++So at Gui@PopupMenu *
++SoGuiFullViewerP::setupStandardPopupMenu(void)
++{
++ So at Gui@PopupMenu * menu = So at Gui@PopupMenu::createInstance();
++
++ menu->newMenu("rootmenu", ROOT_MENU);
++ // FIXME: none of the So*-toolkits so far uses the rootmenu title to
++ // set up a title string at the top of the root popupmenu. 20010810 mortene.
++ menu->setMenuTitle(ROOT_MENU, this->popupmenutitle.getString());
++
++#if 0 // OBSOLETED: this looks ugly and confusing for the user. 20010810 mortene.
++ // Simple hack for a common / generic way of setting up a title for
++ // the popupmenu.
++ menu->newMenuItem("rootmenutitle", ROOT_MENU_TITLE);
++ menu->setMenuItemTitle(ROOT_MENU_TITLE, this->popupmenutitle.getString());
++ menu->addMenuItem(ROOT_MENU, ROOT_MENU_TITLE);
++ menu->setMenuItemEnabled(ROOT_MENU_TITLE, FALSE);
++ menu->addSeparator(ROOT_MENU);
++#endif // OBSOLETED
++
++ menu->newMenu("functionsmenu", FUNCTIONS_MENU);
++ menu->setMenuTitle(FUNCTIONS_MENU, _("Functions"));
++ menu->newMenu("drawstylesmenu", DRAWSTYLES_MENU);
++ menu->setMenuTitle(DRAWSTYLES_MENU, _("Draw Styles"));
++ menu->newMenu("stereomenu", STEREO_MENU);
++ menu->setMenuTitle(STEREO_MENU, _("Stereo Viewing"));
++ menu->newMenuItem("examining", EXAMINING_ITEM);
++ menu->setMenuItemTitle(EXAMINING_ITEM, _("Viewing"));
++ menu->newMenuItem("decoration", DECORATION_ITEM);
++ menu->setMenuItemTitle(DECORATION_ITEM, _("Decorations"));
++ menu->newMenuItem("headlight", HEADLIGHT_ITEM);
++ menu->setMenuItemTitle(HEADLIGHT_ITEM, _("Headlight"));
++ menu->newMenuItem("fullscreen", FULLSCREEN_ITEM);
++ menu->setMenuItemTitle(FULLSCREEN_ITEM, _("Fullscreen"));
++
++ menu->addMenu(ROOT_MENU, FUNCTIONS_MENU);
++ menu->addMenu(ROOT_MENU, DRAWSTYLES_MENU);
++ menu->addMenu(ROOT_MENU, STEREO_MENU);
++ menu->addMenuItem(ROOT_MENU, EXAMINING_ITEM);
++ menu->addMenuItem(ROOT_MENU, DECORATION_ITEM);
++ menu->addMenuItem(ROOT_MENU, HEADLIGHT_ITEM);
++ menu->addMenuItem(ROOT_MENU, FULLSCREEN_ITEM);
++
++ menu->newMenuItem("home", HOME_ITEM);
++ menu->setMenuItemTitle(HOME_ITEM, _("Home"));
++ menu->newMenuItem("set_home", SET_HOME_ITEM);
++ menu->setMenuItemTitle(SET_HOME_ITEM, _("Set Home"));
++ menu->newMenuItem("view_all", VIEW_ALL_ITEM);
++ menu->setMenuItemTitle(VIEW_ALL_ITEM, _("View All"));
++ menu->newMenuItem("seek", SEEK_ITEM);
++ menu->setMenuItemTitle(SEEK_ITEM, _("Seek"));
++
++ menu->addMenuItem(FUNCTIONS_MENU, HOME_ITEM);
++ menu->addMenuItem(FUNCTIONS_MENU, SET_HOME_ITEM);
++ menu->addMenuItem(FUNCTIONS_MENU, VIEW_ALL_ITEM);
++ menu->addMenuItem(FUNCTIONS_MENU, SEEK_ITEM);
++
++ menu->newMenu("drawstylesstill", DRAWSTYLES_STILL_MENU);
++ menu->setMenuTitle(DRAWSTYLES_STILL_MENU, _("Still Drawstyle"));
++
++ menu->newMenuItem("as_is", AS_IS_ITEM);
++ menu->setMenuItemTitle(AS_IS_ITEM, _("as is"));
++ menu->newMenuItem("hidden_line", HIDDEN_LINE_ITEM);
++ menu->setMenuItemTitle(HIDDEN_LINE_ITEM, _("hidden line"));
++ menu->newMenuItem("wireframe_overlay", WIREFRAME_OVERLAY_ITEM);
++ menu->setMenuItemTitle(WIREFRAME_OVERLAY_ITEM, _("wireframe overlay"));
++ menu->newMenuItem("no_textures", NO_TEXTURE_ITEM);
++ menu->setMenuItemTitle(NO_TEXTURE_ITEM, _("no texture"));
++ menu->newMenuItem("low_resolution", LOW_RESOLUTION_ITEM);
++ menu->setMenuItemTitle(LOW_RESOLUTION_ITEM, _("low resolution"));
++ menu->newMenuItem("wireframe", WIREFRAME_ITEM);
++ menu->setMenuItemTitle(WIREFRAME_ITEM, _("wireframe"));
++ menu->newMenuItem("points", POINTS_ITEM);
++ menu->setMenuItemTitle(POINTS_ITEM, _("points"));
++ menu->newMenuItem("bounding_box", BOUNDING_BOX_ITEM);
++ menu->setMenuItemTitle(BOUNDING_BOX_ITEM, _("bounding box (no depth)"));
++
++ menu->newRadioGroup(STILL_GROUP);
++ menu->addRadioGroupItem(STILL_GROUP, AS_IS_ITEM);
++ menu->addRadioGroupItem(STILL_GROUP, HIDDEN_LINE_ITEM);
++ menu->addRadioGroupItem(STILL_GROUP, WIREFRAME_OVERLAY_ITEM);
++ menu->addRadioGroupItem(STILL_GROUP, NO_TEXTURE_ITEM);
++ menu->addRadioGroupItem(STILL_GROUP, LOW_RESOLUTION_ITEM);
++ menu->addRadioGroupItem(STILL_GROUP, WIREFRAME_ITEM);
++ menu->addRadioGroupItem(STILL_GROUP, POINTS_ITEM);
++ menu->addRadioGroupItem(STILL_GROUP, BOUNDING_BOX_ITEM);
++
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, AS_IS_ITEM);
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, HIDDEN_LINE_ITEM);
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, WIREFRAME_OVERLAY_ITEM);
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, NO_TEXTURE_ITEM);
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, LOW_RESOLUTION_ITEM);
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, WIREFRAME_ITEM);
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, POINTS_ITEM);
++ menu->addMenuItem(DRAWSTYLES_STILL_MENU, BOUNDING_BOX_ITEM);
++
++ menu->newMenu("drawstylesanimation", DRAWSTYLES_ANIMATING_MENU);
++ menu->setMenuTitle(DRAWSTYLES_ANIMATING_MENU, _("Animating Drawstyle"));
++
++ menu->newMenuItem("move_same_as_still", MOVE_SAME_AS_STILL_ITEM);
++ menu->setMenuItemTitle(MOVE_SAME_AS_STILL_ITEM, _("same as still"));
++ menu->newMenuItem("move_no_texture", MOVE_NO_TEXTURE_ITEM);
++ menu->setMenuItemTitle(MOVE_NO_TEXTURE_ITEM, _("no texture"));
++ menu->newMenuItem("move_low_res", MOVE_LOW_RES_ITEM);
++ menu->setMenuItemTitle(MOVE_LOW_RES_ITEM, _("low resolution"));
++ menu->newMenuItem("move_wireframe", MOVE_WIREFRAME_ITEM);
++ menu->setMenuItemTitle(MOVE_WIREFRAME_ITEM, _("wireframe"));
++ menu->newMenuItem("move_low_res_wireframe", MOVE_LOW_RES_WIREFRAME_ITEM);
++ menu->setMenuItemTitle(MOVE_LOW_RES_WIREFRAME_ITEM,
++ _("low res wireframe (no depth)"));
++ menu->newMenuItem("move_points", MOVE_POINTS_ITEM);
++ menu->setMenuItemTitle(MOVE_POINTS_ITEM, _("points"));
++ menu->newMenuItem("move_low_res_points", MOVE_LOW_RES_POINTS_ITEM);
++ menu->setMenuItemTitle(MOVE_LOW_RES_POINTS_ITEM,
++ _("low res points (no depth)"));
++ menu->newMenuItem("move_bounding_box", MOVE_BOUNDING_BOX_ITEM);
++ menu->setMenuItemTitle(MOVE_BOUNDING_BOX_ITEM, _("bounding box (no depth)"));
++
++ menu->newRadioGroup(MOVE_GROUP);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_SAME_AS_STILL_ITEM);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_NO_TEXTURE_ITEM);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_ITEM);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_WIREFRAME_ITEM);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_WIREFRAME_ITEM);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_POINTS_ITEM);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_LOW_RES_POINTS_ITEM);
++ menu->addRadioGroupItem(MOVE_GROUP, MOVE_BOUNDING_BOX_ITEM);
++
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_SAME_AS_STILL_ITEM);
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_NO_TEXTURE_ITEM);
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_ITEM);
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_WIREFRAME_ITEM);
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_WIREFRAME_ITEM);
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_POINTS_ITEM);
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_LOW_RES_POINTS_ITEM);
++ menu->addMenuItem(DRAWSTYLES_ANIMATING_MENU, MOVE_BOUNDING_BOX_ITEM);
++
++ menu->newMenu("transparencytype", TRANSPARENCY_TYPE_MENU);
++ menu->setMenuTitle(TRANSPARENCY_TYPE_MENU, _("Transparency Type"));
++ menu->newRadioGroup(TRANSPARENCY_GROUP);
++
++ { // Fill in menu items in radiomenu with transparency selections.
++
++ struct menutransparencyitem {
++ const char * name, * title;
++ int id;
++ };
++
++ struct menutransparencyitem items[] = {
++#ifdef __COIN__
++ { "none", _("none"), NONE_TRANSPARENCY_ITEM },
++#endif // __COIN__
++ { "screen_door", _("screen door"), SCREEN_DOOR_TRANSPARENCY_ITEM },
++ { "add", _("add"), ADD_TRANSPARENCY_ITEM },
++ { "delayed_add", _("delayed add"), DELAYED_ADD_TRANSPARENCY_ITEM },
++ { "sorted_object_add", _("sorted object add"), SORTED_OBJECT_ADD_TRANSPARENCY_ITEM },
++ { "blend", _("blend"), BLEND_TRANSPARENCY_ITEM },
++ { "delayed_blend", _("delayed blend"), DELAYED_BLEND_TRANSPARENCY_ITEM },
++ { "sorted_object_blend", _("sorted object blend"), SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM }
++#ifdef __COIN__ // Coin extensions
++ ,
++ { "sorted_object_sorted_triangle_add", _("sorted object sorted triangle add"), SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM },
++ { "sorted_object_sorted_triangle_blend", _("sorted object sorted triangle blend"), SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM }
++#endif // __COIN__
++#ifdef HAVE_SORTED_LAYERS_BLEND
++ , { "sorted_layers_blend", _("sorted layers blend"), SORTED_LAYERS_BLEND_ITEM }
++#endif // HAVE_SORTED_LAYERS_BLEND
++ };
++
++ int nritems = sizeof(items) / sizeof(struct menutransparencyitem);
++ for (int i = 0; i < nritems; i++) {
++ menu->newMenuItem(items[i].name, items[i].id);
++ menu->setMenuItemTitle(items[i].id, items[i].title);
++ menu->addRadioGroupItem(TRANSPARENCY_GROUP, items[i].id);
++ menu->addMenuItem(TRANSPARENCY_TYPE_MENU, items[i].id);
++ }
++ }
++
++ menu->newMenuItem("stereooff", STEREO_OFF_ITEM);
++ menu->newMenuItem("stereoredcyan", STEREO_ANAGLYPH_ITEM);
++ menu->newMenuItem("stereoquadbuffer", STEREO_QUADBUFFER_ITEM);
++ menu->setMenuItemTitle(STEREO_OFF_ITEM, _("Off"));
++ menu->setMenuItemTitle(STEREO_ANAGLYPH_ITEM, _("Red/Cyan Anaglyph"));
++ menu->setMenuItemTitle(STEREO_QUADBUFFER_ITEM, _("Quad buffer"));
++
++ menu->newMenuItem("stereointerleavedrows", STEREO_INTERLEAVED_ROWS_ITEM);
++ menu->setMenuItemTitle(STEREO_INTERLEAVED_ROWS_ITEM, _("Interleaved Rows"));
++ menu->newMenuItem("stereointerleavedcolumns", STEREO_INTERLEAVED_COLUMNS_ITEM);
++ menu->setMenuItemTitle(STEREO_INTERLEAVED_COLUMNS_ITEM, _("Interleaved Columns"));
++
++ menu->newRadioGroup(STEREO_GROUP);
++ menu->addRadioGroupItem(STEREO_GROUP, STEREO_OFF_ITEM);
++ menu->addRadioGroupItem(STEREO_GROUP, STEREO_ANAGLYPH_ITEM);
++ menu->addRadioGroupItem(STEREO_GROUP, STEREO_QUADBUFFER_ITEM);
++ menu->addRadioGroupItem(STEREO_GROUP, STEREO_INTERLEAVED_ROWS_ITEM);
++ menu->addRadioGroupItem(STEREO_GROUP, STEREO_INTERLEAVED_COLUMNS_ITEM);
++
++ menu->addMenuItem(STEREO_MENU, STEREO_OFF_ITEM);
++ menu->addMenuItem(STEREO_MENU, STEREO_ANAGLYPH_ITEM);
++ menu->addMenuItem(STEREO_MENU, STEREO_QUADBUFFER_ITEM);
++ menu->addMenuItem(STEREO_MENU, STEREO_INTERLEAVED_ROWS_ITEM);
++ menu->addMenuItem(STEREO_MENU, STEREO_INTERLEAVED_COLUMNS_ITEM);
++
++ menu->newMenu("renderbuffertype", RENDER_BUFFER_TYPE_MENU);
++ menu->setMenuTitle(RENDER_BUFFER_TYPE_MENU, _("Render Buffer Type"));
++
++ menu->newMenuItem("single_buffer", SINGLE_BUFFER_ITEM);
++ menu->setMenuItemTitle(SINGLE_BUFFER_ITEM, _("single"));
++ menu->newMenuItem("double_buffer", DOUBLE_BUFFER_ITEM);
++ menu->setMenuItemTitle(DOUBLE_BUFFER_ITEM, _("double"));
++ menu->newMenuItem("interactive_buffer", INTERACTIVE_BUFFER_ITEM);
++ menu->setMenuItemTitle(INTERACTIVE_BUFFER_ITEM, _("interactive"));
++
++ menu->newRadioGroup(BUFFER_GROUP);
++ menu->addRadioGroupItem(BUFFER_GROUP, SINGLE_BUFFER_ITEM);
++ menu->addRadioGroupItem(BUFFER_GROUP, DOUBLE_BUFFER_ITEM);
++ menu->addRadioGroupItem(BUFFER_GROUP, INTERACTIVE_BUFFER_ITEM);
++
++ menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, SINGLE_BUFFER_ITEM);
++ menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, DOUBLE_BUFFER_ITEM);
++ menu->addMenuItem(RENDER_BUFFER_TYPE_MENU, INTERACTIVE_BUFFER_ITEM);
++
++ menu->addMenu(DRAWSTYLES_MENU, DRAWSTYLES_STILL_MENU);
++ menu->addMenu(DRAWSTYLES_MENU, DRAWSTYLES_ANIMATING_MENU);
++ menu->addMenu(DRAWSTYLES_MENU, TRANSPARENCY_TYPE_MENU);
++ menu->addMenu(DRAWSTYLES_MENU, RENDER_BUFFER_TYPE_MENU);
++
++ int toggle;
++ toggle = menu->newRadioGroup();
++ menu->addRadioGroupItem(toggle, EXAMINING_ITEM);
++ toggle = menu->newRadioGroup();
++ menu->addRadioGroupItem(toggle, DECORATION_ITEM);
++ toggle = menu->newRadioGroup();
++ menu->addRadioGroupItem(toggle, HEADLIGHT_ITEM);
++ toggle = menu->newRadioGroup();
++ menu->addRadioGroupItem(toggle, FULLSCREEN_ITEM);
++
++ menu->addMenuSelectionCallback(SoGuiFullViewerP::menuSelectionCallback,
++ (void *) this);
++
++ // this instance is freed in the native viewer component
++ PUBLIC(this)->prefmenu = menu;
++ return menu;
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::prepareMenu(So at Gui@PopupMenu * menu)
++{
++ //// Misc. //////////////////////////////////////////////////////////
++ menu->setMenuItemMarked(DECORATION_ITEM, PUBLIC(this)->isDecoration());
++ menu->setMenuItemMarked(EXAMINING_ITEM, PUBLIC(this)->isViewing());
++ menu->setMenuItemMarked(HEADLIGHT_ITEM, PUBLIC(this)->isHeadlight());
++ menu->setMenuItemMarked(FULLSCREEN_ITEM, PUBLIC(this)->isFullScreen());
++
++ //// Basic drawstyles. //////////////////////////////////////////////
++ this->setDrawStyleMenuActivation(So at Gui@FullViewer::STILL,
++ PUBLIC(this)->getDrawStyle(So at Gui@FullViewer::STILL));
++ this->setDrawStyleMenuActivation(So at Gui@FullViewer::INTERACTIVE,
++ PUBLIC(this)->getDrawStyle(So at Gui@FullViewer::INTERACTIVE));
++
++ //// Transparency setting. //////////////////////////////////////////
++ switch (PUBLIC(this)->getTransparencyType()) {
++ case SoGLRenderAction::SCREEN_DOOR:
++ menu->setMenuItemMarked(SCREEN_DOOR_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::ADD:
++ menu->setMenuItemMarked(ADD_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::DELAYED_ADD:
++ menu->setMenuItemMarked(DELAYED_ADD_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::SORTED_OBJECT_ADD:
++ menu->setMenuItemMarked(SORTED_OBJECT_ADD_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::BLEND:
++ menu->setMenuItemMarked(BLEND_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::DELAYED_BLEND:
++ menu->setMenuItemMarked(DELAYED_BLEND_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::SORTED_OBJECT_BLEND:
++ menu->setMenuItemMarked(SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM, TRUE);
++ break;
++#ifdef __COIN__ // Coin extensions
++ case SoGLRenderAction::NONE:
++ menu->setMenuItemMarked(NONE_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD:
++ menu->setMenuItemMarked(SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM, TRUE);
++ break;
++ case SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND:
++ menu->setMenuItemMarked(SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM, TRUE);
++ break;
++#endif // __COIN__
++#ifdef HAVE_SORTED_LAYERS_BLEND
++ case SoGLRenderAction::SORTED_LAYERS_BLEND:
++ menu->setMenuItemMarked(SORTED_LAYERS_BLEND_ITEM, TRUE);
++ break;
++#endif // HAVE_SORTED_LAYERS_BLEND
++ default:
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("SoGuiFullViewerP::prepareMenu",
++ "Unknown transparency type");
++#endif // SO at GUI@_DEBUG
++ break;
++ }
++
++ //// Stereo viewing. ////////////////////////////////////////////////
++
++ const So at Gui@Viewer::StereoType type = PUBLIC(this)->getStereoType();
++ switch (type) {
++ case So at Gui@Viewer::STEREO_NONE:
++ menu->setMenuItemMarked(STEREO_OFF_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::STEREO_ANAGLYPH:
++ menu->setMenuItemMarked(STEREO_ANAGLYPH_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::STEREO_QUADBUFFER:
++ menu->setMenuItemMarked(STEREO_QUADBUFFER_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++ menu->setMenuItemMarked(STEREO_INTERLEAVED_ROWS_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++ menu->setMenuItemMarked(STEREO_INTERLEAVED_COLUMNS_ITEM, TRUE);
++ break;
++ default:
++ assert(FALSE); break;
++ }
++
++ //// GL canvas settings. ////////////////////////////////////////////
++ switch (PUBLIC(this)->getBufferingType()) {
++ case So at Gui@Viewer::BUFFER_SINGLE:
++ menu->setMenuItemMarked(SINGLE_BUFFER_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::BUFFER_DOUBLE:
++ menu->setMenuItemMarked(DOUBLE_BUFFER_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::BUFFER_INTERACTIVE:
++ menu->setMenuItemMarked(INTERACTIVE_BUFFER_ITEM, TRUE);
++ break;
++ default:
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("SoGuiFullViewerP::prepareMenu",
++ "Unknown buffer type");
++#endif // SO at GUI@_DEBUG
++ break;
++ }
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::menuSelection(int menuitemid)
++{
++ SbBool ok;
++
++ switch (menuitemid) {
++ case -1:
++ // means no item was selected
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("SoGuiFullViewerP::menuSelection",
++ "-1 not appropriate on callback usage");
++#endif // SO at GUI@_DEBUG
++ break;
++
++ case EXAMINING_ITEM:
++ PUBLIC(this)->setViewing(PUBLIC(this)->isViewing() ? FALSE : TRUE);
++ break;
++ case DECORATION_ITEM:
++ PUBLIC(this)->setDecoration(PUBLIC(this)->isDecoration() ? FALSE : TRUE);
++ break;
++ case HEADLIGHT_ITEM:
++ PUBLIC(this)->setHeadlight(PUBLIC(this)->isHeadlight() ? FALSE : TRUE);
++ break;
++ case FULLSCREEN_ITEM:
++ (void)PUBLIC(this)->setFullScreen(PUBLIC(this)->isFullScreen() ? FALSE : TRUE);
++ break;
++
++ case HOME_ITEM:
++ PUBLIC(this)->resetToHomePosition();
++ break;
++ case SET_HOME_ITEM:
++ PUBLIC(this)->saveHomePosition();
++ break;
++ case VIEW_ALL_ITEM:
++ PUBLIC(this)->viewAll();
++ break;
++ case SEEK_ITEM:
++ ((So at Gui@FullViewerP *)this)->seekbuttonClicked();
++ break;
++
++ case AS_IS_ITEM:
++ case HIDDEN_LINE_ITEM:
++ case WIREFRAME_OVERLAY_ITEM:
++ case NO_TEXTURE_ITEM:
++ case LOW_RESOLUTION_ITEM:
++ case WIREFRAME_ITEM:
++ case POINTS_ITEM:
++ case BOUNDING_BOX_ITEM:
++ this->drawstyleActivated(menuitemid);
++ break;
++
++ case MOVE_SAME_AS_STILL_ITEM:
++ case MOVE_NO_TEXTURE_ITEM:
++ case MOVE_LOW_RES_ITEM:
++ case MOVE_WIREFRAME_ITEM:
++ case MOVE_LOW_RES_WIREFRAME_ITEM:
++ case MOVE_POINTS_ITEM:
++ case MOVE_LOW_RES_POINTS_ITEM:
++ case MOVE_BOUNDING_BOX_ITEM:
++ this->drawstyleActivated(menuitemid);
++ break;
++
++ case SCREEN_DOOR_TRANSPARENCY_ITEM:
++ case ADD_TRANSPARENCY_ITEM:
++ case DELAYED_ADD_TRANSPARENCY_ITEM:
++ case SORTED_OBJECT_ADD_TRANSPARENCY_ITEM:
++ case BLEND_TRANSPARENCY_ITEM:
++ case DELAYED_BLEND_TRANSPARENCY_ITEM:
++ case SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM:
++ case SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM:
++ case SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM:
++ case NONE_TRANSPARENCY_ITEM:
++ case SORTED_LAYERS_BLEND_ITEM: // define test is not needed. This enum is always defined
++ this->drawstyleActivated(menuitemid);
++ PUBLIC(this)->scheduleRedraw();
++ break;
++
++ case SINGLE_BUFFER_ITEM:
++ case DOUBLE_BUFFER_ITEM:
++ case INTERACTIVE_BUFFER_ITEM:
++ this->drawstyleActivated(menuitemid);
++ break;
++
++ case STEREO_OFF_ITEM:
++ ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE);
++ assert(ok);
++ break;
++ case STEREO_ANAGLYPH_ITEM:
++ ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_ANAGLYPH);
++ assert(ok && "anaglyph stereo should always be possible");
++ break;
++ case STEREO_QUADBUFFER_ITEM:
++ ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_QUADBUFFER);
++ if (!ok) { PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE); }
++ break;
++ case STEREO_INTERLEAVED_ROWS_ITEM:
++ ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_INTERLEAVED_ROWS);
++ if (!ok) { PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE); }
++ break;
++ case STEREO_INTERLEAVED_COLUMNS_ITEM:
++ ok = PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS);
++ if (!ok) { PUBLIC(this)->setStereoType(So at Gui@Viewer::STEREO_NONE); }
++ break;
++
++ default:
++ SoDebugError::postInfo("SoGuiFullViewerP::menuSelection",
++ "popup menu handling for item %d is not implemented",
++ menuitemid);
++ break;
++ }
++}
++
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::menuSelectionCallback(int menuitemid,
++ void * userdata)
++{
++ SoGuiFullViewerP * viewer = (SoGuiFullViewerP *) userdata;
++ viewer->menuSelection(menuitemid);
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::setDrawStyleMenuActivation(So at Gui@Viewer::DrawType type,
++ So at Gui@Viewer::DrawStyle value)
++{
++ assert(PUBLIC(this)->prefmenu != NULL);
++
++ switch (type) {
++ case So at Gui@Viewer::STILL:
++ switch (value) {
++ case So at Gui@Viewer::VIEW_AS_IS:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(AS_IS_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_HIDDEN_LINE:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(HIDDEN_LINE_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(WIREFRAME_OVERLAY_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_NO_TEXTURE:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(NO_TEXTURE_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(LOW_RESOLUTION_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++ "Use VIEW_LINE, not VIEW_LOW_RES_LINE for the STILL drawstyle.");
++#endif // debug
++ case So at Gui@Viewer::VIEW_LINE:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(WIREFRAME_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++ "Use VIEW_POINT, not VIEW_LOW_RES_POINT for the STILL drawstyle.");
++#endif // debug
++ case So at Gui@Viewer::VIEW_POINT:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(POINTS_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_BBOX:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(BOUNDING_BOX_ITEM, TRUE);
++ break;
++ default:
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++ "Unsupporter still-drawstyle");
++#endif // debug
++ break;
++ }
++ break;
++
++ case So at Gui@Viewer::INTERACTIVE:
++ switch (value) {
++ case So at Gui@Viewer::VIEW_SAME_AS_STILL:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_SAME_AS_STILL_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_NO_TEXTURE:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_NO_TEXTURE_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_LINE:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_WIREFRAME_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_WIREFRAME_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_POINT:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_POINTS_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_LOW_RES_POINTS_ITEM, TRUE);
++ break;
++ case So at Gui@Viewer::VIEW_BBOX:
++ PUBLIC(this)->prefmenu->setMenuItemMarked(MOVE_BOUNDING_BOX_ITEM, TRUE);
++ break;
++ default:
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++ "Unsupporter interactive drawstyle");
++#endif // debug
++ break;
++ }
++ break;
++
++ default:
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@FullViewer::setDrawStyleMenuActivation",
++ "Unsupporter drawstyle type");
++#endif // debug
++ break;
++ }
++}
++
++// ************************************************************************
++
++void
++SoGuiFullViewerP::drawstyleActivated(int menuitemid)
++{
++ switch (menuitemid) {
++ case SINGLE_BUFFER_ITEM:
++ PUBLIC(this)->setBufferingType(So at Gui@Viewer::BUFFER_SINGLE);
++ return;
++ case DOUBLE_BUFFER_ITEM:
++ PUBLIC(this)->setBufferingType(So at Gui@Viewer::BUFFER_DOUBLE);
++ return;
++ case INTERACTIVE_BUFFER_ITEM:
++ PUBLIC(this)->setBufferingType(So at Gui@Viewer::BUFFER_INTERACTIVE);
++ return;
++ default:
++ break;
++ }
++
++ // FIXME: should perhaps override transparency type to be screendoor
++ // if we detect that the OpenGL canvas has 0 alpha bits available?
++ // 20030626 mortene.
++ switch (menuitemid) {
++ case SCREEN_DOOR_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::SCREEN_DOOR);
++ return;
++ case ADD_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::ADD);
++ return;
++ case DELAYED_ADD_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::DELAYED_ADD);
++ return;
++ case SORTED_OBJECT_ADD_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_ADD);
++ return;
++ case BLEND_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::BLEND);
++ return;
++ case DELAYED_BLEND_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::DELAYED_BLEND);
++ return;
++ case SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_BLEND);
++ return;
++#ifdef __COIN__ // Coin extensions
++ case NONE_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::NONE);
++ return;
++ case SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_ADD);
++ return;
++ case SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_OBJECT_SORTED_TRIANGLE_BLEND);
++ return;
++#endif // __COIN__
++#ifdef HAVE_SORTED_LAYERS_BLEND
++ case SORTED_LAYERS_BLEND_ITEM:
++ PUBLIC(this)->setTransparencyType(SoGLRenderAction::SORTED_LAYERS_BLEND);
++ return;
++#endif // HAVE_SORTED_LAYERS_BLEND
++ default:
++ // some other menu item, just continue
++ break;
++ }
++
++ So at Gui@Viewer::DrawStyle val = So at Gui@Viewer::VIEW_AS_IS;
++ switch (menuitemid) {
++ case AS_IS_ITEM:
++ val = So at Gui@Viewer::VIEW_AS_IS;
++ break;
++ case HIDDEN_LINE_ITEM:
++ val = So at Gui@Viewer::VIEW_HIDDEN_LINE;
++ break;
++ case WIREFRAME_OVERLAY_ITEM:
++ val = So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY;
++ break;
++ case NO_TEXTURE_ITEM:
++ val = So at Gui@Viewer::VIEW_NO_TEXTURE;
++ break;
++ case LOW_RESOLUTION_ITEM:
++ val = So at Gui@Viewer::VIEW_LOW_COMPLEXITY;
++ break;
++ case WIREFRAME_ITEM:
++ val = So at Gui@Viewer::VIEW_LINE;
++ break;
++ case POINTS_ITEM:
++ val = So at Gui@Viewer::VIEW_POINT;
++ break;
++ case BOUNDING_BOX_ITEM:
++ val = So at Gui@Viewer::VIEW_BBOX;
++ break;
++
++ case MOVE_SAME_AS_STILL_ITEM:
++ val = So at Gui@Viewer::VIEW_SAME_AS_STILL;
++ break;
++ case MOVE_NO_TEXTURE_ITEM:
++ val = So at Gui@Viewer::VIEW_NO_TEXTURE;
++ break;
++ case MOVE_LOW_RES_ITEM:
++ val = So at Gui@Viewer::VIEW_LOW_COMPLEXITY;
++ break;
++ case MOVE_WIREFRAME_ITEM:
++ val = So at Gui@Viewer::VIEW_LINE;
++ break;
++ case MOVE_LOW_RES_WIREFRAME_ITEM:
++ val = So at Gui@Viewer::VIEW_LOW_RES_LINE;
++ break;
++ case MOVE_POINTS_ITEM:
++ val = So at Gui@Viewer::VIEW_POINT;
++ break;
++ case MOVE_LOW_RES_POINTS_ITEM:
++ val = So at Gui@Viewer::VIEW_LOW_RES_POINT;
++ break;
++ case MOVE_BOUNDING_BOX_ITEM:
++ val = So at Gui@Viewer::VIEW_BBOX;
++ break;
++
++ default:
++ assert(0);
++ break;
++ }
++
++ So at Gui@Viewer::DrawType type = So at Gui@Viewer::STILL;
++
++ switch (menuitemid) {
++ case AS_IS_ITEM:
++ case HIDDEN_LINE_ITEM:
++ case WIREFRAME_OVERLAY_ITEM:
++ case NO_TEXTURE_ITEM:
++ case LOW_RESOLUTION_ITEM:
++ case WIREFRAME_ITEM:
++ case POINTS_ITEM:
++ case BOUNDING_BOX_ITEM:
++ type = So at Gui@Viewer::STILL;
++ break;
++
++ case MOVE_SAME_AS_STILL_ITEM:
++ case MOVE_NO_TEXTURE_ITEM:
++ case MOVE_LOW_RES_ITEM:
++ case MOVE_WIREFRAME_ITEM:
++ case MOVE_LOW_RES_WIREFRAME_ITEM:
++ case MOVE_POINTS_ITEM:
++ case MOVE_LOW_RES_POINTS_ITEM:
++ case MOVE_BOUNDING_BOX_ITEM:
++ type = So at Gui@Viewer::INTERACTIVE;
++ break;
++
++ default:
++ assert(0);
++ break;
++ }
++
++ PUBLIC(this)->setDrawStyle(type, val);
++}
++
++// ************************************************************************
++
++// Move camera parallel with the plane orthogonal to the camera
++// direction vector.
++//
++// Used from both SoGuiPlaneViewer and SoGuiExaminerViewer.
++// Implemented in the SoGuiFullViewer private class to collect common
++// code.
++void
++SoGuiFullViewerP::pan(SoCamera * cam,
++ float aspectratio, const SbPlane & panningplane,
++ const SbVec2f & currpos, const SbVec2f & prevpos)
++{
++ if (cam == NULL) return; // can happen for empty scenegraph
++ if (currpos == prevpos) return; // useless invocation
++
++#if SO at GUI@_DEBUG && 0
++ SoDebugError::postInfo("SoGuiFullViewerP::pan",
++ "was(%.3g, %.3g) -> now(%.3g, %.3g)",
++ prevpos[0], prevpos[1], currpos[0], currpos[1]);
++#endif // SO at GUI@_DEBUG
++
++ // Find projection points for the last and current mouse coordinates.
++ SbViewVolume vv = cam->getViewVolume(aspectratio);
++ SbLine line;
++ vv.projectPointToLine(currpos, line);
++ SbVec3f current_planept;
++ panningplane.intersect(line, current_planept);
++ vv.projectPointToLine(prevpos, line);
++ SbVec3f old_planept;
++ panningplane.intersect(line, old_planept);
++
++ // Reposition camera according to the vector difference between the
++ // projected points.
++ cam->position = cam->position.getValue() - (current_planept - old_planept);
++}
++
++// *************************************************************************
++
++// Dependent on the camera type this will either shrink or expand the
++// height of the viewport (orthogonal camera) or move the camera
++// closer or further away from the focal point in the scene.
++//
++// Used from both SoGuiPlaneViewer and SoGuiExaminerViewer.
++// Implemented in the SoGuiFullViewer private class to collect common
++// code.
++void
++SoGuiFullViewerP::zoom(SoCamera * cam, const float diffvalue)
++{
++ if (cam == NULL) return; // can happen for empty scenegraph
++ SoType t = cam->getTypeId();
++ SbName tname = t.getName();
++
++ // This will be in the range of <0, ->>.
++ float multiplicator = float(exp(diffvalue));
++
++ if (t.isDerivedFrom(SoOrthographicCamera::getClassTypeId())) {
++
++ // Since there's no perspective, "zooming" in the original sense
++ // of the word won't have any visible effect. So we just increase
++ // or decrease the field-of-view values of the camera instead, to
++ // "shrink" the projection size of the model / scene.
++ SoOrthographicCamera * oc = (SoOrthographicCamera *)cam;
++ oc->height = oc->height.getValue() * multiplicator;
++
++ }
++ else {
++ // FrustumCamera can be found in the SmallChange CVS module (it's
++ // a camera that lets you specify (for instance) an off-center
++ // frustum (similar to glFrustum())
++ if (!t.isDerivedFrom(SoPerspectiveCamera::getClassTypeId()) &&
++ tname != "FrustumCamera") {
++ static SbBool first = TRUE;
++ if (first) {
++ SoDebugError::postWarning("SoGuiFullViewerP::zoom",
++ "Unknown camera type, "
++ "will zoom by moving position, but this might not be correct.");
++ first = FALSE;
++ }
++ }
++
++ const float oldfocaldist = cam->focalDistance.getValue();
++ const float newfocaldist = oldfocaldist * multiplicator;
++
++ SbVec3f direction;
++ cam->orientation.getValue().multVec(SbVec3f(0, 0, -1), direction);
++
++ const SbVec3f oldpos = cam->position.getValue();
++ const SbVec3f newpos = oldpos + (newfocaldist - oldfocaldist) * -direction;
++
++ // This catches a rather common user interface "buglet": if the
++ // user zooms the camera out to a distance from origo larger than
++ // what we still can safely do floating point calculations on
++ // (i.e. without getting NaN or Inf values), the faulty floating
++ // point values will propagate until we start to get debug error
++ // messages and eventually an assert failure from core Coin code.
++ //
++ // With the below bounds check, this problem is avoided.
++ //
++ // (But note that we depend on the input argument ''diffvalue'' to
++ // be small enough that zooming happens gradually. Ideally, we
++ // should also check distorigo with isinf() and isnan() (or
++ // inversely; isinfite()), but those only became standardized with
++ // C99.)
++ const float distorigo = newpos.length();
++ // sqrt(FLT_MAX) == ~ 1e+19, which should be both safe for further
++ // calculations and ok for the end-user and app-programmer.
++ if (distorigo > float(sqrt(FLT_MAX))) {
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postWarning("SoGuiFullViewerP::zoom",
++ "zoomed too far (distance to origo==%f (%e))",
++ distorigo, distorigo);
++#endif // debug
++ }
++ else {
++ cam->position = newpos;
++ cam->focalDistance = newfocaldist;
++ }
++ }
++}
++
++// ************************************************************************
++
++#endif // DOXYGEN_SKIP_THIS
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFullViewer.h.in
+@@ -0,0 +1,177 @@
++#ifndef SO at GUI@_FULLVIEWER_H
++#define SO at GUI@_FULLVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++
++class So at Gui@PopupMenu;
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@FullViewer : public So at Gui@Viewer {
++ SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@FullViewer, So at Gui@Viewer);
++
++public:
++ enum BuildFlag {
++ BUILD_NONE = 0x00,
++ BUILD_DECORATION = 0x01,
++ BUILD_POPUP = 0x02,
++ BUILD_ALL = (BUILD_DECORATION | BUILD_POPUP)
++ };
++
++ void setDecoration(const SbBool on);
++ SbBool isDecoration(void) const;
++
++ void setPopupMenuEnabled(const SbBool on);
++ SbBool isPopupMenuEnabled(void) const;
++
++ @WIDGET@ getAppPushButtonParent(void) const;
++ void addAppPushButton(@WIDGET@ newButton);
++ void insertAppPushButton(@WIDGET@ newButton, int index);
++ void removeAppPushButton(@WIDGET@ oldButton);
++ int findAppPushButton(@WIDGET@ oldButton) const;
++ int lengthAppPushButton(void) const;
++
++ @WIDGET@ getRenderAreaWidget(void) const;
++
++ virtual void setViewing(SbBool on);
++
++ virtual void setComponentCursor(const So at Gui@Cursor & cursor);
++
++protected:
++ So at Gui@FullViewer(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ BuildFlag flag,
++ Type type,
++ SbBool build);
++ ~So at Gui@FullViewer();
++
++ virtual void sizeChanged(const SbVec2s & size);
++
++ @WIDGET@ buildWidget(@WIDGET@ parent);
++
++ virtual void buildDecoration(@WIDGET@ parent);
++ virtual @WIDGET@ buildLeftTrim(@WIDGET@ parent);
++ virtual @WIDGET@ buildBottomTrim(@WIDGET@ parent);
++ virtual @WIDGET@ buildRightTrim(@WIDGET@ parent);
++ @WIDGET@ buildAppButtons(@WIDGET@ parent);
++ @WIDGET@ buildViewerButtons(@WIDGET@ parent);
++ virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++
++ virtual void buildPopupMenu(void);
++ virtual void setPopupMenuString(const char * title);
++ virtual void openPopupMenu(const SbVec2s position);
++
++ virtual void leftWheelStart(void);
++ virtual void leftWheelMotion(float);
++ virtual void leftWheelFinish(void);
++ float getLeftWheelValue(void) const;
++ void setLeftWheelValue(const float value);
++
++ virtual void bottomWheelStart(void);
++ virtual void bottomWheelMotion(float);
++ virtual void bottomWheelFinish(void);
++ float getBottomWheelValue(void) const;
++ void setBottomWheelValue(const float value);
++
++ virtual void rightWheelStart(void);
++ virtual void rightWheelMotion(float);
++ virtual void rightWheelFinish(void);
++ float getRightWheelValue(void) const;
++ void setRightWheelValue(const float value);
++
++ void setLeftWheelString(const char * const name);
++ @WIDGET@ getLeftWheelLabelWidget(void) const;
++ void setBottomWheelString(const char * const name);
++ @WIDGET@ getBottomWheelLabelWidget(void) const;
++ void setRightWheelString(const char * const name);
++ const char * getRightWheelString() const;
++ @WIDGET@ getRightWheelLabelWidget(void) const;
++
++ virtual SbBool processSoEvent(const SoEvent * const event);
++
++protected:
++ @WIDGET@ leftWheel;
++ @WIDGET@ rightWheel;
++ @WIDGET@ bottomWheel;
++
++ @WIDGET@ leftDecoration;
++ @WIDGET@ rightDecoration;
++ @WIDGET@ bottomDecoration;
++
++ @WIDGET@ leftWheelLabel;
++ char * leftWheelStr;
++ float leftWheelVal;
++
++ @WIDGET@ rightWheelLabel;
++ char * rightWheelStr;
++ float rightWheelVal;
++
++ @WIDGET@ bottomWheelLabel;
++ char * bottomWheelStr;
++ float bottomWheelVal;
++
++ So at Gui@PopupMenu * prefmenu;
++
++private:
++ // Private class for implementation hiding. The idiom we're using is
++ // a variant of what is known as the "Cheshire Cat", and is also
++ // described as the "Bridge" pattern in �Design Patterns� by Gamma
++ // et al (aka The Gang Of Four).
++ class So at Gui@FullViewerP * pimpl;
++
++ friend class SoGuiFullViewerP;
++ friend class So at Gui@FullViewerP;
++
++
++
++// FIXME: get rid of non-templatized code. 20020108 mortene.
++
++#ifdef __COIN_SOXT__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++protected:
++ Widget buildFunctionsSubmenu(Widget popup);
++ Widget buildDrawStyleSubmenu(Widget popup);
++
++ char * popupTitle;
++ SbBool popupEnabled;
++ SbPList * viewerButtonWidgets;
++#endif // __COIN_SOXT__
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_FULLVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiFullViewerP.h.in
+@@ -0,0 +1,154 @@
++#ifndef SOGUIFULLVIEWERP_H
++#define SOGUIFULLVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbString.h>
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++
++class So at Gui@FullViewer;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiFullViewer class.
++
++class SoGuiFullViewerP
++{
++public:
++ ~SoGuiFullViewerP();
++
++ enum So at Gui@FullViewerPopupMenuItem {
++ // FIXME: there's code in (some of) the popupmenu widgets which
++ // assumes the root id is equal to 0. Yup, lousy design. :-/
++ // Anyway, don't change it until those cases are fixed.
++ // 20010810 mortene.
++ ROOT_MENU = 0,
++ ROOT_MENU_TITLE,
++
++ FUNCTIONS_MENU,
++ HOME_ITEM,
++ SET_HOME_ITEM,
++ VIEW_ALL_ITEM,
++ SEEK_ITEM,
++
++ DRAWSTYLES_MENU,
++ DRAWSTYLES_STILL_MENU,
++ AS_IS_ITEM,
++ HIDDEN_LINE_ITEM,
++ WIREFRAME_OVERLAY_ITEM,
++ NO_TEXTURE_ITEM,
++ LOW_RESOLUTION_ITEM,
++ WIREFRAME_ITEM,
++ POINTS_ITEM,
++ BOUNDING_BOX_ITEM,
++
++ DRAWSTYLES_ANIMATING_MENU,
++ MOVE_SAME_AS_STILL_ITEM,
++ MOVE_NO_TEXTURE_ITEM,
++ MOVE_LOW_RES_ITEM,
++ MOVE_WIREFRAME_ITEM,
++ MOVE_LOW_RES_WIREFRAME_ITEM,
++ MOVE_POINTS_ITEM,
++ MOVE_LOW_RES_POINTS_ITEM,
++ MOVE_BOUNDING_BOX_ITEM,
++
++ TRANSPARENCY_TYPE_MENU,
++ SCREEN_DOOR_TRANSPARENCY_ITEM,
++ ADD_TRANSPARENCY_ITEM,
++ DELAYED_ADD_TRANSPARENCY_ITEM,
++ SORTED_OBJECT_ADD_TRANSPARENCY_ITEM,
++ BLEND_TRANSPARENCY_ITEM,
++ DELAYED_BLEND_TRANSPARENCY_ITEM,
++ SORTED_OBJECT_BLEND_TRANSPARENCY_ITEM,
++ // These are Coin extensions.
++ SORTED_OBJECT_SORTED_TRIANGLE_ADD_TRANSPARENCY_ITEM,
++ SORTED_OBJECT_SORTED_TRIANGLE_BLEND_TRANSPARENCY_ITEM,
++ SORTED_LAYERS_BLEND_ITEM,
++ NONE_TRANSPARENCY_ITEM,
++
++ RENDER_BUFFER_TYPE_MENU,
++ SINGLE_BUFFER_ITEM,
++ DOUBLE_BUFFER_ITEM,
++ INTERACTIVE_BUFFER_ITEM,
++
++ EXAMINING_ITEM,
++ DECORATION_ITEM,
++ HEADLIGHT_ITEM,
++ FULLSCREEN_ITEM,
++
++ STEREO_MENU,
++ STEREO_OFF_ITEM,
++ STEREO_ANAGLYPH_ITEM,
++ STEREO_QUADBUFFER_ITEM,
++ STEREO_INTERLEAVED_ROWS_ITEM,
++ STEREO_INTERLEAVED_COLUMNS_ITEM
++ };
++
++ enum So at Gui@ViewerPopupMenuRadioGroup {
++ STILL_GROUP = 1,
++ MOVE_GROUP,
++ TRANSPARENCY_GROUP,
++ BUFFER_GROUP,
++ STEREO_GROUP
++ };
++
++ class So at Gui@PopupMenu * setupStandardPopupMenu(void);
++ void prepareMenu(class So at Gui@PopupMenu * menu);
++ void menuSelection(int menuitemid);
++ static void menuSelectionCallback(int menuitemid, void * userdata);
++ SbString popupmenutitle;
++
++ void setDrawStyleMenuActivation(So at Gui@Viewer::DrawType type,
++ So at Gui@Viewer::DrawStyle value);
++ void drawstyleActivated(int menuitemid);
++
++ static void pan(SoCamera * cam,
++ float aspectratio, const SbPlane & panplane,
++ const SbVec2f & currpos, const SbVec2f & prevpos);
++ static void zoom(SoCamera * cam, const float diffvalue);
++
++protected:
++ SoGuiFullViewerP(So at Gui@FullViewer * publ);
++ So at Gui@FullViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIFULLVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiPlaneViewer.cpp.in
+@@ -0,0 +1,990 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*PlaneViewer sourcecode.
++
++/*!
++ \class So at Gui@PlaneViewer Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h
++ \brief The So at Gui@PlaneViewer class is for examining 3D models by moving the camera in orthogonal planes.
++ \ingroup components viewers
++
++ The So at Gui@PlaneViewer is a viewer that is useful for "CAD-style"
++ applications, where you want the end-user to examine your model with
++ the viewpoint set from one of the three principal axes.
++
++ <center>
++ <img src="http://doc.coin3d.org/images/SoLibs/viewers/planeviewer.png">
++ </center>
++
++
++ Controls:
++ <ul>
++
++ <li>hold down left mousebutton and move mouse pointer to dolly (or
++ hold both left and middle mousebuttons)</li>
++
++ <li>hold middle mousebutton to pan (or a CTRL-key plus left
++ mousebutton, or a SHIFT-key plus left mousebutton)</li>
++
++ <li>hold down CTRL + middle mousebutton to rotate (or CTRL + SHIFT +
++ the left mousebutton)</li>
++
++ <li>click 's', then pick with the left mousebutton to seek</li>
++
++ <li>right mousebutton open the popup menu</li>
++
++ <li>click 'ESC' key to switch to and from 'view' mode and
++ 'scenegraph interaction' mode (see setViewing() documentation)</li>
++
++ <!--
++ FIXME: This functionality has been disabled. See FIXME comment
++ 20050202 larsa below.
++
++ <li>hold down the 'ALT' key to temporary toggle from
++ camera-interaction mode to scenegraph-interaction mode</li>
++
++ //-->
++
++ </ul>
++
++ Hitting any of the X, Y or Z buttons in the panel on the right side
++ of the render canvas will "flip" the current camera direction around
++ it's focal point to point along the selected axis (towards negative
++ infinity).
++
++ The So at Gui@PlaneViewer also provides a user decoration's button for
++ toggling between orthographic or perspective camera view volumes and
++ projection methods. This is the bottom-most click button on the
++ right decoration border.
++
++ It also inherits the decoration buttons from the So at Gui@FullViewer:
++ the arrow for switching to "scenegraph interaction" mode, the hand
++ for setting back to "camera interaction" mode, the house for "reset
++ camera to home position", the blueprint house for "set new camera
++ home position", the eye for "zoom camera out to view full scene" and
++ the flashlight for setting "click to seek" mode.
++
++ Note that a common faulty assumption about all the viewer-classes is
++ that user interaction (in the "examine"-mode, not the
++ scenegraph-interaction mode) influences the model or 3D-scene in the
++ view. This is not correct, as it is always the viewer's \e camera
++ that is translated and rotated.
++
++ The initial position of the camera is placed such that all of the
++ scenegraph's geometry fits within it's view.
++*/
++
++// *************************************************************************
++
++#include <Inventor/@Gui@/viewers/So at Gui@PlaneViewer.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <math.h>
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/So at Gui@Cursor.h>
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoCoordinate3.h>
++#include <Inventor/nodes/SoDrawStyle.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/events/SoLocation2Event.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++
++#include <so at gui@defs.h>
++
++#include <Inventor/@Gui@/viewers/SoGuiFullViewerP.h> // for pan() and zoom()
++#include <Inventor/@Gui@/viewers/SoGuiViewerP.h> // for adjusting final camera orientation before seek
++#include <Inventor/@Gui@/viewers/So at Gui@PlaneViewerP.h>
++
++// *************************************************************************
++
++// To access SoGuiPlaneViewerP "private implementation" class.
++
++#define PRIVATE(ptr) (ptr->pimpl)
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_SOURCE(So at Gui@PlaneViewer);
++
++// ************************************************************************
++
++/*!
++ \fn So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent, const char * const name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type)
++
++ The public constructor, to be used by application programmers who
++ want to instantiate the plain, standard So at Gui@PlaneViewer.
++*/
++So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type)
++ : inherited(parent, name, embed, flag, type, FALSE)
++{
++ PRIVATE(this) = new So at Gui@PlaneViewerP(this);
++ PRIVATE(this)->constructor(TRUE);
++}
++
++/*!
++ \fn So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent, const char * const name, SbBool embed, So at Gui@FullViewer::BuildFlag flag, So at Gui@Viewer::Type type, SbBool build)
++
++ A protected constructor, to be used by application programmers who
++ want to extend the So at Gui@PlaneViewer.
++*/
++So at Gui@PlaneViewer::So at Gui@PlaneViewer(@WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build)
++ : inherited(parent, name, embed, flag, type, FALSE)
++{
++ PRIVATE(this) = new So at Gui@PlaneViewerP(this);
++ PRIVATE(this)->constructor(build);
++}
++
++/*!
++ \fn So at Gui@PlaneViewer::~So at Gui@PlaneViewer()
++
++ The destructor. Cleans up all internal resources used by the
++ So at Gui@PlaneViewer instance.
++*/
++So at Gui@PlaneViewer::~So at Gui@PlaneViewer()
++{
++ delete PRIVATE(this);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@PlaneViewer::processSoEvent(const SoEvent * const ev)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@PlaneViewer::processSoEvent",
++ "[invoked], event '%s' "
++ "(isViewing()==%d, isSeekMode()==%d, mode==%d)",
++ ev->getTypeId().getName().getString(),
++ this->isViewing(), this->isSeekMode(),
++ PRIVATE(this)->mode);
++#endif // debug
++
++ // We're in "interact" mode (ie *not* the camera modification mode),
++ // so don't handle the event here. It should either be forwarded to
++ // the scenegraph, or caught by So at Gui@Viewer::processSoEvent() if
++ // it's an ESC and ALT press (to switch modes).
++ if (!this->isViewing()) { return inherited::processSoEvent(ev); }
++
++ // Events when in "ready-to-seek" mode are ignored, except those
++ // which influence the seek mode itself -- these are handled further
++ // up the inheritance hierarchy.
++ if (this->isSeekMode()) { return inherited::processSoEvent(ev); }
++
++
++ SbBool processed = FALSE;
++ const SoGuiPlaneViewerP::PlaneViewerMode currentmode = PRIVATE(this)->mode;
++ SoGuiPlaneViewerP::PlaneViewerMode newmode = currentmode;
++
++ const SoType type(ev->getTypeId());
++
++ const SbVec2s size(this->getGLSize());
++ const SbVec2s pos(ev->getPosition());
++ const SbVec2f posn((float)pos[0] / (float) So at Gui@Max(size[0], (short int)1),
++ (float)pos[1] / (float) So at Gui@Max(size[1], (short int)1));
++
++ PRIVATE(this)->ctrldown = ev->wasCtrlDown();
++ PRIVATE(this)->shiftdown = ev->wasShiftDown();
++
++ if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++ processed = TRUE;
++ const SoMouseButtonEvent * event = (const SoMouseButtonEvent *) ev;
++ const SbBool press = (event->getState() == SoButtonEvent::DOWN) ? TRUE : FALSE;
++
++ if (press) {
++ // Called twice to initialize both "now" (current) and "then"
++ // (previous) pointer location.
++ PRIVATE(this)->setPointerLocation(pos);
++ PRIVATE(this)->setPointerLocation(pos);
++ }
++
++ switch (event->getButton()) {
++ case SoMouseButtonEvent::BUTTON1:
++ PRIVATE(this)->button1down = press;
++
++ if (press && (currentmode == SoGuiPlaneViewerP::SEEK_WAIT_MODE)) {
++ newmode = SoGuiPlaneViewerP::SEEK_MODE;
++ this->seekToPoint(pos); // implicitly calls interactiveCountInc()
++ }
++ break;
++
++ case SoMouseButtonEvent::BUTTON2:
++ processed = FALSE; // pass on to superclass, so popup menu is shown
++ break;
++
++ case SoMouseButtonEvent::BUTTON3:
++ PRIVATE(this)->button3down = press;
++ break;
++
++#ifdef HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++ case SoMouseButtonEvent::BUTTON4:
++ if (press) SoGuiFullViewerP::zoom(this->getCamera(), 0.1f);
++ break;
++
++ case SoMouseButtonEvent::BUTTON5:
++ if (press) SoGuiFullViewerP::zoom(this->getCamera(), -0.1f);
++ break;
++#endif // HAVE_SOMOUSEBUTTONEVENT_BUTTON5
++
++ default:
++ break;
++ } // switch (event->getButton())
++ } // SoMouseButtonEvent::getClassTypeId()
++
++ if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
++ const SoKeyboardEvent * event = (const SoKeyboardEvent *) ev;
++ const SbBool press = (event->getState() == SoButtonEvent::DOWN) ? TRUE : FALSE;
++
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@PlaneViewer::processSoEvent",
++ "keyboard %s: \"%c\"",
++ press ? "press" : "release",
++ event->getPrintableCharacter());
++#endif // debug
++
++ switch (event->getKey()) {
++ case SoKeyboardEvent::LEFT_CONTROL:
++ case SoKeyboardEvent::RIGHT_CONTROL:
++ processed = TRUE;
++ PRIVATE(this)->ctrldown = press;
++ break;
++ case SoKeyboardEvent::LEFT_SHIFT:
++ case SoKeyboardEvent::RIGHT_SHIFT:
++ processed = TRUE;
++ PRIVATE(this)->shiftdown = press;
++ break;
++
++ default:
++ break;
++ }
++
++ } // SoKeyboardEvent::getClassTypeId()
++
++
++ if (type.isDerivedFrom(SoLocation2Event::getClassTypeId())) {
++ processed = TRUE;
++ const SoLocation2Event * event = (const SoLocation2Event *) ev;
++ PRIVATE(this)->setPointerLocation(pos);
++ const SbVec2f prevn((float) PRIVATE(this)->pointer.then[0] / (float) So at Gui@Max(size[0], (short int)1),
++ (float) PRIVATE(this)->pointer.then[1] / (float) So at Gui@Max(size[1], (short int)1));
++
++ do {
++ if (currentmode == SoGuiPlaneViewerP::ROTZ_MODE) {
++ PRIVATE(this)->rotateZ(PRIVATE(this)->getPointerOrigoMotionAngle());
++ break;
++ }
++
++ if (currentmode == SoGuiPlaneViewerP::TRANSLATE_MODE) {
++ if (posn != prevn) {
++ SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++ PRIVATE(this)->panningplane, posn, prevn);
++ }
++ break;
++ }
++
++ if (currentmode == SoGuiPlaneViewerP::DOLLY_MODE) {
++ if (posn[1] != prevn[1]) {
++ float value = this->getRightWheelValue() + (prevn[1] - posn[1]) * 10.0f;
++ this->rightWheelMotion(value);
++ this->setRightWheelValue(value);
++ }
++ break;
++ }
++
++ } while (FALSE);
++ } // SoLocation2Event::getClassTypeId()
++
++ enum {
++ BUTTON1DOWN = 1 << 0,
++ BUTTON3DOWN = 1 << 1,
++ CTRLDOWN = 1 << 2,
++ SHIFTDOWN = 1 << 3
++ };
++ unsigned int combo =
++ (PRIVATE(this)->button1down ? BUTTON1DOWN : 0) |
++ (PRIVATE(this)->button3down ? BUTTON3DOWN : 0) |
++ (PRIVATE(this)->ctrldown ? CTRLDOWN : 0) |
++ (PRIVATE(this)->shiftdown ? SHIFTDOWN : 0);
++
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@PlaneViewer::processSoEvent",
++ "button1==%d, button3==%d, "
++ "ctrl==%d, shift==%d",
++ PRIVATE(this)->button1down, PRIVATE(this)->button3down,
++ PRIVATE(this)->ctrldown,
++ PRIVATE(this)->shiftdown);
++#endif // debug
++
++
++ switch (combo) {
++ case BUTTON1DOWN:
++ case BUTTON1DOWN|BUTTON3DOWN:
++ newmode = SoGuiPlaneViewerP::DOLLY_MODE;
++ break;
++ case BUTTON3DOWN:
++ case CTRLDOWN|BUTTON1DOWN:
++ case SHIFTDOWN|BUTTON1DOWN:
++ newmode = SoGuiPlaneViewerP::TRANSLATE_MODE;
++ break;
++ case CTRLDOWN|BUTTON3DOWN:
++ case CTRLDOWN|SHIFTDOWN|BUTTON1DOWN:
++ newmode = SoGuiPlaneViewerP::ROTZ_MODE;
++ break;
++ case CTRLDOWN:
++ case CTRLDOWN|SHIFTDOWN:
++ newmode = SoGuiPlaneViewerP::ROTZ_WAIT_MODE;
++ break;
++ default:
++ if ((currentmode != SoGuiPlaneViewerP::SEEK_WAIT_MODE) &&
++ (currentmode != SoGuiPlaneViewerP::SEEK_MODE)) {
++ newmode = SoGuiPlaneViewerP::IDLE_MODE;
++ }
++ break;
++ }
++
++ if (newmode != currentmode) {
++ if (newmode == SoGuiPlaneViewerP::ROTZ_MODE) {
++ PRIVATE(this)->setCanvasSize(size);
++ PRIVATE(this)->setPointerLocation(pos);
++ PRIVATE(this)->setPointerLocation(pos);
++ }
++
++ PRIVATE(this)->changeMode(newmode);
++ }
++
++ // If not handled in this class, pass on upwards in the inheritance
++ // hierarchy.
++ return processed || inherited::processSoEvent(ev);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::actualRedraw(void)
++{
++ if (PRIVATE(this)->mode == SoGuiPlaneViewerP::ROTZ_MODE) {
++ PRIVATE(this)->updateAnchorScenegraph();
++ }
++
++ inherited::actualRedraw();
++}
++
++// ************************************************************************
++
++// documented in superclass
++void
++So at Gui@PlaneViewer::setSeekMode(SbBool on)
++{
++#if SO at GUI@_DEBUG
++ if (!!on == !!this->isSeekMode()) {
++ SoDebugError::postWarning("So at Gui@PlaneViewer::setSeekMode",
++ "seek mode already %sset", on ? "" : "un");
++ return;
++ }
++#endif // SO at GUI@_DEBUG
++
++ inherited::setSeekMode(on);
++
++ PRIVATE(this)->changeMode(on ?
++ SoGuiPlaneViewerP::SEEK_WAIT_MODE :
++ (this->isViewing() ?
++ SoGuiPlaneViewerP::IDLE_MODE :
++ SoGuiPlaneViewerP::SCENEGRAPH_INTERACT_MODE));
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::setCursorEnabled(SbBool enable)
++{
++ inherited::setCursorEnabled(enable);
++ PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->mode);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::setViewing(SbBool enable)
++{
++ if (!!enable == !!this->isViewing()) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("SoQtPlaneViewer::setViewing",
++ "unnecessary invocation");
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++
++ inherited::setViewing(enable);
++
++ PRIVATE(this)->changeMode(this->isViewing() ?
++ SoGuiPlaneViewerP::IDLE_MODE :
++ SoGuiPlaneViewerP::SCENEGRAPH_INTERACT_MODE);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++const char *
++So at Gui@PlaneViewer::getDefaultWidgetName(void) const
++{
++ return "So at Gui@PlaneViewer";
++}
++
++// Documented in superclass.
++const char *
++So at Gui@PlaneViewer::getDefaultTitle(void) const
++{
++ return "Plane Viewer";
++}
++
++// Documented in superclass.
++const char *
++So at Gui@PlaneViewer::getDefaultIconTitle(void) const
++{
++ return "Plane Viewer";
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::bottomWheelStart(void)
++{
++ PRIVATE(this)->changeMode(SoGuiPlaneViewerP::TRANSLATE_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::bottomWheelMotion(float value)
++{
++ // This method set up the bottom wheel to control camera translation
++ // in the horizontal direction.
++
++ if (value != this->getBottomWheelValue()) {
++ SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++ PRIVATE(this)->panningplane,
++ SbVec2f(value, 0),
++ SbVec2f(this->getBottomWheelValue(), 0));
++ }
++ inherited::bottomWheelMotion(value);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::bottomWheelFinish(void)
++{
++ PRIVATE(this)->changeMode(SoGuiPlaneViewerP::IDLE_MODE);
++}
++
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::leftWheelStart(void)
++{
++ PRIVATE(this)->changeMode(SoGuiPlaneViewerP::TRANSLATE_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::leftWheelMotion(float value)
++{
++ // This method set up the left wheel to control camera translation
++ // in the vertical direction.
++
++ if (value != this->getLeftWheelValue()) {
++ SoGuiFullViewerP::pan(this->getCamera(), this->getGLAspectRatio(),
++ PRIVATE(this)->panningplane,
++ SbVec2f(0, this->getLeftWheelValue()),
++ SbVec2f(0, value));
++ }
++
++ inherited::leftWheelMotion(value);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::leftWheelFinish(void)
++{
++ PRIVATE(this)->changeMode(SoGuiPlaneViewerP::IDLE_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::rightWheelStart(void)
++{
++ PRIVATE(this)->changeMode(SoGuiPlaneViewerP::DOLLY_MODE);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::rightWheelMotion(float value)
++{
++ // This method set up the right wheel to control camera movement in
++ // the inwards direction.
++
++ SoGuiFullViewerP::zoom(this->getCamera(), this->getRightWheelValue() - value);
++ inherited::rightWheelMotion(value);
++}
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::rightWheelFinish(void)
++{
++ PRIVATE(this)->changeMode(SoGuiPlaneViewerP::IDLE_MODE);
++}
++
++// ************************************************************************
++
++// Documented in superclass.
++void
++So at Gui@PlaneViewer::afterRealizeHook(void)
++{
++ PRIVATE(this)->setCursorRepresentation(PRIVATE(this)->mode);
++ inherited::afterRealizeHook();
++}
++
++// ************************************************************************
++
++#ifndef DOXYGEN_SKIP_THIS
++
++// This method locates a named node in the superimposed scene.
++static SoNode *
++get_scenegraph_node(SoSearchAction * search, SoNode * root, const char * name)
++{
++ search->reset();
++ search->setName(SbName(name));
++ search->setInterest(SoSearchAction::FIRST);
++ search->setSearchingAll(TRUE);
++ search->apply(root);
++ assert(search->getPath());
++ return search->getPath()->getTail();
++}
++
++// *************************************************************************
++
++// Remaining code is for the SoGuiPlaneViewerP "private
++// implementation" class.
++
++#define PUBLIC(ptr) (ptr->pub)
++
++SoGuiPlaneViewerP::SoGuiPlaneViewerP(So at Gui@PlaneViewer * publ)
++{
++ PUBLIC(this) = publ;
++}
++
++SoGuiPlaneViewerP::~SoGuiPlaneViewerP()
++{
++ if (this->superimposition != NULL) {
++ PUBLIC(this)->removeSuperimposition(this->superimposition);
++ this->superimposition->unref();
++ }
++}
++
++void
++SoGuiPlaneViewerP::commonConstructor(void)
++{
++ this->mode = SoGuiPlaneViewerP::IDLE_MODE;
++
++ this->canvas = SbVec2s(0, 0);
++ this->pointer.now = SbVec2s(0, 0);
++ this->pointer.then = SbVec2s(0, 0);
++ this->ctrldown = FALSE;
++ this->shiftdown = FALSE;
++ this->button1down = FALSE;
++ this->button3down = FALSE;
++
++
++ static const char * superimposed = {
++ "#Inventor V2.1 ascii\n\n"
++ ""
++ "Separator {"
++ " DEF so at gui@->orthocam OrthographicCamera {"
++ " height 1"
++ " nearDistance 0"
++ " farDistance 1"
++ " }"
++ " LightModel {"
++ " model BASE_COLOR"
++ " }"
++ ""
++ " Separator {"
++ " DEF so at gui@->geometry Coordinate3 {"
++ " point [" // coordinates set from code
++ " 0 0 0,"
++ " 0 0 0,"
++ " 0 0 0,"
++ " 0 0 0"
++ " ]"
++ " }"
++ " BaseColor { rgb 1 1 1 }"
++ " DEF so at gui@->style0 DrawStyle { }" // lineWidth set in code
++ " DEF so at gui@->mainline IndexedLineSet {" // fat line (exterior)
++ " coordIndex ["
++ " 0, 1, -1, 1, 2, -1, 1, 3, -1"
++ " ]"
++ " }"
++ " BaseColor { rgb 0.5 0.5 0.5 }"
++ " DEF so at gui@->style1 DrawStyle { }" // lineWidth set in code
++ " USE so at gui@->mainline" // thin line (interior)
++ " }"
++ "}"
++ };
++
++ SoInput * input = new SoInput;
++ input->setBuffer((void *)superimposed, strlen(superimposed));
++ SbBool ok = SoDB::read(input, this->superimposition);
++ assert(ok && "error in superimposed scenegraph");
++ delete input;
++ this->superimposition->ref();
++
++ SoSearchAction s;
++ this->super.coords = (SoCoordinate3 *)
++ get_scenegraph_node(&s, this->superimposition, "so at gui@->geometry");
++ this->super.camera = (SoOrthographicCamera *)
++ get_scenegraph_node(&s, this->superimposition, "so at gui@->orthocam");
++
++ // drawstyle settings for the superimposed lines will be updated on
++ // demand, according to the capabilities of the GL driver & context.
++ this->lineds[0] = (SoDrawStyle *)
++ get_scenegraph_node(&s, this->superimposition, "so at gui@->style0");
++ this->lineds[1] = (SoDrawStyle *)
++ get_scenegraph_node(&s, this->superimposition, "so at gui@->style1");
++
++ PUBLIC(this)->addSuperimposition(this->superimposition);
++ PUBLIC(this)->setSuperimpositionEnabled(this->superimposition, FALSE);
++}
++
++void
++SoGuiPlaneViewerP::rotateZ(const float angle) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (! camera) return; // probably a scene-less viewer
++
++ SbVec3f dir;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++ camera->orientation =
++ camera->orientation.getValue() * SbRotation(dir, angle);
++}
++
++void
++SoGuiPlaneViewerP::viewPlaneX(void) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (! camera) return; // probably a scene-less viewer
++
++ SbVec3f dir;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++ SbVec3f focalpoint = camera->position.getValue() +
++ camera->focalDistance.getValue() * dir;
++ camera->position = focalpoint +
++ camera->focalDistance.getValue() * SbVec3f(1, 0, 0);
++ camera->orientation = SbRotation(SbVec3f(0, 1, 0), float(M_PI) / 2.0f);
++}
++
++void
++SoGuiPlaneViewerP::viewPlaneY(void) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (! camera) return; // probably a scene-less viewer
++
++ SbVec3f dir;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++ SbVec3f focalpoint = camera->position.getValue() +
++ camera->focalDistance.getValue() * dir;
++ camera->position = focalpoint +
++ camera->focalDistance.getValue() * SbVec3f(0, 1, 0);
++ camera->orientation = SbRotation(SbVec3f(1, 0, 0), -float(M_PI) / 2.0f);
++}
++
++void
++SoGuiPlaneViewerP::viewPlaneZ(void) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (! camera) return; // probably a scene-less viewer
++
++ SbVec3f dir;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), dir);
++ SbVec3f focalpoint = camera->position.getValue() +
++ camera->focalDistance.getValue() * dir;
++ camera->position = focalpoint +
++ camera->focalDistance.getValue() * SbVec3f(0, 0, 1);
++ camera->orientation = SbRotation(SbVec3f(0, 1, 0), 0);
++}
++
++void
++SoGuiPlaneViewerP::setCanvasSize(const SbVec2s size)
++{
++ this->canvas = size;
++}
++
++void
++SoGuiPlaneViewerP::setPointerLocation(const SbVec2s position)
++{
++ this->pointer.then = this->pointer.now;
++ this->pointer.now = position;
++}
++
++int
++SoGuiPlaneViewerP::getPointerXMotion(void) const
++{
++ return this->pointer.now[0] - this->pointer.then[0];
++}
++
++int
++SoGuiPlaneViewerP::getPointerYMotion(void) const
++{
++ return this->pointer.now[1] - this->pointer.then[1];
++}
++
++float
++SoGuiPlaneViewerP::getPointerOrigoAngle(void) const
++{
++ SbVec2s now = this->pointer.now;
++ now[0] -= this->canvas[0] / 2;
++ now[1] -= this->canvas[1] / 2;
++
++ double nowradval = (now[0] != 0) ? atan(fabs((double) (now[1] / now[0]))) : 0.0;
++
++ if (now[0] < 0) nowradval = M_PI - nowradval;
++ if (now[1] < 0) nowradval = 2 * M_PI - nowradval;
++
++ return (float)nowradval;
++}
++
++float
++SoGuiPlaneViewerP::getPointerOrigoMotionAngle(void) const
++{
++ if (this->pointer.then == this->pointer.now)
++ return 0.0f;
++
++ SbVec2s now = this->pointer.now;
++ now[0] -= this->canvas[0] / 2;
++ now[1] -= this->canvas[1] / 2;
++
++ SbVec2s then = this->pointer.then;
++ then[0] -= this->canvas[0] / 2;
++ then[1] -= this->canvas[1] / 2;
++
++ double nowradval = (now[0] != 0) ? atan(fabs((double) (now[1] / now[0]))) : 0.0;
++ if (now[0] < 0) nowradval = M_PI - nowradval;
++ if (now[1] < 0) nowradval = 2 * M_PI - nowradval;
++
++ double thenradval = (then[0] != 0) ? atan(fabs((double) (then[1] / then[0]))) : 0.0;
++ if (then[0] < 0) thenradval = M_PI - thenradval;
++ if (then[1] < 0) thenradval = 2 * M_PI - thenradval;
++
++ return (float)(nowradval - thenradval);
++}
++
++// This method updates the contents of the scenegraph which renders
++// the rotate-"anchor".
++void
++SoGuiPlaneViewerP::updateAnchorScenegraph(void) const
++{
++ // must re-check this, since the GL context may be different between
++ // invocations:
++ SbVec2f range;
++ float granularity;
++ PUBLIC(this)->getLineWidthLimits(range, granularity);
++ // Draw a thinner line on top of a fat line, to make an outline.
++ const float lw0 = So at Gui@Clamp(5.0f, range[0], range[1]);
++ const float lw1 = So at Gui@Clamp(3.0f, range[0], range[1]);
++ if (this->lineds[0]->lineWidth.getValue() != lw0) { this->lineds[0]->lineWidth = lw0; }
++ if (this->lineds[1]->lineWidth.getValue() != lw1) { this->lineds[1]->lineWidth = lw1; }
++
++
++ float x = float(this->pointer.now[0]) / float(this->canvas[0]);
++ float y = float(this->pointer.now[1]) / float(this->canvas[1]);
++
++ float aspectratio = PUBLIC(this)->getViewportRegion().getViewportAspectRatio();
++ SbViewVolume vv = this->super.camera->getViewVolume(aspectratio);
++ // know we have ADJUST_CAMERA mapping
++ if (aspectratio < 1.0f) vv.scale(1.0f / aspectratio);
++
++ SbVec3f p = vv.getPlanePoint(1.0, SbVec2f(x, y));
++
++ this->super.coords->point.set1Value(0, SbVec3f(0, 0, 0));
++ this->super.coords->point.set1Value(1, SbVec3f(p[0], p[1], 0));
++
++ float angle = this->getPointerOrigoAngle();
++ SbRotation r(SbVec3f(0, 0, 1), angle);
++
++ SbVec3f xarrow(-0.02f, -0.1f, 0.0f);
++ r.multVec(xarrow, xarrow);
++ SbVec3f pa = SbVec3f(p[0] + xarrow[0], p[1] + xarrow[1], 0);
++ this->super.coords->point.set1Value(2, SbVec3f(pa[0], pa[1], 0));
++
++ SbVec3f yarrow(-0.02f, 0.1f, 0.0f);
++ r.multVec(yarrow, yarrow);
++ pa = SbVec3f(p[0] + yarrow[0], p[1] + yarrow[1], 0);
++ this->super.coords->point.set1Value(3, SbVec3f(pa[0], pa[1], 0));
++}
++
++// Set cursor graphics according to mode.
++void
++SoGuiPlaneViewerP::setCursorRepresentation(PlaneViewerMode modearg)
++{
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@PlaneViewer::setCursorRepresentation",
++ "mode==%d", mode);
++#endif // debug
++
++ assert(PUBLIC(this)->getGLWidget());
++
++ if (!PUBLIC(this)->isCursorEnabled()) {
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getBlankCursor());
++ return;
++ }
++
++ switch (modearg) {
++ case SoGuiPlaneViewerP::SCENEGRAPH_INTERACT_MODE:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::DEFAULT));
++ break;
++
++ case SoGuiPlaneViewerP::IDLE_MODE:
++ case SoGuiPlaneViewerP::DOLLY_MODE:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::UPARROW));
++ break;
++ case SoGuiPlaneViewerP::ROTZ_WAIT_MODE:
++ case SoGuiPlaneViewerP::ROTZ_MODE:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getRotateCursor());
++ break;
++ case SoGuiPlaneViewerP::SEEK_WAIT_MODE:
++ case SoGuiPlaneViewerP::SEEK_MODE:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor(So at Gui@Cursor::CROSSHAIR));
++ break;
++ case SoGuiPlaneViewerP::TRANSLATE_MODE:
++ PUBLIC(this)->setComponentCursor(So at Gui@Cursor::getPanCursor());
++ break;
++ default:
++ assert(0 && "unknown PlaneViewer mode");
++ break;
++ }
++}
++
++
++/*!
++ Overridden to make sure camera orientation is not affected by a
++ seek
++ */
++void
++So at Gui@PlaneViewer::computeSeekFinalOrientation(void)
++{
++ So at Gui@ViewerP * thisp = ((So at Gui@Viewer *)this)->pimpl;
++ thisp->cameraendorient = thisp->camera->orientation.getValue();
++}
++
++
++void
++SoGuiPlaneViewerP::changeMode(PlaneViewerMode newmode)
++{
++ if (newmode == this->mode) { return; }
++
++ switch (newmode) {
++ case SoGuiPlaneViewerP::TRANSLATE_MODE:
++ case SoGuiPlaneViewerP::DOLLY_MODE:
++ PUBLIC(this)->interactiveCountInc();
++ break;
++
++ case SoGuiPlaneViewerP::ROTZ_MODE:
++ PUBLIC(this)->interactiveCountInc();
++ PUBLIC(this)->setSuperimpositionEnabled(this->superimposition, TRUE);
++ PUBLIC(this)->scheduleRedraw();
++ break;
++
++ default:
++ break;
++ }
++
++ switch (this->mode) {
++ case SoGuiPlaneViewerP::ROTZ_MODE:
++ PUBLIC(this)->setSuperimpositionEnabled(this->superimposition, FALSE);
++ PUBLIC(this)->scheduleRedraw();
++ // fall through
++
++ case SoGuiPlaneViewerP::TRANSLATE_MODE:
++ case SoGuiPlaneViewerP::DOLLY_MODE:
++ PUBLIC(this)->interactiveCountDec();
++ break;
++ default:
++ break;
++ }
++
++ if (newmode == SoGuiPlaneViewerP::TRANSLATE_MODE) {
++ // The plane we're projecting the mouse coordinates to get 3D
++ // coordinates should stay the same during the whole pan
++ // operation, so we should calculate this value here.
++ SoCamera * cam = PUBLIC(this)->getCamera();
++ if (cam == NULL) { // can happen for empty scenegraph
++ this->panningplane = SbPlane(SbVec3f(0, 0, 1), 0);
++ }
++ else {
++ SbViewVolume vv = cam->getViewVolume(PUBLIC(this)->getGLAspectRatio());
++ this->panningplane = vv.getPlane(cam->focalDistance.getValue());
++ }
++ }
++
++ this->setCursorRepresentation(newmode);
++ this->mode = newmode;
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiPlaneViewer.h.in
+@@ -0,0 +1,99 @@
++#ifndef SO at GUI@PLANEVIEWER_H
++#define SO at GUI@PLANEVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@FullViewer.h>
++
++// ************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@PlaneViewer : public So at Gui@FullViewer {
++ SO at GUI@_OBJECT_HEADER(So at Gui@PlaneViewer, So at Gui@FullViewer);
++
++public:
++ So at Gui@PlaneViewer(@WIDGET@ parent = NULL,
++ const char * const name = NULL,
++ SbBool embed = TRUE,
++ So at Gui@FullViewer::BuildFlag flag = BUILD_ALL,
++ So at Gui@Viewer::Type type = BROWSER);
++ ~So at Gui@PlaneViewer();
++
++ virtual void setViewing(SbBool enable);
++ virtual void setCamera(SoCamera * camera);
++ virtual void setCursorEnabled(SbBool enable);
++
++protected:
++ So at Gui@PlaneViewer(@WIDGET@ parent,
++ const char * const name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build);
++
++ @WIDGET@ buildWidget(@WIDGET@ parent);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++ virtual SbBool processSoEvent(const SoEvent * const event);
++ virtual void setSeekMode(SbBool enable);
++ virtual void actualRedraw(void);
++
++ virtual void bottomWheelStart(void);
++ virtual void bottomWheelMotion(float value);
++ virtual void bottomWheelFinish(void);
++
++ virtual void leftWheelStart(void);
++ virtual void leftWheelMotion(float value);
++ virtual void leftWheelFinish(void);
++
++ virtual void rightWheelStart(void);
++ virtual void rightWheelMotion(float value);
++ virtual void rightWheelFinish(void);
++
++ virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttons);
++
++ virtual void afterRealizeHook(void);
++ virtual void computeSeekFinalOrientation(void);
++
++private:
++ class So at Gui@PlaneViewerP * pimpl;
++
++ friend class SoGuiPlaneViewerP;
++ friend class So at Gui@PlaneViewerP;
++};
++
++#endif // !SO at GUI@PLANEVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiPlaneViewerP.h.in
+@@ -0,0 +1,120 @@
++#ifndef SOGUIPLANEVIEWERP_H
++#define SOGUIPLANEVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbLinear.h>
++
++class So at Gui@PlaneViewer;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiPlaneViewer class.
++
++class SoGuiPlaneViewerP
++{
++public:
++ ~SoGuiPlaneViewerP();
++
++ void commonConstructor(void);
++
++ void pan(const SbVec2f & thispos, const SbVec2f & prevpos);
++ void rotateZ(const float angle) const;
++
++ void viewPlaneX(void) const;
++ void viewPlaneY(void) const;
++ void viewPlaneZ(void) const;
++
++ void setCanvasSize(const SbVec2s size);
++ void setPointerLocation(const SbVec2s location);
++ int getPointerXMotion(void) const;
++ int getPointerYMotion(void) const;
++ float getPointerOrigoAngle(void) const;
++ float getPointerOrigoMotionAngle(void) const;
++
++ void updateAnchorScenegraph(void) const;
++
++ enum PlaneViewerMode {
++ SCENEGRAPH_INTERACT_MODE,
++
++ IDLE_MODE,
++
++ DOLLY_MODE,
++ TRANSLATE_MODE,
++
++ ROTZ_WAIT_MODE,
++ ROTZ_MODE,
++
++ SEEK_WAIT_MODE,
++ SEEK_MODE
++ } mode;
++
++ void changeMode(PlaneViewerMode newmode);
++ void setCursorRepresentation(PlaneViewerMode mode);
++
++ struct pointerdata {
++ SbVec2s now;
++ SbVec2s then;
++ } pointer;
++ SbVec2s canvas;
++
++ SbBool ctrldown;
++ SbBool shiftdown;
++ SbBool button1down;
++ SbBool button3down;
++
++ SbPlane panningplane;
++
++ class SoDrawStyle * lineds[2];
++
++ class SoNode * superimposition;
++ struct superdata {
++ class SoCoordinate3 * coords;
++ class SoOrthographicCamera * camera;
++ } super;
++
++protected:
++ SoGuiPlaneViewerP(So at Gui@PlaneViewer * publ);
++ So at Gui@PlaneViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIPLANEVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiViewer.cpp.in
+@@ -0,0 +1,3862 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// NOTE: The So at Gui@Viewer.cpp sourcecode file is completely
++// autogenerated from "templatized" source code.
++
++// *************************************************************************
++
++/*!
++ \class So at Gui@Viewer Inventor/@Gui@/viewers/So at Gui@Viewer.h
++ \brief The So at Gui@Viewer class is the top level base viewer class.
++ \ingroup components viewers
++
++ This is an abstract class, which adds the following features to it's
++ So at Gui@RenderArea superclass: convenient methods for camera
++ handling, an automatic headlight configuration.
++
++ As for the camera handling: when setting a new scenegraph for the
++ viewer, the scenegraph will automatically be scanned for a node
++ derived from SoCamera. If not found, the viewer will itself set up a
++ camera for the scene. The camera can then be conveniently controlled
++ by the application programmers in many aspects:
++
++ <ul>
++
++ <li>camera type: toggle between using an orthographic camera and a
++ perspective camera with So at Gui@Viewer::toggleCameraType()</li>
++
++ <li>zoom out to exactly encompass all scene geometry within the view
++ by using So at Gui@Viewer::viewAll()</li>
++
++ <li>tag a specific position and orientation for the camera as the
++ "home" position with So at Gui@Viewer::saveHomePosition(), which one
++ can then return to by using
++ So at Gui@Viewer::resetToHomePosition()</li>
++
++ <li>automatically fit the near and far clipping planes of the camera
++ around the scene's geometry by using
++ So at Gui@Viewer::setAutoClipping()</li>
++
++ <li>control stereo viewing parameters</li>
++
++ </ul>
++
++ Note that there is no dragger or manipulator attached to the scene
++ camera. The camera transform manipulation is calculated in a more
++ direct manner in the non-abstract viewer classes inheriting
++ So at Gui@Viewer by reading mouse and keyboard events and interpreting
++ how these should influence the camera. The calculations results in
++ new values for SoCamera::position, SoCamera::orientation, and the
++ other SoCamera field values for the camera designated to be the
++ viewer viewpoint camera. These values are then inserted directly
++ into the viewer's SoCamera node.
++
++ See e.g. the source code for So at Gui@ExaminerViewer::processSoEvent()
++ for the details.
++
++
++
++ The So at Gui@Viewer class automatically adds a headlight to the scene,
++ which will always point in the approximate same direction as the
++ current viewer camera, thereby securing that the scene geometry is
++ always lighted and visible. (If you don't want the constant
++ headlight, but rather want to light the scene on your own, this
++ behavior can be turned off with So at Gui@Viewer::setHeadlight()).
++
++
++ So at Gui@Viewer-derived viewers all inherit the following keyboard
++ controls from this class (but only when the viewer is in "examine
++ mode", ie So at Gui@Viewer::isViewing() returns \c TRUE):
++
++ <ul>
++
++ <li>"s": put the viewer in "seek mode", where the end user may click
++ anywhere on scene geometry to trigger an animation which moves the
++ camera towards the point clicked</li>
++
++ <li>"Home": hit this key to move camera back to last saved "home
++ position"</li>
++
++ <li>arrow keys: moves camera slightly left, right, up or down</li>
++
++ <li>"q": exit application</li>
++
++ </ul>
++*/
++
++// *************************************************************************
++
++/*!
++ \enum So at Gui@Viewer::AutoClippingStrategy
++
++ Enum for auto clipping strategy.
++
++ \sa setAutoClippingStrategy()
++*/
++
++/*!
++ \var So at Gui@Viewer::AutoClippingStrategy So at Gui@Viewer::CONSTANT_NEAR_PLANE
++
++ Constant near plane auto clipping strategy. Explained in detail in
++ the documentation for the So at Gui@Viewer::setAutoClippingStrategy()
++ method.
++*/
++
++/*!
++ \var So at Gui@Viewer::AutoClippingStrategy So at Gui@Viewer::VARIABLE_NEAR_PLANE
++
++ Variable near plane auto clipping strategy. Explained in detail in
++ the documentation for the So at Gui@Viewer::setAutoClippingStrategy()
++ method.
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <stdlib.h>
++#include <string.h>
++#include <math.h>
++#include <float.h> // FLT_MAX
++
++#include <Inventor/SbLinear.h>
++#include <Inventor/SoDB.h>
++#include <Inventor/SoLists.h>
++#include <Inventor/SoPickedPoint.h>
++#include <Inventor/SoSceneManager.h>
++#include <Inventor/actions/SoGetBoundingBoxAction.h>
++#include <Inventor/actions/SoGetMatrixAction.h>
++#include <Inventor/actions/SoRayPickAction.h>
++#include <Inventor/actions/SoSearchAction.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/events/SoKeyboardEvent.h>
++#include <Inventor/events/SoMouseButtonEvent.h>
++#include <Inventor/misc/SoCallbackList.h>
++#include <Inventor/nodekits/SoBaseKit.h>
++#include <Inventor/nodes/SoBaseColor.h>
++#include <Inventor/nodes/SoComplexity.h>
++#include <Inventor/nodes/SoDirectionalLight.h>
++#include <Inventor/nodes/SoDrawStyle.h>
++#include <Inventor/nodes/SoLightModel.h>
++#include <Inventor/nodes/SoLocateHighlight.h>
++#include <Inventor/nodes/SoMaterialBinding.h>
++#include <Inventor/nodes/SoOrthographicCamera.h>
++#include <Inventor/nodes/SoPerspectiveCamera.h>
++#include <Inventor/nodes/SoSeparator.h>
++#include <Inventor/nodes/SoSwitch.h>
++#include <Inventor/SbColor4f.h>
++#include <Inventor/sensors/SoTimerSensor.h>
++
++#ifdef HAVE_SOPOLYGONOFFSET
++#include <Inventor/nodes/SoPolygonOffset.h>
++#endif // HAVE_SOPOLYGONOFFSET
++
++#include <Inventor/@Gui@/So at Gui@.h>
++#include <Inventor/@Gui@/SoAny.h>
++#include <Inventor/@Gui@/common/SbGuiList.h>
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/nodes/SoGuiViewpointWrapper.h>
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++#include <Inventor/@Gui@/viewers/SoGuiViewerP.h>
++#include <so at gui@defs.h>
++
++// *************************************************************************
++
++// (note: this *must* be a #define, not a static variable -- to avoid
++// initialization race conditions with the static variables being set
++// to the value of this)
++#define UNINITIALIZED_ENVVAR -1 // value of envvars before tested
++
++// Environment variable for debugging purpose: display a running
++// frames-per-second counter. See code comments above
++// So at Gui@ViewerP::recordFPS() function below for more information.
++static int COIN_SHOW_FPS_COUNTER = UNINITIALIZED_ENVVAR;
++
++// *************************************************************************
++
++#define PRIVATE(ptr) (ptr->pimpl)
++#define PUBLIC(ptr) (ptr->pub)
++
++// *************************************************************************
++
++So at Gui@ViewerP::So at Gui@ViewerP(So at Gui@Viewer * publ)
++{
++ PUBLIC(this) = publ;
++ this->searchaction = new SoSearchAction;
++ this->matrixaction = new SoGetMatrixAction(SbViewportRegion(100,100));
++ this->superimpositions = NULL;
++
++ this->storedcamera = NULL;
++
++ // initialize auto clipping parameters
++ this->autoclipstrategy = So at Gui@Viewer::VARIABLE_NEAR_PLANE;
++ this->autoclipvalue = 0.6f;
++ this->autoclipcb = NULL;
++
++ this->stereotype = So at Gui@Viewer::STEREO_NONE;
++ this->stereotypesetexplicit = FALSE;
++ this->stereostencilmaskvp = SbViewportRegion(0, 0);
++ this->stereostencilmask = NULL;
++ this->stereostenciltype = So at Gui@Viewer::STEREO_NONE;
++ this->stereoanaglyphmask[0][0] = TRUE;
++ this->stereoanaglyphmask[0][1] = this->stereoanaglyphmask[0][2] = FALSE;
++ this->stereoanaglyphmask[1][0] = FALSE;
++ this->stereoanaglyphmask[1][1] = this->stereoanaglyphmask[1][2] = TRUE;
++}
++
++So at Gui@ViewerP::~So at Gui@ViewerP()
++{
++ // This impossible to miss reminder was inserted so we don't
++ // accidentally let an So* v2 slip out the door without fixing this
++ // API design flaw. 20030625 mortene.
++#if (SO at GUI@_MAJOR_VERSION == 2)
++#error This is a reminder: when jumping to version 2 of an So* toolkit, the viewer destructors (at least, possibly also further up in the inheritance hierarchy) should be made virtual.
++#endif // version = 2
++
++ delete[] this->stereostencilmask;
++
++ if ( this->superimpositions != NULL ) delete this->superimpositions;
++ delete this->searchaction;
++ delete this->matrixaction;
++
++ if (this->storedcamera) { this->storedcamera->unref(); }
++}
++
++SoSeparator *
++So at Gui@ViewerP::createSuperScene(void)
++{
++ static const char * superSceneGraph[] =
++ {
++ "#Inventor V2.1 ascii",
++ "",
++ "Separator {",
++ " renderCaching OFF",
++ " renderCulling OFF",
++ " pickCulling OFF",
++ " boundingBoxCaching OFF",
++
++ // Headlight. By inserting this before any scenegraph camera, the
++ // light will always be pointing in the correct direction.
++ " DEF so at gui@->headlight DirectionalLight {",
++ " direction 1 -1 -10",
++ " }",
++
++ " DEF so at gui@->drawstyleroot Switch {",
++ " whichChild -1",
++ " DEF so at gui@->lightmodel LightModel {",
++ " model BASE_COLOR",
++ " }",
++ " DEF so at gui@->drawstyle DrawStyle {",
++ " pointSize ~",
++ " lineWidth ~",
++ " linePattern ~",
++ " }",
++ " DEF so at gui@->complexity Complexity {",
++ " textureQuality 0.0",
++ " value 0.1",
++ " }",
++ " }",
++ " DEF so at gui@->hiddenlineroot Switch {",
++ " whichChild -1",
++ " DEF so at gui@->basecolor BaseColor { }",
++ " DEF so at gui@->materialbinding MaterialBinding {",
++ " value OVERALL",
++ " }",
++ " DEF so at gui@->polygonoffsetparent Switch {",
++ " whichChild -1",
++#ifdef HAVE_SOPOLYGONOFFSET
++ " DEF so at gui@->polygonoffset PolygonOffset { }",
++#endif // HAVE_SOPOLYGONOFFSET
++ " }",
++ " }",
++ " DEF so at gui@->userscenegraphroot Separator {",
++ // turn off caching to make it possible for users to disable
++ // caching in their scene graphs.
++ " renderCaching OFF\n",
++ " }",
++ "}",
++ NULL
++ };
++
++ int i, bufsize;
++ for (i = bufsize = 0; superSceneGraph[i]; i++)
++ bufsize += strlen(superSceneGraph[i]) + 1;
++ char * buf = new char [bufsize + 1];
++ for (i = bufsize = 0; superSceneGraph[i]; i++) {
++ strcpy(buf + bufsize, superSceneGraph[i]);
++ bufsize += strlen(superSceneGraph[i]);
++ buf[bufsize] = '\n';
++ bufsize++;
++ }
++ SoInput * input = new SoInput;
++ input->setBuffer(buf, bufsize);
++ SoNode * root = NULL;
++ SbBool ok = SoDB::read(input, root);
++ delete input;
++ delete [] buf;
++ if (!ok) {
++ // FIXME: this looks unnecessary robust, and I believe it should
++ // be replaced by an assert()..? 20030430 mortene.
++ SoDebugError::post("So at Gui@ViewerP::createSuperScene",
++ "couldn't create viewer superscene");
++ return NULL;
++ }
++ assert(root->isOfType(SoSeparator::getClassTypeId()));
++ root->ref();
++
++ this->searchaction->reset();
++ this->searchaction->setSearchingAll(TRUE);
++ this->searchaction->setInterest(SoSearchAction::FIRST);
++
++#define LOCATE_NODE(member, type, name) \
++ do { \
++ member = NULL; \
++ this->searchaction->setName(SbName(name)); \
++ this->searchaction->apply(root); \
++ if (this->searchaction->getPath() != NULL) { \
++ SoNode * node = this->searchaction->getPath()->getTail(); \
++ assert(node != NULL); \
++ if (node->isOfType(type::getClassTypeId())) \
++ member = (type *) node; \
++ } else { \
++ SoDebugError::post("So at Gui@ViewerP::createSuperScene", \
++ "didn't locate node \"%s\"", name); \
++ } \
++ } while (FALSE)
++
++ LOCATE_NODE(this->headlight, SoDirectionalLight, "so at gui@->headlight");
++ LOCATE_NODE(this->drawstyleroot, SoSwitch, "so at gui@->drawstyleroot");
++ LOCATE_NODE(this->hiddenlineroot, SoSwitch, "so at gui@->hiddenlineroot");
++ LOCATE_NODE(this->polygonoffsetparent, SoSwitch,
++ "so at gui@->polygonoffsetparent");
++ LOCATE_NODE(this->usersceneroot, SoSeparator, "so at gui@->userscenegraphroot");
++
++ LOCATE_NODE(this->sobasecolor, SoBaseColor, "so at gui@->basecolor");
++ LOCATE_NODE(this->socomplexity, SoComplexity, "so at gui@->complexity");
++ LOCATE_NODE(this->sodrawstyle, SoDrawStyle, "so at gui@->drawstyle");
++ LOCATE_NODE(this->solightmodel, SoLightModel, "so at gui@->lightmodel");
++ LOCATE_NODE(this->somaterialbinding, SoMaterialBinding, "so at gui@->materialbinding");
++ if (this->sobasecolor) this->sobasecolor->setOverride(TRUE);
++ if (this->socomplexity) this->socomplexity->setOverride(TRUE);
++ if (this->sodrawstyle) this->sodrawstyle->setOverride(TRUE);
++ if (this->solightmodel) this->solightmodel->setOverride(TRUE);
++ if (this->somaterialbinding) this->somaterialbinding->setOverride(TRUE);
++#ifdef HAVE_SOPOLYGONOFFSET
++ LOCATE_NODE(this->sopolygonoffset, SoPolygonOffset, "so at gui@->polygonoffset");
++ if (this->sopolygonoffset) this->sopolygonoffset->setOverride(TRUE);
++#endif // HAVE_SOPOLYGONOFFSET
++
++#undef LOCATE_NODE
++ this->searchaction->reset();
++
++ root->unrefNoDelete();
++ return (SoSeparator *) root;
++}
++
++// Returns the coordinate system the current camera is located in. If
++// there are transformations before the camera in the scene graph,
++// this must be considered before doing certain operations. \a matrix
++// and \a inverse will not contain the transformations caused by the
++// camera fields, only the transformations traversed before the camera
++// in the scene graph.
++void
++So at Gui@ViewerP::getCameraCoordinateSystem(SoCamera * cameraarg,
++ SoNode * root,
++ SbMatrix & matrix,
++ SbMatrix & inverse)
++{
++ this->searchaction->reset();
++ this->searchaction->setSearchingAll(TRUE);
++ this->searchaction->setInterest(SoSearchAction::FIRST);
++ this->searchaction->setNode(cameraarg);
++ this->searchaction->apply(root);
++
++ matrix = inverse = SbMatrix::identity();
++ if (this->searchaction->getPath()) {
++ this->matrixaction->apply(this->searchaction->getPath());
++ matrix = this->matrixaction->getMatrix();
++ inverse = this->matrixaction->getInverse();
++ }
++ this->searchaction->reset();
++}
++
++
++// These functions do this:
++//
++// * when going from orthocam -> perspectivecam: set the
++// heightAngle field to its default value (45�), and move
++// camera to a position where the scene/model would fill about
++// the same screenspace as it did in the orthocam
++//
++// * when going from perspectivecam -> orthocam: keep the
++// current position, but tune the view-volume height so the
++// scene/model takes up about the same screenspace
++//
++// 20020522 mortene.
++
++void
++So at Gui@ViewerP::convertOrtho2Perspective(const SoOrthographicCamera * in,
++ SoPerspectiveCamera * out)
++{
++ out->aspectRatio.setValue(in->aspectRatio.getValue());
++ out->focalDistance.setValue(in->focalDistance.getValue());
++ out->orientation.setValue(in->orientation.getValue());
++ out->position.setValue(in->position.getValue());
++ out->viewportMapping.setValue(in->viewportMapping.getValue());
++
++ SbRotation camrot = in->orientation.getValue();
++
++ float focaldist = in->height.getValue() / (2.0*tan(M_PI / 8.0));
++
++ SbVec3f offset(0,0,focaldist-in->focalDistance.getValue());
++
++ camrot.multVec(offset,offset);
++ out->position.setValue(offset+in->position.getValue());
++
++ out->focalDistance.setValue(focaldist);
++
++ // 45� is the default value of this field in SoPerspectiveCamera.
++ out->heightAngle = (float)(M_PI / 4.0);
++
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@ViewerP::convertOrtho2Perspective",
++ "perspective heightAngle==%f",
++ 180.0f * out->heightAngle.getValue() / M_PI);
++#endif // debug
++}
++
++void
++So at Gui@ViewerP::convertPerspective2Ortho(const SoPerspectiveCamera * in,
++ SoOrthographicCamera * out)
++{
++ out->aspectRatio.setValue(in->aspectRatio.getValue());
++ out->focalDistance.setValue(in->focalDistance.getValue());
++ out->orientation.setValue(in->orientation.getValue());
++ out->position.setValue(in->position.getValue());
++ out->viewportMapping.setValue(in->viewportMapping.getValue());
++
++ float focaldist = in->focalDistance.getValue();
++
++ out->height = 2.0f * focaldist * (float)tan(in->heightAngle.getValue() / 2.0);
++
++#if SO at GUI@_DEBUG && 0 // debug
++ SoDebugError::postInfo("So at Gui@ViewerP::convertOrtho2Perspective",
++ "ortho height==%f",
++ out->height.getValue());
++#endif // debug
++}
++
++void
++So at Gui@ViewerP::reallyRedraw(const SbBool clearcol, const SbBool clearz)
++{
++ // Recalculate near/far planes. Must be done in reallyRedraw() --
++ // not actualRedraw() -- so the clipping planes are correct even
++ // when rendering multiple times with different camera settings.
++ if (this->camera && PUBLIC(this)->isAutoClipping()) {
++ // Temporarily turn off notification when changing near and far
++ // clipping planes, to avoid latency.
++ const SbBool notif = this->camera->isNotifyEnabled();
++ this->camera->enableNotify(FALSE);
++ this->setClippingPlanes();
++ this->camera->enableNotify(notif);
++ }
++
++ if (this->drawAsHiddenLine()) {
++
++ // First pass: render as filled, but with the background color.
++
++ this->solightmodel->model.setIgnored(FALSE); // override as SoLightModel::BASE
++ this->sodrawstyle->style.setIgnored(TRUE); // draw as-is filled/lines/points
++ this->socomplexity->type.setIgnored(TRUE); // as-is rendering space
++ this->socomplexity->value.setIgnored(TRUE); // as-is complexity on non-simple shapes
++ // textureQuality field of socomplexity node is always 0.0
++
++ this->sobasecolor->rgb.setValue(PUBLIC(this)->getBackgroundColor());
++ this->sobasecolor->rgb.setIgnored(FALSE);
++ this->somaterialbinding->value.setIgnored(FALSE); // override with OVERALL
++ this->polygonoffsetparent->whichChild = SO_SWITCH_ALL;
++
++ PUBLIC(this)->getSceneManager()->render(clearcol, clearz);
++
++ // Second pass, render wireframe on top.
++
++ this->sodrawstyle->style = SoDrawStyle::LINES;
++ this->sodrawstyle->style.setIgnored(FALSE); // force lines
++ this->sobasecolor->rgb.setIgnored(TRUE); // use as-is line colors
++ this->somaterialbinding->value.setIgnored(TRUE); // as-is
++ this->polygonoffsetparent->whichChild = SO_SWITCH_NONE;
++
++ PUBLIC(this)->getSceneManager()->render(FALSE, FALSE);
++
++ return;
++ }
++ if (this->drawAsWireframeOverlay()) {
++ // First pass: render as-is, with polygon offset
++
++ this->solightmodel->model.setIgnored(TRUE);
++ this->somaterialbinding->value.setIgnored(TRUE);
++ this->sobasecolor->rgb.setIgnored(TRUE);
++ this->sodrawstyle->style.setIgnored(TRUE); // draw as-is filled/lines/points
++ this->socomplexity->type.setIgnored(TRUE); // as-is rendering space
++ this->socomplexity->value.setIgnored(TRUE); // as-is complexity on non-simple shapes
++ this->socomplexity->textureQuality.setIgnored(TRUE);
++
++ this->somaterialbinding->value.setIgnored(TRUE); // override with OVERALL
++ this->polygonoffsetparent->whichChild = SO_SWITCH_ALL;
++
++ PUBLIC(this)->getSceneManager()->render(clearcol, clearz);
++
++ // Second pass, render wireframe on top.
++ this->sobasecolor->rgb.setValue(this->wireframeoverlaycolor);
++ this->sobasecolor->rgb.setIgnored(FALSE);
++ this->somaterialbinding->value.setIgnored(FALSE); // override with OVERALL
++
++ this->solightmodel->model.setIgnored(FALSE); // override as SoLightModel::BASE
++ this->sodrawstyle->style = SoDrawStyle::LINES;
++ this->sodrawstyle->style.setIgnored(FALSE); // force lines
++ this->polygonoffsetparent->whichChild = SO_SWITCH_NONE;
++ this->socomplexity->textureQuality.setIgnored(FALSE);
++
++ PUBLIC(this)->getSceneManager()->render(FALSE, FALSE);
++
++ // disable override nodes
++ (void) this->sobasecolor->rgb.enableNotify(FALSE);
++ this->sobasecolor->rgb.setIgnored(TRUE);
++ (void) this->sobasecolor->rgb.enableNotify(TRUE);
++
++ (void) this->somaterialbinding->value.enableNotify(FALSE);
++ this->somaterialbinding->value.setIgnored(TRUE);
++ (void) this->somaterialbinding->value.enableNotify(TRUE);
++
++ (void) this->solightmodel->model.enableNotify(FALSE);
++ this->solightmodel->model.setIgnored(TRUE);
++ (void) this->solightmodel->model.enableNotify(TRUE);
++
++ (void) this->socomplexity->textureQuality.enableNotify(FALSE);
++ this->socomplexity->textureQuality.setIgnored(TRUE);
++ (void) this->socomplexity->textureQuality.enableNotify(TRUE);
++
++ (void) this->sodrawstyle->style.enableNotify(FALSE);
++ this->sodrawstyle->style.setIgnored(TRUE);
++ (void) this->sodrawstyle->style.enableNotify(TRUE);
++ return;
++ }
++
++ SbBool clearzbuffer = TRUE;
++ So at Gui@Viewer::DrawStyle style = this->currentDrawStyle();
++ switch (style) {
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ case So at Gui@Viewer::VIEW_BBOX:
++ clearzbuffer = FALSE;
++ default:
++ break; // Include "default:" case to avoid compiler warning.
++ }
++
++ PUBLIC(this)->getSceneManager()->render(clearcol, clearzbuffer && clearz);
++}
++
++
++// *************************************************************************
++
++// Returns a boolean to indicate if the dynamic drawstyle equals
++// the static drawstyle.
++
++SbBool
++So at Gui@ViewerP::drawInteractiveAsStill(void) const
++{
++ SbBool moveasstill = this->drawstyles[So at Gui@Viewer::INTERACTIVE] == So at Gui@Viewer::VIEW_SAME_AS_STILL;
++ if (! moveasstill)
++ moveasstill = this->drawstyles[So at Gui@Viewer::INTERACTIVE] == this->drawstyles[So at Gui@Viewer::STILL];
++ if (! moveasstill)
++ moveasstill =
++ this->drawstyles[So at Gui@Viewer::INTERACTIVE] == So at Gui@Viewer::VIEW_NO_TEXTURE &&
++ this->drawstyles[So at Gui@Viewer::STILL] != So at Gui@Viewer::VIEW_AS_IS;
++ return moveasstill;
++}
++
++// Returns the current drawing style.
++So at Gui@Viewer::DrawStyle
++So at Gui@ViewerP::currentDrawStyle(void) const
++{
++ SbBool interactivemode = PUBLIC(this)->getInteractiveCount() > 0 ? TRUE : FALSE;
++
++ if (!interactivemode || this->drawInteractiveAsStill())
++ return this->drawstyles[So at Gui@Viewer::STILL];
++ else
++ return this->drawstyles[So at Gui@Viewer::INTERACTIVE];
++}
++
++// Returns a boolean to indicate if the current drawstyle settings implies
++// hidden line rendering.
++SbBool
++So at Gui@ViewerP::drawAsHiddenLine(void) const
++{
++ return ((this->currentDrawStyle() == So at Gui@Viewer::VIEW_HIDDEN_LINE) ? TRUE : FALSE);
++}
++
++// Returns a boolean to indicate if the current drawstyle settings
++// implies wirefram overlay rendering.
++SbBool
++So at Gui@ViewerP::drawAsWireframeOverlay(void) const
++{
++ return ((this->currentDrawStyle() == So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY) ? TRUE : FALSE);
++}
++
++// Use the given style setting to set the correct states in the
++// rendering control nodes. This will affect the way the scene is
++// currently rendered.
++void
++So at Gui@ViewerP::changeDrawStyle(So at Gui@Viewer::DrawStyle style)
++{
++ // Turn on/off Z-buffering based on the style setting.
++ switch (style) {
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ case So at Gui@Viewer::VIEW_BBOX:
++ PUBLIC(this)->glLockNormal();
++ // FIXME: shouldn't this be done "lazy", i.e. before we do any
++ // actual rendering? 20001126 mortene.
++ glDisable(GL_DEPTH_TEST);
++ PUBLIC(this)->glUnlockNormal();
++ break;
++
++ default:
++ PUBLIC(this)->glLockNormal();
++ // FIXME: shouldn't this be done "lazy", i.e. before we do any
++ // actual rendering? 20001126 mortene.
++ glEnable(GL_DEPTH_TEST);
++ PUBLIC(this)->glUnlockNormal();
++ break;
++ }
++
++ // Render everything as its supposed to be done, don't override
++ // any of the settings in the ``real'' graph.
++ if (style == So at Gui@Viewer::VIEW_AS_IS) {
++ this->drawstyleroot->whichChild = SO_SWITCH_NONE;
++ return;
++ }
++
++ this->drawstyleroot->whichChild = SO_SWITCH_ALL;
++ if ((style == So at Gui@Viewer::VIEW_HIDDEN_LINE) ||
++ (style == So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY)) {
++ this->hiddenlineroot->whichChild = SO_SWITCH_ALL;
++ return;
++ } else {
++ this->hiddenlineroot->whichChild = SO_SWITCH_NONE;
++ }
++
++ // Set or unset lightmodel override.
++ switch (style) {
++ case So at Gui@Viewer::VIEW_NO_TEXTURE:
++ case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++ this->solightmodel->model.setIgnored(TRUE); // as-is BASE or PHONG
++ break;
++
++ case So at Gui@Viewer::VIEW_LINE:
++ case So at Gui@Viewer::VIEW_POINT:
++ case So at Gui@Viewer::VIEW_BBOX:
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ this->solightmodel->model.setIgnored(FALSE); // force BASE lighting
++ break;
++
++ default:
++ assert(FALSE); break;
++ }
++
++
++ // Set or unset drawstyle override.
++ switch (style) {
++ case So at Gui@Viewer::VIEW_NO_TEXTURE:
++ case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++ this->sodrawstyle->style.setIgnored(TRUE); // as-is drawing style filled/lines/points
++ break;
++
++ case So at Gui@Viewer::VIEW_LINE:
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ case So at Gui@Viewer::VIEW_BBOX:
++ this->sodrawstyle->style = SoDrawStyle::LINES;
++ this->sodrawstyle->style.setIgnored(FALSE); // force line rendering
++ break;
++
++ case So at Gui@Viewer::VIEW_POINT:
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ this->sodrawstyle->style = SoDrawStyle::POINTS;
++ this->sodrawstyle->style.setIgnored(FALSE); // force point rendering
++ break;
++
++ default:
++ assert(FALSE); break;
++ }
++
++ // Set or unset complexity value override.
++ switch (style) {
++ case So at Gui@Viewer::VIEW_NO_TEXTURE:
++ case So at Gui@Viewer::VIEW_LINE:
++ case So at Gui@Viewer::VIEW_POINT:
++ case So at Gui@Viewer::VIEW_BBOX:
++ this->socomplexity->value.setIgnored(TRUE); // as-is complexity
++ break;
++
++ case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ this->socomplexity->value.setIgnored(FALSE); // force complexity setting of 0.1
++ break;
++
++ default:
++ assert(FALSE); break;
++ }
++
++ // Set or unset complexity textureQuality override (the value of the
++ // override-field is always 0.0, ie signalling "textures off").
++ switch (style) {
++ case So at Gui@Viewer::VIEW_HIDDEN_LINE:
++ case So at Gui@Viewer::VIEW_NO_TEXTURE:
++ case So at Gui@Viewer::VIEW_LINE:
++ case So at Gui@Viewer::VIEW_POINT:
++ case So at Gui@Viewer::VIEW_BBOX:
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ this->socomplexity->textureQuality.setIgnored(FALSE); // textures off
++ break;
++
++ default:
++ this->socomplexity->textureQuality.setIgnored(TRUE); // don't override
++ break;
++ }
++
++ // Set or unset complexity type override.
++ switch (style) {
++ case So at Gui@Viewer::VIEW_NO_TEXTURE:
++ case So at Gui@Viewer::VIEW_LOW_COMPLEXITY:
++ case So at Gui@Viewer::VIEW_LINE:
++ case So at Gui@Viewer::VIEW_POINT:
++ case So at Gui@Viewer::VIEW_LOW_RES_LINE:
++ case So at Gui@Viewer::VIEW_LOW_RES_POINT:
++ this->socomplexity->type.setIgnored(TRUE); // as-is
++ break;
++
++ case So at Gui@Viewer::VIEW_BBOX:
++ this->socomplexity->type = SoComplexity::BOUNDING_BOX;
++ this->socomplexity->type.setIgnored(FALSE); // force bounding box rendering
++ break;
++
++ default:
++ assert(FALSE); break;
++ }
++
++#if 0 // debug
++ SoDebugError::postInfo("So at Gui@Viewer::changeDrawStyle",
++ "\n"
++ "\tdrawstyle style: 0x%02x (isIgnored() == %s)\n"
++ "\tlightmodel model: 0x%02x, (isIgnored() == %s)\n"
++ "\tcomplexity type: 0x%02x, (isIgnored() == %s)\n"
++ "\tcomplexity value: %f, (isIgnored() == %s)\n"
++ "",
++ this->sodrawstyle->style.getValue(),
++ this->sodrawstyle->style.isIgnored() ? "T" : "F",
++ this->solightmodel->model.getValue(),
++ this->solightmodel->model.isIgnored() ? "T" : "F",
++ this->socomplexity->type.getValue(),
++ this->socomplexity->type.isIgnored() ? "T" : "F",
++ this->socomplexity->value.getValue(),
++ this->socomplexity->value.isIgnored() ? "T" : "F");
++#endif // debug
++}
++
++// Position the near and far clipping planes just in front of and
++// behind the scene's bounding box. This will give us the optimal
++// utilization of the z buffer resolution by shrinking it to its
++// minimum depth.
++//
++// Near and far clipping planes are specified in the camera fields
++// nearDistance and farDistance.
++void
++So at Gui@ViewerP::setClippingPlanes(void)
++{
++ // This is necessary to avoid a crash in case there is no scene
++ // graph specified by the user.
++ if (this->camera == NULL) return;
++
++ if (this->autoclipbboxaction == NULL)
++ this->autoclipbboxaction =
++ new SoGetBoundingBoxAction(PUBLIC(this)->getViewportRegion());
++ else
++ this->autoclipbboxaction->setViewportRegion(PUBLIC(this)->getViewportRegion());
++
++ this->autoclipbboxaction->apply(this->sceneroot);
++
++ SbXfBox3f xbox = this->autoclipbboxaction->getXfBoundingBox();
++
++ SbMatrix cammat;
++ SbMatrix inverse;
++ this->getCameraCoordinateSystem(this->camera, this->sceneroot, cammat, inverse);
++ xbox.transform(inverse);
++
++ SbMatrix mat;
++ mat.setTranslate(- this->camera->position.getValue());
++ xbox.transform(mat);
++ mat = this->camera->orientation.getValue().inverse();
++ xbox.transform(mat);
++ SbBox3f box = xbox.project();
++
++ // Bounding box was calculated in camera space, so we need to "flip"
++ // the box (because camera is pointing in the (0,0,-1) direction
++ // from origo.
++ float nearval = -box.getMax()[2];
++ float farval = -box.getMin()[2];
++
++ // FIXME: what if we have a weird scale transform in the scenegraph?
++ // Could we end up with nearval > farval then? Investigate, then
++ // either use an assert() (if it can't happen) or an So at Gui@Swap()
++ // (to handle it). 20020116 mortene.
++
++ // Check if scene is completely behind us.
++ // Do NOT check for orthographic cameras.
++ if (farval <= 0.0f && !this->camera->isOfType(SoOrthographicCamera::getClassTypeId())) { return; }
++
++ if (this->camera->isOfType(SoPerspectiveCamera::getClassTypeId())) {
++ // Disallow negative and small near clipping plane distance.
++
++ float nearlimit; // the smallest value allowed for nearval
++ if (this->autoclipstrategy == So at Gui@Viewer::CONSTANT_NEAR_PLANE) {
++ nearlimit = this->autoclipvalue;
++ }
++ else {
++ assert(this->autoclipstrategy == So at Gui@Viewer::VARIABLE_NEAR_PLANE);
++ // From glFrustum() documentation: Depth-buffer precision is
++ // affected by the values specified for znear and zfar. The
++ // greater the ratio of zfar to znear is, the less effective the
++ // depth buffer will be at distinguishing between surfaces that
++ // are near each other. If r = far/near, roughly log (2) r bits
++ // of depth buffer precision are lost. Because r approaches
++ // infinity as znear approaches zero, you should never set znear
++ // to zero.
++
++ GLint depthbits[1];
++ glGetIntegerv(GL_DEPTH_BITS, depthbits);
++
++ int use_bits = (int) (float(depthbits[0]) * (1.0f-this->autoclipvalue));
++ float r = (float) pow(2.0, (double) use_bits);
++ nearlimit = farval / r;
++ }
++
++ if (nearlimit >= farval) {
++ // (The "5000" magic constant was found by fiddling around a bit
++ // on an OpenGL implementation with a 16-bit depth-buffer
++ // resolution, adjusting to find something that would work well
++ // with both a very "stretched" / deep scene and a more compact
++ // single-model one.)
++ nearlimit = farval / 5000.0f;
++ }
++
++ // adjust the near plane if the the value is too small.
++ if (nearval < nearlimit) { nearval = nearlimit; }
++ }
++
++ // Some slack around the bounding box, in case the scene fits
++ // exactly inside it. This is done to minimize the chance of
++ // artifacts caused by the limitation of the z-buffer
++ // resolution. One common artifact if this is not done is that the
++ // near clipping plane cuts into the corners of the model as it's
++ // rotated.
++ const float SLACK = 0.001f;
++
++ // FrustumCamera can be found in the SmallChange CVS module. We
++ // should not change the nearDistance for this camera, as this will
++ // modify the frustum.
++ //
++ // FIXME: quite the hack that So at Gui@ needs to know about the
++ // FrustumCamera class. Wouldn't it be better if FrustumCamera
++ // instead registered a callback with setAutoClippingStrategy() and
++ // handled this itself? 20040908 mortene.
++ if (this->camera->getTypeId().getName() == "FrustumCamera") {
++ nearval = this->camera->nearDistance.getValue();
++ farval *= (1.0f + SLACK);
++ if (farval <= nearval) {
++ // nothing is visible, so just set farval to som value > nearval.
++ farval = nearval + 10.0f;
++ }
++ }
++ else {
++ // For orthographic cameras also negative values nearval/farval
++ // are reasonable.
++ nearval *= (1.0f - (nearval>0?1:-1)*SLACK);
++ farval *= (1.0f + (farval>0?1:-1)*SLACK);
++ }
++
++ if (this->autoclipcb) {
++ SbVec2f nearfar(nearval, farval);
++ nearfar = this->autoclipcb(this->autoclipuserdata, nearfar);
++
++ nearval = nearfar[0];
++ farval = nearfar[1];
++ }
++
++ if (nearval != this->camera->nearDistance.getValue()) {
++ this->camera->nearDistance = nearval;
++ }
++ if (farval != this->camera->farDistance.getValue()) {
++ this->camera->farDistance = farval;
++ }
++
++ // FIXME: there's a possible optimization to take advantage of here,
++ // since we are able to sometimes know for sure that all geometry is
++ // completely inside the view volume. I quote from the "OpenGL FAQ
++ // and Troubleshooting Guide":
++ //
++ // "10.050 I know my geometry is inside the view volume. How can I
++ // turn off OpenGL's view-volume clipping to maximize performance?
++ //
++ // Standard OpenGL doesn't provide a mechanism to disable the
++ // view-volume clipping test; thus, it will occur for every
++ // primitive you send.
++ //
++ // Some implementations of OpenGL support the
++ // GL_EXT_clip_volume_hint extension. If the extension is
++ // available, a call to
++ // glHint(GL_CLIP_VOLUME_CLIPPING_HINT_EXT,GL_FASTEST) will inform
++ // OpenGL that the geometry is entirely within the view volume and
++ // that view-volume clipping is unnecessary. Normal clipping can
++ // be resumed by setting this hint to GL_DONT_CARE. When clipping
++ // is disabled with this hint, results are undefined if geometry
++ // actually falls outside the view volume."
++ //
++ // 20020117 mortene.
++
++
++ // Debug assistance, can be turned on without recompilation (just
++ // set the environment variable SO at GUI@_DEBUG_CLIPPLANES):
++
++#if SO at GUI@_DEBUG
++ static int debugoutputnearfar = -1;
++ if (debugoutputnearfar == -1) {
++ const char * env = SoAny::si()->getenv("SO at GUI@_DEBUG_CLIPPLANES");
++ debugoutputnearfar = (env && atoi(env) > 0) ? 1 : 0;
++ }
++
++ if (debugoutputnearfar == 1) { // debug
++ SoDebugError::postInfo("So at Gui@Viewer::setClippingPlanes",
++ "near, far: %f (%f), %f (%f)",
++ nearval, this->camera->nearDistance.getValue(),
++ farval, this->camera->farDistance.getValue());
++ }
++#endif // debug
++}
++
++// Translate camera a distance equal to the difference in projected,
++// normalized screen coordinates given by the argument.
++void
++So at Gui@ViewerP::moveCameraScreen(const SbVec2f & screenpos)
++{
++ SoCamera * cam = PUBLIC(this)->getCamera();
++ assert(cam);
++
++ if (SO at GUI@_DEBUG && 0) { // debug
++ SoDebugError::postInfo("So at Gui@Viewer::moveCameraScreen",
++ "screenpos: <%f, %f>, campos: <%f, %f, %f>",
++ screenpos[0], screenpos[1],
++ cam->position.getValue()[0],
++ cam->position.getValue()[1],
++ cam->position.getValue()[2]);
++ }
++
++ SbViewVolume vv = cam->getViewVolume(PUBLIC(this)->getGLAspectRatio());
++ SbPlane panplane = vv.getPlane(cam->focalDistance.getValue());
++
++ SbLine line;
++ vv.projectPointToLine(screenpos + SbVec2f(0.5, 0.5f), line);
++ SbVec3f current_planept;
++ panplane.intersect(line, current_planept);
++ vv.projectPointToLine(SbVec2f(0.5f, 0.5f), line);
++ SbVec3f old_planept;
++ panplane.intersect(line, old_planept);
++
++ // Reposition camera according to the vector difference between the
++ // projected points.
++ cam->position = cam->position.getValue() - (current_planept - old_planept);
++
++ if (SO at GUI@_DEBUG && 0) { // debug
++ SoDebugError::postInfo("So at Gui@Viewer::moveCameraScreen",
++ "newcampos: <%f, %f, %f>",
++ cam->position.getValue()[0],
++ cam->position.getValue()[1],
++ cam->position.getValue()[2]);
++ }
++}
++
++// Called when viewer enters interactive mode (animation, drag, ...).
++void
++So at Gui@ViewerP::interactivestartCB(void *, So at Gui@Viewer * thisp)
++{
++ // In interactive buffer mode, doublebuffering is used during interaction.
++ if (PRIVATE(thisp)->buffertype == So at Gui@Viewer::BUFFER_INTERACTIVE) {
++ PRIVATE(thisp)->localsetbuffertype = TRUE;
++ thisp->So at Gui@RenderArea::setDoubleBuffer(TRUE);
++ PRIVATE(thisp)->localsetbuffertype = FALSE;
++ }
++
++ // Use the dynamic drawstyle.
++ if (!PRIVATE(thisp)->drawInteractiveAsStill())
++ PRIVATE(thisp)->changeDrawStyle(PRIVATE(thisp)->drawstyles[So at Gui@Viewer::INTERACTIVE]);
++}
++
++// Called when viewer goes out of interactive mode and into "frozen"
++// mode.
++void
++So at Gui@ViewerP::interactiveendCB(void *, So at Gui@Viewer * thisp)
++{
++ // In interactive buffer mode, doublebuffering is used during
++ // interaction, singelbuffering while the camera is static.
++ if (PRIVATE(thisp)->buffertype == So at Gui@Viewer::BUFFER_INTERACTIVE) {
++ PRIVATE(thisp)->localsetbuffertype = TRUE;
++ thisp->So at Gui@RenderArea::setDoubleBuffer(FALSE);
++ PRIVATE(thisp)->localsetbuffertype = FALSE;
++ }
++
++ // Back to static drawstyle.
++ if (!PRIVATE(thisp)->drawInteractiveAsStill())
++ PRIVATE(thisp)->changeDrawStyle(PRIVATE(thisp)->drawstyles[So at Gui@Viewer::STILL]);
++}
++
++// Called repeatedly during the seek animation.
++void
++So at Gui@ViewerP::seeksensorCB(void * data, SoSensor * s)
++{
++ SbTime currenttime = SbTime::getTimeOfDay();
++
++ So at Gui@Viewer * thisp = (So at Gui@Viewer *)data;
++ SoTimerSensor * sensor = (SoTimerSensor *)s;
++
++ float t =
++ float((currenttime - sensor->getBaseTime()).getValue()) / PRIVATE(thisp)->seekperiod;
++ if ((t > 1.0f) || (t + sensor->getInterval().getValue() > 1.0f)) t = 1.0f;
++ SbBool end = (t == 1.0f);
++
++ t = (float) ((1.0 - cos(M_PI*t)) * 0.5);
++
++ PRIVATE(thisp)->camera->position = PRIVATE(thisp)->camerastartposition +
++ (PRIVATE(thisp)->cameraendposition - PRIVATE(thisp)->camerastartposition) * t;
++ PRIVATE(thisp)->camera->orientation =
++ SbRotation::slerp(PRIVATE(thisp)->camerastartorient,
++ PRIVATE(thisp)->cameraendorient,
++ t);
++
++ if (end) thisp->setSeekMode(FALSE);
++}
++
++// Reset the frames-per-second counter upon window resize events,
++// abnormal delays, etc.
++//
++// The methods for recording FPS values are Coin extensions, not
++// available in the original Open Inventor API.
++//
++// \sa addFrametime(), recordFPS()
++void
++So at Gui@ViewerP::resetFrameCounter(void)
++{
++ this->framecount = 0;
++ for (int i = 0; i < So at Gui@ViewerP::FRAMESARRAY_SIZE; i++)
++ this->frames[i] = SbVec2f(0.0f, 0.0f);
++ this->totalcoin = 0.0f;
++ this->totaldraw = 0.0f;
++ this->lastgettimeofday = SbTime::getTimeOfDay().getValue();
++}
++
++// Adds the time spent drawing the last frame to the array of past
++// frame times. Returns the current averaged fps-value.
++//
++// The methods for recording FPS values are Coin extensions, not
++// available in the original Open Inventor API.
++//
++// \sa resetFrameCounter(), recordFPS()
++SbVec2f
++So at Gui@ViewerP::addFrametime(const double ft)
++{
++ this->framecount++;
++
++ int arrayptr = (this->framecount - 1) % FRAMESARRAY_SIZE;
++
++ this->totalcoin += (float(ft) - this->frames[arrayptr][0]);
++ float coinfps =
++ this->totalcoin / So at Gui@Min(this->framecount, (int) FRAMESARRAY_SIZE);
++
++ double timeofday = SbTime::getTimeOfDay().getValue();
++ double ct = timeofday - this->lastgettimeofday;
++ this->totaldraw += (float(ct) - this->frames[arrayptr][1]);
++ float drawfps =
++ this->totaldraw / So at Gui@Min(this->framecount, (int) FRAMESARRAY_SIZE);
++
++ this->frames[arrayptr] = SbVec2f((float)ft, (float)ct);
++ this->lastgettimeofday = timeofday;
++
++ return SbVec2f(1.0f / coinfps, 1.0f / drawfps);
++}
++
++static unsigned char fps2dfont[][12] = {
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, //
++ { 0, 0, 12, 12, 0, 8, 12, 12, 12, 12, 12, 0 }, // !
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 20, 20, 20 }, // \"
++ { 0, 0, 18, 18, 18, 63, 18, 18, 63, 18, 18, 0 }, // #
++ { 0, 8, 28, 42, 10, 10, 12, 24, 40, 42, 28, 8 }, // $
++ { 0, 0, 6, 73, 41, 22, 8, 52, 74, 73, 48, 0 }, // %
++ { 0, 12, 18, 18, 12, 25, 37, 34, 34, 29, 0, 0 }, // &
++ { 12, 12, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // '
++ { 0, 6, 8, 8, 16, 16, 16, 16, 16, 8, 8, 6 }, // (
++ { 0, 48, 8, 8, 4, 4, 4, 4, 4, 8, 8, 48 }, //)
++ { 0, 0, 0, 0, 0, 0, 8, 42, 20, 42, 8, 0 }, // *
++ { 0, 0, 0, 8, 8, 8,127, 8, 8, 8, 0, 0 }, // +
++ { 0, 24, 12, 12, 0, 0, 0, 0, 0, 0, 0, 0 }, // ,
++ { 0, 0, 0, 0, 0, 0,127, 0, 0, 0, 0, 0 }, // -
++ { 0, 0, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0 }, // .
++ { 0, 32, 32, 16, 16, 8, 8, 8, 4, 4, 2, 2 }, // /
++ { 0, 0, 28, 34, 34, 34, 34, 34, 34, 34, 28, 0 }, // 0
++ { 0, 0, 8, 8, 8, 8, 8, 8, 40, 24, 8, 0 }, // 1
++ { 0, 0, 62, 32, 16, 8, 4, 2, 2, 34, 28, 0 }, // 2
++ { 0, 0, 28, 34, 2, 2, 12, 2, 2, 34, 28, 0 }, // 3
++ { 0, 0, 4, 4, 4,126, 68, 36, 20, 12, 4, 0 }, // 4
++ { 0, 0, 28, 34, 2, 2, 2, 60, 32, 32, 62, 0 }, // 5
++ { 0, 0, 28, 34, 34, 34, 60, 32, 32, 34, 28, 0 }, // 6
++ { 0, 0, 16, 16, 16, 8, 8, 4, 2, 2, 62, 0 }, // 7
++ { 0, 0, 28, 34, 34, 34, 28, 34, 34, 34, 28, 0 }, // 8
++ { 0, 0, 28, 34, 2, 2, 30, 34, 34, 34, 28, 0 }, // 9
++ { 0, 0, 24, 24, 0, 0, 0, 24, 24, 0, 0, 0 }, // :
++ { 0, 48, 24, 24, 0, 0, 0, 24, 24, 0, 0, 0 }, // ;
++ { 0, 0, 0, 2, 4, 8, 16, 8, 4, 2, 0, 0 }, // <
++ { 0, 0, 0, 0, 0,127, 0,127, 0, 0, 0, 0 }, // =
++ { 0, 0, 0, 16, 8, 4, 2, 4, 8, 16, 0, 0 }, // >
++ { 0, 0, 16, 16, 0, 16, 28, 2, 2, 2, 60, 0 }, // ?
++ { 0, 0, 28, 32, 73, 86, 82, 82, 78, 34, 28, 0 }, // @
++ { 0, 0, 33, 33, 33, 63, 18, 18, 18, 12, 12, 0 }, // A
++ { 0, 0, 60, 34, 34, 34, 60, 34, 34, 34, 60, 0 }, // B
++ { 0, 0, 14, 16, 32, 32, 32, 32, 32, 18, 14, 0 }, // C
++ { 0, 0, 56, 36, 34, 34, 34, 34, 34, 36, 56, 0 }, // D
++ { 0, 0, 62, 32, 32, 32, 60, 32, 32, 32, 62, 0 }, // E
++ { 0, 0, 16, 16, 16, 16, 30, 16, 16, 16, 30, 0 }, // F
++ { 0, 0, 14, 18, 34, 34, 32, 32, 32, 18, 14, 0 }, // G
++ { 0, 0, 34, 34, 34, 34, 62, 34, 34, 34, 34, 0 }, // H
++ { 0, 0, 62, 8, 8, 8, 8, 8, 8, 8, 62, 0 }, // I
++ { 0, 0,112, 8, 8, 8, 8, 8, 8, 8, 62, 0 }, // J
++ { 0, 0, 33, 33, 34, 36, 56, 40, 36, 34, 33, 0 }, // K
++ { 0, 0, 30, 16, 16, 16, 16, 16, 16, 16, 16, 0 }, // L
++ { 0, 0, 33, 33, 33, 45, 45, 45, 51, 51, 33, 0 }, // M
++ { 0, 0, 34, 34, 38, 38, 42, 42, 50, 50, 34, 0 }, // N
++ { 0, 0, 12, 18, 33, 33, 33, 33, 33, 18, 12, 0 }, // O
++ { 0, 0, 32, 32, 32, 60, 34, 34, 34, 34, 60, 0 }, // P
++ { 3, 6, 12, 18, 33, 33, 33, 33, 33, 18, 12, 0 }, // Q
++ { 0, 0, 34, 34, 34, 36, 60, 34, 34, 34, 60, 0 }, // R
++ { 0, 0, 60, 2, 2, 6, 28, 48, 32, 32, 30, 0 }, // S
++ { 0, 0, 8, 8, 8, 8, 8, 8, 8, 8,127, 0 }, // T
++ { 0, 0, 28, 34, 34, 34, 34, 34, 34, 34, 34, 0 }, // U
++ { 0, 0, 12, 12, 18, 18, 18, 33, 33, 33, 33, 0 }, // V
++ { 0, 0, 34, 34, 34, 54, 85, 73, 73, 73, 65, 0 }, // W
++ { 0, 0, 34, 34, 20, 20, 8, 20, 20, 34, 34, 0 }, // X
++ { 0, 0, 8, 8, 8, 8, 20, 20, 34, 34, 34, 0 }, // Y
++ { 0, 0, 62, 32, 16, 16, 8, 4, 4, 2, 62, 0 }, // Z
++ { 0, 14, 8, 8, 8, 8, 8, 8, 8, 8, 8, 14 }, // [
++ { 0, 2, 2, 4, 4, 8, 8, 8, 16, 16, 32, 32 }, // [backslash]
++ { 0, 56, 8, 8, 8, 8, 8, 8, 8, 8, 8, 56 }, // ]
++ { 0, 0, 0, 0, 0, 34, 34, 20, 20, 8, 8, 0 }, // ^
++ { 0,127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // _
++ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 12 }, // `
++ { 0, 0, 29, 34, 34, 30, 2, 34, 28, 0, 0, 0 }, // a
++ { 0, 0, 60, 34, 34, 34, 34, 50, 44, 32, 32, 32 }, // b
++ { 0, 0, 14, 16, 32, 32, 32, 16, 14, 0, 0, 0 }, // c
++ { 0, 0, 26, 38, 34, 34, 34, 34, 30, 2, 2, 2 }, // d
++ { 0, 0, 28, 34, 32, 62, 34, 34, 28, 0, 0, 0 }, // e
++ { 0, 0, 16, 16, 16, 16, 16, 16, 62, 16, 16, 14 }, // f
++ { 28, 2, 2, 26, 38, 34, 34, 34, 30, 0, 0, 0 }, // g
++ { 0, 0, 34, 34, 34, 34, 34, 50, 44, 32, 32, 32 }, // h
++ { 0, 0, 8, 8, 8, 8, 8, 8, 56, 0, 8, 8 }, // i
++ { 56, 4, 4, 4, 4, 4, 4, 4, 60, 0, 4, 4 }, // j
++ { 0, 0, 33, 34, 36, 56, 40, 36, 34, 32, 32, 32 }, // k
++ { 0, 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 56 }, // l
++ { 0, 0, 73, 73, 73, 73, 73,109, 82, 0, 0, 0 }, // m
++ { 0, 0, 34, 34, 34, 34, 34, 50, 44, 0, 0, 0 }, // n
++ { 0, 0, 28, 34, 34, 34, 34, 34, 28, 0, 0, 0 }, // o
++ { 32, 32, 60, 34, 34, 34, 34, 50, 44, 0, 0, 0 }, // p
++ { 2, 2, 26, 38, 34, 34, 34, 34, 30, 0, 0, 0 }, // q
++ { 0, 0, 16, 16, 16, 16, 16, 24, 22, 0, 0, 0 }, // r
++ { 0, 0, 60, 2, 2, 28, 32, 32, 30, 0, 0, 0 }, // s
++ { 0, 0, 14, 16, 16, 16, 16, 16, 62, 16, 16, 0 }, // t
++ { 0, 0, 26, 38, 34, 34, 34, 34, 34, 0, 0, 0 }, // u
++ { 0, 0, 8, 8, 20, 20, 34, 34, 34, 0, 0, 0 }, // v
++ { 0, 0, 34, 34, 34, 85, 73, 73, 65, 0, 0, 0 }, // w
++ { 0, 0, 34, 34, 20, 8, 20, 34, 34, 0, 0, 0 }, // x
++ { 48, 16, 8, 8, 20, 20, 34, 34, 34, 0, 0, 0 }, // y
++ { 0, 0, 62, 32, 16, 8, 4, 2, 62, 0, 0, 0 }, // z
++ { 0, 6, 8, 8, 8, 4, 24, 4, 8, 8, 8, 6 }, // {
++ { 0, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 }, // |
++ { 0, 48, 8, 8, 8, 16, 12, 16, 8, 8, 8, 48 }, // }
++ { 0, 0, 0, 0, 0, 0, 78, 57, 0, 0, 0, 0 } // ~
++};
++
++static void
++printString(const char * s)
++{
++ int i,n;
++ n = strlen(s);
++ for (i = 0; i < n; i++)
++ glBitmap(8, 12, 0.0, 2.0, 10.0, 0.0, fps2dfont[s[i] - 32]);
++}
++
++static void
++Draw2DString(const char * str, SbVec2s glsize, SbVec2f position)
++{
++ // Store GL state.
++ glPushAttrib(GL_ENABLE_BIT|GL_CURRENT_BIT);
++
++ glDisable(GL_LIGHTING);
++ glDisable(GL_DEPTH_TEST);
++ glDisable(GL_TEXTURE_2D);
++ glDisable(GL_BLEND);
++
++ glMatrixMode(GL_MODELVIEW);
++ glPushMatrix();
++ glLoadIdentity();
++
++ glMatrixMode(GL_PROJECTION);
++ glPushMatrix();
++ glLoadIdentity();
++ glOrtho(0.0, glsize[0], 0.0, glsize[1], -1, 1);
++
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++
++ glColor3f(0.0, 0.0, 0.0);
++ glRasterPos2f(position[0] + 1, position[1]);
++ printString(str);
++ glRasterPos2f(position[0] - 1, position[1]);
++ printString(str);
++ glRasterPos2f(position[0], position[1] + 1);
++ printString(str);
++ glRasterPos2f(position[0], position[1] - 1);
++ printString(str);
++
++ glColor3f(1.0, 1.0, 0.0);
++ glRasterPos2f(position[0], position[1]);
++ printString(str);
++
++ glMatrixMode(GL_PROJECTION);
++ glPopMatrix();
++ glMatrixMode(GL_MODELVIEW);
++ glPopMatrix();
++
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 4); // restore default value
++
++ glPopAttrib();
++}
++
++
++// FIXME: the following is just a temporary hack to enable the FPS
++// counter. We should really write a proper interface against it, so
++// applications can set up feedback loops to control scene complexity
++// and get a nice and steady maximum framerate, for instance.
++//
++// For anyone who want to execute that task, check what TGS has done
++// first. If their API is fine, use the same approach.
++//
++// 20001124 mortene.
++
++// Draw a text string showing the current frame-per-seconds value in
++// the lower left corner of the OpenGL canvas (after recording
++// information needed to calculate the fps).
++//
++// The methods for recording FPS values are Coin extensions, not
++// available in the original Open Inventor API.
++//
++// The two displayed values can be explained as follows:
++//
++// The first number is the time it takes for the SoGLRenderAction to
++// traverse the scene graph (displayed as Hz / FPS). The second is the
++// interval between each time SoGLRenderAction::apply() is invoked
++// (i.e. the "actual" rendering rate, as experienced by the user).
++//
++// The first number is mainly useful just for internal debugging
++// purposes.
++//
++// The second number will always be <= to the first, because it will
++// also include the time stalling on glFlush() upon releasing the
++// OpenGL context after traversal (glFlush() stalls until the GPU
++// completes all OpenGL commands), and any application-code processing
++// inbetween rendering.
++//
++// There is by the way a useful "trick" to improve application
++// performance implied in that last paragraph above: if
++// application-code processing is interleaved between the completion
++// of the SoGLRenderAction traversal and the release of the OpenGL
++// context, application-code is likely to run on the CPU in parallel
++// with GPU processing OpenGL commands.
++//
++// FIXME: the above optimization trick should be documented in the
++// visible API docs somewhere, with code to show how to do it. The
++// example code would probably involve making an application-specific
++// viewer, and overriding actualRedraw()? Or can it be done by using a
++// callback mechanism somewhere? Ask pederb. 20031009 mortene.
++//
++// \sa resetFrameCounter(), addFrametime()
++void
++So at Gui@ViewerP::recordFPS(const double rendertime)
++{
++ const char * env = SoAny::si()->getenv("COIN_SHOW_FPS_COUNTER");
++ if ( !env ) {
++ COIN_SHOW_FPS_COUNTER = UNINITIALIZED_ENVVAR;
++ } else {
++ COIN_SHOW_FPS_COUNTER = atoi(env);
++ }
++
++#if 0
++ // disabled to make fps-couter dynamically adjustable
++ if (COIN_SHOW_FPS_COUNTER == UNINITIALIZED_ENVVAR) {
++ const char * env = SoAny::si()->getenv("COIN_SHOW_FPS_COUNTER");
++ COIN_SHOW_FPS_COUNTER = env ? atoi(env) : 0;
++ }
++#endif
++
++ if (COIN_SHOW_FPS_COUNTER > 0) {
++ SbVec2f fps = this->addFrametime(rendertime);
++
++ char buffer[64];
++ int nr = sprintf(buffer, "%.1f/%.1f fps", fps[0], fps[1]);
++ assert(nr < 64);
++ Draw2DString(buffer, PUBLIC(this)->getGLSize(), SbVec2f(10, 10));
++ }
++}
++
++// *************************************************************************
++
++SO at GUI@_OBJECT_ABSTRACT_SOURCE(So at Gui@Viewer);
++
++// *************************************************************************
++
++/*!
++ \enum So at Gui@Viewer::Type
++
++ Hints about what context the viewer will be used in. Usually not
++ very interesting for the application programmer, it doesn't matter
++ much which value is used for the viewer type. This "feature" of the
++ viewer is included just to be compatible with the old SGI Inventor
++ API.
++*/
++/*!
++ \var So at Gui@Viewer::Type So at Gui@Viewer::BROWSER
++
++ If a user-supplied scenegraph passed into the setSceneGraph()
++ function does not contain a camera, setting the viewer type to
++ BROWSER will make the viewer in that case automatically set up a
++ camera outside the scene, as part of the viewer's private and hidden
++ "supergraph".
++*/
++/*!
++ \var So at Gui@Viewer::Type So at Gui@Viewer::EDITOR
++
++ If a user-supplied scenegraph passed into the setSceneGraph()
++ function does not contain a camera, setting the viewer type to
++ EDITOR will make the viewer in that case automatically set up a
++ camera \e in the user-supplied scene.
++
++ So if you want to avoid having the So at Gui@Viewer class muck about
++ with your supplied scenegraph, set the type-flag to
++ So at Gui@Viewer::BROWSER instead, which makes an inserted camera node
++ go into the viewer's own "wrapper" scene graph instead.
++*/
++
++/*!
++ \enum So at Gui@Viewer::DrawType
++
++ Contains valid values for the first argument to the
++ So at Gui@Viewer::setDrawStyle() call. Decides the effect of the second
++ argument.
++
++ \sa So at Gui@Viewer::setDrawStyle(), So at Gui@Viewer::DrawStyle
++*/
++/*!
++ \var So at Gui@Viewer::DrawType So at Gui@Viewer::STILL
++
++ If this value is passed as the first argument of
++ So at Gui@Viewer::setDrawStyle(), the second argument decides which
++ draw style to use when the viewer camera is standing still in the
++ same position with the same orientation -- i.e. when the end user is
++ \e not interacting with the scene camera.
++*/
++/*!
++ \var So at Gui@Viewer::DrawType So at Gui@Viewer::INTERACTIVE
++
++ If this value is passed as the first argument of
++ So at Gui@Viewer::setDrawStyle(), the second argument decides which
++ draw style to use when the end user is interacting with the scene
++ camera, causing continuous animation redraws.
++*/
++
++/*!
++ \enum So at Gui@Viewer::DrawStyle
++
++ Decides drawstyle for a scene with either a still camera or an
++ animating camera.
++
++ \sa So at Gui@Viewer::setDrawStyle(), So at Gui@Viewer::DrawType
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_AS_IS
++
++ Normal rendering, draws all scene geometry in it's original style.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_HIDDEN_LINE
++
++ Draw scene in "hidden line" mode: that is, as wireframe with no
++ "see-through".
++
++ Note that this is actually an expensive way to render, as the scene
++ must be rendered twice to achieve the effect of hiding lines behind
++ the invisible geometry.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_WIREFRAME_OVERLAY
++
++ Render the scene as normal, but overlay a set of lines showing the
++ contours of all polygons.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_NO_TEXTURE
++
++ Render scene without textures.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LOW_COMPLEXITY
++
++ Render all "complex" shape types with low complexity to improve
++ rendering performance.
++
++ "Complex shapes" in this context includes spheres, cones, cylinder,
++ NURBS surfaces, and others which are tesselated to polygons before
++ being rendered.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LINE
++
++ View all polygon geometry in wireframe mode.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_POINT
++
++ Render only the vertex positions of the geometry.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_BBOX
++
++ View the scene's bounding boxes, instead of rendering the full
++ geometry.
++
++ A very efficient way of optimizing rendering performance for scenes
++ with high primitive counts while moving the camera about is to set
++ this mode for the So at Gui@Viewer::INTERACTIVE DrawType.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LOW_RES_LINE
++
++ Render as wireframe and don't bother with getting them rendered
++ correctly in depth.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_LOW_RES_POINT
++
++ Render as vertex points and don't bother with getting them rendered
++ correctly in depth.
++*/
++/*!
++ \var So at Gui@Viewer::DrawStyle So at Gui@Viewer::VIEW_SAME_AS_STILL
++
++ Always render a scene with an animating camera (ie
++ So at Gui@Viewer::INTERACTIVE DrawType) in the same manner as scene
++ with a still camera.
++*/
++
++/*!
++ \enum So at Gui@Viewer::BufferType
++ Set of valid values for So at Gui@Viewer::setBufferingType().
++*/
++/*!
++ \var So at Gui@Viewer::BufferType So at Gui@Viewer::BUFFER_SINGLE
++ Change underlying OpenGL canvas to be single-buffered.
++*/
++/*!
++ \var So at Gui@Viewer::BufferType So at Gui@Viewer::BUFFER_DOUBLE
++ Change underlying OpenGL canvas to be double-buffered.
++*/
++/*!
++ \var So at Gui@Viewer::BufferType So at Gui@Viewer::BUFFER_INTERACTIVE
++
++ Set up so animation rendering is done in a double-buffered OpenGL
++ canvas, but ordinary rendering happens directly in the front-buffer.
++
++ This mode can be useful with absurdly large scenes, as the rendering
++ will \e visibly progress, and one will avoid having the end user
++ wonder why nothing is happening while the scene is rendered to the
++ back buffer in the default So at Gui@Viewer::BUFFER_DOUBLE mode.
++*/
++
++// *************************************************************************
++
++/*
++ Return the parent node in the scene graph of the given \a node.
++ NB: this is just a quick'n'dirty thing for often executed code,
++ and doesn't cover cases where nodes have multiple parents.
++*/
++
++SoGroup *
++So at Gui@ViewerP::getParentOfNode(SoNode * root, SoNode * node) const
++{
++ assert(node && root && "called with null argument");
++
++ const SbBool oldsearch = SoBaseKit::isSearchingChildren();
++ SoBaseKit::setSearchingChildren(TRUE);
++
++ this->searchaction->reset();
++ this->searchaction->setSearchingAll(TRUE);
++ this->searchaction->setNode(node);
++ this->searchaction->apply(root);
++
++ SoPath * p = this->searchaction->getPath();
++
++ SoGroup * parent = NULL;
++ if (p) {
++ parent = (SoGroup *) ((SoFullPath *)p)->getNodeFromTail(1);
++ assert(parent && "couldn't find parent");
++ }
++
++ this->searchaction->reset();
++
++ SoBaseKit::setSearchingChildren(oldsearch);
++
++ return parent;
++}
++
++// *************************************************************************
++
++/*!
++ Constructor. \a parent, \a name and \a embed are passed on to
++ So at Gui@RenderArea, so see the documentation for our parent
++ constructor for for more information on those.
++
++ The \a t type setting hints about what context the viewer will be
++ used in. Usually not very interesting for the application
++ programmer, but if you want to make sure the So at Gui@Viewer class
++ doesn't muck about with your supplied scenegraph, set the type-flag
++ to So at Gui@Viewer::BROWSER. (This "feature" of the viewer is
++ included just to be compatible with the old SGI Inventor API.)
++
++ The \a build flag decides whether or not to delay building the
++ widgets / window which is going to make up the components of the
++ viewer.
++*/
++So at Gui@Viewer::So at Gui@Viewer(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ So at Gui@Viewer::Type t,
++ SbBool build)
++ : inherited(parent, name, embed, TRUE, TRUE, FALSE)
++{
++ PRIVATE(this) = new So at Gui@ViewerP(this);
++
++ // initialization of protected data
++ PRIVATE(this)->type = t;
++ PRIVATE(this)->viewingflag = TRUE;
++ PRIVATE(this)->altdown = FALSE;
++ PRIVATE(this)->camera = NULL;
++ PRIVATE(this)->scenegraph = NULL;
++
++ // initialization of internal data
++ PRIVATE(this)->cursoron = TRUE;
++ PRIVATE(this)->localsetbuffertype = FALSE;
++
++ PRIVATE(this)->cameratype = SoPerspectiveCamera::getClassTypeId();
++ PRIVATE(this)->buffertype = this->isDoubleBuffer() ? BUFFER_DOUBLE : BUFFER_SINGLE;
++
++ PRIVATE(this)->interactionstartCallbacks = new SoCallbackList;
++ PRIVATE(this)->interactionendCallbacks = new SoCallbackList;
++ PRIVATE(this)->interactionnesting = 0;
++
++ PRIVATE(this)->seekdistance = 50.0f;
++ PRIVATE(this)->seekdistanceabs = FALSE;
++ PRIVATE(this)->seektopoint = TRUE;
++ PRIVATE(this)->seekperiod = 2.0f;
++ PRIVATE(this)->inseekmode = FALSE;
++ PRIVATE(this)->seeksensor = new SoTimerSensor(So at Gui@ViewerP::seeksensorCB, this);
++
++ PRIVATE(this)->sceneroot = PRIVATE(this)->createSuperScene();
++ PRIVATE(this)->sceneroot->ref();
++
++ PRIVATE(this)->drawstyles[STILL] = VIEW_AS_IS;
++ PRIVATE(this)->drawstyles[INTERACTIVE] = VIEW_SAME_AS_STILL;
++
++ this->addStartCallback(So at Gui@ViewerP::interactivestartCB);
++ this->addFinishCallback(So at Gui@ViewerP::interactiveendCB);
++
++ PRIVATE(this)->adjustclipplanes = TRUE;
++ PRIVATE(this)->autoclipbboxaction = NULL;
++
++ PRIVATE(this)->stereoviewing = FALSE;
++ PRIVATE(this)->stereooffset = 0.1f;
++
++ PRIVATE(this)->wireframeoverlaycolor = SbColor(1.0f, 0.0f, 0.0f);
++
++ if (build) {
++ this->setClassName("So at Gui@Viewer");
++ @WIDGET@ widget = this->buildWidget(this->getParentWidget());
++ this->setBaseWidget(widget);
++ }
++
++ PRIVATE(this)->resetFrameCounter();
++}
++
++// *************************************************************************
++
++/*!
++ Destructor.
++*/
++
++So at Gui@Viewer::~So at Gui@Viewer()
++{
++ delete PRIVATE(this)->autoclipbboxaction;
++
++ delete PRIVATE(this)->interactionstartCallbacks;
++ delete PRIVATE(this)->interactionendCallbacks;
++
++ delete PRIVATE(this)->seeksensor;
++
++ if (PRIVATE(this)->scenegraph) this->setSceneGraph(NULL);
++ if (PRIVATE(this)->superimpositions != NULL) {
++ while ( PRIVATE(this)->superimpositions->getLength() > 0 ) {
++ SoNode * node = (SoNode *) (*PRIVATE(this)->superimpositions)[0];
++ this->removeSuperimposition(node);
++ }
++ }
++ PRIVATE(this)->sceneroot->unref();
++ delete PRIVATE(this);
++}
++
++// *************************************************************************
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++ Set the camera we want the viewer to manipulate when interacting with
++ the viewer controls.
++
++ The camera passed in as an argument to this method \e must already
++ be part of the viewer's scenegraph. You do \e not inject viewpoint
++ cameras to the viewer with this method.
++
++ You should rather insert a camera into the scene graph first (if
++ necessary, often one will be present already), then register it as
++ the camera used by the viewer controls with this method.
++
++ If the application code doesn't explicitly set up a camera through
++ this method, the viewer will automatically scan through the
++ scenegraph to find a camera to use. If no camera is available in the
++ scenegraph at all, it will set up it's own camera.
++
++ \sa getCamera()
++*/
++void
++So at Gui@Viewer::setCamera(SoCamera * cam)
++{
++ if (PRIVATE(this)->camera) {
++ // remove the camera from the super scene graph if we inserted a camera there
++ int idx = PRIVATE(this)->sceneroot->findChild(PRIVATE(this)->camera);
++ if (idx >= 0) {
++ PRIVATE(this)->sceneroot->removeChild(idx);
++ }
++ PRIVATE(this)->camera->unref();
++ }
++
++ if (cam) {
++ cam->ref();
++ PRIVATE(this)->cameratype = cam->getTypeId();
++ }
++
++ PRIVATE(this)->camera = cam;
++
++ this->saveHomePosition();
++}
++
++// *************************************************************************
++
++/*!
++ Returns the camera currently used by the viewer for the user's main
++ viewpoint.
++
++ It \e is possible that this function returns \c NULL, for instance
++ if there's no scenegraph present in the viewer. (This is mostly
++ meant as a note for developers extending the So at Gui@ library, as
++ application programmers usually controls if and when a viewer
++ contains a scenegraph, and therefore know in advance if this method
++ will return a valid camera pointer.)
++
++ \sa setCamera()
++*/
++SoCamera *
++So at Gui@Viewer::getCamera(void) const
++{
++ // This impossible to miss reminder was inserted so we don't
++ // accidentally let an So* v2 slip out the door without fixing this
++ // API design flaw. 20030903 mortene.
++#if (SO at GUI@_MAJOR_VERSION == 2)
++#error This is a reminder: when jumping to version 2 of an So* toolkit, the So at Gui@Viewer::getCamera() method should be made virtual.
++#endif // version = 2
++
++ return PRIVATE(this)->camera;
++}
++
++// *************************************************************************
++
++/*!
++ When the viewer has to make its own camera as a result of the graph
++ passed to setSceneGraph() not containing any camera nodes, this call
++ can be made in advance to decide which type the camera will be of.
++
++ Default is to use an SoPerspectiveCamera.
++
++ If this method is called when there is a scene graph and a camera
++ already set up, it will delete the old camera and set up a camera
++ with the new type if the \a t type is different from that of the
++ current camera.
++
++ \sa getCameraType()
++*/
++
++void
++So at Gui@Viewer::setCameraType(SoType t)
++{
++ if (PRIVATE(this)->camera &&
++ !PRIVATE(this)->camera->isOfType(SoPerspectiveCamera::getClassTypeId()) &&
++ !PRIVATE(this)->camera->isOfType(SoOrthographicCamera::getClassTypeId())) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postWarning("So at Gui@Viewer::setCameraType",
++ "Only SoPerspectiveCamera and SoOrthographicCamera is supported.");
++#endif // SO at GUI_DEBUG
++ return;
++ }
++
++
++ SoType perspectivetype = SoPerspectiveCamera::getClassTypeId();
++ SoType orthotype = SoOrthographicCamera::getClassTypeId();
++ SbBool oldisperspective = PRIVATE(this)->cameratype.isDerivedFrom(perspectivetype);
++ SbBool newisperspective = t.isDerivedFrom(perspectivetype);
++
++ if ((oldisperspective && newisperspective) ||
++ (!oldisperspective && !newisperspective)) // Same old, same old..
++ return;
++
++ if (SO at GUI@_DEBUG) {
++ SbBool valid = TRUE;
++ if (t == SoType::badType()) valid = FALSE;
++ if (valid) {
++ valid = FALSE;
++ if (newisperspective) valid = TRUE;
++ if (t.isDerivedFrom(orthotype)) valid = TRUE;
++ }
++
++ if (!valid) {
++ SoDebugError::post("So at Gui@Viewer::setCameraType",
++ "not a valid camera type: '%s'",
++ t == SoType::badType() ?
++ "badType" : t.getName().getString());
++ return;
++ }
++ }
++
++ SoCamera * currentcam = PRIVATE(this)->camera;
++
++ if (currentcam == NULL) {
++ // A camera has not been set up for the scene yet, so just store
++ // the type and short-cut the rest of this function.
++ PRIVATE(this)->cameratype = t;
++ return;
++ }
++
++ SoCamera * newcamera = (SoCamera *)t.createInstance();
++
++ // Transfer and convert values from one camera type to the other.
++ if (newisperspective) {
++ So at Gui@ViewerP::convertOrtho2Perspective((SoOrthographicCamera *)currentcam,
++ (SoPerspectiveCamera *)newcamera);
++ }
++ else {
++ So at Gui@ViewerP::convertPerspective2Ortho((SoPerspectiveCamera *)currentcam,
++ (SoOrthographicCamera *)newcamera);
++ }
++
++ SoGroup * cameraparent =
++ PRIVATE(this)->getParentOfNode(PRIVATE(this)->sceneroot, currentcam);
++ if (cameraparent) { cameraparent->replaceChild(currentcam, newcamera); }
++ else {
++ // camera not actually present in the scene graph, so just NULL
++ // and void.
++ newcamera->ref();
++ newcamera->unref();
++ newcamera = NULL;
++
++ // Yes, this can "legally" happen, if e.g. the camera is taken out
++ // of the scene graph by the app programmer, and no new camera was
++ // set with setCamera() -- but this is a quite odd thing to do, so
++ // we warn about this for now.
++ SoDebugError::postWarning("So at Gui@Viewer::setCameraType",
++ "Could not find the current camera in the "
++ "scene graph, for some odd reason.");
++ }
++
++ // The setCamera() invokation below will set the saved "home"
++ // position of the camera to the current camera position. We make
++ // no attempt to avoid this, as it would involve nasty hacks, and
++ // it shouldn't really matter.
++
++ this->setCamera(newcamera); // This will set PRIVATE(this)->cameratype.
++}
++
++// *************************************************************************
++
++/*!
++ Returns camera type which will be used when the viewer has to make its
++ own camera.
++
++ Note that this call does \e not return the current cameratype, as one
++ might expect. Use getCamera() and SoType::getTypeId() for that inquiry.
++
++ \sa setCameraType()
++*/
++
++SoType
++So at Gui@Viewer::getCameraType(void) const
++{
++ return PRIVATE(this)->cameratype;
++}
++
++// *************************************************************************
++
++/*!
++ Reposition the current camera so we can see the complete scene.
++*/
++void
++So at Gui@Viewer::viewAll(void)
++{
++ SoCamera * cam = PRIVATE(this)->camera;
++ if (cam && PRIVATE(this)->scenegraph) {
++ cam->viewAll(PRIVATE(this)->scenegraph, this->getViewportRegion());
++ }
++}
++
++// *************************************************************************
++
++/*!
++ Store the current camera settings for later retrieval with
++ resetToHomePosition().
++
++ \sa resetToHomePosition()
++*/
++void
++So at Gui@Viewer::saveHomePosition(void)
++{
++ if (! PRIVATE(this)->camera) return; // probably a scene-less viewer
++
++ // We use SoType::createInstance() to store a copy of the camera,
++ // not just assuming it's either a perspective or an orthographic
++ // camera.
++
++ SoType t = PRIVATE(this)->camera->getTypeId();
++ assert(t.isDerivedFrom(SoNode::getClassTypeId()));
++ assert(t.canCreateInstance());
++
++ if (PRIVATE(this)->storedcamera) { PRIVATE(this)->storedcamera->unref(); }
++
++ PRIVATE(this)->storedcamera = (SoNode *)t.createInstance();
++ PRIVATE(this)->storedcamera->ref();
++
++ // We copy the field data directly, instead of using
++ // SoFieldContainer::copyContents(), as that has one problematic
++ // side-effect: the new camera node used for storing the data would
++ // also get the *name* of the old camera, which would overwrite the
++ // old name->ptr entry of the global dictionary behind
++ // SoNode::getByName(). This can cause surprising and hard to find
++ // bugs for app programmers, for instance when using
++ // SoNode::getByName() to get at a camera loaded from an iv-file.
++ PRIVATE(this)->storedcamera->copyFieldValues(PRIVATE(this)->camera);
++}
++
++// *************************************************************************
++
++/*!
++ Restore the saved camera settings.
++
++ \sa saveHomePosition()
++*/
++void
++So at Gui@Viewer::resetToHomePosition(void)
++{
++ if (!PRIVATE(this)->camera) { return; } // probably a scene-less viewer
++ if (!PRIVATE(this)->storedcamera) { return; }
++
++ SoType t = PRIVATE(this)->camera->getTypeId();
++ SoType s = PRIVATE(this)->storedcamera->getTypeId();
++
++ // most common case
++ if (t == s) {
++ // We copy the field data directly, instead of using
++ // SoFieldContainer::copyContents(), for the reason described in
++ // detail in So at Gui@Viewer::saveHomePosition().
++ PRIVATE(this)->camera->copyFieldValues(PRIVATE(this)->storedcamera);
++ }
++ // handle common case #1
++ else if (t == SoOrthographicCamera::getClassTypeId() &&
++ s == SoPerspectiveCamera::getClassTypeId()) {
++ So at Gui@ViewerP::convertPerspective2Ortho((SoPerspectiveCamera *)PRIVATE(this)->storedcamera,
++ (SoOrthographicCamera *)PRIVATE(this)->camera);
++ }
++ // handle common case #2
++ else if (t == SoPerspectiveCamera::getClassTypeId() &&
++ s == SoOrthographicCamera::getClassTypeId()) {
++ So at Gui@ViewerP::convertOrtho2Perspective((SoOrthographicCamera *)PRIVATE(this)->storedcamera,
++ (SoPerspectiveCamera *)PRIVATE(this)->camera);
++ }
++ // otherwise, cameras have changed in ways we don't understand since
++ // the last saveHomePosition() invokation, and so we're just going
++ // to ignore the reset request
++}
++
++// *************************************************************************
++
++/*!
++ Turn the camera headlight on or off.
++
++ Default is to have a headlight turned on.
++
++ \sa isHeadlight(), getHeadlight()
++*/
++
++void
++So at Gui@Viewer::setHeadlight(SbBool on)
++{
++ PRIVATE(this)->headlight->on = on;
++}
++
++// *************************************************************************
++
++/*!
++ Returns status of the viewer headlight, whether it is on or off.
++
++ \sa setHeadlight(), getHeadlight()
++*/
++
++SbBool
++So at Gui@Viewer::isHeadlight(void) const
++{
++ return PRIVATE(this)->headlight->on.getValue();
++}
++
++// *************************************************************************
++
++/*!
++ Returns the a pointer to the directional light node which is the
++ viewer headlight.
++
++ The fields of the node is available for user editing.
++
++ \sa isHeadlight(), setHeadlight()
++*/
++
++SoDirectionalLight *
++So at Gui@Viewer::getHeadlight(void) const
++{
++ return PRIVATE(this)->headlight;
++}
++
++// *************************************************************************
++
++/*!
++ Set up a drawing style. The \a type argument specifies if the given
++ \a style should be interpreted as the drawstyle during animation or
++ when the camera is static.
++
++ Default values for the drawing style is to render the scene "as is"
++ in both still mode and while the camera is moving.
++
++ See the documentation for the \a DrawType and \a DrawStyle for more
++ information.
++
++ \sa getDrawStyle()
++*/
++void
++So at Gui@Viewer::setDrawStyle(So at Gui@Viewer::DrawType type,
++ So at Gui@Viewer::DrawStyle style)
++{
++ if (SO at GUI@_DEBUG) {
++ if ((type != STILL) && (type != INTERACTIVE)) {
++ SoDebugError::postWarning("So at Gui@Viewer::setDrawStyle",
++ "unknown drawstyle type setting 0x%x", type);
++ return;
++ }
++ }
++
++ if (style == this->getDrawStyle(type)) {
++ if (SO at GUI@_DEBUG && 0) { // debug
++ SoDebugError::postWarning("So at Gui@Viewer::setDrawStyle",
++ "drawstyle for type 0x%02x already 0x%02x",
++ type, style);
++ }
++ return;
++ }
++
++ PRIVATE(this)->drawstyles[type] = style;
++ PRIVATE(this)->changeDrawStyle(PRIVATE(this)->currentDrawStyle());
++}
++
++// *************************************************************************
++
++/*!
++ Return current drawstyles for the given type (\a STILL or
++ \a INTERACTIVE).
++
++ \sa setDrawStyle()
++*/
++
++So at Gui@Viewer::DrawStyle
++So at Gui@Viewer::getDrawStyle(const So at Gui@Viewer::DrawType type) const
++{
++ if (SO at GUI@_DEBUG) {
++ if ((type != STILL) && (type != INTERACTIVE)) {
++ SoDebugError::postWarning("So at Gui@Viewer::setDrawStyle",
++ "unknown drawstyle type setting 0x%x", type);
++ return PRIVATE(this)->drawstyles[STILL];
++ }
++ }
++
++ return PRIVATE(this)->drawstyles[type];
++}
++
++// *************************************************************************
++
++/*!
++ Set the viewer's buffer type. Available types are \c
++ So at Gui@Viewer::BUFFER_SINGLE, \c So at Gui@Viewer::BUFFER_DOUBLE and \c
++ So at Gui@Viewer::BUFFER_INTERACTIVE.
++
++ (With a buffer type of \c So at Gui@Viewer::BUFFER_INTERACTIVE, the
++ viewer will render with doublebuffering during user interaction and
++ with single buffering otherwise.)
++
++ Default is \c So at Gui@Viewer::BUFFER_DOUBLE.
++
++ \sa getBufferingType()
++*/
++
++void
++So at Gui@Viewer::setBufferingType(So at Gui@Viewer::BufferType type)
++{
++ if (type == PRIVATE(this)->buffertype) return;
++
++ if (type != BUFFER_SINGLE &&
++ type != BUFFER_DOUBLE &&
++ type != BUFFER_INTERACTIVE) {
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postWarning("So at Gui@Viewer::setBufferingType",
++ "unknown buffer type 0x%x", type);
++ }
++ return;
++ }
++
++ PRIVATE(this)->buffertype = type;
++
++ PRIVATE(this)->localsetbuffertype = TRUE;
++ inherited::setDoubleBuffer(type == BUFFER_DOUBLE);
++ PRIVATE(this)->localsetbuffertype = FALSE;
++}
++
++// *************************************************************************
++
++/*!
++ Return the viewer's buffer type.
++
++ \sa setBufferingType()
++*/
++
++So at Gui@Viewer::BufferType
++So at Gui@Viewer::getBufferingType(void) const
++{
++ return PRIVATE(this)->buffertype;
++}
++
++// *************************************************************************
++
++// Note: this documentation for setViewing() will also be used for all
++// the miscellaneous viewer subclasses, so keep it general.
++/*!
++ Set view mode.
++
++ If the view mode is on, user events will be caught and used to
++ influence the camera position / orientation. If view mode is off,
++ all events in the viewer canvas (like for instance keypresses or
++ mouseclicks and -movements) will be passed along to the scene graph.
++
++ Default is to have the view mode active.
++
++ \sa isViewing()
++*/
++void
++So at Gui@Viewer::setViewing(SbBool enable)
++{
++ if (PRIVATE(this)->viewingflag == enable) {
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postWarning("So at Gui@Viewer::setViewing",
++ "unnecessary called");
++ }
++ return;
++ }
++
++ PRIVATE(this)->viewingflag = enable;
++
++ // Turn off the selection indicators when we go back from picking
++ // mode into viewing mode.
++ if (PRIVATE(this)->viewingflag) {
++ SoGLRenderAction * action = this->getGLRenderAction();
++ if (action != NULL)
++ SoLocateHighlight::turnOffCurrentHighlight(action);
++ }
++}
++
++// *************************************************************************
++
++/*!
++ Return state of view mode.
++
++ \c TRUE means that the mode of the viewer is set such that user
++ interaction with the mouse is used to modify the position and
++ orientation of the camera.
++
++ \sa setViewing()
++*/
++SbBool
++So at Gui@Viewer::isViewing(void) const
++{
++ return PRIVATE(this)->viewingflag;
++}
++
++// *************************************************************************
++
++/*!
++ Set whether or not the mouse cursor representation should be visible
++ in the viewer canvas.
++
++ Default value is on.
++
++ \sa isCursorEnabled()
++*/
++
++void
++So at Gui@Viewer::setCursorEnabled(SbBool on)
++{
++ PRIVATE(this)->cursoron = on;
++}
++
++// *************************************************************************
++
++/*!
++ Returns visibility status of mouse cursor.
++
++ \sa setCursorEnabled()
++*/
++
++SbBool
++So at Gui@Viewer::isCursorEnabled(void) const
++{
++ return PRIVATE(this)->cursoron;
++}
++
++// *************************************************************************
++
++/*!
++ Turn on or off continuous automatic adjustments of the near and far
++ clipping planes.
++
++ If on, the distance from the camera position to the near and far
++ planes will be calculated to be a "best fit" around the geometry in
++ the scene, to maximize the "stretch" of values for the visible
++ geometry in the z-buffer. This is important, as z-buffer resolution
++ is usually limited enough that one will quickly see flickering in
++ the rasterization of close polygons upon lousy utilization of the
++ z-buffer.
++
++ Automatic calculations of near and far clip planes are on as
++ default.
++
++ For better control over what happens in boundary conditions (for
++ instance when the distance between near and far planes get very far,
++ or if geometry gets very close to the camera position), it is
++ possible to use the So at Gui@Viewer::setAutoClippingStrategy() method
++ to fine-tune the near/far clipping plane settings.
++
++ On a major note, be aware that turning auto-updating of near and far
++ clip planes \e off have a potentially serious detrimental effect on
++ performance, due to an important side effect: updating the near and
++ far clip planes triggers an SoGetBoundingBoxAction to traverse the
++ scene graph, which causes bounding boxes to be calculated and stored
++ in caches. The bounding box caches are then used by the
++ SoGLRenderAction traversal for view frustum culling operations. With
++ no bounding box caches, the rendering will not do culling, which can
++ cause much worse performance. Kongsberg Oil & Gas Technologies are
++ working on correcting this problem properly from within the Coin
++ library.
++
++ On a minor note, be aware that notifications will be temporarily
++ turned off for the scene's SoCamera when changing the near and far
++ clipping planes (which is done right before each redraw). This is
++ done to avoid notifications being sent through the scene graph right
++ before rendering, as that causes some latency. It is mentioned here
++ in case you have any client code which for some reason needs to
++ sense all changes to the scene camera. This is however unlikely, so
++ you can very probably ignore this.
++
++ \sa getAutoClipping()
++*/
++
++void
++So at Gui@Viewer::setAutoClipping(SbBool enable)
++{
++ if (SO at GUI@_DEBUG) {
++ if (PRIVATE(this)->adjustclipplanes == enable) {
++ SoDebugError::postWarning("So at Gui@Viewer::setAutoClipping",
++ "unnecessary called");
++ return;
++ }
++ }
++
++ PRIVATE(this)->adjustclipplanes = enable;
++ if (enable) { this->scheduleRedraw(); }
++}
++
++/*!
++ Set the strategy used for automatic updates of the distances to the
++ near and far clipping planes.
++
++ When auto clipping is enabled, the near plane distance is calculated
++ so that it is just in front of the scene bounding box. If this near
++ plane is behind or very close to the projection point, one of the
++ following strategies will be used to calculate the new clipping
++ plane.
++
++ The VARIABLE_NEAR_PLANE strategy considers the number of z buffer
++ bits available for the current OpenGL context, and uses \a value to
++ calculate the number of bits that is lost because of the far/near
++ ratio. \a value should be in the range [0.0, 1.0]. A higher \a value
++ will increase the z-buffer precision, but also push the near plane
++ further away from the projection point.
++
++ The CONSTANT_NEAR_PLANE strategy simply sets the near plane to
++ \a value. If \a value at some point approaches the far clipping
++ plane distance, the near plane distance will be set to far plane
++ distance divided by 5000.0.
++
++ The default strategy is VARIABLE_NEAR_PLANE.
++
++
++ It is also possible to register a callback method \a cb, which will
++ then be invoked after the near and far clipping planes has been
++ calculated by the So at Gui@Viewer code. The callback can then adjust
++ the values for the distance to the near and far planes to exactly
++ match the needs of the application (for instance at specific parts
++ in the scene), to limit the distance to either plane, or whatever
++ else needs to be controlled.
++
++ The signature of the So at Gui@AutoClippingCB callback must match:
++ \code
++ SbVec2f myfunc(void * data, const SbVec2f & nearfar);
++ \endcode
++
++ The first argument is the \a cbuserdata passed in along with the
++ callback function pointer itself (ie the callback function's
++ closure). The second argument is the near and far clipping plane
++ distances from the camera position, as calculated internally by the
++ viewer, including "slack".
++
++ The function callback can then modify the near and far clipping
++ plane distances to what will \e actually be used by the
++ viewer. These values will then be used unmodified for the viewer's
++ camera.
++
++ This is a good way of dynamically modifying the near and far
++ distances such that they at all times exactly matches the specific
++ layout of the application scene, for instance with regard to the
++ trade-off between z-buffer resolution and how early geometry is
++ clipped at the near plane (or at the far plane).
++
++ Note that the internal near/far calculations should be good enough
++ for the vast majority of scenes. Application programmers should only
++ need to set up their own adjustments upon "unusual" scenes, like for
++ instance scenes with a large world space, but where one would still
++ like to be able to get up extremely close on details in some parts
++ of the scene.
++
++
++ \sa setAutoClipping()
++*/
++void
++So at Gui@Viewer::setAutoClippingStrategy(const AutoClippingStrategy strategy,
++ const float value,
++ So at Gui@AutoClippingCB * cb,
++ void * cbuserdata)
++{
++ PRIVATE(this)->autoclipstrategy = strategy;
++ PRIVATE(this)->autoclipvalue = value;
++ PRIVATE(this)->autoclipcb = cb;
++ PRIVATE(this)->autoclipuserdata = cbuserdata;
++
++ if (PRIVATE(this)->autoclipstrategy == VARIABLE_NEAR_PLANE) {
++ // normalize the value so that the near plane isn't too near or
++ // too far from the projection point. FIXME: calibrate this
++ // normalization, pederb, 2002-04-25
++ float v = So at Gui@Clamp(value, 0.0f, 1.0f); // just in case
++ v *= 0.8f;
++ v += 0.1f; // v will be in range [0.1, 0.9]
++
++ PRIVATE(this)->autoclipvalue = v;
++ }
++ if (PRIVATE(this)->adjustclipplanes) {
++ this->scheduleRedraw();
++ }
++}
++
++// *************************************************************************
++
++/*!
++ Return value of the automatic near/far clipplane adjustment indicator.
++
++ \sa setAutoClipping()
++*/
++
++SbBool
++So at Gui@Viewer::isAutoClipping(void) const
++{
++ return PRIVATE(this)->adjustclipplanes;
++}
++
++// *************************************************************************
++
++/*!
++ Turn stereo viewing on or off.
++
++ Note: this function is being obsoleted, you should use the
++ setStereoType() function instead.
++
++ Coin does "correct" stereo rendering, using the method known as
++ "parallel axis asymmetric frustum perspective projection". For more
++ information, see this link:
++
++ http://astronomy.swin.edu.au/~pbourke/opengl/stereogl/
++
++ \sa isStereoViewing(), setStereoType()
++*/
++
++void
++So at Gui@Viewer::setStereoViewing(SbBool enable)
++{
++ PRIVATE(this)->stereoviewing = enable;
++ this->scheduleRedraw();
++}
++
++/*!
++ Returns a boolean indicating whether or not we're in stereo viewing
++ mode.
++
++ NOTE: in the original InventorXt API, this method was virtual. It is not
++ virtual here.
++
++ \sa setStereoViewing(), getStereoType()
++*/
++
++SbBool
++So at Gui@Viewer::isStereoViewing(void) const
++{
++ return PRIVATE(this)->stereoviewing;
++}
++
++// *************************************************************************
++
++/*!
++ \enum So at Gui@Viewer::StereoType
++
++ Contains list of supported stereo rendering techniques.
++
++ \sa So at Gui@Viewer::setStereoType()
++*/
++/*!
++ \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_NONE
++
++ Use monoscopic rendering.
++*/
++/*!
++ \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_ANAGLYPH
++
++ Render stereo by superimposing two images of the same scene, but with
++ different color filters over the left and right view (or "eye").
++
++ This is a way of rendering stereo which works on any display, using
++ color-filter glasses. Such glasses are usually cheap and easy to
++ come by.
++
++ \sa setAnaglyphStereoColorMasks()
++*/
++/*!
++ \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_QUADBUFFER
++
++ Render stereo by using OpenGL quad-buffers. This is the most common
++ interface for stereo rendering for more expensive hardware devices,
++ such as shutter glasses and polarized glasses.
++
++ The well known Crystal Eyes glasses are commonly used with this type
++ of stereo display.
++*/
++/*!
++ \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_INTERLEAVED_ROWS
++
++ Interleaving / interlacing rows from the left and right eye is
++ another stereo rendering method requiring special hardware. One
++ example of a provider of shutter glasses working with interleaved
++ glasses is VRex:
++
++ http://www.vrex.com/
++*/
++/*!
++ \var So at Gui@Viewer::StereoType So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS
++
++ Same basic technique as So at Gui@Viewer::STEREO_INTERLEAVED_ROWS, only
++ it is vertical lines that are interleaved / interlaced, instead of
++ horizontal lines.
++*/
++
++/*!
++ Set up stereo rendering.
++
++ Coin does "correct" stereo rendering, using the method known as
++ "parallel axis asymmetric frustum perspective projection". For more
++ information, see this link:
++
++ http://astronomy.swin.edu.au/~pbourke/opengl/stereogl/
++
++
++ Note: it is prefered that one uses this function for control of
++ which type of stereo rendering to use, instead of the older
++ So at Gui@Viewer::setStereoViewing() and
++ So at Gui@GLWidget::setQuadBufferStereo() functions.
++
++ The default is to do monoscopic rendering, i.e. the default
++ So at Gui@Viewer::StereoType value is So at Gui@Viewer::STEREO_NONE.
++
++ \sa So at Gui@Viewer::StereoType, SoCamera::setStereoAdjustment
++ \since So at Gui@ 1.2
++*/
++SbBool
++So at Gui@Viewer::setStereoType(So at Gui@Viewer::StereoType s)
++{
++ if (s == this->getStereoType()) { return TRUE; }
++
++ // We need to know this to keep compatibility with older client
++ // code, which controlled stereo rendering with setStereoViewing()
++ // and setQuadBufferStereo() only.
++ PRIVATE(this)->stereotypesetexplicit = TRUE;
++
++ switch (s) {
++ case So at Gui@Viewer::STEREO_NONE:
++ this->setQuadBufferStereo(FALSE);
++ this->setStereoViewing(FALSE);
++ break;
++
++ case So at Gui@Viewer::STEREO_ANAGLYPH:
++ this->setStereoViewing(TRUE);
++ this->setQuadBufferStereo(FALSE);
++ break;
++
++ case So at Gui@Viewer::STEREO_QUADBUFFER:
++ this->setStereoViewing(TRUE);
++ this->setQuadBufferStereo(TRUE);
++
++ // Check, in case GL quad buffers not supported with the driver
++ // config:
++ if (!this->isQuadBufferStereo()) {
++ this->setStereoViewing(FALSE);
++ return FALSE;
++ }
++ break;
++
++ case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++ case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++ this->setStereoViewing(TRUE);
++ this->setQuadBufferStereo(FALSE);
++ this->setStencilBuffer(TRUE);
++
++ // Check, in case GL stencil buffers not supported with the driver
++ // config:
++ if (!this->getStencilBuffer()) {
++ this->setStereoViewing(FALSE);
++ return FALSE;
++ }
++ break;
++
++ default:
++ assert(FALSE); break;
++ }
++
++ PRIVATE(this)->stereotype = s;
++ return TRUE;
++}
++
++/*!
++ Returns the current type of stereo rendering used (or
++ So at Gui@Viewer::STEREO_NONE if monoscopic).
++*/
++So at Gui@Viewer::StereoType
++So at Gui@Viewer::getStereoType(void) const
++{
++ // Stereo can be set up without using setStereoType() through the
++ // older functions setStereoViewing() and setQuadBufferStereo(), so
++ // we need to check for this separately.
++ if (!PRIVATE(this)->stereotypesetexplicit) {
++ if (this->isQuadBufferStereo()) {
++ PRIVATE(this)->stereotype = So at Gui@Viewer::STEREO_QUADBUFFER;
++ }
++ else if (this->isStereoViewing()) {
++ PRIVATE(this)->stereotype = So at Gui@Viewer::STEREO_ANAGLYPH;
++ }
++ }
++
++ return PRIVATE(this)->stereotype;
++}
++
++// *************************************************************************
++
++/*!
++ If display is configured to render in anaglyph stereo, this function
++ can be used to control which filter is used for each eye.
++
++ The default filters are red (i.e. color vector [TRUE,FALSE,FALSE])
++ for the left eye, and cyan (color vector [FALSE,TRUE,TRUE]) for the
++ right eye.
++
++ \sa So at Gui@Viewer::StereoType, setStereoType()
++*/
++void
++So at Gui@Viewer::setAnaglyphStereoColorMasks(const SbBool left[3], const SbBool right[3])
++{
++ for (unsigned int i = 0; i < 3; i++) {
++ PRIVATE(this)->stereoanaglyphmask[0][i] = left[i];
++ PRIVATE(this)->stereoanaglyphmask[1][i] = right[i];
++ }
++
++ this->scheduleRedraw();
++}
++
++/*!
++ Returns color masks for left and right eye filters in anaglyph
++ stereo.
++
++ \sa setAnaglyphStereoColorMasks()
++*/
++void
++So at Gui@Viewer::getAnaglyphStereoColorMasks(SbBool left[3], SbBool right[3])
++{
++ for (unsigned int i = 0; i < 3; i++) {
++ left[i] = PRIVATE(this)->stereoanaglyphmask[0][i];
++ right[i] = PRIVATE(this)->stereoanaglyphmask[1][i];
++ }
++}
++
++// *************************************************************************
++
++/*!
++ Set the offset between the two viewpoints when in stereo mode.
++ Default value is 0.1.
++
++ NOTE: In the original InventorXt API, this method was not virtual.
++
++ \sa getStereoOffset()
++*/
++void
++So at Gui@Viewer::setStereoOffset(const float dist)
++{
++ PRIVATE(this)->stereooffset = dist;
++ this->scheduleRedraw();
++}
++
++/*!
++ Return the offset distance between the two viewpoints when in stereo
++ mode.
++
++ \sa setStereoOffset()
++*/
++float
++So at Gui@Viewer::getStereoOffset(void) const
++{
++ return PRIVATE(this)->stereooffset;
++}
++
++// *************************************************************************
++
++/*!
++ Toggle between seeking to a point or seeking to an object.
++
++ Default is to seek to a point.
++
++ \sa isDetailSeek()
++*/
++
++void
++So at Gui@Viewer::setDetailSeek(const SbBool on)
++{
++ if (SO at GUI@_DEBUG) {
++ if (PRIVATE(this)->seektopoint == on) {
++ SoDebugError::postWarning("So at Gui@Viewer::setDetailSeek",
++ "unnecessary called");
++ return;
++ }
++ }
++
++ PRIVATE(this)->seektopoint = on;
++}
++
++// *************************************************************************
++
++/*!
++ Returns a value indicating whether or not seeks will be performed
++ to the exact point of picking or just towards the picked object.
++
++ \sa setDetailSeek()
++*/
++
++SbBool
++So at Gui@Viewer::isDetailSeek(void) const
++{
++ return PRIVATE(this)->seektopoint;
++}
++
++// *************************************************************************
++
++/*!
++ Set the duration of animating the camera repositioning
++ after a successful seek. Call with \a seconds equal to \a 0.0 to make
++ the camera jump immediately to the correct spot.
++
++ Default value is 2 seconds.
++
++ \sa getSeekTime()
++*/
++
++void
++So at Gui@Viewer::setSeekTime(const float seconds)
++{
++ if (seconds < 0.0f) {
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postWarning("So at Gui@Viewer::setSeekTime",
++ "an attempt was made to set a negative seek "
++ "time duration");
++ }
++ return;
++ }
++ PRIVATE(this)->seekperiod = seconds;
++}
++
++// *************************************************************************
++
++/*!
++ Returns the camera repositioning duration following a seek action.
++
++ \sa setSeekTime()
++*/
++
++float
++So at Gui@Viewer::getSeekTime(void) const
++{
++ return PRIVATE(this)->seekperiod;
++}
++
++// *************************************************************************
++
++/*!
++ Add a function to call when user interaction with the scene starts.
++
++ \sa removeStartCallback(), addFinishCallback()
++*/
++
++void
++So at Gui@Viewer::addStartCallback(So at Gui@ViewerCB * func, void * data)
++{
++ PRIVATE(this)->interactionstartCallbacks->addCallback((SoCallbackListCB *)func, data);
++}
++
++/*!
++ Remove one of the functions which has been set up to be called when user
++ interaction with the scene starts.
++
++ \sa addStartCallback(), removeFinishCallback()
++*/
++
++void
++So at Gui@Viewer::removeStartCallback(So at Gui@ViewerCB * func, void * data)
++{
++ PRIVATE(this)->interactionstartCallbacks->removeCallback((SoCallbackListCB *)func,
++ data);
++}
++
++// *************************************************************************
++
++/*!
++ Add a function to call when user interaction with the scene ends.
++
++ \sa removeFinishCallback(), addStartCallback()
++*/
++
++void
++So at Gui@Viewer::addFinishCallback(So at Gui@ViewerCB * func, void * data)
++{
++ PRIVATE(this)->interactionendCallbacks->addCallback((SoCallbackListCB *)func, data);
++}
++
++/*!
++ Remove one of the functions which has been set up to be called when user
++ interaction with the scene ends.
++
++ \sa addFinishCallback(), removeStartCallback()
++*/
++
++void
++So at Gui@Viewer::removeFinishCallback(So at Gui@ViewerCB * func, void * data)
++{
++ PRIVATE(this)->interactionendCallbacks->removeCallback((SoCallbackListCB *)func,
++ data);
++}
++
++// *************************************************************************
++
++/*!
++ Set the color of the overlay wireframe to \a color.
++
++ \sa getWireframeOverlayColor()
++*/
++void So at Gui@Viewer::setWireframeOverlayColor(const SbColor & color)
++{
++ PRIVATE(this)->wireframeoverlaycolor = color;
++ this->scheduleRedraw();
++}
++
++// *************************************************************************
++
++/*!
++ Returns the current color of the overlay wireframe. The default
++ color is [1,0,0], ie pure red.
++
++ \sa setWireframeOverlayColor()
++*/
++const SbColor &So at Gui@Viewer::getWireframeOverlayColor(void) const
++{
++ return PRIVATE(this)->wireframeoverlaycolor;
++}
++
++// *************************************************************************
++
++/*!
++ Overloaded to update the local bufferingtype variable.
++
++ \sa setBufferingType(), getBufferingType()
++*/
++
++void
++So at Gui@Viewer::setDoubleBuffer(const SbBool on)
++{
++ if (!PRIVATE(this)->localsetbuffertype)
++ PRIVATE(this)->buffertype = on ? BUFFER_DOUBLE : BUFFER_SINGLE;
++
++ inherited::setDoubleBuffer(on);
++}
++
++// *************************************************************************
++
++/*!
++ Give the viewer a scenegraph to render and interact with. Overridden
++ from parent class so the viewer can add it's own nodes to control
++ rendering in different styles, rendering with a headlight, etc.
++
++ The \a root node will be inserted under the \e viewer's root node,
++ which also covers the nodes necessary to implement the different
++ preferences drawing style settings.
++
++ If no camera is part of the scene graph under \a root, one will
++ automatically be instantiated and added. You can get a reference to
++ this camera by using the So at Gui@Viewer::getCamera() method.
++
++ \sa getSceneGraph(), setCameraType()
++*/
++
++void
++So at Gui@Viewer::setSceneGraph(SoNode * root)
++{
++ if ((root != NULL) && (root == PRIVATE(this)->scenegraph)) {
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postWarning("So at Gui@Viewer::setSceneGraph",
++ "called with the same root as already set");
++ }
++ return;
++ }
++
++ // If the So at Gui@RenderArea hasn't yet set up its pointer to the
++ // So at Gui@Viewer "viewer root" (i.e. the viewer-generated root above
++ // the user-supplied root), do that first.
++ if (!inherited::getSceneGraph())
++ inherited::setSceneGraph(PRIVATE(this)->sceneroot);
++
++ if (PRIVATE(this)->scenegraph) {
++ if (this->getCamera())
++ this->setCamera(NULL);
++ // Release the old user-supplied graph.
++ PRIVATE(this)->usersceneroot->removeChild(PRIVATE(this)->scenegraph);
++ // old: PRIVATE(this)->sceneroot->removeChild(PRIVATE(this)->scenegraph);
++ }
++
++ PRIVATE(this)->scenegraph = root;
++ if (!root) return;
++
++ PRIVATE(this)->usersceneroot->addChild(PRIVATE(this)->scenegraph);
++
++ // Search for a camera in the user-supplied scenegraph.
++
++ SbBool oldsearch = SoBaseKit::isSearchingChildren();
++ SoBaseKit::setSearchingChildren(TRUE);
++
++ PRIVATE(this)->searchaction->reset();
++ PRIVATE(this)->searchaction->setType(SoCamera::getClassTypeId());
++ PRIVATE(this)->searchaction->apply(PRIVATE(this)->scenegraph);
++
++ SoBaseKit::setSearchingChildren(oldsearch);
++
++ SoCamera * scenecamera = NULL;
++ if ( PRIVATE(this)->searchaction->getPath() != NULL ) {
++ SoFullPath * fullpath =
++ (SoFullPath *) PRIVATE(this)->searchaction->getPath();
++ scenecamera = (SoCamera *)fullpath->getTail();
++ }
++
++#if 0 // debug
++ SoDebugError::postInfo("So at Gui@Viewer::setSceneGraph",
++ "camera %sfound in graph",
++ scenecamera ? "" : "not ");
++#endif // debug
++
++ // Make our own camera if none was available.
++ if (!scenecamera) {
++ if (SoGuiViewpointWrapper::hasViewpoints(root)) {
++ scenecamera = new SoGuiViewpointWrapper;
++ PRIVATE(this)->cameratype = SoGuiViewpointWrapper::getClassTypeId();
++ ((SoGuiViewpointWrapper*)scenecamera)->setSceneGraph(root);
++ }
++ else {
++ scenecamera = (SoCamera *) PRIVATE(this)->cameratype.createInstance();
++ }
++
++ // If type==BROWSER, camera should be inserted in the private
++ // viewer "supergraph", if it's equal to EDITOR it should be
++ // inserted in the user-supplied scenegraph.
++ if (PRIVATE(this)->type == So at Gui@Viewer::BROWSER) {
++ PRIVATE(this)->sceneroot->insertChild(scenecamera, 1);
++ }
++ else { // PRIVATE(this)->type == So at Gui@Viewer::EDITOR
++ if (PRIVATE(this)->scenegraph->isOfType(SoGroup::getClassTypeId())) {
++ // At the uppermost leftmost position in the user-supplied
++ // scenegraph.
++ ((SoGroup *)PRIVATE(this)->scenegraph)->insertChild(scenecamera, 0);
++ }
++ else {
++ // Make an extra depth level to fit the camera node into the
++ // user-scenegraph.
++ SoGroup * g = new SoGroup;
++ g->addChild(scenecamera);
++ g->addChild(PRIVATE(this)->scenegraph);
++ PRIVATE(this)->usersceneroot->removeChild(PRIVATE(this)->scenegraph);
++ PRIVATE(this)->usersceneroot->addChild(g);
++ PRIVATE(this)->scenegraph = g;
++ }
++ }
++ if (PRIVATE(this)->cameratype != SoGuiViewpointWrapper::getClassTypeId()) {
++ scenecamera->viewAll(PRIVATE(this)->scenegraph, this->getViewportRegion());
++ }
++ }
++
++ this->setCamera(scenecamera);
++}
++
++// *************************************************************************
++
++// doc in super
++SoNode *
++So at Gui@Viewer::getSceneGraph(void)
++{
++ // Overloaded from parent class to return the root of the scene
++ // graph set by the user, without the extras added by the viewer to
++ // control rendering.
++ return PRIVATE(this)->scenegraph;
++}
++
++// *************************************************************************
++
++// Note: the following function documentation block will also be used
++// for all the miscellaneous viewer subclasses, so keep it general.
++/*!
++ Put the viewer in or out of "waiting-to-seek" mode.
++
++ If the user performs a mouse button click when the viewer is in
++ "waiting-to-seek" mode, the camera will be repositioned so the
++ camera focal point lies on the point of the geometry under the mouse
++ cursor.
++
++ \sa isSeekMode(), setDetailSeek()
++*/
++void
++So at Gui@Viewer::setSeekMode(SbBool enable)
++{
++ if (SO at GUI@_DEBUG) {
++ // User might have switched mode during seek, so if enable==FALSE,
++ // isViewing() is irrelevant.
++ if (enable) { assert(this->isViewing()); }
++ }
++
++ if (!enable && PRIVATE(this)->seeksensor->isScheduled()) {
++ PRIVATE(this)->seeksensor->unschedule();
++ this->interactiveCountDec();
++ }
++
++ PRIVATE(this)->inseekmode = enable;
++}
++
++// *************************************************************************
++
++/*!
++ Return a flag which indicates whether or not the viewer is in
++ "waiting-to-seek" mode.
++
++ (The actual animated translation will not occur until the end user
++ really \e starts the seek operation, typically by clicking with the
++ left mousebutton.)
++
++ \sa setSeekMode()
++*/
++SbBool
++So at Gui@Viewer::isSeekMode(void) const
++{
++ return PRIVATE(this)->inseekmode;
++}
++
++// *************************************************************************
++
++/*!
++ Call this method to initiate a seek action towards the 3D
++ intersection of the scene and the ray from the screen coordinate's
++ point and in the same direction as the camera is pointing.
++
++ Returns \c TRUE if the ray from the \a screenpos position intersect
++ with any parts of the onscreen geometry, otherwise \c FALSE.
++*/
++SbBool
++So at Gui@Viewer::seekToPoint(const SbVec2s screenpos)
++{
++ if (! PRIVATE(this)->camera)
++ return FALSE;
++
++ SoRayPickAction rpaction(this->getViewportRegion());
++ rpaction.setPoint(screenpos);
++ rpaction.setRadius(2);
++ rpaction.apply(PRIVATE(this)->sceneroot);
++
++ SoPickedPoint * picked = rpaction.getPickedPoint();
++ if (!picked) {
++ // FIXME: this inc seems bogus, but is needed now due to buggy
++ // code in for instance the examinerviewer
++ // processSoEvent(). 20020510 mortene.
++#if 1
++ this->interactiveCountInc(); // decremented in setSeekMode(FALSE)
++#endif // FIXME
++ this->setSeekMode(FALSE);
++ return FALSE;
++ }
++
++ SbVec3f hitpoint;
++ if (PRIVATE(this)->seektopoint) {
++ hitpoint = picked->getPoint();
++ }
++ else {
++ SoGetBoundingBoxAction bbaction(this->getViewportRegion());
++ bbaction.apply(picked->getPath());
++ SbBox3f bbox = bbaction.getBoundingBox();
++ hitpoint = bbox.getCenter();
++ }
++
++ this->seekToPoint(hitpoint);
++ return TRUE;
++}
++
++/*!
++ Call this method to initiate a seek action towards the give 3D world
++ coordinate point in the scene, \a scenepos.
++
++ \since So at Gui@ 1.3.0
++*/
++void
++So at Gui@Viewer::seekToPoint(const SbVec3f & scenepos)
++{
++ SbVec3f hitpoint(scenepos);
++
++ PRIVATE(this)->camerastartposition = PRIVATE(this)->camera->position.getValue();
++ PRIVATE(this)->camerastartorient = PRIVATE(this)->camera->orientation.getValue();
++
++ // move point to the camera coordinate system, consider
++ // transformations before camera in the scene graph
++ SbMatrix cameramatrix, camerainverse;
++ PRIVATE(this)->getCameraCoordinateSystem(PRIVATE(this)->camera,
++ PRIVATE(this)->sceneroot,
++ cameramatrix,
++ camerainverse);
++ camerainverse.multVecMatrix(hitpoint, hitpoint);
++
++ float fd = PRIVATE(this)->seekdistance;
++ if (!PRIVATE(this)->seekdistanceabs)
++ fd *= (hitpoint - PRIVATE(this)->camera->position.getValue()).length()/100.0f;
++ PRIVATE(this)->camera->focalDistance = fd;
++
++ SbVec3f dir = hitpoint - PRIVATE(this)->camerastartposition;
++ dir.normalize();
++
++ // find a rotation that rotates current camera direction into new
++ // camera direction.
++ SbVec3f olddir;
++ PRIVATE(this)->camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), olddir);
++ SbRotation diffrot(olddir, dir);
++ PRIVATE(this)->cameraendposition = hitpoint - fd * dir;
++ PRIVATE(this)->cameraendorient = PRIVATE(this)->camera->orientation.getValue() * diffrot;
++
++ // Subclasses that want another cameraendorient than what is
++ // computed here should override this function and set the desired
++ // orientation there
++ this->computeSeekFinalOrientation();
++
++ if (PRIVATE(this)->seeksensor->isScheduled()) {
++ PRIVATE(this)->seeksensor->unschedule();
++ this->interactiveCountDec();
++ }
++
++ PRIVATE(this)->seeksensor->setBaseTime(SbTime::getTimeOfDay());
++ PRIVATE(this)->seeksensor->schedule();
++ this->interactiveCountInc();
++}
++
++// *************************************************************************
++
++void
++So at Gui@ViewerP::setStereoEye(SoCamera * thecamera,
++ const So at Gui@ViewerP::Eye eye,
++ So at Gui@ViewerP::StereoData & s) const
++{
++#ifdef HAVE_SOCAMERA_SETSTEREOMODE
++
++ // SoCamera::setStereoMode() is a fairly recent addition to Coin and
++ // TGS Inventor. If available, camera eye setup is quite
++ // straightforward.
++
++ if (eye == So at Gui@ViewerP::LEFT) {
++ thecamera->setStereoAdjustment(PUBLIC(this)->getStereoOffset());
++ thecamera->setStereoMode(SoCamera::LEFT_VIEW);
++ }
++ else if (eye == So at Gui@ViewerP::RIGHT) {
++ thecamera->setStereoMode(SoCamera::RIGHT_VIEW);
++ }
++ else {
++ assert(eye == So at Gui@ViewerP::RESTORE);
++
++ thecamera->setStereoMode(SoCamera::MONOSCOPIC);
++ }
++
++#else // ! HAVE_SOCAMERA_SETSTEREOMODE
++
++ // To support older versions of Coin, and SGI/TGS Inventor, we also
++ // provide "manual" tuning of the camera left/right eye split.
++
++ if (eye == So at Gui@ViewerP::LEFT) {
++ s.camerapos = thecamera->position.getValue();
++ s.cameradir.setValue(0.0f, 0.0f, -1.0f);
++ s.offsetvec.setValue(1.0f, 0.0f, 0.0f);
++ s.offset = PUBLIC(this)->getStereoOffset() * 0.5f;
++ s.camerarot = thecamera->orientation.getValue();
++ s.camerarot.multVec(s.cameradir, s.cameradir);
++ s.camerarot.multVec(s.offsetvec, s.offsetvec);
++ s.focalpoint = s.camerapos + s.cameradir * thecamera->focalDistance.getValue();
++
++ s.nodenotify = thecamera->isNotifyEnabled();
++ s.positionnotify = thecamera->position.isNotifyEnabled();
++ s.orientationnotify = thecamera->orientation.isNotifyEnabled();
++ // turn off notification to avoid redraws
++ thecamera->enableNotify(FALSE);
++ thecamera->position.enableNotify(FALSE);
++ thecamera->orientation.enableNotify(FALSE);
++
++ thecamera->position = s.camerapos - s.offsetvec * s.offset;
++ SbVec3f dir = s.focalpoint - thecamera->position.getValue();
++ SbRotation rot(s.cameradir, dir);
++ thecamera->orientation = s.camerarot * rot;
++ }
++ else if (eye == So at Gui@ViewerP::RIGHT) {
++ thecamera->position = s.camerapos + s.offsetvec * s.offset;
++ SbVec3f dir = s.focalpoint - thecamera->position.getValue();
++ SbRotation rot(s.cameradir, dir);
++ thecamera->orientation = s.camerarot * rot;
++ }
++ else {
++ assert(eye == So at Gui@ViewerP::RESTORE);
++
++ thecamera->position = s.camerapos;
++ thecamera->orientation = s.camerarot;
++ thecamera->position.enableNotify(s.positionnotify);
++ thecamera->orientation.enableNotify(s.orientationnotify);
++ thecamera->enableNotify(s.nodenotify);
++ }
++
++#endif // ! HAVE_SOCAMERA_SETSTEREOMODE
++}
++
++void
++So at Gui@ViewerP::initStencilBufferForInterleavedStereo(void)
++{
++ const SbViewportRegion & currentvp = PUBLIC(this)->getViewportRegion();
++ if (this->stereostencilmaskvp == currentvp) { return; } // the common case
++
++ So at Gui@Viewer::StereoType s = PUBLIC(this)->getStereoType();
++ assert((s == So at Gui@Viewer::STEREO_INTERLEAVED_ROWS) ||
++ (s == So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS));
++
++ // Find out whether or not we need to regenerate the mask data.
++ SbBool allocnewmask = (this->stereostencilmask == NULL);
++
++ const SbVec2s neworigin = currentvp.getViewportOriginPixels();
++ const SbVec2s newsize = currentvp.getViewportSizePixels();
++
++ const SbVec2s oldorigin = this->stereostencilmaskvp.getViewportOriginPixels();
++ const SbVec2s oldsize = this->stereostencilmaskvp.getViewportSizePixels();
++
++ allocnewmask = allocnewmask ||
++ ((oldsize[0] + 7) / 8 * oldsize[1]) < ((newsize[0] + 7) / 8 * newsize[1]);
++
++ const SbBool fillmask = allocnewmask || (this->stereostenciltype != s) ||
++ ((s == So at Gui@Viewer::STEREO_INTERLEAVED_ROWS) && (oldsize[0] != newsize[0]));
++
++ const SbBool layoutchange = !(this->stereostencilmaskvp == currentvp);
++
++ const short bytewidth = (newsize[0] + 7) / 8;
++
++ if (allocnewmask) {
++ delete[] this->stereostencilmask;
++ this->stereostencilmask = new GLubyte[bytewidth * newsize[1]];
++ }
++
++ this->stereostencilmaskvp = currentvp;
++
++ if (fillmask) {
++ GLubyte * mask = this->stereostencilmask;
++
++ if (s == So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS) {
++ // alternating columns of 0's and 1's
++ (void)memset(mask, 0x55, bytewidth * newsize[1]);
++ }
++ else {
++ // alternating rows of 0's and 1's
++ for (short h=0; h < newsize[1]; h++) {
++ const GLubyte fill = (h % 2) ? 0xff : 0x00;
++ (void)memset(mask + (h * bytewidth), fill, bytewidth);
++ }
++ }
++
++ this->stereostenciltype = s;
++ }
++
++ if (layoutchange) {
++ glClearStencil(0x0);
++
++ glClear(GL_STENCIL_BUFFER_BIT);
++ glStencilFunc(GL_ALWAYS, GL_REPLACE, GL_REPLACE);
++
++ glMatrixMode(GL_MODELVIEW);
++ glPushMatrix();
++ glLoadIdentity();
++ glMatrixMode(GL_PROJECTION);
++ glPushMatrix();
++ glLoadIdentity();
++
++ glViewport(neworigin[0], neworigin[1], newsize[0], newsize[1]);
++
++ glOrtho(0, newsize[0], 0, newsize[1], -1.0f, 1.0f);
++
++ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
++
++ // FIXME: I've noticed a problem with this approach. If there is
++ // something in the window system obscuring part of the canvas
++ // while this is called (as could e.g. happen with a size
++ // indicator, as with the Sawfish window manager), the stencil
++ // mask will not be set up for that part. 20041019 mortene.
++ //
++ // UPDATE 20041019 mortene: discussed this with pederb, and we
++ // believe this may be due to a bug in either the OpenGL driver
++ // (Nvidia 61.11, Linux) or window system or manager (Sawfish,
++ // XFree86 v4.1.0.1). Should test on other systems to see if they
++ // show the same artifact.
++
++ glRasterPos2f(0, 0);
++ glDrawPixels(newsize[0], newsize[1], GL_STENCIL_INDEX, GL_BITMAP,
++ this->stereostencilmask);
++
++ glMatrixMode(GL_PROJECTION);
++ glPopMatrix();
++ glMatrixMode(GL_MODELVIEW);
++ glPopMatrix();
++ }
++}
++
++// Documented in superclass. Overridden from parent class to be able
++// to do the necessary two-pass rendering e.g. if the drawing style is
++// hidden line.
++void
++So at Gui@Viewer::actualRedraw(void)
++{
++ SbTime redrawtime = SbTime::getTimeOfDay();
++ const SbBool clearcol = this->isClearBeforeRender();
++ const SbBool clearz = this->isClearZBufferBeforeRender();
++ const So at Gui@Viewer::StereoType stereotype = this->getStereoType();
++
++ if (stereotype != So at Gui@Viewer::STEREO_NONE) {
++#if HAVE_SBCOLOR4F_GETBACKGROUNDCOLOR
++ const SbColor4f bgcol = this->getSceneManager()->getBackgroundColor();
++#else
++ const SbColor4f bgcol(this->getSceneManager()->getBackgroundColor(), 0.0f);
++#endif
++ SoCamera * camera = this->getCamera();
++ So at Gui@ViewerP::StereoData tmpstorage;
++
++ // Render left eye:
++
++ PRIVATE(this)->setStereoEye(camera, So at Gui@ViewerP::LEFT, tmpstorage);
++
++ switch (stereotype) {
++ case So at Gui@Viewer::STEREO_ANAGLYPH:
++ glDrawBuffer(this->isDoubleBuffer() ? GL_BACK : GL_FRONT);
++ glClearColor(bgcol[0], bgcol[1], bgcol[2], 0.0f);
++ glClear(GL_DEPTH_BUFFER_BIT|GL_COLOR_BUFFER_BIT);
++ glColorMask(PRIVATE(this)->stereoanaglyphmask[0][0] ? GL_TRUE : GL_FALSE,
++ PRIVATE(this)->stereoanaglyphmask[0][1] ? GL_TRUE : GL_FALSE,
++ PRIVATE(this)->stereoanaglyphmask[0][2] ? GL_TRUE : GL_FALSE,
++ GL_TRUE);
++ PRIVATE(this)->reallyRedraw(FALSE, FALSE);
++ break;
++ case So at Gui@Viewer::STEREO_QUADBUFFER:
++ glDrawBuffer(this->isDoubleBuffer() ? GL_BACK_LEFT : GL_FRONT_LEFT);
++ PRIVATE(this)->reallyRedraw(clearcol, clearz);
++ break;
++ case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++ case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++ PRIVATE(this)->initStencilBufferForInterleavedStereo();
++ glEnable(GL_STENCIL_TEST);
++ // immutable data in the stencil buffer
++ glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
++ glStencilFunc(GL_EQUAL, 0x1, 0x1);
++ PRIVATE(this)->reallyRedraw(clearcol, clearz);
++ break;
++
++ default: assert(FALSE); break;
++ }
++
++ // Render right eye:
++
++ PRIVATE(this)->setStereoEye(camera, So at Gui@ViewerP::RIGHT, tmpstorage);
++
++ switch (stereotype) {
++ case So at Gui@Viewer::STEREO_ANAGLYPH:
++ glColorMask(PRIVATE(this)->stereoanaglyphmask[1][0] ? GL_TRUE : GL_FALSE,
++ PRIVATE(this)->stereoanaglyphmask[1][1] ? GL_TRUE : GL_FALSE,
++ PRIVATE(this)->stereoanaglyphmask[1][2] ? GL_TRUE : GL_FALSE,
++ GL_TRUE);
++ PRIVATE(this)->reallyRedraw(FALSE, TRUE);
++ break;
++ case So at Gui@Viewer::STEREO_QUADBUFFER:
++ glDrawBuffer(this->isDoubleBuffer() ? GL_BACK_RIGHT : GL_FRONT_RIGHT);
++ PRIVATE(this)->reallyRedraw(clearcol, clearz);
++ break;
++ case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++ case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++ glStencilFunc(GL_NOTEQUAL, 0x1, 0x1);
++ PRIVATE(this)->reallyRedraw(FALSE, FALSE);
++ break;
++ default: assert(FALSE); break;
++ }
++
++ // Clean-up, post-rendering:
++
++ PRIVATE(this)->setStereoEye(camera, So at Gui@ViewerP::RESTORE, tmpstorage);
++
++ switch (stereotype) {
++ case So at Gui@Viewer::STEREO_ANAGLYPH:
++ glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); // restore GL color mask
++ break;
++ case So at Gui@Viewer::STEREO_QUADBUFFER:
++ glDrawBuffer(this->isDoubleBuffer() ? GL_BACK : GL_FRONT);
++ break;
++ case So at Gui@Viewer::STEREO_INTERLEAVED_ROWS:
++ case So at Gui@Viewer::STEREO_INTERLEAVED_COLUMNS:
++ // FIXME: restore old val. 20040618 mortene.
++ glDisable(GL_STENCIL_TEST);
++ break;
++ default: assert(FALSE); break;
++ }
++ }
++ else { // No stereo:
++ PRIVATE(this)->reallyRedraw(clearcol, clearz);
++ }
++
++ if (PRIVATE(this)->superimpositions != NULL) {
++ SoGLRenderAction * raaction = this->getSceneManager()->getGLRenderAction();
++ SbBool first = TRUE;
++ SbBool zWasEnabled = FALSE;
++ for (int i = 0; i < PRIVATE(this)->superimpositions->getLength(); i++) {
++ if (PRIVATE(this)->superimpositionsenabled[i] != FALSE) {
++ if (first) {
++ // save Z buffer state and disable
++ zWasEnabled = glIsEnabled(GL_DEPTH_TEST) ? TRUE : FALSE;
++ glDisable(GL_DEPTH_TEST);
++ first = FALSE;
++ }
++ SoNode * scene = (SoNode *) (*PRIVATE(this)->superimpositions)[i];
++ raaction->apply(scene);
++ }
++ }
++ if (!first && zWasEnabled) glEnable(GL_DEPTH_TEST);
++ }
++
++ redrawtime = SbTime::getTimeOfDay() - redrawtime;
++ PRIVATE(this)->recordFPS(redrawtime.getValue());
++}
++
++// *************************************************************************
++
++/*!
++ To be able to trigger callback functions when user interaction starts
++ and/or stops, we need to keep track of the viewer state (i.e. are we in
++ still mode or in animation mode?).
++
++ So at Gui@Viewer automatically adds callbacks to switch between still and
++ moving draw style, and to switch between single/double buffer when
++ the buffer type is \a INTERACTIVE.
++
++ \sa interactiveCountDec(), getInteractiveCount()
++ \sa addStartCallback(), addFinishCallback()
++ \sa removeStartCallback(), removeFinishCallback()
++ \sa setDrawStyle(), setBufferingType()
++*/
++
++void
++So at Gui@Viewer::interactiveCountInc(void)
++{
++ // Catch problems with missing interactiveCountDec() calls.
++ assert(PRIVATE(this)->interactionnesting < 100);
++
++ if (++(PRIVATE(this)->interactionnesting) == 1) {
++ PRIVATE(this)->interactionstartCallbacks->invokeCallbacks(this);
++ PRIVATE(this)->resetFrameCounter();
++ }
++
++#if 0 // debug
++ SoDebugError::postInfo("So at Gui@Viewer::interactiveCountInc", "%d -> %d",
++ PRIVATE(this)->interactionnesting - 1,
++ PRIVATE(this)->interactionnesting);
++#endif // debug
++}
++
++// *************************************************************************
++
++/*!
++ To be able to trigger callback functions when user interaction starts
++ and/or stops, we need to keep track of the viewer state (i.e. are we in
++ still mode or in animation mode?).
++
++ So at Gui@Viewer automatically adds callbacks to switch between still and
++ moving draw style, and to switch between single/double buffer when
++ the buffer type is \a INTERACTIVE.
++
++ \sa interactiveCountInc(), getInteractiveCount()
++ \sa addStartCallback(), addFinishCallback()
++ \sa removeStartCallback(), removeFinishCallback()
++ \sa setDrawStyle(), setBufferingType()
++*/
++
++void
++So at Gui@Viewer::interactiveCountDec(void)
++{
++ // FIXME: The UI toolkits may cause the interactionnesting to go
++ // below zero by triggering press and release events in different
++ // widgets. mariusbu 20010709.
++
++ // FIXME: just to clarify; this is due to programming mistakes on
++ // our behalf and should be cleaned up. We're using a simple
++ // work-around / ignore strategy for now, though, as getting this
++ // 100% correct is hard (there are so many possible ways of user
++ // interaction with a viewer canvas) and the end-user will usually
++ // not notice any problems at all. So that's why we are using a
++ // warning instead of an assert(). 20010815 mortene.
++
++ // FIXME: here's one known way to trigger the bug: hit "s" in the
++ // examinerviewer in EXAMINE mode, then while seeking hit ESC to put
++ // the viewer in INTERACT mode. When the seek is completed, the
++ // count will become -1. 20010912 mortene.
++
++ // FIXME: and another one (tested with SoXt): click and hold LMB in
++ // the canvas while in INTERACT mode, then hit 'Esc' to switch to
++ // EXAMINE mode, then release LMB. 20020325 mortene.
++
++ if (SO at GUI@_DEBUG) {
++ if (PRIVATE(this)->interactionnesting <= 0) {
++ SoDebugError::postWarning("So at Gui@Viewer::interactiveCountDec",
++ "interaction count nesting went below zero. "
++ "This is due to an internal So at Gui@ bug.");
++ }
++ }
++
++ if (--(PRIVATE(this)->interactionnesting) <= 0) {
++ PRIVATE(this)->interactionendCallbacks->invokeCallbacks(this);
++ PRIVATE(this)->interactionnesting = 0;
++ }
++}
++
++// *************************************************************************
++
++/*!
++ Return current interaction count nesting. If equal to zero, the viewer
++ is in animation mode, otherwise the camera is still.
++
++ \sa interactiveCountInc(), interactiveCountDec()
++*/
++
++int
++So at Gui@Viewer::getInteractiveCount(void) const
++{
++ return PRIVATE(this)->interactionnesting;
++}
++
++// *************************************************************************
++
++/*!
++ Set the value used for calculating how close the camera and intersection
++ hit point should be made at the end of a seek operation.
++
++ The value can be interpreted as an absolute value in the given world
++ unit (which typically is meters) or as a percentage value of the
++ distance between the camera starting position and the intersection
++ hit point. This can be controlled through the
++ setSeekValueAsPercentage() method. It is as default used as an
++ absolute value.
++
++ Default value is 50 (absolute distance or percent).
++
++ \sa getSeekDistance(), setSeekValueAsPercentage(), setSeekTime()
++*/
++
++void
++So at Gui@Viewer::setSeekDistance(const float distance)
++{
++ if (distance <= 0.0f) {
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postWarning("So at Gui@Viewer::setSeekDistance",
++ "invalid seek distance value: %f",
++ distance);
++ }
++ return;
++ }
++ PRIVATE(this)->seekdistance = distance;
++}
++
++// *************************************************************************
++
++/*!
++ Returns the current seek distance. Value given as an absolute scalar
++ length or as a percentage value of the original distance between
++ the hitpoint and the camera starting position.
++
++ \sa setSeekDistance(), isSeekValueAsPercentage()
++*/
++
++float
++So at Gui@Viewer::getSeekDistance(void) const
++{
++ return PRIVATE(this)->seekdistance;
++}
++
++// *************************************************************************
++
++/*!
++ Control whether or not the seek distance value should be interpreted as
++ a percentage value or as an absolute distance. See documentation on
++ setSeekDistance() for more information.
++
++ \sa setSeekDistance(), isSeekValueAsPercentage()
++*/
++
++void
++So at Gui@Viewer::setSeekValueAsPercentage(const SbBool on)
++{
++ if (SO at GUI@_DEBUG) {
++ if ((on && this->isSeekValuePercentage()) ||
++ (!on && !this->isSeekValuePercentage())) {
++ SoDebugError::postWarning("So at Gui@Viewer::setSeekDistanceAsPercentage",
++ "unnecessary called, value already %s",
++ on ? "on" : "off");
++ return;
++ }
++ }
++
++ PRIVATE(this)->seekdistanceabs = on ? FALSE : TRUE;
++}
++
++// *************************************************************************
++
++/*!
++ Returns an boolean which indicates if the seek distance value from
++ getSeekDistance() should be interpreted as a percentage value or
++ as an absolute value.
++
++ \sa setSeekValuePercentage(), getSeekDistance()
++*/
++
++SbBool
++So at Gui@Viewer::isSeekValuePercentage(void) const
++{
++ return PRIVATE(this)->seekdistanceabs ? FALSE : TRUE;
++}
++
++// ************************************************************************
++
++/*!
++ This method can be overridden in subclasses if the final
++ orientation of the camera after a seek should be something other
++ than what is computed in So at Gui@Viewer::seekToPoint(const SbVec3f &
++ scenepos)
++ */
++void
++So at Gui@Viewer::computeSeekFinalOrientation(void)
++{
++
++}
++
++// *************************************************************************
++
++/*!
++ If the current camera is of perspective type, switch to
++ orthographic, and vice versa.
++
++ Automatically calls So at Gui@Viewer::setCameraType() so the change
++ will immediately take place.
++*/
++void
++So at Gui@Viewer::toggleCameraType(void)
++{
++ SoType perspectivetype = SoPerspectiveCamera::getClassTypeId();
++ SoType orthotype = SoOrthographicCamera::getClassTypeId();
++ this->setCameraType(PRIVATE(this)->cameratype.isDerivedFrom(perspectivetype)
++ ? orthotype : perspectivetype);
++}
++
++// ************************************************************************
++
++/*!
++ Copies the settings of \a camera into our current camera. Cameras
++ must be of the same class type.
++ */
++void
++So at Gui@Viewer::changeCameraValues(// virtual, protected
++ SoCamera * camera)
++{
++ assert(camera != NULL);
++
++ SoCamera * cam = this->getCamera();
++ if (!cam) {
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postWarning("So at Gui@Viewer::changeCameraValues",
++ "no current camera in the scenegraph");
++ }
++ return;
++ }
++ if (cam->getTypeId() != camera->getTypeId()) {
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postWarning("So at Gui@Viewer::changeCameraValues",
++ "tried to copy data from camera of "
++ "different type");
++ }
++ return;
++ }
++
++ cam->copyFieldValues(camera, FALSE);
++}
++
++// *************************************************************************
++
++// doc in super
++void
++So at Gui@Viewer::sizeChanged(const SbVec2s & size)
++{
++ inherited::sizeChanged(size);
++}
++
++// *************************************************************************
++
++// Documented in superclass.
++SbBool
++So at Gui@Viewer::processSoEvent(const SoEvent * const event)
++{
++ const SoType type(event->getTypeId());
++ const SoKeyboardEvent * keyevent = NULL;
++
++ if (type.isDerivedFrom(SoKeyboardEvent::getClassTypeId())) {
++ keyevent = (SoKeyboardEvent *) event;
++ switch (keyevent->getKey()) {
++
++ // the ESC key switches between view and interact mode
++ case SoKeyboardEvent::ESCAPE:
++ if (keyevent->getState() == SoButtonEvent::DOWN) {
++ this->setViewing(this->isViewing() ? FALSE : TRUE);
++ return TRUE;
++ }
++ break;
++
++ // Let the end-user toggle between camera-interaction mode
++ // ("viewing") and scenegraph-interaction mode with ALT key(s).
++ case SoKeyboardEvent::LEFT_ALT:
++ case SoKeyboardEvent::RIGHT_ALT:
++ if (!this->isViewing() && (keyevent->getState() == SoButtonEvent::DOWN)) {
++ PRIVATE(this)->altdown = TRUE;
++ this->setViewing(TRUE);
++ return TRUE;
++ }
++ else if (PRIVATE(this)->altdown && (keyevent->getState() == SoButtonEvent::UP)) {
++ this->setViewing(FALSE);
++ PRIVATE(this)->altdown = FALSE;
++ return TRUE;
++ }
++ break;
++ default:
++ break;
++ }
++ }
++
++ // If not viewing, break off further handling and pass the event on
++ // to the So at Gui@RenderArea, which will pass it on to the
++ // scenegraph.
++ if (!this->isViewing()) { return inherited::processSoEvent(event); }
++
++
++ if (keyevent && (keyevent->getState() == SoButtonEvent::DOWN)) {
++ switch (keyevent->getKey()) {
++ case SoKeyboardEvent::S:
++ this->setSeekMode(this->isSeekMode() ? FALSE : TRUE);
++ return TRUE;
++ case SoKeyboardEvent::HOME:
++ this->resetToHomePosition();
++ return TRUE;
++ case SoKeyboardEvent::LEFT_ARROW:
++ PRIVATE(this)->moveCameraScreen(SbVec2f(-0.1f, 0.0f));
++ return TRUE;
++ case SoKeyboardEvent::UP_ARROW:
++ PRIVATE(this)->moveCameraScreen(SbVec2f(0.0f, 0.1f));
++ return TRUE;
++ case SoKeyboardEvent::RIGHT_ARROW:
++ PRIVATE(this)->moveCameraScreen(SbVec2f(0.1f, 0.0f));
++ return TRUE;
++ case SoKeyboardEvent::DOWN_ARROW:
++ PRIVATE(this)->moveCameraScreen(SbVec2f(0.0f, -0.1f));
++ return TRUE;
++ default:
++ break;
++ }
++ }
++
++ if (this->isSeekMode()) {
++ if (type.isDerivedFrom(SoMouseButtonEvent::getClassTypeId())) {
++ SoMouseButtonEvent * const e = (SoMouseButtonEvent *) event;
++ if (e->getButton() == SoMouseButtonEvent::BUTTON1) {
++ if (e->getState() == SoButtonEvent::DOWN) {
++ this->seekToPoint(e->getPosition());
++ }
++ else {
++ // We got an LMB UP-event while in seek-mode, and we just
++ // swallow the event.
++ }
++ return TRUE;
++ }
++ }
++ }
++
++ return FALSE;
++}
++
++// *************************************************************************
++
++/*!
++ This method is for setting up a superimposed scene graph on top
++ of the viewer scene graph. It will be used for adding spin-rotation
++ coordinate systems, fly-viewer speed indicators and similar things.
++
++ This method is not part of the original InventorXt API.
++*/
++
++void
++So at Gui@Viewer::addSuperimposition(SoNode * scene)
++{
++ if (PRIVATE(this)->superimpositions == NULL)
++ PRIVATE(this)->superimpositions = new SbPList;
++ assert(scene != NULL);
++ scene->ref();
++ PRIVATE(this)->searchaction->reset();
++ PRIVATE(this)->searchaction->setType(SoCamera::getClassTypeId());
++ PRIVATE(this)->searchaction->setInterest(SoSearchAction::FIRST);
++ PRIVATE(this)->searchaction->apply(scene);
++ if (PRIVATE(this)->searchaction->getPath() == NULL) {
++ // FIXME: set up default environment if there is no camera in the
++ // superimposition scene - or not...
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::postInfo("So at Gui@Viewer::addSuperimposition",
++ "cameraless superimpositions are not "
++ "supported");
++ }
++ scene->unrefNoDelete();
++ return;
++ }
++ PRIVATE(this)->superimpositions->append(scene);
++ PRIVATE(this)->superimpositionsenabled.append(TRUE);
++}
++
++// *************************************************************************
++
++/*!
++ This method is not part of the original InventorXt API.
++*/
++
++void
++So at Gui@Viewer::removeSuperimposition(SoNode * scene)
++{
++ assert(scene);
++ int idx = -1;
++ if (PRIVATE(this)->superimpositions == NULL) goto error;
++ idx = PRIVATE(this)->superimpositions->find(scene);
++ if (idx == -1) goto error;
++ assert(PRIVATE(this)->superimpositions != NULL);
++ PRIVATE(this)->superimpositions->remove(idx);
++ PRIVATE(this)->superimpositionsenabled.remove(idx);
++ scene->unref();
++ return;
++
++ error:
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::post("So at Gui@Viewer::removeSuperimposition",
++ "no such superimposition");
++ }
++ return;
++}
++
++// *************************************************************************
++
++/*!
++ This method sets whether the superimposed scene graph should be traversed
++ or not.
++
++ This method is not part of the original InventorXt API.
++*/
++
++void
++So at Gui@Viewer::setSuperimpositionEnabled(SoNode * scene,
++ const SbBool enable)
++{
++ int idx = -1;
++ if (PRIVATE(this)->superimpositions == NULL) goto error;
++ idx = PRIVATE(this)->superimpositions->find(scene);
++ if (idx == -1) goto error;
++ PRIVATE(this)->superimpositionsenabled[idx] = enable;
++ return;
++
++ error:
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::post("So at Gui@Viewer::setSuperimpositionEnabled",
++ "no such superimposition");
++ }
++ return;
++}
++
++// *************************************************************************
++
++/*!
++ This method returns whether the superimposed scene is rendered or not.
++
++ This method is not part of the original InventorXt API.
++*/
++
++SbBool
++So at Gui@Viewer::getSuperimpositionEnabled(SoNode * scene) const
++{
++ int idx = -1;
++ if (PRIVATE(this)->superimpositions == NULL) goto error;
++ idx = PRIVATE(this)->superimpositions->find(scene);
++ if (idx == -1) goto error;
++ return PRIVATE(this)->superimpositionsenabled[idx];
++
++ error:
++ if (SO at GUI@_DEBUG) {
++ SoDebugError::post("So at Gui@Viewer::getSuperimpositionEnabled",
++ "no such superimposition");
++ }
++ return FALSE;
++}
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiViewer.h.in
+@@ -0,0 +1,244 @@
++#ifndef SO at GUI@_VIEWER_H
++#define SO at GUI@_VIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/**************************************************************************\
++ *
++ * A WORD OF ADVICE
++ *
++ * It is fruitless to modify the contents of the So at Gui@Viewer.h file
++ * because it is autogenerated by configure from the SoAnyViewer.h.in
++ * file which you will find in the src/Inventor/@Gui@/common/ directory.
++ * Do your modifications to that file instead.
++ *
++\**************************************************************************/
++
++// Include this first, as a workaround for building on top of SGI and
++// TGS Inventor on some Linux distributions. (The bug is in SGI/TGS
++// Inventor.)
++#include <math.h>
++
++#include <Inventor/SbTime.h>
++#include <Inventor/SoType.h>
++#include <Inventor/SbLinear.h>
++
++#include <Inventor/@Gui@/So at Gui@RenderArea.h>
++
++#ifndef SO at GUI@_INTERNAL
++#include <Inventor/events/SoKeyboardEvent.h>
++#endif // SO at GUI@_INTERNAL
++
++class SoCallbackList;
++class SoBaseColor;
++class SoCamera;
++class SoComplexity;
++class SoDirectionalLight;
++class SoDrawStyle;
++class SoGetBoundingBoxAction;
++class SoGroup;
++class SoLightModel;
++class SoMaterialBinding;
++class SoNode;
++class SoPolygonOffset;
++class SoSensor;
++class SoSeparator;
++class SoSwitch;
++class SoTimerSensor;
++
++class So at Gui@Viewer;
++
++typedef void So at Gui@ViewerCB(void * data, So at Gui@Viewer * viewer);
++typedef void So at Gui@ViewerFPSCB(float fps, void * data, So at Gui@Viewer * viewer);
++
++typedef SbVec2f So at Gui@AutoClippingCB(void * data, const SbVec2f & nearfar);
++
++// *************************************************************************
++
++class SO at GUI@_DLL_API So at Gui@Viewer : public So at Gui@RenderArea {
++ SO at GUI@_OBJECT_ABSTRACT_HEADER(So at Gui@Viewer, So at Gui@RenderArea);
++
++public:
++ enum Type {
++ BROWSER,
++ EDITOR
++ };
++
++ enum DrawStyle {
++ VIEW_AS_IS,
++ VIEW_HIDDEN_LINE,
++ VIEW_NO_TEXTURE,
++ VIEW_LOW_COMPLEXITY,
++ VIEW_LINE,
++ VIEW_POINT,
++ VIEW_BBOX,
++ VIEW_LOW_RES_LINE,
++ VIEW_LOW_RES_POINT,
++ VIEW_SAME_AS_STILL,
++ VIEW_WIREFRAME_OVERLAY
++ };
++
++ enum DrawType {
++ STILL = 0,
++ INTERACTIVE
++ };
++
++ enum BufferType {
++ BUFFER_SINGLE,
++ BUFFER_DOUBLE,
++ BUFFER_INTERACTIVE
++ };
++
++ enum AutoClippingStrategy {
++ VARIABLE_NEAR_PLANE,
++ CONSTANT_NEAR_PLANE
++ };
++
++ virtual void setCamera(SoCamera * camera);
++ SoCamera * getCamera(void) const;
++
++ virtual void setCameraType(SoType type);
++ SoType getCameraType(void) const;
++
++ virtual void toggleCameraType(void);
++
++ virtual void viewAll(void);
++
++ virtual void saveHomePosition(void);
++ virtual void resetToHomePosition(void);
++
++ virtual void setHeadlight(SbBool enable);
++ SbBool isHeadlight(void) const;
++ SoDirectionalLight * getHeadlight(void) const;
++
++ virtual void setDrawStyle(So at Gui@Viewer::DrawType type, So at Gui@Viewer::DrawStyle style);
++ So at Gui@Viewer::DrawStyle getDrawStyle(const So at Gui@Viewer::DrawType type) const;
++
++ virtual void setBufferingType(So at Gui@Viewer::BufferType type);
++ So at Gui@Viewer::BufferType getBufferingType(void) const;
++
++ virtual void setViewing(SbBool enable);
++ SbBool isViewing(void) const;
++
++ virtual void setCursorEnabled(SbBool enable);
++ SbBool isCursorEnabled(void) const;
++
++ void setAutoClipping(SbBool enable);
++ SbBool isAutoClipping(void) const;
++
++ void setAutoClippingStrategy(const AutoClippingStrategy strategy,
++ const float value = 0.6f,
++ So at Gui@AutoClippingCB * cb = NULL,
++ void * cbuserdata = NULL);
++
++ virtual void setStereoViewing(SbBool enable);
++ SbBool isStereoViewing(void) const;
++
++ virtual void setStereoOffset(const float dist);
++ float getStereoOffset(void) const;
++
++ enum StereoType {
++ STEREO_NONE, STEREO_ANAGLYPH, STEREO_QUADBUFFER,
++ STEREO_INTERLEAVED_ROWS, STEREO_INTERLEAVED_COLUMNS
++ };
++
++ SbBool setStereoType(So at Gui@Viewer::StereoType s);
++ So at Gui@Viewer::StereoType getStereoType(void) const;
++
++ void setAnaglyphStereoColorMasks(const SbBool left[3], const SbBool right[3]);
++ void getAnaglyphStereoColorMasks(SbBool left[3], SbBool right[3]);
++
++ void setDetailSeek(const SbBool enable);
++ SbBool isDetailSeek(void) const;
++
++ void setSeekTime(const float seconds);
++ float getSeekTime(void) const;
++
++ void addStartCallback(So at Gui@ViewerCB * func, void * data = NULL);
++ void addFinishCallback(So at Gui@ViewerCB * func, void * data = NULL);
++ void removeStartCallback(So at Gui@ViewerCB * func, void * data = NULL);
++ void removeFinishCallback(So at Gui@ViewerCB * func, void * data = NULL);
++
++ void setWireframeOverlayColor(const SbColor & color);
++ const SbColor & getWireframeOverlayColor(void) const;
++
++ virtual void setDoubleBuffer(const SbBool enable);
++
++ virtual void setSceneGraph(SoNode * root);
++ virtual SoNode * getSceneGraph(void);
++
++protected:
++ So at Gui@Viewer(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ Type type,
++ SbBool build);
++ ~So at Gui@Viewer();
++
++ virtual void sizeChanged(const SbVec2s & size);
++ virtual void setSeekMode(SbBool enable);
++ SbBool isSeekMode(void) const;
++ SbBool seekToPoint(const SbVec2s screenpos);
++ void seekToPoint(const SbVec3f & scenepos);
++ virtual void computeSeekFinalOrientation(void);
++
++ virtual void actualRedraw(void);
++ virtual SbBool processSoEvent(const SoEvent * const event);
++
++ void interactiveCountInc(void);
++ void interactiveCountDec(void);
++ int getInteractiveCount(void) const;
++
++ void setSeekDistance(const float distance);
++ float getSeekDistance(void) const;
++ void setSeekValueAsPercentage(const SbBool on);
++ SbBool isSeekValuePercentage(void) const;
++
++ virtual void changeCameraValues(SoCamera * camera);
++
++ void addSuperimposition(SoNode * scene);
++ void removeSuperimposition(SoNode * scene);
++ void setSuperimpositionEnabled(SoNode * scene, const SbBool enable);
++ SbBool getSuperimpositionEnabled(SoNode * scene) const;
++
++private:
++ class So at Gui@ViewerP * pimpl;
++ friend class So at Gui@ViewerP;
++ friend class So at Gui@PlaneViewer;
++};
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_VIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiViewerP.h.in
+@@ -0,0 +1,205 @@
++#ifndef SOGUIVIEWERP_H
++#define SOGUIVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++#include <Inventor/SbRotation.h>
++#include <Inventor/SbVec3f.h>
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/common/gl.h>
++#include <Inventor/@Gui@/common/SbGuiList.h>
++#include <Inventor/@Gui@/viewers/So at Gui@Viewer.h>
++
++class SoSeparator;
++class SoCamera;
++class SoOrthographicCamera;
++class SoPerspectiveCamera;
++class SoGetBoundingBoxAction;
++class SoNode;
++class SoTimerSensor;
++class SoDirectionalLight;
++class SoSwitch;
++class SoBaseColor;
++class SoDrawStyle;
++class SoLightModel;
++class SoMaterialBinding;
++class SoPolygonOffset;
++class SoComplexity;
++class SoSearchAction;
++class SoGetMatrixAction;
++class SoAlarmSensor;
++
++class So at Gui@ViewerP {
++public:
++ So at Gui@ViewerP(So at Gui@Viewer * publ);
++ ~So at Gui@ViewerP(void);
++
++ SoSeparator * createSuperScene(void);
++
++ static void convertOrtho2Perspective(const SoOrthographicCamera * in,
++ SoPerspectiveCamera * out);
++ static void convertPerspective2Ortho(const SoPerspectiveCamera * in,
++ SoOrthographicCamera * out);
++
++ SoCamera * camera;
++ So at Gui@Viewer::Type type;
++ SbBool viewingflag;
++ SbBool altdown;
++ SoGetBoundingBoxAction * autoclipbboxaction;
++ SoSeparator * sceneroot;
++ SoNode * scenegraph;
++
++
++ // Seek functionality
++ SoTimerSensor * seeksensor;
++ float seekperiod;
++ SbBool inseekmode;
++ SbBool seektopoint;
++ SbVec3f camerastartposition, cameraendposition;
++ SbRotation camerastartorient, cameraendorient;
++ float seekdistance;
++ SbBool seekdistanceabs;
++
++ // Home position storage.
++ SoNode * storedcamera;
++
++ SoDirectionalLight * headlight;
++
++ // Drawstyles
++ So at Gui@Viewer::DrawStyle drawstyles[2];
++ SoSwitch * drawstyleroot, * hiddenlineroot, * polygonoffsetparent;
++ SoBaseColor * sobasecolor;
++ SoComplexity * socomplexity;
++ SoDrawStyle * sodrawstyle;
++ SoLightModel * solightmodel;
++ SoMaterialBinding * somaterialbinding;
++ SoSeparator * usersceneroot;
++ SoSwitch * superimpositionroot;
++#ifdef HAVE_SOPOLYGONOFFSET
++ SoPolygonOffset * sopolygonoffset;
++#endif // HAVE_SOPOLYGONOFFSET
++ // Automatic setting of clipping planes
++ SbBool adjustclipplanes;
++
++ // Keep track of the frames-per-second counter.
++ // Const value trick for old compilers.
++ enum Constants { FRAMESARRAY_SIZE = 100 };
++ SbVec2f frames[FRAMESARRAY_SIZE];
++ float totalcoin, totaldraw;
++ double lastgettimeofday;
++ int framecount;
++
++ // Stereo-related
++ SbBool stereoviewing, stereotypesetexplicit;
++ float stereooffset;
++ So at Gui@Viewer::StereoType stereotype;
++ SbBool stereoanaglyphmask[2][3];
++ SbViewportRegion stereostencilmaskvp;
++ GLubyte * stereostencilmask;
++ enum StencilType { ROWS, COLUMNS, NONE };
++ So at Gui@Viewer::StereoType stereostenciltype;
++ enum Eye { LEFT, RIGHT, RESTORE };
++ struct StereoData {
++ SbVec3f camerapos, cameradir, offsetvec, focalpoint;
++ SbRotation camerarot;
++ float offset;
++ SbBool nodenotify, positionnotify, orientationnotify;
++ };
++ void setStereoEye(SoCamera * camera,
++ const So at Gui@ViewerP::Eye eye,
++ So at Gui@ViewerP::StereoData & storage) const;
++ void initStencilBufferForInterleavedStereo(void);
++
++ // Misc
++ SoType cameratype;
++ SbBool cursoron, localsetbuffertype;
++ SoCallbackList * interactionstartCallbacks, * interactionendCallbacks;
++ int interactionnesting;
++ So at Gui@Viewer::BufferType buffertype;
++ SbColor wireframeoverlaycolor;
++
++ void reallyRedraw(const SbBool clearcol, const SbBool clearz = TRUE);
++
++ // Seek functionality
++ static void seeksensorCB(void * data, SoSensor *);
++
++ // Drawstyles
++ void changeDrawStyle(So at Gui@Viewer::DrawStyle style);
++ SbBool drawInteractiveAsStill(void) const;
++ SbBool drawAsHiddenLine(void) const;
++ SbBool drawAsWireframeOverlay(void) const;
++ So at Gui@Viewer::DrawStyle currentDrawStyle(void) const;
++
++ // Automatic setting of clipping planes
++ void setClippingPlanes(void);
++
++ // Methods to keep track of frames-per-second value.
++ void resetFrameCounter(void);
++ SbVec2f addFrametime(const double ft);
++ void recordFPS(const double rendertime);
++
++ // Misc
++ static void interactivestartCB(void *, So at Gui@Viewer * thisp);
++ static void interactiveendCB(void *, So at Gui@Viewer * thisp);
++ void moveCameraScreen(const SbVec2f & screenpos);
++ void getCameraCoordinateSystem(SoCamera * camera, SoNode * root,
++ SbMatrix & matrix, SbMatrix & inverse);
++
++ SoGroup * getParentOfNode(SoNode * root, SoNode * node) const;
++ SoSearchAction * searchaction;
++
++ SoGetMatrixAction * matrixaction;
++ SbPList * superimpositions;
++ SbGuiList<SbBool> superimpositionsenabled;
++ So at Gui@Viewer * pub;
++
++ // auto clipping parameters
++ So at Gui@Viewer::AutoClippingStrategy autoclipstrategy;
++ float autoclipvalue;
++ So at Gui@AutoClippingCB * autoclipcb;
++ void * autoclipuserdata;
++
++ SoAlarmSensor * redrawalarm;
++};
++
++#endif // SOGUIVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiWalkViewer.cpp.in
+@@ -0,0 +1,118 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++// This file contains the generic, "templatize-able" parts of the
++// So*WalkViewer sourcecode.
++
++// *************************************************************************
++
++/*!
++ \class So at Gui@WalkViewer Inventor/@Gui@/viewers/So at Gui@WalkViewer.h
++ \brief The So at Gui@WalkViewer class is a viewer for moving about in "walk"-like style.
++ \ingroup components viewers
++
++ This is a viewer suitable for architectural-type walk-throughs, for
++ instance.
++
++ FIXME: more class doc
++*/
++
++// *************************************************************************
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <Inventor/@Gui@/viewers/So at Gui@WalkViewer.h>
++#include <Inventor/@Gui@/viewers/SoGuiWalkViewerP.h>
++#include <Inventor/SbLinear.h>
++#include <Inventor/errors/SoDebugError.h>
++#include <Inventor/nodes/SoCamera.h>
++#include <assert.h>
++#include <so at gui@defs.h>
++
++#define PRIVATE(ptr) ptr->pimpl
++#define PUBLIC(ptr) ptr->pub
++
++#ifndef DOXYGEN_SKIP_THIS
++
++SoGuiWalkViewerP::SoGuiWalkViewerP(So at Gui@WalkViewer * publ)
++{
++ PUBLIC(this) = publ;
++}
++
++SoGuiWalkViewerP::~SoGuiWalkViewerP()
++{
++}
++
++// This method dollies the camera back and forth in the scene.
++void
++SoGuiWalkViewerP::dollyCamera(const float delta) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++ SbPlane walkplane(PUBLIC(this)->getUpDirection(), camera->position.getValue());
++ SbVec3f campos = camera->position.getValue();
++ SbVec3f camvec;
++ camera->orientation.getValue().multVec(SbVec3f(0, 0, -1), camvec);
++ SbLine cross(campos + camvec,
++ campos + camvec + PUBLIC(this)->getUpDirection());
++ SbVec3f intersect;
++ walkplane.intersect(cross, intersect);
++ SbVec3f dir = intersect - campos;
++ dir.normalize();
++
++ camera->position = campos - dir * delta;
++}
++
++// This method elevates the camera up and down.
++void
++SoGuiWalkViewerP::elevateCamera(const float delta) const
++{
++ SoCamera * const camera = PUBLIC(this)->getCamera();
++ if (camera == NULL) { return; } // if there's no scenegraph, for instance
++
++ SbVec3f up = PUBLIC(this)->getUpDirection();
++ up.normalize();
++ camera->position = camera->position.getValue() - up * delta;
++}
++
++#endif // DOXYGEN_SKIP_THIS
++
++// *************************************************************************
++
++#undef PRIVATE
++#undef PUBLIC
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiWalkViewer.h.in
+@@ -0,0 +1,113 @@
++#ifndef SO at GUI@_WALKVIEWER_H
++#define SO at GUI@_WALKVIEWER_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/@Gui@/viewers/So at Gui@ConstrainedViewer.h>
++
++class SO at GUI@_DLL_API So at Gui@WalkViewer : public So at Gui@ConstrainedViewer {
++ SO at GUI@_OBJECT_HEADER(So at Gui@WalkViewer, So at Gui@ConstrainedViewer);
++
++public:
++ So at Gui@WalkViewer(@WIDGET@ parent = NULL,
++ const char * name = NULL,
++ SbBool embed = TRUE,
++ So at Gui@FullViewer::BuildFlag flag = BUILD_ALL,
++ So at Gui@Viewer::Type type = BROWSER);
++ ~So at Gui@WalkViewer();
++
++ virtual void setViewing(SbBool enable);
++ virtual void setCamera(SoCamera * camera);
++ virtual void setCursorEnabled(SbBool enable);
++
++ virtual void setCameraType(SoType type);
++
++protected:
++ So at Gui@WalkViewer(@WIDGET@ parent,
++ const char * name,
++ SbBool embed,
++ So at Gui@FullViewer::BuildFlag flag,
++ So at Gui@Viewer::Type type,
++ SbBool build);
++
++ virtual const char * getDefaultWidgetName(void) const;
++ virtual const char * getDefaultTitle(void) const;
++ virtual const char * getDefaultIconTitle(void) const;
++
++ virtual void processEvent(@EVENT@ event);
++
++ virtual void setSeekMode(SbBool enable);
++ virtual void actualRedraw(void);
++
++ virtual void rightWheelMotion(float value);
++
++ virtual @WIDGET@ buildLeftTrim(@WIDGET@ parent);
++
++private:
++ class So at Gui@WalkViewerP * pimpl;
++ friend class SoGuiWalkViewerP;
++ friend class So at Gui@WalkViewerP;
++
++/// FIXME!: merge the So*WalkViewer.h parts in properly. 20020109 mortene. ////
++
++#ifdef __COIN_SOXT__
++protected:
++ virtual void leftWheel2Start(void);
++ virtual void leftWheel2Motion(float value);
++ virtual void leftWheel2Finish(void);
++ float getLeftWheel2Value(void) const;
++ void setLeftWheel2String(char * string);
++
++private:
++ void constructor(SbBool build);
++
++ Widget heightwheel;
++ float heightvalue;
++
++ void wheelarmed(void);
++ static void wheelarmedCB(Widget, XtPointer, XtPointer);
++ void wheelchanged(float value);
++ static void wheelchangedCB(Widget, XtPointer, XtPointer);
++ void wheeldisarmed(void);
++ static void wheeldisarmedCB(Widget, XtPointer, XtPointer);
++#endif // ! __COIN_SOXT__
++
++#ifdef __COIN_SOGTK__
++private:
++ void constructor(const SbBool build);
++#endif // ! __COIN_SOGTK__
++};
++
++#endif // ! SO at GUI@_WALKVIEWER_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/SoGuiWalkViewerP.h.in
+@@ -0,0 +1,64 @@
++#ifndef SOGUIWALKVIEWERP_H
++#define SOGUIWALKVIEWERP_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifndef SO at GUI@_INTERNAL
++#error this is a private header file
++#endif /* !SO at GUI@_INTERNAL */
++
++class So at Gui@WalkViewer;
++
++// ************************************************************************
++
++// This class contains private data and methods used within the
++// SoGuiWalkViewer class.
++
++class SoGuiWalkViewerP
++{
++public:
++ ~SoGuiWalkViewerP();
++
++ void dollyCamera(const float change) const;
++ void elevateCamera(const float change) const;
++
++protected:
++ SoGuiWalkViewerP(So at Gui@WalkViewer * publ);
++ So at Gui@WalkViewer * pub;
++};
++
++// ************************************************************************
++
++#endif // ! SOGUIWALKVIEWERP_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/viewers/killed-prefs.diff
+@@ -0,0 +1,355 @@
++This file contains the big diff resulting when killing off all the
++common template code for handling the preference sheet. It has been
++added to the CVS repository in case someone (important) loudly
++complains about me ripping out the prefsheet support.
++
++The native toolkit specific diff can be found in
++src/Inventor/@Gui@/viewers/.
++
++20020606 mortene.
++
++
++Index: SoGuiExaminerViewer.cpp.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiExaminerViewer.cpp.in,v
++retrieving revision 1.17
++diff -u -w -r1.17 SoGuiExaminerViewer.cpp.in
++--- SoGuiExaminerViewer.cpp.in 6 Jun 2002 13:01:12 -0000 1.17
+++++ SoGuiExaminerViewer.cpp.in 6 Jun 2002 15:50:30 -0000
++@@ -1108,8 +1108,8 @@
++ // *************************************************************************
++
++ // Documented in superclass. Overrides this method to be able to draw
++-// the axis cross if selected in the preferences sheet, and to keep a
++-// continuous animation upon spin.
+++// the axis cross, if selected, and to keep a continuous animation
+++// upon spin.
++ void
++ So at Gui@ExaminerViewer::actualRedraw(void)
++ {
++Index: SoGuiExaminerViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiExaminerViewer.h.in,v
++retrieving revision 1.17
++diff -u -w -r1.17 SoGuiExaminerViewer.h.in
++--- SoGuiExaminerViewer.h.in 3 Jun 2002 19:28:18 -0000 1.17
+++++ SoGuiExaminerViewer.h.in 6 Jun 2002 15:50:30 -0000
++@@ -75,7 +75,6 @@
++ virtual void bottomWheelMotion(float val);
++ virtual void rightWheelMotion(float val);
++
++- virtual @WIDGET@ makeSubPreferences(@WIDGET@ parent);
++ virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttonlist);
++
++ virtual const char * getDefaultWidgetName(void) const;
++@@ -89,7 +88,6 @@
++ virtual void actualRedraw(void);
++
++ virtual void afterRealizeHook(void);
++- virtual void createPrefSheet(void);
++
++ private:
++ class So at Gui@ExaminerViewerP * pimpl;
++Index: SoGuiFlyViewer.cpp.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFlyViewer.cpp.in,v
++retrieving revision 1.14
++diff -u -w -r1.14 SoGuiFlyViewer.cpp.in
++--- SoGuiFlyViewer.cpp.in 6 Jun 2002 12:40:23 -0000 1.14
+++++ SoGuiFlyViewer.cpp.in 6 Jun 2002 15:50:30 -0000
++@@ -1042,17 +1042,6 @@
++
++ // ************************************************************************
++
++-/*!
++- FIXME: doc
++- */
++-void
++-So at Gui@FlyViewer::createPrefSheet(void)
++-{
++- SO at GUI@_STUB();
++-}
++-
++-// ************************************************************************
++-
++ // doc in super
++ void
++ So at Gui@FlyViewer::openViewerHelpCard(void)
++@@ -1071,22 +1060,3 @@
++ }
++
++ // ************************************************************************
++-
++-// FIXME: this code is "left over" after we migrated to a common
++-// code-base in SoGuiFlyViewer.cpp.in. Fix up and re-enable. 20011209 mortene.
++-
++-// void
++-// SoXtFlyViewer::createPrefSheet(void)
++-// {
++-// if (! this->prefshell) {
++-// this->prefparts = new Widget [ 16 ];
++-// this->createPrefSheetShellAndForm(this->prefshell, this->prefsheet);
++-// this->createDefaultPrefSheetParts(this->prefparts, this->numprefparts,
++-// this->prefsheet);
++-// this->prefparts[this->numprefparts] =
++-// this->createFramedSpeedPrefSheetGuts(this->prefsheet);
++-// if (this->prefparts[this->numprefparts] != NULL) this->numprefparts++;
++-// }
++-// this->layoutPartsAndMapPrefSheet(this->prefparts, this->numprefparts,
++-// this->prefsheet, this->prefshell);
++-// }
++Index: SoGuiFlyViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFlyViewer.h.in,v
++retrieving revision 1.4
++diff -u -w -r1.4 SoGuiFlyViewer.h.in
++--- SoGuiFlyViewer.h.in 4 Jun 2002 15:16:11 -0000 1.4
+++++ SoGuiFlyViewer.h.in 6 Jun 2002 15:50:30 -0000
++@@ -66,7 +66,6 @@
++
++ virtual void rightWheelMotion(float value);
++
++- virtual void createPrefSheet(void);
++ virtual void openViewerHelpCard(void);
++
++ virtual void afterRealizeHook(void);
++Index: SoGuiFullViewer.cpp.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFullViewer.cpp.in,v
++retrieving revision 1.18
++diff -u -w -r1.18 SoGuiFullViewer.cpp.in
++--- SoGuiFullViewer.cpp.in 6 Jun 2002 13:01:12 -0000 1.18
+++++ SoGuiFullViewer.cpp.in 6 Jun 2002 15:50:30 -0000
++@@ -105,31 +105,6 @@
++
++ // ************************************************************************
++
++-// Note: common documentation for all subclasses aswell.
++-/*!
++- \fn void So at Gui@FullViewer::createPrefSheet(void)
++-
++- Create preferences sheet.
++-
++- This is a hook for constructing the preferences window in the
++- derived viewer classes.
++-
++- Basically, derived classes will do the following in this method:
++-
++- \code
++- if (! this->prefshell) {
++- createPrefSheetShellAndForm(this->prefshell, this->prefsheet);
++- createDefaultPrefSheetParts(this->prefparts, this->numprefparts,
++- this->prefsheet);
++- // add parts specific for derived viewer
++- }
++- layoutPartsAndMapPrefSheet(this->prefparts, this->numprefparts,
++- this->prefsheet, this->prefshell);
++- \endcode
++-*/
++-
++-// ************************************************************************
++-
++ // Note: the following function documentation blocks for thumbwheel
++ // handling will also be used for all the miscellaneous viewer
++ // subclasses, so keep'em general.
++@@ -499,8 +474,6 @@
++ menu->setMenuItemTitle(HEADLIGHT_ITEM, _("Headlight"));
++ menu->newMenuItem("fullscreen", FULLSCREEN_ITEM);
++ menu->setMenuItemTitle(FULLSCREEN_ITEM, _("Fullscreen"));
++- menu->newMenuItem("preferences", PREFERENCES_ITEM);
++- menu->setMenuItemTitle(PREFERENCES_ITEM, _("Preferences..."));
++
++ menu->addMenu(ROOT_MENU, FUNCTIONS_MENU);
++ menu->addMenu(ROOT_MENU, DRAWSTYLES_MENU);
++@@ -509,8 +482,6 @@
++ menu->addMenuItem(ROOT_MENU, DECORATION_ITEM);
++ menu->addMenuItem(ROOT_MENU, HEADLIGHT_ITEM);
++ menu->addMenuItem(ROOT_MENU, FULLSCREEN_ITEM);
++- menu->addSeparator(ROOT_MENU);
++- menu->addMenuItem(ROOT_MENU, PREFERENCES_ITEM);
++
++ menu->newMenuItem("help", HELP_ITEM);
++ menu->setMenuItemTitle(HELP_ITEM, _("Help"));
++@@ -812,9 +783,6 @@
++ case FULLSCREEN_ITEM:
++ (void)PUBLIC(this)->setFullScreen(PUBLIC(this)->isFullScreen() ? FALSE : TRUE);
++ break;
++- case PREFERENCES_ITEM:
++- ((So at Gui@FullViewerP *)this)->selectedPrefs();
++- break;
++
++ case HELP_ITEM:
++ PUBLIC(this)->openViewerHelpCard();
++Index: SoGuiFullViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFullViewer.h.in,v
++retrieving revision 1.22
++diff -u -w -r1.22 SoGuiFullViewer.h.in
++--- SoGuiFullViewer.h.in 3 Jun 2002 16:27:59 -0000 1.22
+++++ SoGuiFullViewer.h.in 6 Jun 2002 15:50:30 -0000
++@@ -66,7 +66,6 @@
++
++ virtual void setViewing(SbBool on);
++ virtual void setCamera(SoCamera * cam);
++- virtual void hide(void);
++
++ virtual void setComponentCursor(const So at Gui@Cursor & cursor);
++
++@@ -95,8 +94,6 @@
++ virtual void setPopupMenuString(const char * title);
++ virtual void openPopupMenu(const SbVec2s position);
++
++- void setPrefSheetString(const char * title);
++-
++ virtual void leftWheelStart(void);
++ virtual void leftWheelMotion(float);
++ virtual void leftWheelFinish(void);
++@@ -126,8 +123,6 @@
++
++ virtual void openViewerHelpCard(void);
++
++- virtual void createPrefSheet(void);
++-
++ protected:
++ @WIDGET@ leftDecoration;
++ @WIDGET@ rightDecoration;
++@@ -164,9 +159,6 @@
++ @WIDGET@ leftWheel;
++ @WIDGET@ rightWheel;
++ @WIDGET@ bottomWheel;
++-
++- virtual bool eventFilter(QObject * obj, QEvent * e);
++- virtual @WIDGET@ makeSubPreferences(@WIDGET@ parent);
++ #endif // __COIN_SOQT__
++
++ #ifdef __COIN_SOXT__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++@@ -180,31 +172,9 @@
++ Widget buildFunctionsSubmenu(Widget popup);
++ Widget buildDrawStyleSubmenu(Widget popup);
++
++- char * prefstring;
++ char * popupTitle;
++ SbBool popupEnabled;
++ SbPList * viewerButtonWidgets;
++-
++- Widget prefshell;
++- Widget prefsheet;
++-
++- void createPrefSheetShellAndForm(Widget & shell, Widget & form);
++- void createDefaultPrefSheetParts(Widget * widgets, int & num, Widget form);
++- void layoutPartsAndMapPrefSheet(Widget * widgets, int num, Widget form, Widget shell);
++-
++- Widget createSeekPrefSheetGuts(Widget parent);
++- Widget createSeekDistPrefSheetGuts(Widget parent);
++- Widget createZoomPrefSheetGuts(Widget parent);
++- Widget createClippingPrefSheetGuts(Widget parent);
++- Widget createStereoPrefSheetGuts(Widget parent);
++- Widget createSpeedPrefSheetGuts(Widget parent);
++-
++- Widget createFramedSeekPrefSheetGuts(Widget parent);
++- Widget createFramedSeekDistPrefSheetGuts(Widget parent);
++- Widget createFramedZoomPrefSheetGuts(Widget parent);
++- Widget createFramedClippingPrefSheetGuts(Widget parent);
++- Widget createFramedStereoPrefSheetGuts(Widget parent);
++- Widget createFramedSpeedPrefSheetGuts(Widget parent);
++ #endif // __COIN_SOXT__
++
++ #ifdef __COIN_SOGTK__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++@@ -212,9 +182,6 @@
++ @WIDGET@ leftWheel;
++ @WIDGET@ rightWheel;
++ @WIDGET@ bottomWheel;
++-
++- virtual SbBool eventFilter(GtkWidget * object, GdkEvent * event);
++- virtual GtkWidget * makeSubPreferences(GtkWidget * parent);
++ #endif // __COIN_SOGTK__
++
++ #ifdef __COIN_SOWIN__ // FIXME: get rid of non-templatized code. 20020108 mortene.
++@@ -236,21 +203,12 @@
++ virtual LRESULT onMeasureItem(HWND window, UINT message, WPARAM wparam, LPARAM lparam);
++
++
++- class SoFieldSensor * zoomSensor;
++-
++ class SoWinThumbWheel * rightWheel;
++ class SoWinThumbWheel * bottomWheel;
++ class SoWinThumbWheel * leftWheel;
++
++- SbVec2f zoomrange;
++- class SoWinViewerPrefSheet * prefsheet;
++-
++ HWND viewerWidget;
++ HWND renderAreaWidget;
++-
++- // FIXME: quick hack done while merging all the header file
++- // definitions for So*FullViewer. 20020111 mortene.
++- friend class SoWinViewerPrefSheet;
++
++ protected:
++ SbPList * viewerButtonList;
++Index: SoGuiFullViewerP.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiFullViewerP.h.in,v
++retrieving revision 1.3
++diff -u -w -r1.3 SoGuiFullViewerP.h.in
++--- SoGuiFullViewerP.h.in 6 Jun 2002 13:01:12 -0000 1.3
+++++ SoGuiFullViewerP.h.in 6 Jun 2002 15:50:30 -0000
++@@ -98,7 +98,6 @@
++ DECORATION_ITEM,
++ HEADLIGHT_ITEM,
++ FULLSCREEN_ITEM,
++- PREFERENCES_ITEM,
++
++ STEREO_MENU,
++ STEREO_OFF_ITEM,
++Index: SoGuiPlaneViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiPlaneViewer.h.in,v
++retrieving revision 1.18
++diff -u -w -r1.18 SoGuiPlaneViewer.h.in
++--- SoGuiPlaneViewer.h.in 15 May 2002 20:29:03 -0000 1.18
+++++ SoGuiPlaneViewer.h.in 6 Jun 2002 15:50:30 -0000
++@@ -73,8 +73,6 @@
++ virtual void rightWheelMotion(float value);
++ virtual void rightWheelFinish(void);
++
++- virtual void createPrefSheet(void);
++-
++ virtual void createViewerButtons(@WIDGET@ parent, SbPList * buttons);
++ virtual void openViewerHelpCard(void);
++
++Index: SoGuiWalkViewer.h.in
++===================================================================
++RCS file: /export/cvsroot/SoGUI/viewers/SoGuiWalkViewer.h.in,v
++retrieving revision 1.7
++diff -u -w -r1.7 SoGuiWalkViewer.h.in
++--- SoGuiWalkViewer.h.in 31 May 2002 13:54:11 -0000 1.7
+++++ SoGuiWalkViewer.h.in 6 Jun 2002 15:50:30 -0000
++@@ -64,7 +64,6 @@
++
++ virtual @WIDGET@ buildLeftTrim(@WIDGET@ parent);
++
++- virtual void createPrefSheet(void);
++ virtual void openViewerHelpCard(void);
++
++ private:
++@@ -85,9 +84,6 @@
++ private:
++ void constructor(SbBool build);
++
++- Widget * prefparts;
++- int numprefparts;
++-
++ Widget heightwheel;
++ float heightvalue;
++
++@@ -100,9 +96,6 @@
++ #endif // ! __COIN_SOXT__
++
++ #ifdef __COIN_SOGTK__
++-protected:
++- virtual GtkWidget * makeSubPreferences(GtkWidget * parent);
++-
++ private:
++ void constructor(const SbBool build);
++ #endif // ! __COIN_SOGTK__
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoAnyThumbWheel.cpp.in
+@@ -0,0 +1,669 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++#include <math.h>
++#include <stdio.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/So at Gui@Object.h> // for __COIN_SOQT__
++#include <Inventor/@Gui@/widgets/SoAnyThumbWheel.h>
++
++#ifdef __COIN_SOQT__
++#include <qglobal.h> // for Q_WS_MAC
++#endif
++
++#ifndef M_PI
++#define M_PI 3.14159265358979323846f
++#endif // ! M_PI
++
++/*!
++ \class SoAnyThumbWheel SoAnyThumbWheel.h
++ \brief The ThumbWheel class is a helper class for managing thumb wheel
++ GUI widgets.
++ \internal
++*/
++
++/*!
++ \var int SoAnyThumbWheel::dirtyTables
++ If this flag is set, the internal tables needs to be recalculated.
++*/
++
++/*!
++ \var int SoAnyThumbWheel::dirtyVariables
++ If this flag is set, the internal variables that are calculated from the
++ tables and wheel settings need to be recalculated.
++*/
++
++static unsigned int
++int8clamp(float f) {
++ assert(f >= 0.0f);
++ if (f >= 255.0f)
++ return 255;
++ return (unsigned int) floor(f);
++} // int8clamp()
++
++// ************************************************************************
++
++/*!
++ Constructor.
++*/
++
++SoAnyThumbWheel::SoAnyThumbWheel(
++ void)
++: diameter(0)
++, width(0)
++, byteorder(ABGR)
++, boundaryhandling(ACCUMULATE)
++, movement(AUTHENTIC)
++, dirtyTables(1)
++, dirtyVariables(1)
++{
++ assert(sizeof(int) == 4 && "FIXME: use int32 datatype instead");
++
++// this->disabledred = 1.0f;
++// this->disabledgreen = 1.0f;
++// this->disabledblue = 1.0f;
++
++ this->red = 220.0f / 255.0f;
++ this->green = 180.0f / 255.0f;
++ this->blue = 180.0f / 255.0f;
++
++ this->light = 1.3f;
++ this->front = 1.2f;
++ this->normal = 1.0f;
++ this->shade = 0.8f;
++
++ for (int i = 0; i < NUMTABLES; i++)
++ this->tables[i] = NULL;
++} // SoAnyThumbWheel()
++
++/*!
++ Destructor.
++*/
++
++SoAnyThumbWheel::~SoAnyThumbWheel(
++ void)
++{
++ for (int i = 0; i < NUMTABLES; i++)
++ delete [] this->tables[i];
++} // ~ThumbWheel()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setSize(
++ const int diameterarg,
++ const int widtharg)
++{
++ if (this->diameter != diameterarg) {
++ this->dirtyTables = 1;
++ this->dirtyVariables = 1;
++ } else if (this->width != widtharg) {
++ this->dirtyVariables = 1; // embossed squares grows...
++ } else {
++ return;
++ }
++ this->diameter = diameterarg;
++ this->width = widtharg;
++} // setSize()
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::getSize(
++ int & diameterref,
++ int & widthref) const
++{
++ diameterref = this->diameter;
++ widthref = this->width;
++} // getSize()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setColor(
++ const float redval,
++ const float greenval,
++ const float blueval)
++{
++ this->red = redval;
++ this->green = greenval;
++ this->blue = blueval;
++} // setColor()
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::getColor(
++ float & redref,
++ float & greenref,
++ float & blueref) const
++{
++ redref = this->red;
++ greenref = this->green;
++ blueref = this->blue;
++} // GetColor()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setColorFactors(
++ const float lightval,
++ const float frontval,
++ const float normalval,
++ const float shadeval)
++{
++ this->light = lightval;
++ this->front = frontval;
++ this->normal = normalval;
++ this->shade = shadeval;
++} // setColorFactors()
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::getColorFactors(
++ float & lightref,
++ float & frontref,
++ float & normalref,
++ float & shaderef) const
++{
++ lightref = this->light;
++ frontref = this->front;
++ normalref = this->normal;
++ shaderef = this->shade;
++} // getColorFactors()
++
++// ************************************************************************
++
++/*!
++ This method returns the number of bitmaps required to represent all the
++ possible rotations of the thumb wheel.
++*/
++
++int
++SoAnyThumbWheel::getNumBitmaps(
++ void) const
++{
++ return this->width - 4 + 2 + 1;
++} // getNumBitmaps()
++
++// ************************************************************************
++
++/*!
++ This method draws thumb wheel bitmap \a number. \a direction decides
++ if it should be rendered in the vertical or horizontal position.
++*/
++
++void
++SoAnyThumbWheel::drawBitmap(
++ const int number,
++ void * bitmap,
++ Alignment alignment) const
++{
++ if (number == 0) {
++ drawDisabledWheel(number, bitmap, alignment);
++ } else {
++ drawEnabledWheel(number, bitmap, alignment);
++ }
++}
++
++// ************************************************************************
++
++/*!
++ This method calculates the thumb wheel value based on the users mouse
++ interaction. origpos and origval is the mouseposition at the moment of
++ pressing the button, and origval is the thumbwheels original value at
++ that point. deltapos is the number of pixels the mouse has moved since
++ pressing the button.
++
++ The point in doing it this way is that the thumbwheel can easily be made
++ to behave like an authentic wheel when all of these parameters are known.
++
++ After doing a CalculateValue, you should redraw the wheel if the value has
++ changed (since last time, not compared to origval).
++*/
++
++float
++SoAnyThumbWheel::calculateValue(
++ const float origval,
++ const int origpos,
++ const int deltapos) const
++{
++ this->validate();
++
++// fprintf(stderr, "calc(%8.4f, %d, %d)\n", origval, origpos, deltapos);
++
++ float diff = 0.0f;
++ switch (this->movement) {
++ case UNIFORM:
++ diff = this->unistep * deltapos;
++ break;
++ case AUTHENTIC:
++ int newpos = origpos + deltapos;
++ if (newpos < 0) newpos = 0;
++ if (newpos >= diameter) newpos = diameter - 1;
++ diff = this->tables[RAD][newpos] - this->tables[RAD][origpos];
++ break;
++ } // switch (this->movement)
++
++ switch (this->boundaryhandling) {
++ case MODULATE:
++ while ((origval + diff) < 0.0f ) diff += 2.0f * float(M_PI);
++ while ((origval + diff) > (2.0f * float(M_PI))) diff -= 2.0f * float(M_PI);
++ break;
++ case CLAMP:
++ if ((origval + diff) < 0.0f ) diff = 0.0f - origval;
++ if ((origval + diff) > (2.0f * float(M_PI))) diff = (2.0f * float(M_PI)) - origval;
++ break;
++ case ACCUMULATE:
++ // nothing - just add the difference on top of original value
++ break;
++ } // switch (this->boundaryhandling)
++
++ return origval + diff;
++} // calculateValue()
++
++// ************************************************************************
++
++/*!
++ This method returns the bitmap you need to display to represent a thumb
++ wheel with the given value and active state.
++*/
++
++int
++SoAnyThumbWheel::getBitmapForValue(
++ const float value,
++ const State state) const
++{
++ this->validate();
++
++ if (state == DISABLED)
++ return 0; // only one disabled bitmap in this implementation
++
++ double squarerange = (2.0 * M_PI) / this->numsquares;
++ double normalizedmodval = fmod((double) value, squarerange) / squarerange;
++ if (normalizedmodval < 0.0) normalizedmodval += 1.0;
++ int bitmap = 1 + (int) (normalizedmodval * (this->width - 4 + 2));
++ return bitmap;
++} // getBitmapForValue()
++
++// ************************************************************************
++
++/*!
++ This method sets whether to set up uints in ARGB or BGRA mode before
++ storing them in the 32-bit frame buffer.
++*/
++
++void
++SoAnyThumbWheel::setGraphicsByteOrder(
++ const GraphicsByteOrder byteorderval)
++{
++ this->byteorder = byteorderval;
++} // setGraphicsByteOrder()
++
++/*!
++*/
++
++SoAnyThumbWheel::GraphicsByteOrder
++SoAnyThumbWheel::getGraphicsByteOrder(
++ void) const
++{
++ return this->byteorder;
++} // getGraphicsByteOrder()
++
++// ************************************************************************
++
++/*!
++*/
++
++void
++SoAnyThumbWheel::setMovement(
++ const Movement movementval)
++{
++ this->movement = movementval;
++} // setMovement()
++
++/*!
++*/
++
++SoAnyThumbWheel::Movement
++SoAnyThumbWheel::getMovement(
++ void) const
++{
++ return this->movement;
++} // getMovement()
++
++// ************************************************************************
++
++void
++SoAnyThumbWheel::setBoundaryHandling(
++ const BoundaryHandling handling)
++{
++ this->boundaryhandling = handling;
++} // setBoundaryHandling()
++
++/*!
++*/
++
++SoAnyThumbWheel::BoundaryHandling
++SoAnyThumbWheel::getBoundaryHandling(
++ void) const
++{
++ return this->boundaryhandling;
++} // getBoundaryHandling()
++
++// ************************************************************************
++
++/*!
++ This method validates the ThumbWheel object, recalculating the tables and
++ state variables if necessary. If object is already valid, no calculations
++ are performed.
++*/
++
++void
++SoAnyThumbWheel::validate(// private
++ void) const
++{
++ int i;
++
++ if (this->dirtyTables) {
++ assert(this->dirtyVariables);
++ for (i = 0; i < NUMTABLES; i++) {
++ if (this->tables[i]) delete [] this->tables[i];
++ this->tables[i] = new float [ this->diameter ];
++ }
++
++ float radius = ((float) this->diameter + 1.0f) / 2.0f;
++// float range = 2.0f * M_PI;
++ float acos0times2 = 2.0f * (float)acos(0.0);
++
++ for (i = 0; i < this->diameter; i++) {
++ if ((float) i <= radius) {
++ this->tables[COS][i] = (radius - (float) i) / radius;
++ this->tables[RAD][i] = (float)acos(this->tables[COS][i]);
++ } else {
++ this->tables[COS][i] = ((float) i - radius) / radius;
++ this->tables[RAD][i] = acos0times2 - (float)acos(this->tables[COS][i]);
++ }
++ this->tables[SIN][i] = (float)sqrt(1.0f - this->tables[COS][i] * this->tables[COS][i]);
++ }
++
++ this->dirtyTables = 0;
++ }
++
++ if (this->dirtyVariables) {
++ assert(this->dirtyTables == 0);
++ if ((this->diameter % 2) == 0)
++ this->unistep = this->tables[RAD][this->diameter/2] -
++ this->tables[RAD][(this->diameter/2)-1];
++ else
++ this->unistep = (this->tables[RAD][(this->diameter/2)+1] -
++ this->tables[RAD][(this->diameter/2)-1]) / 2.0f;
++
++ this->squarespacing = 2.0f * this->unistep;
++ this->shadelength = this->unistep; // remove?
++
++ int squares = (int) floor(((2.0f * M_PI) /
++ ((((float) width - 4.0f) * this->unistep) + this->squarespacing)) + 0.5f);
++ this->numsquares = (float)squares;
++ this->squarelength = (float(2.0 * M_PI) / (float) squares) - this->squarespacing;
++
++ this->dirtyVariables = 0;
++ }
++} // validate()
++
++// ************************************************************************
++
++inline unsigned int
++SoAnyThumbWheel::swapWord(
++ unsigned int orig) const
++{
++ // orig is RGBA
++ unsigned int copy;
++ if (this->byteorder == ABGR) {
++ copy = (orig & 0x000000ff) << 24;
++ copy |= (orig & 0x0000ff00) << 8;
++ copy |= (orig & 0x00ff0000) >> 8;
++ copy |= (orig & 0xff000000) >> 24;
++ } else if (this->byteorder == ARGB) {
++ copy = orig >> 8; // RGB
++ // FIXME: QImage::hasAlphaBuffer() is ignored on Qt4 on Mac OS X,
++ // thus we must explicitly set the alpha component to 0xff (opaque).
++ // Bug reported to Trolltech. 20050805 kyrah.
++#if (defined(Q_WS_MAC) && (QT_VERSION >= 0x040000))
++ copy |= 0xff << 24; // A
++#else
++ copy |= (orig & 0xff) << 24; // A
++#endif
++ } else if (this->byteorder == BGRA) {
++ copy = orig & 0x00ff00ff; // G & A
++ copy |= (orig & 0x0000ff00) << 16; // B
++ copy |= (orig & 0xff000000) >> 16; // R
++ } else {
++ copy = orig; // ?
++ }
++ return copy;
++} // swapWord()
++
++/*!
++ This method draws a wheel that has been disabled from being rotated.
++*/
++
++void
++SoAnyThumbWheel::drawDisabledWheel(// private
++ const int number,
++ void * bitmap,
++ Alignment alignment) const
++{
++ assert(number == 0);
++
++ this->validate();
++
++ unsigned int * buffer = (unsigned int *) bitmap;
++
++ for (int j = 0; j < this->diameter; j++) {
++ unsigned int lightval, frontval, normalval, shadeval;
++ lightval = int8clamp(255.0f * this->tables[SIN][j] * 1.15f);
++ frontval = 0;
++ normalval = int8clamp(255.0f * this->tables[SIN][j]);
++ shadeval = int8clamp(255.0f * this->tables[SIN][j] * 0.85f);
++
++ // rgbx
++ lightval = (lightval << 24) | (lightval << 16) | (lightval << 8);
++ frontval = (frontval << 24) | (frontval << 16) | (frontval << 8);
++ normalval = (normalval << 24) | (normalval << 16) | (normalval << 8);
++ shadeval = (shadeval << 24) | (shadeval << 16) | (shadeval << 8);
++
++ if (this->byteorder != RGBA) {
++ lightval = this->swapWord(lightval);
++ frontval = this->swapWord(frontval);
++ normalval = this->swapWord(normalval);
++ shadeval = this->swapWord(shadeval);
++ }
++
++ if (alignment == VERTICAL) {
++ buffer[j*this->width] = lightval;
++ for (int i = 1; i < (width - 1); i++)
++ buffer[(j*this->width)+i] = normalval;
++ buffer[(j*this->width)+(this->width-1)] = shadeval;
++ } else {
++ buffer[j] = lightval;
++ for (int i = 1; i < (this->width-1); i++)
++ buffer[j+(i*this->diameter)] = normalval;
++ buffer[j+((this->width-1)*this->diameter)] = shadeval;
++ }
++ }
++} // drawDisabledWheel()
++
++// ************************************************************************
++
++/*
++ This method draws the thumb wheel.
++ Shading/lighting aliasing can still be done better...
++ Can also optimize the drawing to use less computing power...
++*/
++
++void
++SoAnyThumbWheel::drawEnabledWheel(
++ const int number,
++ void * bitmap,
++ Alignment alignment) const
++{
++ this->validate();
++
++ int numEnabledBitmaps = this->width - 4 + 2;
++ assert(number > 0 && number <= numEnabledBitmaps);
++
++ float modulo = (2.0f * (float)M_PI) / this->numsquares;
++ float radian = modulo - (((2.0f * (float)M_PI) / this->numsquares) * (((float) (number - 1)) / (float) numEnabledBitmaps));
++
++ int newsquare = 1;
++ int flag = 1;
++ unsigned int * buffer = (unsigned int *) bitmap;
++ for (int j = 0; j < this->diameter; j++) {
++ unsigned int lightval, frontval, normalval, shadeval, color;
++
++ lightval = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->light) << 24) +
++ (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->light) << 16) +
++ (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->light) << 8);
++ frontval = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->front) << 24) +
++ (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->front) << 16) +
++ (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->front) << 8);
++ normalval = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->normal) << 24) +
++ (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->normal) << 16) +
++ (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->normal) << 8);
++ shadeval = (int8clamp(255.0f * this->red * this->tables[SIN][j] * this->shade) << 24) +
++ (int8clamp(255.0f * this->green * this->tables[SIN][j] * this->shade) << 16) +
++ (int8clamp(255.0f * this->blue * this->tables[SIN][j] * this->shade) << 8);
++
++ if (this->byteorder != RGBA) {
++ lightval = this->swapWord(lightval);
++ normalval = this->swapWord(normalval);
++ frontval = this->swapWord(frontval);
++ shadeval = this->swapWord(shadeval);
++ }
++
++ if (newsquare) {
++ color=frontval;
++ newsquare = 0;
++ flag = 1;
++ } else {
++ if (flag == 1) {
++ if (j < (this->diameter * 2 / 3))
++ color = shadeval;
++ else
++ color = normalval;
++ flag = 0;
++ } else {
++ color = normalval;
++ }
++ }
++
++ if (alignment == VERTICAL) {
++ buffer[(this->width*j)] = frontval;
++ buffer[(this->width*j)+1] = frontval;
++ if (flag == 1) buffer[(this->width*j)+2] = frontval;
++ else buffer[(this->width*j)+2] = shadeval;
++
++ for (int i = 3; i < (this->width-2); i++)
++ buffer[(j*this->width)+i] = color;
++
++ if (flag == 1) buffer[(this->width*j)+this->width-3] = frontval;
++ else buffer[(this->width*j)+this->width-3] = normalval;
++ buffer[(this->width*j)+this->width-2] = frontval;
++ buffer[(this->width*j)+this->width-1] = frontval;
++ } else {
++
++ buffer[j] = frontval;
++ buffer[j+this->diameter] = frontval;
++ if (flag == 1) buffer[j+(this->diameter*2)] = frontval;
++ else buffer[j+(this->diameter*2)] = shadeval;
++
++ for (int i = 2; i < (this->width-2); i++)
++ buffer[j+(i*this->diameter)] = color;
++
++ if (flag == 1) buffer[j+(this->diameter*(this->width-3))] = frontval;
++ else buffer[j+(this->diameter*(this->width-3))] = normalval;
++ buffer[j+(this->diameter*(this->width-2))] = frontval;
++ buffer[j+(this->diameter*(this->width-1))] = frontval;
++ }
++
++ if (j < (this->diameter - 1)) {
++ radian += this->tables[RAD][j+1] - this->tables[RAD][j];
++ if (radian > modulo) {
++ if (alignment == VERTICAL) {
++ int color = 0;
++ if (j > (this->diameter * 2 / 3))
++ color = lightval;
++ else if (j > (this->diameter / 3))
++ color = frontval;
++ if (color != 0)
++ for (int i = 3; i < (this->width-2); i++)
++ buffer[(j*this->width)+i] = color;
++ } else {
++ int color = 0;
++ if (j > (this->diameter * 2 / 3))
++ color = lightval;
++ else if (j > (this->diameter / 3))
++ color = frontval;
++ if (color != 0)
++ for (int i = 3; i < (this->width-2); i++)
++ buffer[j+(this->diameter*i)] = color;
++ }
++ radian = (float) fmod(radian, modulo);
++ newsquare = 1;
++ }
++ }
++ }
++} // drawEnabledWheel()
++
++// ************************************************************************
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoAnyThumbWheel.h.in
+@@ -0,0 +1,99 @@
++#ifndef SOANY_THUMBWHEEL_H
++#define SOANY_THUMBWHEEL_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++class SoAnyThumbWheel {
++public:
++ enum State { DISABLED, ENABLED };
++ enum Alignment { VERTICAL, HORIZONTAL };
++ enum BoundaryHandling { MODULATE, ACCUMULATE, CLAMP };
++ enum Movement { UNIFORM, AUTHENTIC };
++ enum GraphicsByteOrder { ABGR, RGBA, ARGB, BGRA };
++
++ SoAnyThumbWheel(void);
++ ~SoAnyThumbWheel(void);
++
++ void setSize(const int diameter, const int width);
++ void getSize(int & diameter, int & width) const;
++
++ void setColor(const float red, const float green, const float blue);
++ void getColor(float & red, float & green, float & blue) const;
++ void setColorFactors(const float light, const float front, const float normal, const float shade);
++ void getColorFactors(float & light, float & front, float & normal, float & shade) const;
++
++ int getNumBitmaps(void) const;
++ void drawBitmap(const int number, void * bitmap, Alignment alignment) const;
++ float calculateValue(const float origValue, const int origPosition, const int deltaPosition) const;
++ int getBitmapForValue(const float value, const State state) const;
++
++ void setGraphicsByteOrder(const GraphicsByteOrder byteorder);
++ GraphicsByteOrder getGraphicsByteOrder(void) const;
++
++ void setMovement(const Movement movement);
++ Movement getMovement(void) const;
++
++ void setBoundaryHandling(const BoundaryHandling handling);
++ BoundaryHandling getBoundaryHandling(void) const;
++
++private:
++ unsigned int swapWord(unsigned int) const;
++
++ int diameter, width;
++ // float disabledred, disabledgreen, disabledblue; // not implemented
++ float red, green, blue;
++ float light, front, normal, shade;
++
++ GraphicsByteOrder byteorder;
++ BoundaryHandling boundaryhandling;
++ Movement movement;
++
++ enum Tables { SIN, COS, RAD, NUMTABLES };
++
++ mutable float * tables [ NUMTABLES ];
++ mutable int dirtyTables;
++ mutable int dirtyVariables;
++ mutable float squarelength, squarespacing, shadelength, unistep, numsquares;
++
++ void drawDisabledWheel(const int number, void * bitmap, Alignment alignment) const;
++ void drawEnabledWheel(const int number, void * bitmap, Alignment alignment) const;
++
++ void validate(void) const;
++
++}; // class SoAnyThumbWheel
++
++// ************************************************************************
++
++#endif // ! SOANY_THUMBWHEEL_H
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoGuiPopupMenu.cpp.in
+@@ -0,0 +1,359 @@
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++/*!
++ \class So at Gui@PopupMenu Inventor/@Gui@/widgets/So at Gui@PopupMenu.h
++ \brief The So at Gui@PopupMenu class implements a common interface for popup
++ menu management for all the Coin GUI toolkit libraries.
++
++ The point of this class is to enable client code to be exactly the
++ same for all GUI libraries, even without being template-based.
++*/
++
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif // HAVE_CONFIG_H
++
++#include <assert.h>
++
++#include <Inventor/SoLists.h>
++#include <Inventor/errors/SoDebugError.h>
++
++#include <so at gui@defs.h>
++#include <Inventor/@Gui@/widgets/So at Gui@PopupMenu.h>
++#include <Inventor/@Gui@/widgets/@Gui at NativePopupMenu.h>
++#include <Inventor/@Gui@/common/SbGuiList.h>
++
++// *************************************************************************
++
++// Documentation for abstract methods.
++
++/*!
++ \fn void So at Gui@PopupMenu::popUp(@WIDGET@ inside, int x, int y)
++
++ Invokes this popup menu instance.
++
++ The coordinates for the popup will be used relative to the origo of
++ the widget argument.
++*/
++
++// *************************************************************************
++
++// The private data for the So at Gui@PopupMenu.
++
++class So at Gui@PopupMenuP {
++public:
++ SbGuiList<int> menuitems;
++ SbGuiList<int> radiogroups;
++ SbPList * callbacks;
++ SbPList * userdata;
++};
++
++
++#define PRIVATE(o) (o->pimpl)
++
++// *************************************************************************
++
++/*!
++ Instantiation method.
++
++ So at Gui@PopupMenu is implemented with this "factory" method instead of
++ a public constructor to provide a completely generic interface on
++ top of the toolkit's native popup menu implementation.
++*/
++So at Gui@PopupMenu *
++So at Gui@PopupMenu::createInstance(void)
++{
++ return new @Gui at NativePopupMenu();
++}
++
++
++/*!
++ The class constructor is protected, as So at Gui@PopupMenu uses a factory
++ instantiation method.
++*/
++So at Gui@PopupMenu::So at Gui@PopupMenu(void)
++{
++ PRIVATE(this) = new So at Gui@PopupMenuP;
++
++ PRIVATE(this)->callbacks = NULL;
++ PRIVATE(this)->userdata = NULL;
++} // So at Gui@PopupMenu()
++
++/*!
++ Destructor.
++*/
++So at Gui@PopupMenu::~So at Gui@PopupMenu()
++{
++ delete PRIVATE(this)->callbacks;
++ delete PRIVATE(this)->userdata;
++ delete PRIVATE(this);
++} // ~So at Gui@PopupMenu()
++
++// *************************************************************************
++
++void
++So at Gui@PopupMenu::setMenuItemMarked(int itemid, SbBool marked)
++{
++ // forward to native implementation
++ this->_setMenuItemMarked(itemid, marked);
++
++ if (marked) {
++ const int radiogroupid = this->getRadioGroup(itemid);
++ if (radiogroupid != -1) {
++ this->setRadioGroupMarkedItem(itemid);
++ }
++ }
++}
++
++// *************************************************************************
++
++/*!
++*/
++
++int
++So at Gui@PopupMenu::newRadioGroup(
++ int groupid)
++{
++ const int numGroupedItems = PRIVATE(this)->radiogroups.getLength();
++ int id = groupid;
++ if (id != -1) {
++ SbBool hit = FALSE;
++ int i;
++ for (i = 0; i < numGroupedItems && hit == FALSE; i++) {
++ if (PRIVATE(this)->radiogroups[i] == id)
++ hit = TRUE;
++ }
++ if (hit) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("So at Gui@PopupMenu::NewRadioGroup",
++ "requested group id already taken");
++#endif // SO at GUI@_DEBUG
++ return -1;
++ }
++ } else {
++ id = 0;
++ SbBool found;
++ do {
++ id++;
++ found = FALSE;
++ int i;
++ for (i = 0; i < numGroupedItems && found == FALSE; i++) {
++ if (PRIVATE(this)->radiogroups[i] == id)
++ found = TRUE;
++ }
++ } while (found);
++ }
++ // id is OK here
++ PRIVATE(this)->menuitems.append(-1); // fake menu item
++ PRIVATE(this)->radiogroups.append(id); // register id in array
++ return id;
++} // newRadioGroup()
++
++/*!
++*/
++
++int
++So at Gui@PopupMenu::getRadioGroup(
++ int itemid)
++{
++ assert(itemid != -1);
++ const int numGroupedItems = PRIVATE(this)->radiogroups.getLength();
++ int i;
++ for (i = 0; i < numGroupedItems; i++) {
++ if (PRIVATE(this)->menuitems[i] == itemid)
++ return PRIVATE(this)->radiogroups[i];
++ }
++ return -1;
++} // getRadioGroup()
++
++/*!
++*/
++
++int
++So at Gui@PopupMenu::getRadioGroupSize(
++ int groupid)
++{
++ int count = 0;
++ const int numItems = PRIVATE(this)->radiogroups.getLength();
++ int i;
++ for (i = 0; i < numItems; i++) {
++ if (PRIVATE(this)->radiogroups[i] == groupid &&
++ PRIVATE(this)->menuitems[i] != -1)
++ count++;
++ }
++ return count;
++} // getRadioGroupSize()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::addRadioGroupItem(
++ int groupid,
++ int itemid)
++{
++ PRIVATE(this)->menuitems.append(itemid);
++ PRIVATE(this)->radiogroups.append(groupid);
++} // addRadioGroupItem()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::removeRadioGroupItem(
++ int itemid)
++{
++ assert(itemid != -1);
++ const int numGroupedItems = PRIVATE(this)->menuitems.getLength();
++ int i;
++ for (i = 0; i < numGroupedItems; i++) {
++ if (PRIVATE(this)->menuitems[i] == itemid) {
++ PRIVATE(this)->menuitems.remove(i);
++ PRIVATE(this)->radiogroups.remove(i);
++ return;
++ }
++ }
++} // removeRadioGroupItem()
++
++// *************************************************************************
++
++void
++So at Gui@PopupMenu::setRadioGroupMarkedItem(int itemid)
++{
++ const int idx = PRIVATE(this)->menuitems.find(itemid);
++ assert(idx != -1);
++ const int groupid = PRIVATE(this)->radiogroups[idx];
++
++ if (groupid == -1) {
++ SoDebugError::post("So at Gui@PopupMenu::setRadioGroupMarkedItem",
++ "item not in a radio group");
++ return;
++ }
++
++ const int numItems = PRIVATE(this)->menuitems.getLength();
++ for (int i = 0; i < numItems; i++) {
++ if (i == idx) { continue; }
++ if (PRIVATE(this)->radiogroups[i] == groupid) {
++ const int item = PRIVATE(this)->menuitems[i];
++ if (item != -1) { // FIXME: should this be an assert? 20050622 mortene.
++ if ( this->getMenuItemMarked(item) ) {
++ this->setMenuItemMarked(item, FALSE);
++ }
++ }
++ }
++ }
++}
++
++int
++So at Gui@PopupMenu::getRadioGroupMarkedItem(int groupid)
++{
++ const int numItems = PRIVATE(this)->menuitems.getLength();
++ int i;
++ for (i = 0; i < numItems; i++) {
++ if (PRIVATE(this)->radiogroups[i] == groupid) {
++ int item = PRIVATE(this)->menuitems[i];
++ if (item != -1 && this->getMenuItemMarked(item))
++ return item;
++ }
++ }
++ return -1;
++}
++
++// *************************************************************************
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::addMenuSelectionCallback(
++ So at Gui@MenuSelectionCallback * callback,
++ void * user)
++{
++ if (PRIVATE(this)->callbacks == NULL) {
++ PRIVATE(this)->callbacks = new SbPList;
++ PRIVATE(this)->userdata = new SbPList;
++ }
++ PRIVATE(this)->callbacks->append((void *) callback);
++ PRIVATE(this)->userdata->append(user);
++} // addMenuSelectionCallback()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::removeMenuSelectionCallback(
++ So at Gui@MenuSelectionCallback * callback,
++ void * user)
++{
++ if (PRIVATE(this)->callbacks == NULL) {
++#if SO at GUI@_DEBUG
++ SoDebugError::postInfo("So at Gui@PopupMenu::RemoveMenuSelectionCallback",
++ "no callbacks at all");
++#endif // SO at GUI@_DEBUG
++ return;
++ }
++ int numCallbacks = PRIVATE(this)->callbacks->getLength();
++ int i;
++ for (i = 0; i < numCallbacks; i++) {
++ if ((*PRIVATE(this)->callbacks)[i] == (void *) callback &&
++ (*PRIVATE(this)->userdata)[i] == user) {
++ PRIVATE(this)->callbacks->remove(i);
++ PRIVATE(this)->userdata->remove(i);
++ i--;
++ numCallbacks--;
++ }
++ }
++} // removeMenuSelectionCallback()
++
++/*!
++*/
++
++void
++So at Gui@PopupMenu::invokeMenuSelection(
++ int itemid)
++{
++ if (PRIVATE(this)->callbacks == NULL)
++ return;
++ const int numCallbacks = PRIVATE(this)->callbacks->getLength();
++ int i;
++ for (i = 0; i < numCallbacks; i++) {
++ So at Gui@MenuSelectionCallback * cb = (So at Gui@MenuSelectionCallback *)
++ (*PRIVATE(this)->callbacks)[i];
++ (*cb)(itemid, (*PRIVATE(this)->userdata)[i]);
++ }
++} // invokeMenuSelection()
++
++// *************************************************************************
++
+--- /dev/null
++++ soqt-1.5.0/src/Inventor/Qt/common/widgets/SoGuiPopupMenu.h.in
+@@ -0,0 +1,108 @@
++#ifndef SO at GUI@_POPUPMENU_H
++#define SO at GUI@_POPUPMENU_H
++
++// @configure_input@
++
++/**************************************************************************\
++ * Copyright (c) Kongsberg Oil & Gas Technologies AS
++ * All rights reserved.
++ *
++ * Redistribution and use in source and binary forms, with or without
++ * modification, are permitted provided that the following conditions are
++ * met:
++ *
++ * Redistributions of source code must retain the above copyright notice,
++ * this list of conditions and the following disclaimer.
++ *
++ * Redistributions in binary form must reproduce the above copyright
++ * notice, this list of conditions and the following disclaimer in the
++ * documentation and/or other materials provided with the distribution.
++ *
++ * Neither the name of the copyright holder nor the names of its
++ * contributors may be used to endorse or promote products derived from
++ * this software without specific prior written permission.
++ *
++ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
++ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
++ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
++ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
++ * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
++ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
++ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
++ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
++ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
++ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++\**************************************************************************/
++
++#include <Inventor/SbBasic.h>
++
++#include <Inventor/@Gui@/So at Gui@Component.h>
++
++// *************************************************************************
++
++typedef void So at Gui@MenuSelectionCallback(int itemid, void * user);
++
++class SO at GUI@_DLL_API So at Gui@PopupMenu { // abstract interface class
++public:
++ static So at Gui@PopupMenu * createInstance(void);
++ virtual ~So at Gui@PopupMenu();
++
++ virtual int newMenu(const char * name, int menuid = -1) = 0;
++ virtual int getMenu(const char * name) = 0;
++ virtual void setMenuTitle(int id, const char * title) = 0;
++ virtual const char * getMenuTitle(int id) = 0;
++
++ virtual int newMenuItem(const char * name, int itemid = -1) = 0;
++ virtual int getMenuItem(const char * name) = 0;
++ virtual void setMenuItemTitle(int itemid, const char * title) = 0;
++ virtual const char * getMenuItemTitle(int itemid) = 0;
++ virtual void setMenuItemEnabled(int itemid, SbBool enabled) = 0;
++ virtual SbBool getMenuItemEnabled(int itemid) = 0;
++ void setMenuItemMarked(int itemid, SbBool marked);
++ virtual SbBool getMenuItemMarked(int itemid) = 0;
++
++ virtual void addMenu(int menuid, int submenuid, int pos = -1) = 0;
++ virtual void addMenuItem(int menuid, int itemid, int pos = -1) = 0;
++ virtual void addSeparator(int menuid, int pos = -1) = 0;
++ virtual void removeMenu(int menuid) = 0;
++ virtual void removeMenuItem(int itemid) = 0;
++
++ virtual void popUp(@WIDGET@ inside, int x, int y) = 0;
++
++ int newRadioGroup(int groupid = -1);
++ int getRadioGroup(int itemid);
++ int getRadioGroupSize(int groupid);
++ void addRadioGroupItem(int groupid, int itemid);
++ void removeRadioGroupItem(int itemid);
++
++ // FIXME: bad interface. Should be internal/private, and the name is
++ // wrong. According to what this actually does, it should be
++ // something like "unmarkOtherOfRadioGroup()". 20050622 mortene.
++ void setRadioGroupMarkedItem(int itemid);
++#if SO at GUI@_MAJOR_VERSION == 2
++#error fix API above
++#endif // SO at GUI@_MAJOR_VERSION
++
++ int getRadioGroupMarkedItem(int groupid);
++
++ void addMenuSelectionCallback(So at Gui@MenuSelectionCallback * callback,
++ void * data);
++ void removeMenuSelectionCallback(So at Gui@MenuSelectionCallback * callback,
++ void * data);
++
++protected:
++ So at Gui@PopupMenu(void);
++
++ virtual void _setMenuItemMarked(int itemid, SbBool marked) = 0;
++
++ void invokeMenuSelection(int itemid);
++
++private:
++ class So at Gui@PopupMenuP * pimpl;
++
++}; // class So at Gui@PopupMenu
++
++// *************************************************************************
++
++#endif // ! SO at GUI@_POPUPMENU_H
diff --git a/debian/patches/series b/debian/patches/series
new file mode 100644
index 0000000..13e85d3
--- /dev/null
+++ b/debian/patches/series
@@ -0,0 +1 @@
+add_sogui.patch
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-science/packages/soqt.git
More information about the debian-science-commits
mailing list