]> git.mxchange.org Git - flightgear.git/commitdiff
Fix 2.5D panel hit detection, compute logical panel extend from actions.
authorJames Turner <zakalawe@mac.com>
Sun, 25 Mar 2012 17:46:04 +0000 (18:46 +0100)
committerJames Turner <zakalawe@mac.com>
Sun, 25 Mar 2012 17:46:04 +0000 (18:46 +0100)
src/Cockpit/panel.cxx
src/Cockpit/panel.hxx
src/Cockpit/panel_io.cxx
src/Model/panelnode.cxx
src/Model/panelnode.hxx

index d3f74940b30e957a4c1dda88737573c61b594d93..ff13176e2fa88db2e3035541a5c385e2352cc24b 100644 (file)
@@ -36,6 +36,7 @@
 #include <stdio.h>     // sprintf
 #include <string.h>
 #include <iostream>
+#include <cassert>
 
 #include <osg/CullFace>
 #include <osg/Depth>
@@ -48,6 +49,7 @@
 
 #include <plib/fnt.h>
 
+#include <boost/foreach.hpp>
 #include <simgear/debug/logstream.hxx>
 #include <simgear/misc/sg_path.hxx>
 #include <simgear/scene/model/model.hxx>
@@ -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<int>::max()), 
+    y0(std::numeric_limits<int>::max()), 
+    x1(std::numeric_limits<int>::min()), 
+    y1(std::numeric_limits<int>::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;
+}
 \f
 ////////////////////////////////////////////////////////////////////////.
 // 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)
 {
index 4e29fde83db26e8a353815135026f9edef17749f..361c43984f3e6fa485872097893adffe1ea8b8f7 100644 (file)
@@ -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<FGPanelInstrument *> 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<FGPanelAction *> action_list_type;
index c0dcfd5dc671f2aa4a987f1e0e306f843bd26ab7..f05d057f1b508519c9e6450ca2f02d060675163e 100644 (file)
@@ -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.
index 915d685ba1447e4b993100e881e456e70c21c05c..2c68f95c2fc4dafff05f589a0dc91fc0dcd2b398 100644 (file)
@@ -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);
index c8db4ba29ce17cd9ba37647239678bc38050e02a..2551495f864c654a6f04234c59afe8e405ccbd3c 100644 (file)
@@ -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;  
 };