]> git.mxchange.org Git - flightgear.git/blobdiff - src/Viewer/fg_os_osgviewer.cxx
VoiceSynthesizer: add some test/debug properties
[flightgear.git] / src / Viewer / fg_os_osgviewer.cxx
index d08b7923784326e918d6fc2acf6e89912ee8ecab..7ba9932180ae44d6d6a0f73b639110d319d4c3c9 100644 (file)
@@ -29,6 +29,8 @@
 
 #include <stdlib.h>
 
+// Boost
+#include <boost/algorithm/string/case_conv.hpp>
 #include <boost/foreach.hpp>
 
 #include <simgear/compiler.h>
@@ -42,6 +44,7 @@
 #include <osg/Matrixd>
 #include <osg/Viewport>
 #include <osg/Version>
+#include <osg/Notify>
 #include <osg/View>
 #include <osgViewer/ViewerEventHandlers>
 #include <osgViewer/Viewer>
@@ -98,8 +101,7 @@ using namespace std;
 using namespace flightgear;
 using namespace osg;
 
-static osg::ref_ptr<osgViewer::Viewer> viewer;
-static osg::ref_ptr<osg::Camera> mainCamera;
+osg::ref_ptr<osgViewer::Viewer> viewer;
 
 static void setStereoMode( const char * mode )
 {
@@ -175,11 +177,82 @@ static const char * getStereoMode()
     return "OFF";
 }
 
