]> git.mxchange.org Git - flightgear.git/commitdiff
Lazy-loading of the 2D panel node.
authorJames Turner <zakalawe@mac.com>
Wed, 16 May 2012 10:43:09 +0000 (11:43 +0100)
committerJames Turner <zakalawe@mac.com>
Wed, 16 May 2012 10:43:09 +0000 (11:43 +0100)
Sink the 2D panel logic into FGPanelNode, simplifying
renderer.cxx and a few other places. Also allows potential
for unloading / paging of 2.5D panels in the future.

src/Cockpit/panel.cxx
src/Cockpit/panel.hxx
src/Main/fg_commands.cxx
src/Main/fg_init.cxx
src/Main/globals.cxx
src/Main/globals.hxx
src/Model/panelnode.cxx
src/Model/panelnode.hxx
src/Viewer/renderer.cxx
src/Viewer/renderer.hxx

index bc8f220bad528bbc1ab0a40c422436190d86bc98..480360669b7d30fd638fa75d0937d35fb5ff749a 100644 (file)
@@ -93,28 +93,6 @@ get_aspect_adjust (int xsize, int ysize)
   float real_aspect = float(xsize) / float(ysize);
   return (real_aspect / ideal_aspect);
 }
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Global functions.
-////////////////////////////////////////////////////////////////////////
-
-bool
-fgPanelVisible ()
-{
-     const FGPanel* current = globals->get_current_panel();
-     if (current == 0)
-       return false;
-     if (current->getVisibility() == 0)
-       return false;
-     if (globals->get_viewmgr()->get_current() != 0)
-       return false;
-     if (current->getAutohide() && globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS != 0)
-       return false;
-     return true;
-}
-
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of FGTextureManager.
@@ -201,8 +179,6 @@ FGPanel::FGPanel ()
   : _mouseDown(false),
     _mouseInstrument(0),
     _width(WIN_W), _height(int(WIN_H * 0.5768 + 1)),
- //   _view_height(int(WIN_H * 0.4232)),
-    _visibility(fgGetNode("/sim/panel/visibility", true)),
     _x_offset(fgGetNode("/sim/panel/x-offset", true)),
     _y_offset(fgGetNode("/sim/panel/y-offset", true)),
     _jitter(fgGetNode("/sim/panel/jitter", true)),
@@ -210,6 +186,7 @@ FGPanel::FGPanel ()
     _xsize_node(fgGetNode("/sim/startup/xsize", true)),
     _ysize_node(fgGetNode("/sim/startup/ysize", true)),
     _enable_depth_test(false),
+    _autohide(true),
     _drawPanelHotspots("/sim/panel-hotspots")
 {
 }
@@ -238,44 +215,6 @@ FGPanel::addInstrument (FGPanelInstrument * instrument)
   _instruments.push_back(instrument);
 }
 
-
-/**
- * Initialize the panel.
- */
-void
-FGPanel::init ()
-{
-}
-
-
-/**
- * Bind panel properties.
- */
-void
-FGPanel::bind ()
-{
-  fgSetArchivable("/sim/panel/visibility");
-  fgSetArchivable("/sim/panel/x-offset");
-  fgSetArchivable("/sim/panel/y-offset");
-  fgSetArchivable("/sim/panel/jitter");
-}
-
-
-/**
- * Unbind panel properties.
- */
-void
-FGPanel::unbind ()
-{
-}
-
-
-void
-FGPanel::update (double dt)
-{
-  updateMouseDelay(dt);
-}
-
 double
 FGPanel::getAspectScale() const
 {
@@ -506,26 +445,6 @@ FGPanel::draw(osg::State& state)
   }
 }
 
-/**
- * Set the panel's visibility.
- */
-void
-FGPanel::setVisibility (bool visibility)
-{
-  _visibility->setBoolValue( visibility );
-}
-
-
-/**
- * Return true if the panel is visible.
- */
-bool
-FGPanel::getVisibility () const
-{
-  return _visibility->getBoolValue();
-}
-
-
 /**
  * Set the panel's background texture.
  */
