From 55d6d09524cfd6499c51c823d61c5f9024ba6bf7 Mon Sep 17 00:00:00 2001 From: James Turner Date: Wed, 3 Jul 2013 08:57:48 +0100 Subject: [PATCH] Fix bug 864 - moving the 2D panel around. Bounding box wasn't being dirtied when changing the transform, breaking picking visitor for the panel. Add listeners to the relevant props so we can tell OSG when the panel transform changes. --- src/Model/panelnode.cxx | 56 ++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 14 deletions(-) diff --git a/src/Model/panelnode.cxx b/src/Model/panelnode.cxx index 9e6c81cde..9e664b4c7 100644 --- a/src/Model/panelnode.cxx +++ b/src/Model/panelnode.cxx @@ -30,6 +30,19 @@ using std::vector; +class PanelTransformListener : public SGPropertyChangeListener +{ +public: + PanelTransformListener(FGPanelNode* pn) : _panelNode(pn) {} + + virtual void valueChanged (SGPropertyNode * node) + { + _panelNode->dirtyBound(); + } +private: + FGPanelNode* _panelNode; +}; + static FGPanelNode* global_panel = NULL; /** @@ -158,7 +171,17 @@ FGPanelNode::FGPanelNode() : _resizeToViewport(true), _depthTest(false) { - commonInit(); + // for a 2D panel, various options adjust the transformation + // matrix. We need to pass this data on to OSG or its bounding box + // will be stale, and picking will break. + // http://code.google.com/p/flightgear-bugs/issues/detail?id=864 + PanelTransformListener* ptl = new PanelTransformListener(this); + fgGetNode("/sim/panel/x-offset", true)->addChangeListener(ptl); + fgGetNode("/sim/panel/y-offset", true)->addChangeListener(ptl); + fgGetNode("/sim/startup/xsize", true)->addChangeListener(ptl); + fgGetNode("/sim/startup/ysize", true)->addChangeListener(ptl); + + commonInit(); } void FGPanelNode::setPanelPath(const std::string& panel) @@ -205,7 +228,7 @@ void FGPanelNode::initWithPanel() 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 @@ -217,14 +240,18 @@ void FGPanelNode::initWithPanel() 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; + osg::Matrix& m = _xform; + if ((u.length2() == 0.0) || (b.length2() == 0.0)) { + m.makeIdentity(); + } else { + // 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 @@ -347,10 +374,10 @@ static osg::Node* createGeode(FGPanelNode* panel) return geode; } -class PanelPathObserver : public SGPropertyChangeListener +class PanelPathListener : public SGPropertyChangeListener { public: - PanelPathObserver(FGPanelNode* pn) : _panelNode(pn) {} + PanelPathListener(FGPanelNode* pn) : _panelNode(pn) {} virtual void valueChanged (SGPropertyNode * node) { @@ -360,6 +387,7 @@ private: FGPanelNode* _panelNode; }; + osg::Node* FGPanelNode::create2DPanelNode() { SGCommandMgr::instance()->addCommand("panel-mouse-click", do_panel_mouse_click); @@ -370,10 +398,10 @@ osg::Node* FGPanelNode::create2DPanelNode() // need a global to keep the panel_mouse_click command working, sadly global_panel = drawable; - PanelPathObserver* ppo = new PanelPathObserver(drawable); + PanelPathListener* ppo = new PanelPathListener(drawable); pathNode->addChangeListener(ppo); drawable->setPanelPath(pathNode->getStringValue()); - + osg::Switch* ps = new osg::Switch; osg::StateSet* stateSet = ps->getOrCreateStateSet(); stateSet->setRenderBinDetails(1000, "RenderBin");