From 086df400ded7c61c00c964d7e66445745bab5d49 Mon Sep 17 00:00:00 2001 From: James Turner Date: Sun, 25 Mar 2012 18:46:04 +0100 Subject: [PATCH] Fix 2.5D panel hit detection, compute logical panel extend from actions. --- src/Cockpit/panel.cxx | 80 +++++++++++++++++++++++++++++++++++++++- src/Cockpit/panel.hxx | 14 +++++-- src/Cockpit/panel_io.cxx | 4 +- src/Model/panelnode.cxx | 42 +++++++++++---------- src/Model/panelnode.hxx | 8 ++-- 5 files changed, 117 insertions(+), 31 deletions(-) diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx index d3f74940b..ff13176e2 100644 --- a/src/Cockpit/panel.cxx +++ b/src/Cockpit/panel.cxx @@ -36,6 +36,7 @@ #include // sprintf #include #include +#include #include #include @@ -48,6 +49,7 @@ #include +#include #include #include #include @@ -196,7 +198,7 @@ FGPanel::FGPanel () : _mouseDown(false), _mouseInstrument(0), _width(WIN_W), _height(int(WIN_H * 0.5768 + 1)), - _view_height(int(WIN_H * 0.4232)), + // _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)), @@ -475,6 +477,19 @@ FGPanel::draw(osg::State& state) for ( unsigned int i = 0; i < _instruments.size(); i++ ) _instruments[i]->drawHotspots(state); + glColor3f(0, 1, 1); + + int x0, y0, x1, y1; + getLogicalExtent(x0, y0, x1, y1); + + glBegin(GL_LINE_LOOP); + glVertex2f(x0, y0); + glVertex2f(x1, y0); + glVertex2f(x1, y1); + glVertex2f(x0, y1); + glEnd(); + + glPopAttrib(); state.popStateSet(); @@ -626,7 +641,55 @@ void FGPanel::setDepthTest (bool enable) { _enable_depth_test = enable; } +class IntRect +{ + +public: + IntRect() : + x0(std::numeric_limits::max()), + y0(std::numeric_limits::max()), + x1(std::numeric_limits::min()), + y1(std::numeric_limits::min()) + { } + + IntRect(int x, int y, int w, int h) : + x0(x), y0(y), x1(x + w), y1( y + h) + { + if (x1 < x0) { + std::swap(x0, x1); + } + + if (y1 < y0) { + std::swap(y0, y1); + } + + assert(x0 <= x1); + assert(y0 <= y1); + } + + void extend(const IntRect& r) + { + x0 = std::min(x0, r.x0); + y0 = std::min(y0, r.y0); + x1 = std::max(x1, r.x1); + y1 = std::max(y1, r.y1); + } + + int x0, y0, x1, y1; +}; +void FGPanel::getLogicalExtent(int &x0, int& y0, int& x1, int &y1) +{ + IntRect result; + BOOST_FOREACH(FGPanelInstrument *inst, _instruments) { + inst->extendRect(result); + } + + x0 = result.x0; + y0 = result.y0; + x1 = result.x1; + y1 = result.y1; +} ////////////////////////////////////////////////////////////////////////. // Implementation of FGPanelAction. @@ -774,6 +837,21 @@ FGPanelInstrument::getHeight () const return _h; } +void +FGPanelInstrument::extendRect(IntRect& r) const +{ + IntRect instRect(_x, _y, _w, _h); + r.extend(instRect); + + BOOST_FOREACH(FGPanelAction* act, _actions) { + r.extend(IntRect(getXPos() + act->getX(), + getYPos() + act->getY(), + act->getWidth(), + act->getHeight() + )); + } +} + void FGPanelInstrument::addAction (FGPanelAction * action) { diff --git a/src/Cockpit/panel.hxx b/src/Cockpit/panel.hxx index 4e29fde83..361c43984 100644 --- a/src/Cockpit/panel.hxx +++ b/src/Cockpit/panel.hxx @@ -43,6 +43,7 @@ class FGPanelInstrument; class fntFont; class DCLGPS; +class IntRect; //////////////////////////////////////////////////////////////////////// // Texture management. @@ -166,9 +167,15 @@ public: virtual int getYOffset () const { return _y_offset->getIntValue(); } // View height. - virtual void setViewHeight (int height) { _view_height = height; } - virtual int getViewHeight () const { return _view_height; } + // virtual void setViewHeight (int height) { _view_height = height; } + // virtual int getViewHeight () const { return _view_height; } + /** + * find the actual logical extend of the panel, including all instruments + * and actions. + */ + void getLogicalExtent(int &x0, int& y0, int& x1, int &y1); + // Handle a mouse click. virtual bool doMouseAction (int button, int updown, int x, int y); virtual bool doLocalMouseAction(int button, int updown, int x, int y); @@ -191,7 +198,7 @@ private: typedef std::vector instrument_list_type; int _width; int _height; - int _view_height; + // int _view_height; SGPropertyNode_ptr _visibility; SGPropertyNode_ptr _x_offset; @@ -392,6 +399,7 @@ public: // Coordinates relative to centre. virtual bool doMouseAction (int button, int updown, int x, int y); + void extendRect(IntRect& r) const; protected: int _x, _y, _w, _h; typedef std::vector action_list_type; diff --git a/src/Cockpit/panel_io.cxx b/src/Cockpit/panel_io.cxx index c0dcfd5dc..f05d057f1 100644 --- a/src/Cockpit/panel_io.cxx +++ b/src/Cockpit/panel_io.cxx @@ -662,8 +662,8 @@ readPanel (const SGPropertyNode * root) // // Grab the visible external viewing area, default to // - panel->setViewHeight(root->getIntValue("view-height", - 768 - panel->getHeight() + 2)); +// panel->setViewHeight(root->getIntValue("view-height", +// 768 - panel->getHeight() + 2)); // // Grab the panel's initial offsets, default to 0, 0. diff --git a/src/Model/panelnode.cxx b/src/Model/panelnode.cxx index 915d685ba..2c68f95c2 100644 --- a/src/Model/panelnode.cxx +++ b/src/Model/panelnode.cxx @@ -110,10 +110,11 @@ void FGPanelNode::initWithPanel() _panel->init(); // Read out the pixel-space info - _xmax = _panel->getWidth(); - _ymax = _panel->getHeight(); - + 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 @@ -138,8 +139,8 @@ void FGPanelNode::initWithPanel() // rectangle. Postmultiply scaling factors that match the // pixel-space size of the panel. for(i=0; i<4; ++i) { - m(0,i) *= 1.0/_xmax; - m(1,i) *= 1.0/_ymax; + m(0,i) *= 1.0/panelWidth; + m(1,i) *= 1.0/panelHeight; } dirtyBound(); @@ -181,28 +182,29 @@ FGPanelNode::drawImplementation(osg::State& state) const osg::BoundingBox FGPanelNode::computeBound() const { - osg::Vec3 coords[4]; - osg::Matrix m(transformMatrix()); - coords[0] = m.preMult(osg::Vec3(0,0,0)); - coords[1] = m.preMult(osg::Vec3(_xmax,0,0)); - coords[2] = m.preMult(osg::Vec3(0,_ymax,0)); - - osg::BoundingBox bb; - bb.expandBy(coords[0]); - bb.expandBy(coords[1]); - bb.expandBy(coords[2]); - return bb; + + osg::Vec3 coords[3]; + osg::Matrix m(transformMatrix()); + coords[0] = m.preMult(osg::Vec3(_xmin,_ymin,0)); + coords[1] = m.preMult(osg::Vec3(_xmax,_ymin,0)); + coords[2] = m.preMult(osg::Vec3(_xmin,_ymax,0)); + + osg::BoundingBox bb; + bb.expandBy(coords[0]); + bb.expandBy(coords[1]); + bb.expandBy(coords[2]); + return bb; } void FGPanelNode::accept(osg::PrimitiveFunctor& functor) const { osg::Vec3 coords[4]; osg::Matrix m(transformMatrix()); - - coords[0] = m.preMult(osg::Vec3(0,0,0)); - coords[1] = m.preMult(osg::Vec3(_xmax,0,0)); + + coords[0] = m.preMult(osg::Vec3(_xmin,_ymin,0)); + coords[1] = m.preMult(osg::Vec3(_xmax,_ymin,0)); coords[2] = m.preMult(osg::Vec3(_xmax, _ymax, 0)); - coords[3] = m.preMult(osg::Vec3(0,_ymax,0)); + coords[3] = m.preMult(osg::Vec3(_xmin,_ymax,0)); functor.setVertexArray(4, coords); functor.drawArrays( GL_QUADS, 0, 4); diff --git a/src/Model/panelnode.hxx b/src/Model/panelnode.hxx index c8db4ba29..2551495f8 100644 --- a/src/Model/panelnode.hxx +++ b/src/Model/panelnode.hxx @@ -50,13 +50,11 @@ private: // Panel corner coordinates osg::Vec3 _bottomLeft, _topLeft, _bottomRight; - // The input range expected in the panel definition. These x/y - // coordinates will map to the right/top sides. - float _xmax, _ymax; - + int _xmin, _ymin, _xmax, _ymax; + // The matrix that results, which transforms 2D x/y panel // coordinates into 3D coordinates of the panel quadrilateral. - osg::Matrix _xform; + osg::Matrix _xform; };