+/**
+ * merge OSG output into our logging system, so it gets recorded to file,
+ * and so we can display a GUI console with renderer issues, especially
+ * shader compilation warnings and errors.
+ */
+class NotifyLogger : public osg::NotifyHandler
+{
+public:
+  // note this callback will be invoked by OSG from multiple threads.
+  // fortunately our Simgear logging implementation already handles
+  // that internally, so we simply pass the message on.
+  virtual void notify(osg::NotifySeverity severity, const char *message)
+  {
+    SG_LOG(SG_GL, translateSeverity(severity), message);
+
+    // Detect whether a osg::Reference derived object is deleted with a non-zero
+    // reference count. In this case trigger a segfault to get a stack trace.
+    if( strstr(message, "the final reference count was") )
+    {
+
+      int* trigger_segfault = 0;
+      *trigger_segfault = 0;
+    }
+  }
+  
+private:
+  sgDebugPriority translateSeverity(osg::NotifySeverity severity)
+  {
+    switch (severity) {
+      case osg::ALWAYS:
+      case osg::FATAL:  return SG_ALERT;
+      case osg::WARN:   return SG_WARN;
+      case osg::NOTICE:
+      case osg::INFO:   return SG_INFO;
+      case osg::DEBUG_FP:
+      case osg::DEBUG_INFO: return SG_DEBUG;
+      default: return SG_ALERT;
+    }
+  }
+};
+
+class NotifyLevelListener : public SGPropertyChangeListener
+{
+public:
+    void valueChanged(SGPropertyNode* node)
+    {
+        osg::NotifySeverity severity = osg::WARN;
+        string val = boost::to_lower_copy(string(node->getStringValue()));
+        
+        if (val == "fatal") {
+            severity = osg::FATAL;
+        } else if (val == "warn") {
+            severity = osg::WARN;
+        } else if (val == "notice") {
+            severity = osg::NOTICE;
+        } else if (val == "info") {
+            severity = osg::INFO;
+        } else if ((val == "debug") || (val == "debug-info")) {
+            severity = osg::DEBUG_INFO;
+        }
+        
+        osg::setNotifyLevel(severity);
+    }
+};
+
+void updateOSGNotifyLevel()
+{
+   }
+
 void fgOSOpenWindow(bool stencil)
 {
+    osg::setNotifyHandler(new NotifyLogger);
+    
     viewer = new osgViewer::Viewer;
     viewer->setDatabasePager(FGScenery::getPagerSingleton());
-    CameraGroup* cameraGroup = 0;
+
     std::string mode;
     mode = fgGetString("/sim/rendering/multithreading-mode", "SingleThreaded");
     if (mode == "AutomaticSelection")
@@ -193,49 +266,8 @@ void fgOSOpenWindow(bool stencil)
     else
       viewer->setThreadingModel(osgViewer::Viewer::SingleThreaded);
     WindowBuilder::initWindowBuilder(stencil);
-    WindowBuilder *windowBuilder = WindowBuilder::getWindowBuilder();
-
-    // Look for windows, camera groups, and the old syntax of
-    // top-level cameras
-    SGPropertyNode* renderingNode = fgGetNode("/sim/rendering");
-    SGPropertyNode* cgroupNode = renderingNode->getNode("camera-group", true);
-    bool oldSyntax = !cgroupNode->hasChild("camera");
-    if (oldSyntax) {
-        for (int i = 0; i < renderingNode->nChildren(); ++i) {
-            SGPropertyNode* propNode = renderingNode->getChild(i);
-            const char* propName = propNode->getName();
-            if (!strcmp(propName, "window") || !strcmp(propName, "camera")) {
-                SGPropertyNode* copiedNode
-                    = cgroupNode->getNode(propName, propNode->getIndex(), true);
-                copyProperties(propNode, copiedNode);
-            }
-        }
-        vector<SGPropertyNode_ptr> cameras = cgroupNode->getChildren("camera");
-        SGPropertyNode* masterCamera = 0;
-        BOOST_FOREACH(SGPropertyNode_ptr& camera, cameras) {
-            if (camera->getDoubleValue("shear-x", 0.0) == 0.0
-                && camera->getDoubleValue("shear-y", 0.0) == 0.0) {
-                masterCamera = camera.ptr();
-                break;
-            }
-        }
-        if (!masterCamera) {
-            masterCamera = cgroupNode->getChild("camera", cameras.size(), true);
-            setValue(masterCamera->getNode("window/name", true),
-                     windowBuilder->getDefaultWindowName());
-        }
-        SGPropertyNode* nameNode = masterCamera->getNode("window/name");
-        if (nameNode)
-            setValue(cgroupNode->getNode("gui/window/name", true),
-                     nameNode->getStringValue());
-    }
-    cameraGroup = CameraGroup::buildCameraGroup(viewer.get(), cgroupNode);
-    Camera* guiCamera = getGUICamera(cameraGroup);
-    if (guiCamera) {
-        Viewport* guiViewport = guiCamera->getViewport();
-        fgSetInt("/sim/startup/xsize", guiViewport->width());
-        fgSetInt("/sim/startup/ysize", guiViewport->height());
-    }
+    CameraGroup::buildDefaultGroup(viewer.get());
+    
     FGEventHandler* manipulator = globals->get_renderer()->getEventHandler();
     WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
     if (wsa->windows.size() != 1) {
@@ -248,8 +280,22 @@ void fgOSOpenWindow(bool stencil)
     // The viewer won't start without some root.
     viewer->setSceneData(new osg::Group);
     globals->get_renderer()->setViewer(viewer.get());
-    CameraGroup::setDefault(cameraGroup);
+}
 
+void fgOSResetProperties()
+{
+    SGPropertyNode* osgLevel = fgGetNode("/sim/rendering/osg-notify-level", true);
+    NotifyLevelListener* l = new NotifyLevelListener;
+    globals->addListenerToCleanup(l);
+    osgLevel->addChangeListener(l, true);
+    
+    osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
+    if (guiCamera) {
+        Viewport* guiViewport = guiCamera->getViewport();
+        fgSetInt("/sim/startup/xsize", guiViewport->width());
+        fgSetInt("/sim/startup/ysize", guiViewport->height());
+    }
+    
     DisplaySettings * displaySettings = DisplaySettings::instance();
     fgTie("/sim/rendering/osg-displaysettings/eye-separation", displaySettings, &DisplaySettings::getEyeSeparation, &DisplaySettings::setEyeSeparation );
     fgTie("/sim/rendering/osg-displaysettings/screen-distance", displaySettings, &DisplaySettings::getScreenDistance, &DisplaySettings::setScreenDistance );
@@ -269,21 +315,24 @@ void fgOSExit(int code)
     viewer->setDone(true);
     viewer->getDatabasePager()->cancel();
     status = code;
+    
+    // otherwise we crash if OSG does logging during static destruction, eg
+    // GraphicsWindowX11, since OSG statics may have been created before the
+    // sglog static, despite our best efforts in boostrap.cxx
+    osg::setNotifyHandler(new osg::StandardNotifyHandler);
 }
 
 int fgOSMainLoop()
 {
-    ref_ptr<FGEventHandler> manipulator
-        = globals->get_renderer()->getEventHandler();
     viewer->setReleaseContextAtEndOfFrameHint(false);
     if (!viewer->isRealized())
         viewer->realize();
     while (!viewer->done()) {
-        fgIdleHandler idleFunc = manipulator->getIdleHandler();
+        fgIdleHandler idleFunc = globals->get_renderer()->getEventHandler()->getIdleHandler();
         if (idleFunc)
             (*idleFunc)();
         globals->get_renderer()->update();
-        viewer->frame();
+        viewer->frame( globals->get_sim_time_sec() );
     }
     
     return status;
@@ -309,12 +358,20 @@ void fgOSInit(int* argc, char** argv)
     WindowSystemAdapter::setWSA(new WindowSystemAdapter);
 }
 
+void fgOSCloseWindow()
+{
+    FGScenery::resetPagerSingleton();
+    flightgear::CameraGroup::setDefault(NULL);
+    WindowSystemAdapter::setWSA(NULL);
+    viewer = NULL;
+}
+
 void fgOSFullScreen()
 {
     std::vector<osgViewer::GraphicsWindow*> windows;
     viewer->getWindows(windows);
 
-    if (windows.size() == 0)
+    if (windows.empty())
         return; // Huh?!?
 
     /* Toggling window fullscreen is only supported for the main GUI window.
@@ -345,10 +402,17 @@ void fgOSFullScreen()
         int height;
         window->getWindowRectangle(x, y, width, height);
 
-        bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight;
+        /* Note: the simple "is window size == screen size" check to detect full screen state doesn't work with
+         * X screen servers in Xinerama mode, since the reported screen width (or height) exceeds the maximum width
+         * (or height) usable by a single window (Xserver automatically shrinks/moves the full screen window to fit a
+         * single display) - so we detect full screen mode using "WindowDecoration" state instead.
+         * "false" - even when a single window is display in fullscreen */
+        //bool isFullScreen = x == 0 && y == 0 && width == (int)screenWidth && height == (int)screenHeight;
+        bool isFullScreen = !window->getWindowDecoration();
 
         SG_LOG(SG_VIEW, SG_DEBUG, "Toggling fullscreen. Previous window rectangle ("
-               << x << ", " << y << ") x (" << width << ", " << height << "), fullscreen: " << isFullScreen);
+               << x << ", " << y << ") x (" << width << ", " << height << "), fullscreen: " << isFullScreen
+               << ", number of screens: " << wsi->getNumScreens());
         if (isFullScreen)
         {
             // limit x,y coordinates and window size to screen area
@@ -437,7 +501,9 @@ static int _cursor = -1;
 void fgSetMouseCursor(int cursor)
 {
     _cursor = cursor;
-  
+    if (!viewer)
+        return;
+    
     std::vector<osgViewer::GraphicsWindow*> windows;
     viewer->getWindows(windows);
     BOOST_FOREACH(osgViewer::GraphicsWindow* gw, windows) {