1
0
Fork 0

Fix 2.5D panel hit detection, compute logical panel extend from actions.

This commit is contained in:
James Turner 2012-03-25 18:46:04 +01:00
parent 2e735e6234
commit 086df400de
5 changed files with 117 additions and 31 deletions

View 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;
}
////////////////////////////////////////////////////////////////////////.
// 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)
{

View file

@ -43,6 +43,7 @@
class FGPanelInstrument;
class fntFont;
class DCLGPS;
class IntRect;
////////////////////////////////////////////////////////////////////////
// Texture management.
@ -166,8 +167,14 @@ 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);
@ -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;

View 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.

View file

@ -110,9 +110,10 @@ 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
@ -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,11 +182,12 @@ FGPanelNode::drawImplementation(osg::State& state) const
osg::BoundingBox
FGPanelNode::computeBound() const
{
osg::Vec3 coords[4];
osg::Vec3 coords[3];
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));
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]);
@ -199,10 +201,10 @@ 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);

View file

@ -50,9 +50,7 @@ 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.