]> git.mxchange.org Git - flightgear.git/blobdiff - src/Canvas/gui_mgr.cxx
toggle fullscreen: also adapt GUI plane when resizing
[flightgear.git] / src / Canvas / gui_mgr.cxx
index 6ff2c577b6f50b984ba420e592883722737a52de..229f00edda5f155761bf35a84ca3f7675d688b69 100644 (file)
 
 #include "gui_mgr.hxx"
 #include <Canvas/window.hxx>
-#include <Canvas/canvas.hxx>
 
+#include <Main/fg_props.hxx>
 #include <Main/globals.hxx>
 #include <Viewer/CameraGroup.hxx>
 #include <Viewer/renderer.hxx>
 
+#include <simgear/canvas/Canvas.hxx>
+#include <simgear/canvas/CanvasPlacement.hxx>
+
+#include <osg/BlendFunc>
 #include <osgViewer/Viewer>
 #include <osgGA/GUIEventHandler>
 
@@ -56,11 +60,11 @@ class GUIEventHandler:
  * Track a canvas placement on a window
  */
 class WindowPlacement:
-  public canvas::Placement
+  public simgear::canvas::Placement
 {
   public:
     WindowPlacement( canvas::WindowPtr window,
-                     CanvasPtr canvas ):
+                     simgear::canvas::CanvasPtr canvas ):
       _window(window),
       _canvas(canvas)
     {}
@@ -71,15 +75,28 @@ class WindowPlacement:
     virtual ~WindowPlacement()
     {
       canvas::WindowPtr window = _window.lock();
-      CanvasPtr canvas = _canvas.lock();
+      simgear::canvas::CanvasPtr canvas = _canvas.lock();
 
       if( window && canvas && canvas == window->getCanvas().lock() )
-        window->setCanvas( CanvasPtr() );
+        window->setCanvas( simgear::canvas::CanvasPtr() );
     }
 
   private:
     canvas::WindowWeakPtr _window;
-    CanvasWeakPtr _canvas;
+    simgear::canvas::CanvasWeakPtr _canvas;
+};
+
+/**
+ * Store pointer to window as user data
+ */
+class WindowUserData:
+  public osg::Referenced
+{
+  public:
+    canvas::WindowWeakPtr window;
+    WindowUserData(canvas::WindowPtr window):
+      window(window)
+    {}
 };
 
 //------------------------------------------------------------------------------
@@ -91,31 +108,44 @@ WindowPtr windowFactory(SGPropertyNode* node)
 
 //------------------------------------------------------------------------------
 GUIMgr::GUIMgr():
-  PropertyBasedMgr("/sim/gui/canvas", "window", &windowFactory),
+  PropertyBasedMgr( fgGetNode("/sim/gui/canvas", true),
+                    "window",
+                    &windowFactory ),
   _event_handler( new GUIEventHandler(this) ),
   _transform( new osg::MatrixTransform ),
-  _geode_windows( new osg::Geode ),
   _width(_props, "size[0]"),
-  _height(_props, "size[1]"),
-  _last_push(-1)
+  _height(_props, "size[1]")
 {
   _width = _height = -1;
 
   osg::Camera* camera =
     flightgear::getGUICamera( flightgear::CameraGroup::getDefault() );
   assert(camera);
+  camera->addChild(_transform);
 
   osg::Viewport* vp = camera->getViewport();
   handleResize(vp->x(), vp->y(), vp->width(), vp->height());
 
-  _transform->addChild(_geode_windows);
-  camera->addChild(_transform);
-
-  Canvas::addPlacementFactory
+  simgear::canvas::Canvas::addPlacementFactory
   (
     "window",
     boost::bind(&GUIMgr::addPlacement, this, _1, _2)
   );
+
+  osg::StateSet* stateSet = _transform->getOrCreateStateSet();
+  stateSet->setDataVariance(osg::Object::STATIC);
+  stateSet->setRenderBinDetails(1000, "RenderBin");
+
+  // speed optimization?
+  stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
+  stateSet->setAttribute(new osg::BlendFunc(
+    osg::BlendFunc::SRC_ALPHA,
+    osg::BlendFunc::ONE_MINUS_SRC_ALPHA)
+  );
+  stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
+  stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+  stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
+  stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
 }
 
 //------------------------------------------------------------------------------
@@ -139,12 +169,29 @@ void GUIMgr::shutdown()
 }
 
 //------------------------------------------------------------------------------
-void GUIMgr::elementCreated(PropertyBasedElementPtr element)
+void GUIMgr::elementCreated(simgear::PropertyBasedElementPtr element)
 {
-  _geode_windows->addDrawable
-  (
-    static_cast<canvas::Window*>(element.get())->getDrawable()
-  );
+  canvas::WindowPtr window =
+    boost::static_pointer_cast<canvas::Window>(element);
+
+  size_t layer_index = std::max(0, window->getProps()->getIntValue("layer", 1));
+  osg::Group *layer = 0;
+
+  if( layer_index < _transform->getNumChildren() )
+  {
+    layer = _transform->getChild(layer_index)->asGroup();
+    assert(layer);
+  }
+  else
+  {
+    while( _transform->getNumChildren() <= layer_index )
+    {
+      layer = new osg::Group;
+      _transform->addChild(layer);
+    }
+  }
+  window->getGroup()->setUserData(new WindowUserData(window));
+  layer->addChild(window->getGroup());
 }
 
 //------------------------------------------------------------------------------
