Work on making 2D panels act like standard scene-graph elements for picking and drawing.
(This includes 2.5D panels in the 3D scene)
This commit is contained in:
parent
d2411199e8
commit
8c187164fe
12 changed files with 356 additions and 281 deletions
|
@ -204,7 +204,8 @@ FGPanel::FGPanel ()
|
||||||
_flipx(fgGetNode("/sim/panel/flip-x", true)),
|
_flipx(fgGetNode("/sim/panel/flip-x", true)),
|
||||||
_xsize_node(fgGetNode("/sim/startup/xsize", true)),
|
_xsize_node(fgGetNode("/sim/startup/xsize", true)),
|
||||||
_ysize_node(fgGetNode("/sim/startup/ysize", true)),
|
_ysize_node(fgGetNode("/sim/startup/ysize", true)),
|
||||||
_enable_depth_test(false)
|
_enable_depth_test(false),
|
||||||
|
_drawPanelHotspots("/sim/panel-hotspots")
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,68 +266,24 @@ FGPanel::unbind ()
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGPanel::update (double dt)
|
FGPanel::update (double /* dt */)
|
||||||
{
|
{
|
||||||
std::cout << "OSGFIXME" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
FGPanel::update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
|
|
||||||
{
|
|
||||||
using namespace osg;
|
|
||||||
// Calculate accelerations
|
|
||||||
// and jiggle the panel accordingly
|
|
||||||
// The factors and bounds are just
|
|
||||||
// initial guesses; using sqrt smooths
|
|
||||||
// out the spikes.
|
|
||||||
double x_offset = _x_offset->getIntValue();
|
|
||||||
double y_offset = _y_offset->getIntValue();
|
|
||||||
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPushMatrix();
|
|
||||||
Matrixf proj;
|
|
||||||
if ( _flipx->getBoolValue() ) {
|
|
||||||
proj = Matrixf::ortho2D(winx + winw, winx, winy + winh, winy); /* up side down */
|
|
||||||
} else {
|
|
||||||
proj = Matrixf::ortho2D(winx, winx + winw, winy, winy + winh); /* right side up */
|
|
||||||
}
|
|
||||||
glLoadMatrix(proj.ptr());
|
|
||||||
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPushMatrix();
|
|
||||||
glLoadIdentity();
|
|
||||||
|
|
||||||
glTranslated(x_offset, y_offset, 0);
|
|
||||||
|
|
||||||
draw(state);
|
|
||||||
|
|
||||||
glMatrixMode(GL_PROJECTION);
|
|
||||||
glPopMatrix();
|
|
||||||
glMatrixMode(GL_MODELVIEW);
|
|
||||||
glPopMatrix();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the panel.
|
|
||||||
*/
|
|
||||||
void
|
|
||||||
FGPanel::update (osg::State& state)
|
|
||||||
{
|
|
||||||
// Do nothing if the panel isn't visible.
|
|
||||||
if ( !fgPanelVisible() ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
updateMouseDelay();
|
updateMouseDelay();
|
||||||
|
}
|
||||||
|
|
||||||
|
double
|
||||||
|
FGPanel::getAspectScale() const
|
||||||
|
{
|
||||||
|
// set corner-coordinates correctly
|
||||||
|
|
||||||
|
int xsize = _xsize_node->getIntValue();
|
||||||
|
int ysize = _ysize_node->getIntValue();
|
||||||
|
float aspect_adjust = get_aspect_adjust(xsize, ysize);
|
||||||
|
|
||||||
// Now, draw the panel
|
|
||||||
float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(),
|
|
||||||
_ysize_node->getIntValue());
|
|
||||||
if (aspect_adjust < 1.0)
|
if (aspect_adjust < 1.0)
|
||||||
update(state, WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H);
|
return ysize / (double) WIN_H;
|
||||||
else
|
else
|
||||||
update(state, WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust));
|
return xsize /(double) WIN_W;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -345,10 +302,10 @@ void FGPanel::updateMouseDelay()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
FGPanel::draw(osg::State& state)
|
FGPanel::draw(osg::State& state)
|
||||||
{
|
{
|
||||||
|
|
||||||
// In 3D mode, it's possible that we are being drawn exactly on top
|
// In 3D mode, it's possible that we are being drawn exactly on top
|
||||||
// of an existing polygon. Use an offset to prevent z-fighting. In
|
// of an existing polygon. Use an offset to prevent z-fighting. In
|
||||||
// 2D mode, this is a no-op.
|
// 2D mode, this is a no-op.
|
||||||
|
@ -363,6 +320,7 @@ FGPanel::draw(osg::State& state)
|
||||||
panelStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
panelStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
|
||||||
panelStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
panelStateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
panelStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
|
panelStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
|
||||||
|
|
||||||
osg::Material* material = new osg::Material;
|
osg::Material* material = new osg::Material;
|
||||||
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE);
|
||||||
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1));
|
material->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 1));
|
||||||
|
@ -370,6 +328,7 @@ FGPanel::draw(osg::State& state)
|
||||||
material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
|
material->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
|
||||||
material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
|
material->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1));
|
||||||
panelStateSet->setAttribute(material);
|
panelStateSet->setAttribute(material);
|
||||||
|
|
||||||
panelStateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
panelStateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON);
|
||||||
panelStateSet->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
panelStateSet->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK));
|
||||||
panelStateSet->setAttributeAndModes(new osg::Depth(osg::Depth::LEQUAL));
|
panelStateSet->setAttributeAndModes(new osg::Depth(osg::Depth::LEQUAL));
|
||||||
|
@ -495,7 +454,7 @@ FGPanel::draw(osg::State& state)
|
||||||
|
|
||||||
// Draw yellow "hotspots" if directed to. This is a panel authoring
|
// Draw yellow "hotspots" if directed to. This is a panel authoring
|
||||||
// feature; not intended to be high performance or to look good.
|
// feature; not intended to be high performance or to look good.
|
||||||
if ( fgGetBool("/sim/panel-hotspots") ) {
|
if ( _drawPanelHotspots ) {
|
||||||
static osg::ref_ptr<osg::StateSet> hotspotStateSet;
|
static osg::ref_ptr<osg::StateSet> hotspotStateSet;
|
||||||
if (!hotspotStateSet.valid()) {
|
if (!hotspotStateSet.valid()) {
|
||||||
hotspotStateSet = new osg::StateSet;
|
hotspotStateSet = new osg::StateSet;
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include <simgear/compiler.h>
|
||||||
#include <simgear/props/props.hxx>
|
#include <simgear/props/props.hxx>
|
||||||
|
#include <simgear/props/PropertyObject.hxx>
|
||||||
|
|
||||||
#include <simgear/structure/subsystem_mgr.hxx>
|
#include <simgear/structure/subsystem_mgr.hxx>
|
||||||
#include <simgear/structure/SGBinding.hxx>
|
#include <simgear/structure/SGBinding.hxx>
|
||||||
#include <simgear/math/interpolater.hxx>
|
#include <simgear/math/interpolater.hxx>
|
||||||
|
@ -128,8 +130,9 @@ public:
|
||||||
virtual void unbind ();
|
virtual void unbind ();
|
||||||
virtual void draw (osg::State& state);
|
virtual void draw (osg::State& state);
|
||||||
virtual void update (double);
|
virtual void update (double);
|
||||||
void update (osg::State& state);
|
|
||||||
virtual void update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh);
|
//void update (osg::State& state);
|
||||||
|
//virtual void update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh);
|
||||||
|
|
||||||
virtual void updateMouseDelay();
|
virtual void updateMouseDelay();
|
||||||
|
|
||||||
|
@ -175,6 +178,8 @@ public:
|
||||||
bool getAutohide(void) const { return _autohide; };
|
bool getAutohide(void) const { return _autohide; };
|
||||||
void setAutohide(bool enable) { _autohide = enable; };
|
void setAutohide(bool enable) { _autohide = enable; };
|
||||||
|
|
||||||
|
double getAspectScale() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupVirtualCockpit();
|
void setupVirtualCockpit();
|
||||||
void cleanupVirtualCockpit();
|
void cleanupVirtualCockpit();
|
||||||
|
@ -203,6 +208,8 @@ private:
|
||||||
instrument_list_type _instruments;
|
instrument_list_type _instruments;
|
||||||
bool _enable_depth_test;
|
bool _enable_depth_test;
|
||||||
bool _autohide;
|
bool _autohide;
|
||||||
|
|
||||||
|
SGPropObjBool _drawPanelHotspots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -276,14 +276,9 @@ void FGMouseInput::doMouseClick (int b, int updown, int x, int y, bool mainWindo
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode.pass_through) {
|
if (mode.pass_through) {
|
||||||
|
// remove once PUI uses standard picking mechanism
|
||||||
if (0 <= x && 0 <= y && puMouse(b, updown, x, y))
|
if (0 <= x && 0 <= y && puMouse(b, updown, x, y))
|
||||||
return;
|
return;
|
||||||
else if (0 <= x && 0 <= y && (globals->get_current_panel() != 0) &&
|
|
||||||
globals->get_current_panel()->getVisibility() &&
|
|
||||||
globals->get_current_panel()->doMouseAction(b, updown, x, y))
|
|
||||||
return;
|
|
||||||
else if (0 <= x && 0 <= y && fgHandle3DPanelMouseEvent(b, updown, x, y))
|
|
||||||
return;
|
|
||||||
else {
|
else {
|
||||||
// pui didn't want the click event so compute a
|
// pui didn't want the click event so compute a
|
||||||
// scenegraph intersection point corresponding to the mouse click
|
// scenegraph intersection point corresponding to the mouse click
|
||||||
|
|
|
@ -281,13 +281,19 @@ void CameraGroup::update(const osg::Vec3d& position,
|
||||||
#endif
|
#endif
|
||||||
Camera* camera = info->camera.get();
|
Camera* camera = info->camera.get();
|
||||||
Matrix viewMatrix;
|
Matrix viewMatrix;
|
||||||
if ((info->flags & VIEW_ABSOLUTE) != 0)
|
|
||||||
|
if (info->flags & GUI) {
|
||||||
|
viewMatrix = osg::Matrix(); // identifty transform on the GUI camera
|
||||||
|
} else if ((info->flags & VIEW_ABSOLUTE) != 0)
|
||||||
viewMatrix = slave._viewOffset;
|
viewMatrix = slave._viewOffset;
|
||||||
else
|
else
|
||||||
viewMatrix = masterView * slave._viewOffset;
|
viewMatrix = masterView * slave._viewOffset;
|
||||||
camera->setViewMatrix(viewMatrix);
|
camera->setViewMatrix(viewMatrix);
|
||||||
Matrix projectionMatrix;
|
Matrix projectionMatrix;
|
||||||
if ((info->flags & PROJECTION_ABSOLUTE) != 0) {
|
|
||||||
|
if (info->flags & GUI) {
|
||||||
|
projectionMatrix = osg::Matrix::ortho2D(0, info->width, 0, info->height);
|
||||||
|
} else if ((info->flags & PROJECTION_ABSOLUTE) != 0) {
|
||||||
if (info->flags & ENABLE_MASTER_ZOOM) {
|
if (info->flags & ENABLE_MASTER_ZOOM) {
|
||||||
if (info->relativeCameraParent < _cameras.size()) {
|
if (info->relativeCameraParent < _cameras.size()) {
|
||||||
// template projection matrix and view matrix of the current camera
|
// template projection matrix and view matrix of the current camera
|
||||||
|
@ -920,7 +926,7 @@ CameraInfo* CameraGroup::buildGUICamera(SGPropertyNode* cameraNode,
|
||||||
camera->setCullingMode(osg::CullSettings::NO_CULLING);
|
camera->setCullingMode(osg::CullSettings::NO_CULLING);
|
||||||
camera->setProjectionResizePolicy(Camera::FIXED);
|
camera->setProjectionResizePolicy(Camera::FIXED);
|
||||||
camera->setReferenceFrame(Transform::ABSOLUTE_RF);
|
camera->setReferenceFrame(Transform::ABSOLUTE_RF);
|
||||||
const int cameraFlags = GUI;
|
const int cameraFlags = GUI | DO_INTERSECTION_TEST;
|
||||||
CameraInfo* result = addCamera(cameraFlags, camera, Matrixd::identity(),
|
CameraInfo* result = addCamera(cameraFlags, camera, Matrixd::identity(),
|
||||||
Matrixd::identity(), false);
|
Matrixd::identity(), false);
|
||||||
SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true);
|
SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true);
|
||||||
|
@ -987,19 +993,29 @@ void CameraGroup::resized()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Camera* getGUICamera(CameraGroup* cgroup)
|
const CameraInfo* CameraGroup::getGUICamera() const
|
||||||
{
|
{
|
||||||
CameraGroup::CameraIterator end = cgroup->camerasEnd();
|
ConstCameraIterator result
|
||||||
CameraGroup::CameraIterator result
|
= std::find_if(camerasBegin(), camerasEnd(),
|
||||||
= std::find_if(cgroup->camerasBegin(), end,
|
FlagTester<CameraInfo>(GUI));
|
||||||
FlagTester<CameraInfo>(CameraGroup::GUI));
|
if (result == camerasEnd()) {
|
||||||
if (result != end)
|
return NULL;
|
||||||
return (*result)->camera.get();
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool computeIntersections(const CameraGroup* cgroup,
|
return *result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Camera* getGUICamera(CameraGroup* cgroup)
|
||||||
|
{
|
||||||
|
const CameraInfo* info = cgroup->getGUICamera();
|
||||||
|
if (!info) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return info->camera.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool computeCameraIntersection(const CameraInfo* cinfo,
|
||||||
const osgGA::GUIEventAdapter* ea,
|
const osgGA::GUIEventAdapter* ea,
|
||||||
osgUtil::LineSegmentIntersector::Intersections& intersections)
|
osgUtil::LineSegmentIntersector::Intersections& intersections)
|
||||||
{
|
{
|
||||||
|
@ -1007,24 +1023,22 @@ bool computeIntersections(const CameraGroup* cgroup,
|
||||||
using osgUtil::LineSegmentIntersector;
|
using osgUtil::LineSegmentIntersector;
|
||||||
double x, y;
|
double x, y;
|
||||||
eventToWindowCoords(ea, x, y);
|
eventToWindowCoords(ea, x, y);
|
||||||
// Find camera that contains event
|
|
||||||
for (CameraGroup::ConstCameraIterator iter = cgroup->camerasBegin(),
|
if (!(cinfo->flags & CameraGroup::DO_INTERSECTION_TEST))
|
||||||
e = cgroup->camerasEnd();
|
return false;
|
||||||
iter != e;
|
|
||||||
++iter) {
|
|
||||||
const CameraInfo* cinfo = iter->get();
|
|
||||||
if ((cinfo->flags & CameraGroup::DO_INTERSECTION_TEST) == 0)
|
|
||||||
continue;
|
|
||||||
const Camera* camera = cinfo->camera.get();
|
const Camera* camera = cinfo->camera.get();
|
||||||
if (camera->getGraphicsContext() != ea->getGraphicsContext())
|
if (camera->getGraphicsContext() != ea->getGraphicsContext())
|
||||||
continue;
|
return false;
|
||||||
|
|
||||||
const Viewport* viewport = camera->getViewport();
|
const Viewport* viewport = camera->getViewport();
|
||||||
double epsilon = 0.5;
|
double epsilon = 0.5;
|
||||||
if (!(x >= viewport->x() - epsilon
|
if (!(x >= viewport->x() - epsilon
|
||||||
&& x < viewport->x() + viewport->width() -1.0 + epsilon
|
&& x < viewport->x() + viewport->width() -1.0 + epsilon
|
||||||
&& y >= viewport->y() - epsilon
|
&& y >= viewport->y() - epsilon
|
||||||
&& y < viewport->y() + viewport->height() -1.0 + epsilon))
|
&& y < viewport->y() + viewport->height() -1.0 + epsilon))
|
||||||
continue;
|
return false;
|
||||||
|
|
||||||
Vec4d start(x, y, 0.0, 1.0);
|
Vec4d start(x, y, 0.0, 1.0);
|
||||||
Vec4d end(x, y, 1.0, 1.0);
|
Vec4d end(x, y, 1.0, 1.0);
|
||||||
Matrix windowMat = viewport->computeWindowMatrix();
|
Matrix windowMat = viewport->computeWindowMatrix();
|
||||||
|
@ -1049,10 +1063,33 @@ bool computeIntersections(const CameraGroup* cgroup,
|
||||||
if (picker->containsIntersections()) {
|
if (picker->containsIntersections()) {
|
||||||
intersections = picker->getIntersections();
|
intersections = picker->getIntersections();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool computeIntersections(const CameraGroup* cgroup,
|
||||||
|
const osgGA::GUIEventAdapter* ea,
|
||||||
|
osgUtil::LineSegmentIntersector::Intersections& intersections)
|
||||||
|
{
|
||||||
|
// test the GUI first
|
||||||
|
const CameraInfo* guiCamera = cgroup->getGUICamera();
|
||||||
|
if (guiCamera && computeCameraIntersection(guiCamera, ea, intersections))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Find camera that contains event
|
||||||
|
for (CameraGroup::ConstCameraIterator iter = cgroup->camerasBegin(),
|
||||||
|
e = cgroup->camerasEnd();
|
||||||
|
iter != e;
|
||||||
|
++iter) {
|
||||||
|
const CameraInfo* cinfo = iter->get();
|
||||||
|
if (cinfo == guiCamera)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (computeCameraIntersection(cinfo, ea, intersections))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
intersections.clear();
|
intersections.clear();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,11 @@ public:
|
||||||
* get aspect ratio of master camera's viewport
|
* get aspect ratio of master camera's viewport
|
||||||
*/
|
*/
|
||||||
double getMasterAspectRatio() const;
|
double getMasterAspectRatio() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* find the GUI camera if one is defined
|
||||||
|
*/
|
||||||
|
const CameraInfo* getGUICamera() const;
|
||||||
protected:
|
protected:
|
||||||
CameraList _cameras;
|
CameraList _cameras;
|
||||||
osg::ref_ptr<osgViewer::Viewer> _viewer;
|
osg::ref_ptr<osgViewer::Viewer> _viewer;
|
||||||
|
|
|
@ -515,4 +515,11 @@ void FGGlobals::set_warp_delta( long int d )
|
||||||
fgSetInt("/sim/time/warp-delta", d);
|
fgSetInt("/sim/time/warp-delta", d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGGlobals::set_current_panel( FGPanel *cp )
|
||||||
|
{
|
||||||
|
current_panel = cp;
|
||||||
|
// poke the renderer to rebuild the scene node as necessary
|
||||||
|
get_renderer()->panelChanged();
|
||||||
|
}
|
||||||
|
|
||||||
// end of globals.cxx
|
// end of globals.cxx
|
||||||
|
|
|
@ -243,7 +243,7 @@ public:
|
||||||
inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; }
|
inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; }
|
||||||
|
|
||||||
inline FGPanel *get_current_panel() const { return current_panel; }
|
inline FGPanel *get_current_panel() const { return current_panel; }
|
||||||
inline void set_current_panel( FGPanel *cp ) { current_panel = cp; }
|
void set_current_panel( FGPanel *cp );
|
||||||
|
|
||||||
inline FGControls *get_controls() const { return controls; }
|
inline FGControls *get_controls() const { return controls; }
|
||||||
inline void set_controls( FGControls *c ) { controls = c; }
|
inline void set_controls( FGControls *c ) { controls = c; }
|
||||||
|
|
|
@ -259,19 +259,6 @@ struct GeneralInitOperation : public GraphicsContextOperation
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
osg::Node* load_panel(SGPropertyNode *n)
|
|
||||||
{
|
|
||||||
osg::Geode* geode = new osg::Geode;
|
|
||||||
geode->addDrawable(new FGPanelNode(n));
|
|
||||||
return geode;
|
|
||||||
}
|
|
||||||
|
|
||||||
SGPath resolve_path(const std::string& s)
|
|
||||||
{
|
|
||||||
return globals->resolve_maybe_aircraft_path(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is the top level master main function that is registered as
|
// This is the top level master main function that is registered as
|
||||||
|
@ -349,7 +336,7 @@ static void fgIdleFunction ( void ) {
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
globals->set_matlib( new SGMaterialLib );
|
globals->set_matlib( new SGMaterialLib );
|
||||||
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
|
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
|
||||||
simgear::SGModelLib::setPanelFunc(load_panel);
|
simgear::SGModelLib::setPanelFunc(FGPanelNode::load);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Initialize the TG scenery subsystem.
|
// Initialize the TG scenery subsystem.
|
||||||
|
|
|
@ -85,6 +85,7 @@
|
||||||
#include <Time/light.hxx>
|
#include <Time/light.hxx>
|
||||||
#include <Time/light.hxx>
|
#include <Time/light.hxx>
|
||||||
#include <Cockpit/panel.hxx>
|
#include <Cockpit/panel.hxx>
|
||||||
|
|
||||||
#include <Model/panelnode.hxx>
|
#include <Model/panelnode.hxx>
|
||||||
#include <Model/modelmgr.hxx>
|
#include <Model/modelmgr.hxx>
|
||||||
#include <Model/acmodel.hxx>
|
#include <Model/acmodel.hxx>
|
||||||
|
@ -179,9 +180,9 @@ public:
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
|
||||||
class SGHUDAndPanelDrawable : public osg::Drawable {
|
class SGHUDDrawable : public osg::Drawable {
|
||||||
public:
|
public:
|
||||||
SGHUDAndPanelDrawable()
|
SGHUDDrawable()
|
||||||
{
|
{
|
||||||
// Dynamic stuff, do not store geometry
|
// Dynamic stuff, do not store geometry
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
|
@ -213,20 +214,12 @@ public:
|
||||||
HUD *hud = static_cast<HUD*>(globals->get_subsystem("hud"));
|
HUD *hud = static_cast<HUD*>(globals->get_subsystem("hud"));
|
||||||
hud->draw(state);
|
hud->draw(state);
|
||||||
|
|
||||||
// update the panel subsystem
|
|
||||||
if ( globals->get_current_panel() != NULL )
|
|
||||||
globals->get_current_panel()->update(state);
|
|
||||||
// We don't need a state here - can be safely removed when we can pick
|
|
||||||
// correctly
|
|
||||||
fgUpdate3DPanels();
|
|
||||||
|
|
||||||
glPopClientAttrib();
|
glPopClientAttrib();
|
||||||
glPopAttrib();
|
glPopAttrib();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual osg::Object* cloneType() const { return new SGHUDAndPanelDrawable; }
|
virtual osg::Object* cloneType() const { return new SGHUDDrawable; }
|
||||||
virtual osg::Object* clone(const osg::CopyOp&) const { return new SGHUDAndPanelDrawable; }
|
virtual osg::Object* clone(const osg::CopyOp&) const { return new SGHUDDrawable; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
};
|
};
|
||||||
|
@ -382,6 +375,25 @@ static osg::ref_ptr<osg::Group> mRealRoot = new osg::Group;
|
||||||
|
|
||||||
static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
|
static osg::ref_ptr<osg::Group> mRoot = new osg::Group;
|
||||||
|
|
||||||
|
static osg::ref_ptr<osg::Switch> panelSwitch;
|
||||||
|
|
||||||
|
|
||||||
|
// update callback for the switch node controlling the 2D panel
|
||||||
|
class FGPanelSwitchCallback : public osg::NodeCallback {
|
||||||
|
public:
|
||||||
|
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||||
|
{
|
||||||
|
assert(dynamic_cast<osg::Switch*>(node));
|
||||||
|
osg::Switch* sw = static_cast<osg::Switch*>(node);
|
||||||
|
|
||||||
|
bool enabled = fgPanelVisible();
|
||||||
|
sw->setValue(0, enabled);
|
||||||
|
if (!enabled)
|
||||||
|
return;
|
||||||
|
traverse(node, nv);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef FG_JPEG_SERVER
|
#ifdef FG_JPEG_SERVER
|
||||||
static void updateRenderer()
|
static void updateRenderer()
|
||||||
{
|
{
|
||||||
|
@ -627,11 +639,30 @@ FGRenderer::setupView( void )
|
||||||
// plug in the GUI
|
// plug in the GUI
|
||||||
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
|
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
|
||||||
if (guiCamera) {
|
if (guiCamera) {
|
||||||
|
|
||||||
osg::Geode* geode = new osg::Geode;
|
osg::Geode* geode = new osg::Geode;
|
||||||
geode->addDrawable(new SGPuDrawable);
|
geode->addDrawable(new SGPuDrawable);
|
||||||
geode->addDrawable(new SGHUDAndPanelDrawable);
|
geode->addDrawable(new SGHUDDrawable);
|
||||||
guiCamera->addChild(geode);
|
guiCamera->addChild(geode);
|
||||||
|
|
||||||
|
panelSwitch = new osg::Switch;
|
||||||
|
osg::StateSet* stateSet = panelSwitch->getOrCreateStateSet();
|
||||||
|
stateSet->setRenderBinDetails(1000, "RenderBin");
|
||||||
|
|
||||||
|
// speed optimization?
|
||||||
|
stateSet->setMode(GL_CULL_FACE, osg::StateAttribute::OFF);
|
||||||
|
stateSet->setAttribute(new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA));
|
||||||
|
stateSet->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
|
stateSet->setMode(GL_FOG, osg::StateAttribute::OFF);
|
||||||
|
stateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
|
||||||
|
|
||||||
|
|
||||||
|
panelSwitch->setUpdateCallback(new FGPanelSwitchCallback);
|
||||||
|
panelChanged();
|
||||||
|
|
||||||
|
guiCamera->addChild(panelSwitch.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::Switch* sw = new osg::Switch;
|
osg::Switch* sw = new osg::Switch;
|
||||||
sw->setUpdateCallback(new FGScenerySwitchCallback);
|
sw->setUpdateCallback(new FGScenerySwitchCallback);
|
||||||
sw->addChild(mRoot.get());
|
sw->addChild(mRoot.get());
|
||||||
|
@ -647,6 +678,20 @@ FGRenderer::setupView( void )
|
||||||
stateSet->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
|
stateSet->setAttributeAndModes(new osg::Program, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FGRenderer::panelChanged()
|
||||||
|
{
|
||||||
|
if (!panelSwitch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Node* n = FGPanelNode::createNode(globals->get_current_panel());
|
||||||
|
if (panelSwitch->getNumChildren()) {
|
||||||
|
panelSwitch->setChild(0, n);
|
||||||
|
} else {
|
||||||
|
panelSwitch->addChild(n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update all Visuals (redraws anything graphics related)
|
// Update all Visuals (redraws anything graphics related)
|
||||||
void
|
void
|
||||||
FGRenderer::update( ) {
|
FGRenderer::update( ) {
|
||||||
|
|
|
@ -74,6 +74,10 @@ public:
|
||||||
|
|
||||||
SGSky* getSky() const { return _sky; }
|
SGSky* getSky() const { return _sky; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inform the renderer when the global (2D) panel is changed
|
||||||
|
*/
|
||||||
|
void panelChanged();
|
||||||
protected:
|
protected:
|
||||||
osg::ref_ptr<osgViewer::Viewer> viewer;
|
osg::ref_ptr<osgViewer::Viewer> viewer;
|
||||||
osg::ref_ptr<flightgear::FGEventHandler> eventHandler;
|
osg::ref_ptr<flightgear::FGEventHandler> eventHandler;
|
||||||
|
|
|
@ -2,44 +2,68 @@
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <simgear/compiler.h>
|
#include "panelnode.hxx"
|
||||||
#include <simgear/structure/exception.hxx>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include <osg/Geode>
|
||||||
|
|
||||||
|
#include <simgear/compiler.h>
|
||||||
|
#include <simgear/structure/exception.hxx>
|
||||||
|
#include <simgear/debug/logstream.hxx>
|
||||||
|
|
||||||
|
#include <simgear/scene/util/OSGMath.hxx>
|
||||||
|
#include <simgear/scene/util/SGPickCallback.hxx>
|
||||||
|
#include <simgear/scene/util/SGSceneUserData.hxx>
|
||||||
|
#include <simgear/scene/util/SGNodeMasks.hxx>
|
||||||
|
|
||||||
|
#include <Main/fg_os.hxx>
|
||||||
#include <Cockpit/panel.hxx>
|
#include <Cockpit/panel.hxx>
|
||||||
#include <Cockpit/panel_io.hxx>
|
#include <Cockpit/panel_io.hxx>
|
||||||
#include "panelnode.hxx"
|
|
||||||
|
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
|
class FGPanelPickCallback : public SGPickCallback {
|
||||||
|
public:
|
||||||
|
FGPanelPickCallback(FGPanelNode* p) :
|
||||||
|
panel(p)
|
||||||
|
{}
|
||||||
|
|
||||||
// Static (!) handling for all 3D panels in the program.
|
virtual bool buttonPressed(int b, const Info& info)
|
||||||
// OSGFIXME: Put the panel as different elements in the scenegraph.
|
|
||||||
// Then just pick in that scenegraph.
|
|
||||||
vector<FGPanelNode*> all_3d_panels;
|
|
||||||
bool fgHandle3DPanelMouseEvent( int button, int updown, int x, int y )
|
|
||||||
{
|
{
|
||||||
for ( unsigned int i = 0; i < all_3d_panels.size(); i++ ) {
|
button = b;
|
||||||
if ( all_3d_panels[i]->doMouseAction(button, updown, x, y) ) {
|
// convert to panel coordinates
|
||||||
return true;
|
osg::Matrixd m = osg::Matrixd::inverse(panel->transformMatrix());
|
||||||
}
|
picked = toOsg(info.local) * m;
|
||||||
}
|
SG_LOG( SG_INSTR, SG_DEBUG, "panel pick: " << toSG(picked) );
|
||||||
return false;
|
|
||||||
|
// send to the panel
|
||||||
|
return panel->getPanel()->doLocalMouseAction(button, MOUSE_BUTTON_DOWN,
|
||||||
|
picked.x(), picked.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
void fgUpdate3DPanels()
|
virtual void update(double /* dt */)
|
||||||
{
|
{
|
||||||
for ( unsigned int i = 0; i < all_3d_panels.size(); i++ ) {
|
panel->getPanel()->updateMouseDelay();
|
||||||
all_3d_panels[i]->getPanel()->updateMouseDelay();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FGPanelNode::FGPanelNode(SGPropertyNode* props)
|
virtual void buttonReleased(void)
|
||||||
{
|
{
|
||||||
int i;
|
panel->getPanel()->doLocalMouseAction(button, MOUSE_BUTTON_UP,
|
||||||
|
picked.x(), picked.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
FGPanelNode* panel;
|
||||||
|
int button;
|
||||||
|
osg::Vec3 picked;
|
||||||
|
};
|
||||||
|
|
||||||
|
FGPanelNode::FGPanelNode(SGPropertyNode* props) :
|
||||||
|
_resizeToViewport(false)
|
||||||
|
{
|
||||||
// Make an FGPanel object. But *don't* call init() or bind() on
|
// Make an FGPanel object. But *don't* call init() or bind() on
|
||||||
// it -- those methods touch static state.
|
// it -- those methods touch static state.
|
||||||
const char *path = props->getStringValue("path");
|
const char *path = props->getStringValue("path");
|
||||||
|
@ -47,18 +71,6 @@ FGPanelNode::FGPanelNode(SGPropertyNode* props)
|
||||||
if (!_panel)
|
if (!_panel)
|
||||||
throw sg_io_exception(string("Failed to load panel ") + path);
|
throw sg_io_exception(string("Failed to load panel ") + path);
|
||||||
|
|
||||||
// Never mind. We *have* to call init to make sure the static
|
|
||||||
// state is initialized (it's not, if there aren't any 2D
|
|
||||||
// panels). This is a memory leak and should be fixed!`
|
|
||||||
// FIXME
|
|
||||||
_panel->init();
|
|
||||||
|
|
||||||
_panel->setDepthTest( props->getBoolValue("depth-test") );
|
|
||||||
|
|
||||||
// Read out the pixel-space info
|
|
||||||
_xmax = _panel->getWidth();
|
|
||||||
_ymax = _panel->getHeight();
|
|
||||||
|
|
||||||
// And the corner points
|
// And the corner points
|
||||||
SGPropertyNode* pt = props->getChild("bottom-left");
|
SGPropertyNode* pt = props->getChild("bottom-left");
|
||||||
_bottomLeft[0] = pt->getFloatValue("x-m");
|
_bottomLeft[0] = pt->getFloatValue("x-m");
|
||||||
|
@ -75,6 +87,33 @@ FGPanelNode::FGPanelNode(SGPropertyNode* props)
|
||||||
_bottomRight[1] = pt->getFloatValue("y-m");
|
_bottomRight[1] = pt->getFloatValue("y-m");
|
||||||
_bottomRight[2] = pt->getFloatValue("z-m");
|
_bottomRight[2] = pt->getFloatValue("z-m");
|
||||||
|
|
||||||
|
_panel->setDepthTest( props->getBoolValue("depth-test") );
|
||||||
|
|
||||||
|
initWithPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
FGPanelNode::FGPanelNode(FGPanel* p) :
|
||||||
|
_panel(p),
|
||||||
|
_resizeToViewport(true)
|
||||||
|
{
|
||||||
|
initWithPanel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FGPanelNode::initWithPanel()
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Never mind. We *have* to call init to make sure the static
|
||||||
|
// state is initialized (it's not, if there aren't any 2D
|
||||||
|
// panels). This is a memory leak and should be fixed!`
|
||||||
|
// FIXME
|
||||||
|
_panel->init();
|
||||||
|
|
||||||
|
// Read out the pixel-space info
|
||||||
|
_xmax = _panel->getWidth();
|
||||||
|
_ymax = _panel->getHeight();
|
||||||
|
|
||||||
|
|
||||||
// Now generate our transformation matrix. For shorthand, use
|
// Now generate our transformation matrix. For shorthand, use
|
||||||
// "a", "b", and "c" as our corners and "m" as the matrix. The
|
// "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
|
// vector u goes from a to b, v from a to c, and w is a
|
||||||
|
@ -103,102 +142,93 @@ FGPanelNode::FGPanelNode(SGPropertyNode* props)
|
||||||
m(1,i) *= 1.0/_ymax;
|
m(1,i) *= 1.0/_ymax;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastViewport[0] = 0;
|
|
||||||
_lastViewport[1] = 0;
|
|
||||||
_lastViewport[2] = 0;
|
|
||||||
_lastViewport[3] = 0;
|
|
||||||
|
|
||||||
dirtyBound();
|
dirtyBound();
|
||||||
|
|
||||||
// All done. Add us to the list
|
|
||||||
all_3d_panels.push_back(this);
|
|
||||||
|
|
||||||
setUseDisplayList(false);
|
setUseDisplayList(false);
|
||||||
|
setDataVariance(Object::DYNAMIC);
|
||||||
|
|
||||||
getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
getOrCreateStateSet()->setRenderingHint(osg::StateSet::TRANSPARENT_BIN);
|
||||||
getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
|
||||||
}
|
}
|
||||||
|
|
||||||
FGPanelNode::~FGPanelNode()
|
FGPanelNode::~FGPanelNode()
|
||||||
{
|
{
|
||||||
vector<FGPanelNode*>::iterator i =
|
|
||||||
find(all_3d_panels.begin(), all_3d_panels.end(), this);
|
|
||||||
if (i != all_3d_panels.end()) {
|
|
||||||
all_3d_panels.erase(i);
|
|
||||||
}
|
|
||||||
delete _panel;
|
delete _panel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Matrix FGPanelNode::transformMatrix() const
|
||||||
|
{
|
||||||
|
if (!_resizeToViewport) {
|
||||||
|
return _xform;
|
||||||
|
}
|
||||||
|
|
||||||
|
double s = _panel->getAspectScale();
|
||||||
|
osg::Matrix m = osg::Matrix::scale(s, s, 1.0);
|
||||||
|
m *= osg::Matrix::translate(_panel->getXOffset(), _panel->getYOffset(), 0.0);
|
||||||
|
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FGPanelNode::drawImplementation(osg::State& state) const
|
FGPanelNode::drawImplementation(osg::State& state) const
|
||||||
{
|
{
|
||||||
osg::ref_ptr<osg::RefMatrix> mv = new osg::RefMatrix;
|
osg::ref_ptr<osg::RefMatrix> mv = new osg::RefMatrix;
|
||||||
mv->set(_xform*state.getModelViewMatrix());
|
mv->set(transformMatrix() * state.getModelViewMatrix());
|
||||||
state.applyModelViewMatrix(mv.get());
|
state.applyModelViewMatrix(mv.get());
|
||||||
|
|
||||||
// Grab the matrix state, so that we can get back from screen
|
|
||||||
// coordinates to panel coordinates when the user clicks the
|
|
||||||
// mouse.
|
|
||||||
// OSGFIXME: we don't need that when we can really pick
|
|
||||||
_lastModelview = state.getModelViewMatrix();
|
|
||||||
_lastProjection = state.getProjectionMatrix();
|
|
||||||
|
|
||||||
const osg::Viewport* vp = state.getCurrentViewport();
|
|
||||||
_lastViewport[0] = vp->x();
|
|
||||||
_lastViewport[1] = vp->y();
|
|
||||||
_lastViewport[2] = vp->width();
|
|
||||||
_lastViewport[3] = vp->height();
|
|
||||||
|
|
||||||
_panel->draw(state);
|
_panel->draw(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::BoundingBox
|
osg::BoundingBox
|
||||||
FGPanelNode::computeBound() const
|
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;
|
osg::BoundingBox bb;
|
||||||
bb.expandBy(_bottomLeft);
|
bb.expandBy(coords[0]);
|
||||||
bb.expandBy(_bottomRight);
|
bb.expandBy(coords[1]);
|
||||||
bb.expandBy(_topLeft);
|
bb.expandBy(coords[2]);
|
||||||
return bb;
|
return bb;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FGPanelNode::doMouseAction(int button, int updown, int x, int y)
|
void FGPanelNode::accept(osg::PrimitiveFunctor& functor) const
|
||||||
{
|
{
|
||||||
if (_lastViewport[2] == 0 || _lastViewport[3] == 0) {
|
osg::Vec3 coords[4];
|
||||||
// we haven't been drawn yet, presumably
|
osg::Matrix m(transformMatrix());
|
||||||
return false;
|
|
||||||
|
coords[0] = m.preMult(osg::Vec3(0,0,0));
|
||||||
|
coords[1] = m.preMult(osg::Vec3(_xmax,0,0));
|
||||||
|
coords[2] = m.preMult(osg::Vec3(_xmax, _ymax, 0));
|
||||||
|
coords[3] = m.preMult(osg::Vec3(0,_ymax,0));
|
||||||
|
|
||||||
|
functor.setVertexArray(4, coords);
|
||||||
|
functor.drawArrays( GL_QUADS, 0, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Covert the screen coordinates to viewport coordinates in the
|
static osg::Node* createGeode(FGPanelNode* panel)
|
||||||
// range [0:1], then transform to OpenGL "post projection" coords
|
{
|
||||||
// in [-1:1]. Remember the difference in Y direction!
|
osg::Geode* geode = new osg::Geode;
|
||||||
float vx = (x + 0.5 - _lastViewport[0]) / _lastViewport[2];
|
geode->addDrawable(panel);
|
||||||
float vy = (y + 0.5 - _lastViewport[1]) / _lastViewport[3];
|
|
||||||
vx = 2*vx - 1;
|
|
||||||
vy = 1 - 2*vy;
|
|
||||||
|
|
||||||
// Make two vectors in post-projection coordinates at the given
|
geode->setNodeMask(SG_NODEMASK_PICK_BIT | SG_NODEMASK_2DPANEL_BIT);
|
||||||
// screen, one in the near field and one in the far field.
|
|
||||||
osg::Vec3 a, b;
|
|
||||||
a[0] = b[0] = vx;
|
|
||||||
a[1] = b[1] = vy;
|
|
||||||
a[2] = 0.75; // "Near" Z value
|
|
||||||
b[2] = -0.75; // "Far" Z value
|
|
||||||
|
|
||||||
// Run both vectors "backwards" through the OpenGL matrix
|
SGSceneUserData* userData;
|
||||||
// transformation. Remember to w-normalize the vectors!
|
userData = SGSceneUserData::getOrCreateSceneUserData(geode);
|
||||||
osg::Matrix m = _lastModelview*_lastProjection;
|
userData->setPickCallback(new FGPanelPickCallback(panel));
|
||||||
m = osg::Matrix::inverse(m);
|
return geode;
|
||||||
|
|
||||||
a = m.preMult(a);
|
|
||||||
b = m.preMult(b);
|
|
||||||
|
|
||||||
// And find their intersection on the z=0 plane. The resulting X
|
|
||||||
// and Y coordinates are the hit location in panel coordinates.
|
|
||||||
float dxdz = (b[0] - a[0]) / (b[2] - a[2]);
|
|
||||||
float dydz = (b[1] - a[1]) / (b[2] - a[2]);
|
|
||||||
int panelX = (int)(a[0] - a[2]*dxdz + 0.5);
|
|
||||||
int panelY = (int)(a[1] - a[2]*dydz + 0.5);
|
|
||||||
|
|
||||||
return _panel->doLocalMouseAction(button, updown, panelX, panelY);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
osg::Node* FGPanelNode::createNode(FGPanel* p)
|
||||||
|
{
|
||||||
|
FGPanelNode* drawable = new FGPanelNode(p);
|
||||||
|
return createGeode(drawable);
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Node* FGPanelNode::load(SGPropertyNode *n)
|
||||||
|
{
|
||||||
|
FGPanelNode* drawable = new FGPanelNode(n);
|
||||||
|
return createGeode(drawable);
|
||||||
|
}
|
||||||
|
|
|
@ -8,20 +8,13 @@
|
||||||
class FGPanel;
|
class FGPanel;
|
||||||
class SGPropertyNode;
|
class SGPropertyNode;
|
||||||
|
|
||||||
// PanelNode defines an SSG leaf object that draws a FGPanel object
|
// PanelNode defines an OSG drawable wrapping the 2D panel drawing code
|
||||||
// into the scene graph. Note that this is an incomplete SSG object,
|
|
||||||
// many methods, mostly involved with modelling and runtime
|
|
||||||
// inspection, are unimplemented.
|
|
||||||
|
|
||||||
// Static mouse handler for all FGPanelNodes. Very clumsy; this
|
class FGPanelNode : public osg::Drawable
|
||||||
// should really be done through our container (an aircraft model,
|
|
||||||
// typically).
|
|
||||||
bool fgHandle3DPanelMouseEvent(int button, int updown, int x, int y);
|
|
||||||
void fgUpdate3DPanels();
|
|
||||||
|
|
||||||
class FGPanelNode : public osg::Drawable // OSGFIXME
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
FGPanelNode(FGPanel* panel);
|
||||||
|
|
||||||
FGPanelNode(SGPropertyNode* props);
|
FGPanelNode(SGPropertyNode* props);
|
||||||
virtual ~FGPanelNode();
|
virtual ~FGPanelNode();
|
||||||
|
|
||||||
|
@ -29,18 +22,31 @@ public:
|
||||||
virtual osg::Object* cloneType() const { return 0; }
|
virtual osg::Object* cloneType() const { return 0; }
|
||||||
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return 0; }
|
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return 0; }
|
||||||
|
|
||||||
bool doMouseAction(int button, int updown, int x, int y);
|
|
||||||
|
|
||||||
FGPanel* getPanel() { return _panel; }
|
FGPanel* getPanel() { return _panel; }
|
||||||
|
|
||||||
virtual void drawImplementation(osg::RenderInfo& renderInfo) const
|
virtual void drawImplementation(osg::RenderInfo& renderInfo) const
|
||||||
{ drawImplementation(*renderInfo.getState()); }
|
{ drawImplementation(*renderInfo.getState()); }
|
||||||
|
|
||||||
void drawImplementation(osg::State& state) const;
|
void drawImplementation(osg::State& state) const;
|
||||||
virtual osg::BoundingBox computeBound() const;
|
virtual osg::BoundingBox computeBound() const;
|
||||||
|
|
||||||
|
/** Return true, FGPanelNode does support accept(PrimitiveFunctor&). */
|
||||||
|
virtual bool supports(const osg::PrimitiveFunctor&) const { return true; }
|
||||||
|
|
||||||
|
virtual void accept(osg::PrimitiveFunctor& functor) const;
|
||||||
|
|
||||||
|
static osg::Node* load(SGPropertyNode *n);
|
||||||
|
static osg::Node* createNode(FGPanel* panel);
|
||||||
|
|
||||||
|
osg::Matrix transformMatrix() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void initWithPanel();
|
||||||
|
|
||||||
FGPanel* _panel;
|
FGPanel* _panel;
|
||||||
|
|
||||||
|
bool _resizeToViewport;
|
||||||
|
|
||||||
// Panel corner coordinates
|
// Panel corner coordinates
|
||||||
osg::Vec3 _bottomLeft, _topLeft, _bottomRight;
|
osg::Vec3 _bottomLeft, _topLeft, _bottomRight;
|
||||||
|
|
||||||
|
@ -51,13 +57,6 @@ private:
|
||||||
// The matrix that results, which transforms 2D x/y panel
|
// The matrix that results, which transforms 2D x/y panel
|
||||||
// coordinates into 3D coordinates of the panel quadrilateral.
|
// coordinates into 3D coordinates of the panel quadrilateral.
|
||||||
osg::Matrix _xform;
|
osg::Matrix _xform;
|
||||||
|
|
||||||
// The matrix transformation state that was active the last time
|
|
||||||
// we were rendered. Used by the mouse code to compute
|
|
||||||
// intersections.
|
|
||||||
mutable osg::Matrix _lastModelview;
|
|
||||||
mutable osg::Matrix _lastProjection;
|
|
||||||
mutable double _lastViewport[4];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue