X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FModel%2Fpanelnode.cxx;h=6399133f330e731e0285572442c276abd449bc5a;hb=a5e516fe8cc5775aebfe8afa0328e6f26824d1bd;hp=9e6c81cde878221e3f3adf746bcf766f24629ea1;hpb=b1b6d2f6e273cca1fcabcd5c230629356f52d6cb;p=flightgear.git diff --git a/src/Model/panelnode.cxx b/src/Model/panelnode.cxx index 9e6c81cde..6399133f3 100644 --- a/src/Model/panelnode.cxx +++ b/src/Model/panelnode.cxx @@ -30,30 +30,31 @@ using std::vector; -static FGPanelNode* global_panel = NULL; +class PanelTransformListener : public SGPropertyChangeListener +{ +public: + PanelTransformListener(FGPanelNode* pn) : _panelNode(pn) {} + + virtual void valueChanged (SGPropertyNode * node) + { + _panelNode->dirtyBound(); + } +private: + FGPanelNode* _panelNode; +}; -/** - * 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) +class PanelPathListener : public SGPropertyChangeListener { - 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; -} +public: + PanelPathListener(FGPanelNode* pn) : _panelNode(pn) {} + + virtual void valueChanged (SGPropertyNode * node) + { + _panelNode->setPanelPath(node->getStringValue()); + } +private: + FGPanelNode* _panelNode; +}; class FGPanelPickCallback : public SGPickCallback { public: @@ -64,7 +65,11 @@ public: virtual bool buttonPressed( int b, const osgGA::GUIEventAdapter&, const Info& info ) - { + { + if (!panel->getPanel()) { + return false; + } + button = b; // convert to panel coordinates osg::Matrixd m = osg::Matrixd::inverse(panel->transformMatrix()); @@ -125,12 +130,14 @@ public: private: FGPanelNode* panel; - SGPropertyNode* visProp; + SGPropertyNode_ptr visProp; }; FGPanelNode::FGPanelNode(SGPropertyNode* props) : - _resizeToViewport(false) + _is2d(false), + _resizeToViewport(false), + _listener(NULL) { commonInit(); _panelPath = props->getStringValue("path"); @@ -155,10 +162,45 @@ FGPanelNode::FGPanelNode(SGPropertyNode* props) : } FGPanelNode::FGPanelNode() : + _is2d(true), _resizeToViewport(true), _depthTest(false) { - commonInit(); + globals->get_commands()->addCommand("panel-mouse-click", this, &FGPanelNode::panelMouseClickCommand); + + SGPropertyNode* pathNode = fgGetNode("/sim/panel/path"); + _pathListener.reset(new PanelPathListener(this)); + pathNode->addChangeListener(_pathListener.get()); + setPanelPath(pathNode->getStringValue()); + + // 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 + _listener = new PanelTransformListener(this); + fgGetNode("/sim/panel/x-offset", true)->addChangeListener(_listener); + fgGetNode("/sim/panel/y-offset", true)->addChangeListener(_listener); + fgGetNode("/sim/startup/xsize", true)->addChangeListener(_listener); + fgGetNode("/sim/startup/ysize", true)->addChangeListener(_listener); + + commonInit(); +} + +FGPanelNode::~FGPanelNode() +{ + if (_is2d) { + globals->get_commands()->removeCommand("panel-mouse-click"); + SGPropertyNode* pathNode = fgGetNode("/sim/panel/path"); + pathNode->removeChangeListener(_pathListener.get()); + } + + if (_listener) { + fgGetNode("/sim/panel/x-offset", true)->removeChangeListener(_listener); + fgGetNode("/sim/panel/y-offset", true)->removeChangeListener(_listener); + fgGetNode("/sim/startup/xsize", true)->removeChangeListener(_listener); + fgGetNode("/sim/startup/ysize", true)->removeChangeListener(_listener); + delete _listener; + } } void FGPanelNode::setPanelPath(const std::string& panel) @@ -205,7 +247,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 +259,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 @@ -237,10 +283,6 @@ void FGPanelNode::initWithPanel() dirtyBound(); } -FGPanelNode::~FGPanelNode() -{ -} - osg::Matrix FGPanelNode::transformMatrix() const { if (!_panel) { @@ -273,7 +315,12 @@ FGPanelNode::drawImplementation(osg::State& state) const } osg::BoundingBox -FGPanelNode::computeBound() const +#if OSG_VERSION_LESS_THAN(3,3,2) +FGPanelNode::computeBound() +#else +FGPanelNode::computeBoundingBox() +#endif +const { osg::Vec3 coords[3]; @@ -347,33 +394,10 @@ static osg::Node* createGeode(FGPanelNode* panel) return geode; } -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() { - 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()); - + FGPanelNode* drawable = new FGPanelNode; + osg::Switch* ps = new osg::Switch; osg::StateSet* stateSet = ps->getOrCreateStateSet(); stateSet->setRenderBinDetails(1000, "RenderBin"); @@ -396,3 +420,20 @@ osg::Node* FGPanelNode::load(SGPropertyNode *n) drawable->lazyLoad(); // force load now for 2.5D panels return createGeode(drawable); } + +/** + * 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. + */ +bool +FGPanelNode::panelMouseClickCommand(const SGPropertyNode * arg) +{ + return _panel->doMouseAction(arg->getIntValue("button"), + arg->getBoolValue("is-down") ? PU_DOWN : PU_UP, + arg->getIntValue("x-pos"), + arg->getIntValue("y-pos")); +}