@@ -177,19 +224,20 @@ bool GUIMgr::handleEvent(const osgGA::GUIEventAdapter& ea)
 //------------------------------------------------------------------------------
 canvas::WindowPtr GUIMgr::getWindow(size_t i)
 {
-  return boost::shared_static_cast<canvas::Window>(_elements[i]);
+  return boost::static_pointer_cast<canvas::Window>(_elements[i]);
 }
 
 //------------------------------------------------------------------------------
-canvas::Placements GUIMgr::addPlacement( const SGPropertyNode* node,
-                                         CanvasPtr canvas )
+simgear::canvas::Placements
+GUIMgr::addPlacement( const SGPropertyNode* node,
+                      simgear::canvas::CanvasPtr canvas )
 {
   int placement_index = node->getIntValue("index", -1);
 
-  canvas::Placements placements;
+  simgear::canvas::Placements placements;
   for( size_t i = 0; i < _elements.size(); ++i )
   {
-    if( placement_index > 0 && static_cast<int>(i) != placement_index )
+    if( placement_index >= 0 && static_cast<int>(i) != placement_index )
       continue;
 
     canvas::WindowPtr window = getWindow(i);
@@ -198,7 +246,7 @@ canvas::Placements GUIMgr::addPlacement( const SGPropertyNode* node,
 
     window->setCanvas(canvas);
     placements.push_back(
-      canvas::PlacementPtr(new WindowPlacement(window, canvas))
+      simgear::canvas::PlacementPtr(new WindowPlacement(window, canvas))
     );
   }
   return placements;
@@ -207,7 +255,10 @@ canvas::Placements GUIMgr::addPlacement( const SGPropertyNode* node,
 //------------------------------------------------------------------------------
 bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
 {
-  canvas::MouseEvent event( ea.getEventType() );
+  if( !_transform->getNumChildren() )
+    return false;
+
+  simgear::canvas::MouseEvent event( ea.getEventType() );
 
   event.x = 0.5 * (ea.getXnormalized() + 1) * _width + 0.5;
   event.y = 0.5 * (ea.getYnormalized() + 1) * _height + 0.5;
@@ -220,18 +271,32 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
   event.mod = ea.getModKeyMask();
   event.scroll = ea.getScrollingMotion();
 
-  int window_at_cursor = -1;
-  for( size_t i = 0; i < _elements.size(); ++i )
+  canvas::WindowPtr window_at_cursor;
+  for( int i = _transform->getNumChildren() - 1; i >= 0; --i )
   {
-    if(    _elements[i]
-        && getWindow(i)->getRegion().contains(event.x, event.y) )
+    osg::Group *layer = _transform->getChild(i)->asGroup();
+    assert(layer);
+    if( !layer->getNumChildren() )
+      continue;
+
+    for( int j = layer->getNumChildren() - 1; j >= 0; --j )
     {
-      window_at_cursor = i;
-      break;
+      assert(layer->getChild(j)->getUserData());
+      canvas::WindowPtr window =
+        static_cast<WindowUserData*>(layer->getChild(j)->getUserData())
+          ->window.lock();
+      if( window->getRegion().contains(event.x, event.y) )
+      {
+        window_at_cursor = window;
+        break;
+      }
     }
+
+    if( window_at_cursor )
+      break;
   }
 
-  int target_window = window_at_cursor;
+  canvas::WindowPtr target_window = window_at_cursor;
   switch( ea.getEventType() )
   {
     case osgGA::GUIEventAdapter::PUSH:
@@ -242,25 +307,20 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
       break;
 
     case osgGA::GUIEventAdapter::RELEASE:
-      if( _last_push < 0 )
-        return false;
-
-      target_window = _last_push;
-      _last_push = -1;
+      target_window = _last_push.lock();
+      _last_push.reset();
       break;
 
     case osgGA::GUIEventAdapter::DRAG:
-      target_window = _last_push;
+      target_window = _last_push.lock();
       break;
 
     default:
       return false;
   }
 
-  if( target_window >= 0 )
+  if( target_window )
   {
-    canvas::WindowPtr window = getWindow(target_window);
-
     event.dx = event.x - _last_x;
     event.dy = event.y - _last_y;
 
@@ -268,10 +328,10 @@ bool GUIMgr::handleMouse(const osgGA::GUIEventAdapter& ea)
     _last_y = event.y;
 
     // Let the event position be always relative to the top left window corner
-    event.x -= window->getRegion().x();
-    event.y -= window->getRegion().y();
+    event.x -= target_window->getRegion().x();
+    event.y -= target_window->getRegion().y();
 
-    return window->handleMouseEvent(event);
+    return target_window->handleMouseEvent(event);
   }
   else
     return false;