index 6be50754b77935ac34bbeaf2244a7e29c7a44336..ca1eefbe6aaeafbeff36b02dace81309158b7554 100644 (file)
@@ -29,7 +29,6 @@
 #include <simgear/props/props.hxx>
 #include <simgear/props/propertyObject.hxx>
 
-#include <simgear/structure/subsystem_mgr.hxx>
 #include <simgear/structure/SGBinding.hxx>
 #include <simgear/math/interpolater.hxx>
 #include <simgear/timing/timestamp.hxx>
@@ -118,23 +117,15 @@ private:
  * redraw themselves when necessary, and will pass mouse clicks on to
  * the appropriate instruments for processing.
  */
-class FGPanel : public SGSubsystem
+class FGPanel : public SGReferenced
 {
 public:
 
   FGPanel ();
   virtual ~FGPanel ();
 
-                               // Update the panel (every frame).
-  virtual void init ();
-  virtual void bind ();
-  virtual void unbind ();
   virtual void draw (osg::State& state);
-  virtual void update (double);
  
-  //void update (osg::State& state);
-  //virtual void update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh);
-
   virtual void updateMouseDelay(double dt);
 
                                // transfer pointer ownership!!!
@@ -146,11 +137,6 @@ public:
                                // Background multiple textures.
   virtual void setMultiBackground (osg::Texture2D* texture, int idx);
 
-                               // Make the panel visible or invisible.
-  virtual bool getVisibility () const;
-  virtual void setVisibility (bool visibility);
-
-                               // Full width of panel.
   virtual void setWidth (int width) { _width = width; }
   virtual int getWidth () const { return _width; }
 
@@ -201,7 +187,6 @@ private:
   int _height;
  // int _view_height;
 
-  SGPropertyNode_ptr _visibility;
   SGPropertyNode_ptr _x_offset;
   SGPropertyNode_ptr _y_offset;
   SGPropertyNode_ptr _jitter;
@@ -584,22 +569,7 @@ public:
   FGSwitchLayer ();
   virtual void draw (osg::State& state);
 
-};
-
-
-
-\f
-////////////////////////////////////////////////////////////////////////
-// Functions.
-////////////////////////////////////////////////////////////////////////
-
-/**
- * Test whether the panel should be visible.
- */
-bool fgPanelVisible ();
-
-
-\f
+};\f
 #endif // __PANEL_HXX
 
 // end of panel.hxx
index 4c7e0ffaf3583941792b49ea021c9e9d32bc1321..9c11836aebff2b2802505bf3983ac710fb2d77a6 100644 (file)
@@ -26,8 +26,6 @@
 #include <simgear/misc/interpolator.hxx>
 #include <simgear/io/HTTPRequest.hxx>
 
-#include <Cockpit/panel.hxx>
-#include <Cockpit/panel_io.hxx>
 #include <FDM/flight.hxx>
 #include <GUI/gui.h>
 #include <GUI/new_gui.hxx>
@@ -399,48 +397,15 @@ do_save (const SGPropertyNode * arg)
 static bool
 do_panel_load (const SGPropertyNode * arg)
 {
-  string panel_path =
-    arg->getStringValue("path", fgGetString("/sim/panel/path"));
-  if (panel_path.empty()) {
-    return false;
+  string panel_path = arg->getStringValue("path");
+  if (!panel_path.empty()) {
+    // write to the standard property, which will force a load
+    fgSetString("/sim/panel/path", panel_path.c_str());
   }
   
-  FGPanel * new_panel = fgReadPanel(panel_path);
-  if (new_panel == 0) {
-    SG_LOG(SG_INPUT, SG_ALERT,
-          "Error reading new panel from " << panel_path);
-    return false;
-  }
-  SG_LOG(SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path);
-  globals->get_current_panel()->unbind();
-  globals->set_current_panel( new_panel );
-  globals->get_current_panel()->bind();
   return true;
 }
 
-
-/**
- * Built-in command: pass a mouse click to the panel.
- *
- * button: the mouse button number, zero-based.
- * is-down: true if the button is down, false if it is up.
- * x-pos: the x position of the mouse click.
- * y-pos: the y position of the mouse click.
- */
-static bool
-do_panel_mouse_click (const SGPropertyNode * arg)
-{
-  if (globals->get_current_panel() != 0)
-    return globals->get_current_panel()
-      ->doMouseAction(arg->getIntValue("button"),
-                     arg->getBoolValue("is-down") ? PU_DOWN : PU_UP,
-                     arg->getIntValue("x-pos"),
-                     arg->getIntValue("y-pos"));
-  else
-    return false;
-}
-
-
 /**
  * Built-in command: (re)load preferences.
  *
@@ -1519,7 +1484,6 @@ static struct {
     { "load", do_load },
     { "save", do_save },
     { "panel-load", do_panel_load },
-    { "panel-mouse-click", do_panel_mouse_click },
     { "preferences-load", do_preferences_load },
     { "view-cycle", do_view_cycle },
     { "screen-capture", do_screen_capture },
index b6b8c02cb77ba50f99b43a2d8c31fce975f1f6e6..5f5b5360e9ffc27a4ba7dbdf8365d7ce0adc90da 100644 (file)
@@ -1196,20 +1196,11 @@ bool fgInitSubsystems() {
     // Add a new 2D panel.
     ////////////////////////////////////////////////////////////////////
 
-    string panel_path(fgGetString("/sim/panel/path"));
-    if (!panel_path.empty()) {
-      FGPanel* p = fgReadPanel(panel_path);
-      if (p) {
-        globals->set_current_panel(p);
-        p->init();
-        p->bind();
-        SG_LOG( SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path );
-      } else {
-        SG_LOG( SG_INPUT, SG_ALERT,
-                "Error reading new panel from " << panel_path );
-      }
-    }
-
+    fgSetArchivable("/sim/panel/visibility");
+    fgSetArchivable("/sim/panel/x-offset");
+    fgSetArchivable("/sim/panel/y-offset");
+    fgSetArchivable("/sim/panel/jitter");
+  
     ////////////////////////////////////////////////////////////////////
     // Initialize the controls subsystem.
     ////////////////////////////////////////////////////////////////////
index a2e702c89839bbeaa90713964d149434cf6d9a46..1de5ecc7aeea40ec7e92f08ceb81aa1cfa282d1b 100644 (file)
@@ -46,7 +46,6 @@
 #include <Airports/runways.hxx>
 #include <ATCDCL/ATISmgr.hxx>
 #include <Autopilot/route_mgr.hxx>
-#include <Cockpit/panel.hxx>
 #include <GUI/FGFontCache.hxx>
 #include <GUI/gui.h>
 #include <Model/acmodel.hxx>
@@ -134,7 +133,6 @@ FGGlobals::FGGlobals() :
     mag( NULL ),
     matlib( NULL ),
     route_mgr( NULL ),
-    current_panel( NULL ),
     ATIS_mgr( NULL ),
     controls( NULL ),
     viewmgr( NULL ),
@@ -189,7 +187,6 @@ FGGlobals::~FGGlobals()
     delete mag;
     delete matlib;
     delete route_mgr;
-    current_panel = NULL;
 
     delete ATIS_mgr;
 
@@ -519,11 +516,4 @@ void FGGlobals::set_warp_delta( long int d )
   fgSetInt("/sim/time/warp-delta", d);
 }
 
-void FGGlobals::set_current_panel( FGPanel *cp )
-{
-  current_panel = cp;
-// poke the renderer to rebuild the scene node as necessary
-  get_renderer()->panelChanged();
-}
-    
 // end of globals.cxx
index 85292b58f6697df96f97f4cadbca676a07f5d895..8600e46db4f086cc8a20a0fab3743400d202d300 100644 (file)
@@ -65,7 +65,6 @@ class FGLocale;
 class FGModelMgr;
 class FGRouteMgr;
 class FGScenery;
-class FGPanel;
 class FGTileMgr;
 class FGViewMgr;
 class FGViewer;
@@ -119,9 +118,6 @@ private:
     // Global autopilot "route"
     FGRouteMgr *route_mgr;
 
-    // 2D panel
-    SGSharedPtr<FGPanel> current_panel;
-
     // ATC manager
     FGATISMgr *ATIS_mgr;
 
@@ -243,9 +239,6 @@ public:
     inline FGATISMgr *get_ATIS_mgr() const { return ATIS_mgr; }
     inline void set_ATIS_mgr( FGATISMgr *a ) {ATIS_mgr = a; }
 
-    inline FGPanel *get_current_panel() const { return current_panel; }
-    void set_current_panel( FGPanel *cp );
-
     inline FGControls *get_controls() const { return controls; }
     inline void set_controls( FGControls *c ) { controls = c; }
 
index 150b2ef40654f505bbfe1a12a9d36aabf547fc1f..14375899f83d0cc05c957f27b102ef1b6ccdfaec 100644 (file)
@@ -8,6 +8,8 @@
 #include <algorithm>
 
 #include <osg/Geode>
+#include <osg/Switch>
+#include <osg/BlendFunc>
 
 #include <simgear/compiler.h>
 #include <simgear/structure/exception.hxx>
 #include <simgear/scene/util/SGSceneUserData.hxx>
 #include <simgear/scene/util/SGNodeMasks.hxx>
 
+#include <plib/pu.h>
+
 #include <Main/fg_os.hxx>
 #include <Cockpit/panel.hxx>
 #include <Cockpit/panel_io.hxx>
-
+#include "Viewer/viewer.hxx"
 
 using std::vector;
 
+static FGPanelNode* global_panel = NULL;
+
+/**
+ * Built-in command: pass a mouse click to the panel.
+ *
+ * button: the mouse button number, zero-based.
+ * is-down: true if the button is down, false if it is up.
+ * x-pos: the x position of the mouse click.
+ * y-pos: the y position of the mouse click.
+ */
+static bool
+do_panel_mouse_click (const SGPropertyNode * arg)
+{
+  if (global_panel)
+    return global_panel->getPanel()
+    ->doMouseAction(arg->getIntValue("button"),
+                    arg->getBoolValue("is-down") ? PU_DOWN : PU_UP,
+                    arg->getIntValue("x-pos"),
+                    arg->getIntValue("y-pos"));
+  else
+    return false;
+  
+  return false;
+}
+
 class FGPanelPickCallback : public SGPickCallback {
 public:
   FGPanelPickCallback(FGPanelNode* p) :
@@ -61,94 +90,146 @@ private:
   osg::Vec3 picked;
 };
 
+class FGPanelSwitchCallback : public osg::NodeCallback {
+public:
+  FGPanelSwitchCallback(FGPanelNode* pn) : 
+    panel(pn),
+    visProp(fgGetNode("/sim/panel/visibility"))
+  {
+  }
+  
+  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
+  {
+    assert(dynamic_cast<osg::Switch*>(node));
+    osg::Switch* sw = static_cast<osg::Switch*>(node);
+    
+    if (!visProp->getBoolValue()) {
+      sw->setValue(0, false);
+      return;
+    }
+  
+    
+    panel->lazyLoad(); // isVisible check needs the panel loaded for auto-hide flag
+    bool enabled = panel->isVisible2d();
+    sw->setValue(0, enabled);
+    if (!enabled)
+      return;
+    
+    traverse(node, nv);
+  }
+  
+private:
+  FGPanelNode* panel;
+  SGPropertyNode* visProp;
+};
+
+
 FGPanelNode::FGPanelNode(SGPropertyNode* props) :
   _resizeToViewport(false)
 {  
-    // Make an FGPanel object.  But *don't* call init() or bind() on
-    // it -- those methods touch static state.
-    const char *path = props->getStringValue("path");
-    _panel = fgReadPanel(path);
-    if (!_panel)
-        throw sg_io_exception(string("Failed to load panel ") + path);
-
-    // And the corner points
-    SGPropertyNode* pt = props->getChild("bottom-left");
-    _bottomLeft[0] = pt->getFloatValue("x-m");
-    _bottomLeft[1] = pt->getFloatValue("y-m");
-    _bottomLeft[2] = pt->getFloatValue("z-m");
-    
-    pt = props->getChild("top-left");
-    _topLeft[0] = pt->getFloatValue("x-m");
-    _topLeft[1] = pt->getFloatValue("y-m");
-    _topLeft[2] = pt->getFloatValue("z-m");
-    
-    pt = props->getChild("bottom-right");
-    _bottomRight[0] = pt->getFloatValue("x-m");
-    _bottomRight[1] = pt->getFloatValue("y-m");
-    _bottomRight[2] = pt->getFloatValue("z-m");
+  commonInit();
+  _panelPath = props->getStringValue("path");
+
+  // And the corner points
+  SGPropertyNode* pt = props->getChild("bottom-left");
+  _bottomLeft[0] = pt->getFloatValue("x-m");
+  _bottomLeft[1] = pt->getFloatValue("y-m");
+  _bottomLeft[2] = pt->getFloatValue("z-m");
   
-    _panel->setDepthTest( props->getBoolValue("depth-test") );
+  pt = props->getChild("top-left");
+  _topLeft[0] = pt->getFloatValue("x-m");
+  _topLeft[1] = pt->getFloatValue("y-m");
+  _topLeft[2] = pt->getFloatValue("z-m");
   
-    initWithPanel();
+  pt = props->getChild("bottom-right");
+  _bottomRight[0] = pt->getFloatValue("x-m");
+  _bottomRight[1] = pt->getFloatValue("y-m");
+  _bottomRight[2] = pt->getFloatValue("z-m");
+  
+  _depthTest = props->getBoolValue("depth-test");
 }
 
-FGPanelNode::FGPanelNode(FGPanel* p) :
-  _panel(p),
-  _resizeToViewport(true)
+FGPanelNode::FGPanelNode() :
+  _resizeToViewport(true),
+  _depthTest(false)
 {
-    initWithPanel();
+  commonInit();
 }
 
-void FGPanelNode::initWithPanel()
+void FGPanelNode::setPanelPath(const std::string& panel)
 {
-    int i;
-
-    // Never mind.  We *have* to call init to make sure the static
-    // state is initialized (it's not, if there aren't any 2D
-    // panels).  This is a memory leak and should be fixed!`
-    // FIXME
-    _panel->init();
-
-    // Read out the pixel-space info
-    float panelWidth = _panel->getWidth();
-    float panelHeight = _panel->getHeight();
-
-    _panel->getLogicalExtent(_xmin, _ymin, _xmax, _ymax);
-  
-    // Now generate our transformation matrix.  For shorthand, use
-    // "a", "b", and "c" as our corners and "m" as the matrix. The
-    // vector u goes from a to b, v from a to c, and w is a
-    // perpendicular cross product.
-    osg::Vec3 a = _bottomLeft;
-    osg::Vec3 b = _bottomRight;
-    osg::Vec3 c = _topLeft;
-    osg::Vec3 u = b - a;
-    osg::Vec3 v = c - a;
-    osg::Vec3 w = u^v;
-
-    osg::Matrix& m = _xform;
-    // Now generate a trivial basis transformation matrix.  If we want
-    // to map the three unit vectors to three arbitrary vectors U, V,
-    // and W, then those just become the columns of the 3x3 matrix.
-    m(0,0) = u[0]; m(1,0) = v[0]; m(2,0) = w[0]; m(3,0) = a[0];//    |Ux Vx Wx|
-    m(0,1) = u[1]; m(1,1) = v[1]; m(2,1) = w[1]; m(3,1) = a[1];//m = |Uy Vy Wy|
-    m(0,2) = u[2]; m(1,2) = v[2]; m(2,2) = w[2]; m(3,2) = a[2];//    |Uz Vz Wz|
-    m(0,3) = 0;    m(1,3) = 0;    m(2,3) = 0;    m(3,3) = 1;
-
-    // The above matrix maps the unit (!) square to the panel
-    // rectangle.  Postmultiply scaling factors that match the
-    // pixel-space size of the panel.
-    for(i=0; i<4; ++i) {
-        m(0,i) *= 1.0/panelWidth;
-        m(1,i) *= 1.0/panelHeight;
+  if (panel == _panelPath) {
+    return;
+  }
+  
+  _panelPath = panel;
+  if (_panel) {
+    _panel.clear();
+  }
+}
+
+void FGPanelNode::lazyLoad()
+{
+  if (!_panelPath.empty() && !_panel) {
+    _panel = fgReadPanel(_panelPath);
+    if (!_panel) {
+      SG_LOG(SG_COCKPIT, SG_WARN, "failed to read panel from:" << _panelPath);
+      _panelPath = string(); // don't keep trying to read
+      return;
     }
+    
+    _panel->setDepthTest(_depthTest);
+    initWithPanel();
+  }
+}
 
-    dirtyBound();
-    setUseDisplayList(false);
-    setDataVariance(Object::DYNAMIC);
+void FGPanelNode::commonInit()
+{
+  setUseDisplayList(false);
+  setDataVariance(Object::DYNAMIC);
+  getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
+  getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
+}
+
+void FGPanelNode::initWithPanel()
+{
+  int i;
+
+  // Read out the pixel-space info
+  float panelWidth = _panel->getWidth();
+  float panelHeight = _panel->getHeight();
+
+  _panel->getLogicalExtent(_xmin, _ymin, _xmax, _ymax);
+
+  // Now generate our transformation matrix.  For shorthand, use
+  // "a", "b", and "c" as our corners and "m" as the matrix. The
+  // vector u goes from a to b, v from a to c, and w is a
+  // perpendicular cross product.
+  osg::Vec3 a = _bottomLeft;
+  osg::Vec3 b = _bottomRight;
+  osg::Vec3 c = _topLeft;
+  osg::Vec3 u = b - a;
+  osg::Vec3 v = c - a;
+  osg::Vec3 w = u^v;
+
+  osg::Matrix& m = _xform;
+  // Now generate a trivial basis transformation matrix.  If we want
+  // to map the three unit vectors to three arbitrary vectors U, V,
+  // and W, then those just become the columns of the 3x3 matrix.
+  m(0,0) = u[0]; m(1,0) = v[0]; m(2,0) = w[0]; m(3,0) = a[0];//    |Ux Vx Wx|
+  m(0,1) = u[1]; m(1,1) = v[1]; m(2,1) = w[1]; m(3,1) = a[1];//m = |Uy Vy Wy|
+  m(0,2) = u[2]; m(1,2) = v[2]; m(2,2) = w[2]; m(3,2) = a[2];//    |Uz Vz Wz|
+  m(0,3) = 0;    m(1,3) = 0;    m(2,3) = 0;    m(3,3) = 1;
+
+  // The above matrix maps the unit (!) square to the panel
+  // rectangle.  Postmultiply scaling factors that match the
+  // pixel-space size of the panel.
+  for(i=0; i<4; ++i) {
+      m(0,i) *= 1.0/panelWidth;
+      m(1,i) *= 1.0/panelHeight;
+  }
 
-    getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
-    getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
+  dirtyBound();
 }
 
 FGPanelNode::~FGPanelNode()
@@ -157,6 +238,10 @@ FGPanelNode::~FGPanelNode()
 
 osg::Matrix FGPanelNode::transformMatrix() const
 {
+  if (!_panel) {
+    osg::Matrix();
+  }
+
   if (!_resizeToViewport) {
     return _xform;
   }
@@ -171,6 +256,10 @@ osg::Matrix FGPanelNode::transformMatrix() const
 void
 FGPanelNode::drawImplementation(osg::State& state) const
 {  
+  if (!_panel) {
+    return;
+  }
+  
   osg::ref_ptr<osg::RefMatrix> mv = new osg::RefMatrix;
   mv->set(transformMatrix() * state.getModelViewMatrix());
   state.applyModelViewMatrix(mv.get());
@@ -209,6 +298,23 @@ void FGPanelNode::accept(osg::PrimitiveFunctor& functor) const
   functor.drawArrays( GL_QUADS, 0, 4);
 }
 
+bool FGPanelNode::isVisible2d() const
+{
+  if (!_panel) {
+    return false;
+  }
+  
+  if (_panel->getAutohide()) {
+    if (!globals->get_current_view()) {
+      return false;
+    }
+    
+    return globals->get_current_view()->getHeadingOffset_deg() == 0;
+  }
+  
+  return true;
+}
+
 static osg::Node* createGeode(FGPanelNode* panel)
 {
     osg::Geode* geode = new osg::Geode;
@@ -222,14 +328,52 @@ static osg::Node* createGeode(FGPanelNode* panel)
     return geode;
 }
 
-osg::Node* FGPanelNode::createNode(FGPanel* p)
+class PanelPathObserver : public SGPropertyChangeListener
+{
+public:
+  PanelPathObserver(FGPanelNode* pn) : _panelNode(pn) {}
+  
+  virtual void valueChanged (SGPropertyNode * node)
+  {
+    _panelNode->setPanelPath(node->getStringValue());
+  }
+private:
+  FGPanelNode* _panelNode;
+};
+
+osg::Node* FGPanelNode::create2DPanelNode()
 {
-    FGPanelNode* drawable = new FGPanelNode(p);
-    return createGeode(drawable);
+  SGCommandMgr::instance()->addCommand("panel-mouse-click", do_panel_mouse_click);
+  
+  SGPropertyNode* pathNode = fgGetNode("/sim/panel/path");
+  
+  FGPanelNode* drawable = new FGPanelNode();
+// need a global to keep the panel_mouse_click command working, sadly
+  global_panel = drawable;
+  
+  PanelPathObserver* ppo = new PanelPathObserver(drawable);
+  pathNode->addChangeListener(ppo);
+  drawable->setPanelPath(pathNode->getStringValue());
+  
+  osg::Switch* ps = new osg::Switch;
+  osg::StateSet* stateSet = ps->getOrCreateStateSet();
+  stateSet->setRenderBinDetails(1000, "RenderBin");
+  ps->addChild(createGeode(drawable));
+  
+  // 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_FOG, osg::StateAttribute::OFF);
+  stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+  
+  ps->setUpdateCallback(new FGPanelSwitchCallback(drawable));
+  return ps;
 }
 
 osg::Node* FGPanelNode::load(SGPropertyNode *n)
 {
   FGPanelNode* drawable = new FGPanelNode(n);
+  drawable->lazyLoad(); // force load now for 2.5D panels
   return createGeode(drawable);
 }
index 2ea9c0382ac0dc22a23a6152a9a5753e09faa5d5..83960cf03ce53811cae8db8359c34e3f6703705e 100644 (file)
@@ -14,7 +14,7 @@ class SGPropertyNode;
 class FGPanelNode : public osg::Drawable
 {
 public:
-    FGPanelNode(FGPanel* panel);
+    FGPanelNode();
   
     FGPanelNode(SGPropertyNode* props);
     virtual ~FGPanelNode();
@@ -37,17 +37,27 @@ public:
     virtual void accept(osg::PrimitiveFunctor& functor) const;
   
     static osg::Node* load(SGPropertyNode *n);
-    static osg::Node* createNode(FGPanel* panel);
+    static osg::Node* create2DPanelNode();
   
     osg::Matrix transformMatrix() const;
   
+    void setPanelPath(const std::string& panel);
+    void lazyLoad();
+  
+    /**
+      * is visible in 2D mode or not?
+      */
+    bool isVisible2d() const;
 private:
+    void commonInit();
     void initWithPanel();
     
     SGSharedPtr<FGPanel> _panel;
+    std::string _panelPath;
   
     bool _resizeToViewport;
-
+    bool _depthTest;
+  
     // Panel corner coordinates
     osg::Vec3 _bottomLeft, _topLeft, _bottomRight;
 
index ac156c820e0745cda755f31ec97621b078b226ac..5056b724a8a57ad504b7be2f1eafad2fb5575aab 100644 (file)
@@ -383,25 +383,6 @@ static osg::ref_ptr<osg::Group> mDeferredRealRoot = new osg::Group;
 
 static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
 
-static osg::ref_ptr<osg::Switch> panelSwitch;
-                                    
-                                    
-// update callback for the switch node controlling the 2D panel
-class FGPanelSwitchCallback : public osg::NodeCallback {
-public:
-    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
-    {
-        assert(dynamic_cast<osg::Switch*>(node));
-        osg::Switch* sw = static_cast<osg::Switch*>(node);
-        
-        bool enabled = fgPanelVisible();
-        sw->setValue(0, enabled);
-        if (!enabled)
-            return;
-        traverse(node, nv);
-    }
-};
-
 #ifdef FG_JPEG_SERVER
 static void updateRenderer()
 {
@@ -1625,22 +1606,8 @@ FGRenderer::setupView( void )
         geode->addDrawable(new SGHUDDrawable);
         guiCamera->addChild(geode);
       
-        panelSwitch = new osg::Switch;
-        osg::StateSet* stateSet = panelSwitch->getOrCreateStateSet();
-        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_FOG, osg::StateAttribute::OFF);
-        stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
         
-        
-        panelSwitch->setUpdateCallback(new FGPanelSwitchCallback);
-        panelChanged();
-        
-        guiCamera->addChild(panelSwitch.get());
+      guiCamera->addChild(FGPanelNode::create2DPanelNode());
     }
     
     osg::Switch* sw = new osg::Switch;
@@ -1661,20 +1628,6 @@ FGRenderer::setupView( void )
 
        mDeferredRealRoot->addChild( mRealRoot.get() );
 }
-
-void FGRenderer::panelChanged()
-{
-    if (!panelSwitch) {
-        return;
-    }
-    
-    osg::Node* n = FGPanelNode::createNode(globals->get_current_panel());
-    if (panelSwitch->getNumChildren()) {
-        panelSwitch->setChild(0, n);
-    } else {
-        panelSwitch->addChild(n);
-    }
-}
                                     
 // Update all Visuals (redraws anything graphics related)
 void
index e9770fb3525f493e7c75a6152d6811cb0300b60a..e870fb1219951b76b5da561eda25cf4df0165596 100644 (file)
@@ -117,11 +117,7 @@ public:
     SGSky* getSky() const { return _sky; }
 
        void setPlanes( double zNear, double zFar );
-    
-    /**
-     * inform the renderer when the global (2D) panel is changed
-     */
-    void panelChanged();
+
 protected:
     osg::ref_ptr<osgViewer::Viewer> viewer;
     osg::ref_ptr<flightgear::FGEventHandler> eventHandler;