diff --git a/src/Cockpit/panel.cxx b/src/Cockpit/panel.cxx index 3ac15621e..d3f74940b 100644 --- a/src/Cockpit/panel.cxx +++ b/src/Cockpit/panel.cxx @@ -204,7 +204,8 @@ FGPanel::FGPanel () _flipx(fgGetNode("/sim/panel/flip-x", true)), _xsize_node(fgGetNode("/sim/startup/xsize", 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 -FGPanel::update (double dt) +FGPanel::update (double /* dt */) { - std::cout << "OSGFIXME" << std::endl; + updateMouseDelay(); } -void -FGPanel::update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh) +double +FGPanel::getAspectScale() const { - 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()); + // set corner-coordinates correctly - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + int xsize = _xsize_node->getIntValue(); + int ysize = _ysize_node->getIntValue(); + float aspect_adjust = get_aspect_adjust(xsize, ysize); - 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(); - - // Now, draw the panel - float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(), - _ysize_node->getIntValue()); - if (aspect_adjust <1.0) - update(state, WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H); - else - update(state, WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust)); + if (aspect_adjust < 1.0) + return ysize / (double) WIN_H; + else + return xsize /(double) WIN_W; } /** @@ -345,10 +302,10 @@ void FGPanel::updateMouseDelay() } } - void FGPanel::draw(osg::State& state) { + // 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 // 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_BLEND, osg::StateAttribute::ON); panelStateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON); + osg::Material* material = new osg::Material; material->setColorMode(osg::Material::AMBIENT_AND_DIFFUSE); 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->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4(0, 0, 0, 1)); panelStateSet->setAttribute(material); + panelStateSet->setMode(GL_CULL_FACE, osg::StateAttribute::ON); panelStateSet->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK)); 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 // feature; not intended to be high performance or to look good. - if ( fgGetBool("/sim/panel-hotspots") ) { + if ( _drawPanelHotspots ) { static osg::ref_ptr hotspotStateSet; if (!hotspotStateSet.valid()) { hotspotStateSet = new osg::StateSet; diff --git a/src/Cockpit/panel.hxx b/src/Cockpit/panel.hxx index ab4f5264f..424800e65 100644 --- a/src/Cockpit/panel.hxx +++ b/src/Cockpit/panel.hxx @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -128,8 +130,9 @@ public: virtual void unbind (); virtual void draw (osg::State& state); 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(); @@ -174,6 +177,8 @@ public: bool getAutohide(void) const { return _autohide; }; void setAutohide(bool enable) { _autohide = enable; }; + + double getAspectScale() const; private: void setupVirtualCockpit(); @@ -203,6 +208,8 @@ private: instrument_list_type _instruments; bool _enable_depth_test; bool _autohide; + + SGPropObjBool _drawPanelHotspots; }; diff --git a/src/Input/FGMouseInput.cxx b/src/Input/FGMouseInput.cxx index 927106f47..8ebdb6bec 100644 --- a/src/Input/FGMouseInput.cxx +++ b/src/Input/FGMouseInput.cxx @@ -276,14 +276,9 @@ void FGMouseInput::doMouseClick (int b, int updown, int x, int y, bool mainWindo } if (mode.pass_through) { + // remove once PUI uses standard picking mechanism if (0 <= x && 0 <= y && puMouse(b, updown, x, y)) 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 { // pui didn't want the click event so compute a // scenegraph intersection point corresponding to the mouse click diff --git a/src/Main/CameraGroup.cxx b/src/Main/CameraGroup.cxx index 135c67604..cac2bfa5e 100644 --- a/src/Main/CameraGroup.cxx +++ b/src/Main/CameraGroup.cxx @@ -281,13 +281,19 @@ void CameraGroup::update(const osg::Vec3d& position, #endif Camera* camera = info->camera.get(); 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; else viewMatrix = masterView * slave._viewOffset; camera->setViewMatrix(viewMatrix); 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->relativeCameraParent < _cameras.size()) { // 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->setProjectionResizePolicy(Camera::FIXED); camera->setReferenceFrame(Transform::ABSOLUTE_RF); - const int cameraFlags = GUI; + const int cameraFlags = GUI | DO_INTERSECTION_TEST; CameraInfo* result = addCamera(cameraFlags, camera, Matrixd::identity(), Matrixd::identity(), false); SGPropertyNode* viewportNode = cameraNode->getNode("viewport", true); @@ -987,72 +993,103 @@ void CameraGroup::resized() } } +const CameraInfo* CameraGroup::getGUICamera() const +{ + ConstCameraIterator result + = std::find_if(camerasBegin(), camerasEnd(), + FlagTester(GUI)); + if (result == camerasEnd()) { + return NULL; + } + + return *result; +} + Camera* getGUICamera(CameraGroup* cgroup) { - CameraGroup::CameraIterator end = cgroup->camerasEnd(); - CameraGroup::CameraIterator result - = std::find_if(cgroup->camerasBegin(), end, - FlagTester(CameraGroup::GUI)); - if (result != end) - return (*result)->camera.get(); - else - return 0; + const CameraInfo* info = cgroup->getGUICamera(); + if (!info) { + return NULL; + } + + return info->camera.get(); } +static bool computeCameraIntersection(const CameraInfo* cinfo, + const osgGA::GUIEventAdapter* ea, + osgUtil::LineSegmentIntersector::Intersections& intersections) +{ + using osgUtil::Intersector; + using osgUtil::LineSegmentIntersector; + double x, y; + eventToWindowCoords(ea, x, y); + + if (!(cinfo->flags & CameraGroup::DO_INTERSECTION_TEST)) + return false; + + const Camera* camera = cinfo->camera.get(); + if (camera->getGraphicsContext() != ea->getGraphicsContext()) + return false; + + const Viewport* viewport = camera->getViewport(); + double epsilon = 0.5; + if (!(x >= viewport->x() - epsilon + && x < viewport->x() + viewport->width() -1.0 + epsilon + && y >= viewport->y() - epsilon + && y < viewport->y() + viewport->height() -1.0 + epsilon)) + return false; + + Vec4d start(x, y, 0.0, 1.0); + Vec4d end(x, y, 1.0, 1.0); + Matrix windowMat = viewport->computeWindowMatrix(); + Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix() + * windowMat); + Matrix endPtMat; + if (!cinfo->farCamera.valid() || cinfo->farCamera->getNodeMask() == 0) + endPtMat = startPtMat; + else + endPtMat = Matrix::inverse(cinfo->farCamera->getProjectionMatrix() + * windowMat); + start = start * startPtMat; + start /= start.w(); + end = end * endPtMat; + end /= end.w(); + ref_ptr picker + = new LineSegmentIntersector(Intersector::VIEW, + Vec3d(start.x(), start.y(), start.z()), + Vec3d(end.x(), end.y(), end.z())); + osgUtil::IntersectionVisitor iv(picker.get()); + const_cast(camera)->accept(iv); + if (picker->containsIntersections()) { + intersections = picker->getIntersections(); + return true; + } + + return false; +} + bool computeIntersections(const CameraGroup* cgroup, const osgGA::GUIEventAdapter* ea, osgUtil::LineSegmentIntersector::Intersections& intersections) { - using osgUtil::Intersector; - using osgUtil::LineSegmentIntersector; - double x, y; - eventToWindowCoords(ea, x, y); + // 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->flags & CameraGroup::DO_INTERSECTION_TEST) == 0) + if (cinfo == guiCamera) continue; - const Camera* camera = cinfo->camera.get(); - if (camera->getGraphicsContext() != ea->getGraphicsContext()) - continue; - const Viewport* viewport = camera->getViewport(); - double epsilon = 0.5; - if (!(x >= viewport->x() - epsilon - && x < viewport->x() + viewport->width() -1.0 + epsilon - && y >= viewport->y() - epsilon - && y < viewport->y() + viewport->height() -1.0 + epsilon)) - continue; - Vec4d start(x, y, 0.0, 1.0); - Vec4d end(x, y, 1.0, 1.0); - Matrix windowMat = viewport->computeWindowMatrix(); - Matrix startPtMat = Matrix::inverse(camera->getProjectionMatrix() - * windowMat); - Matrix endPtMat; - if (!cinfo->farCamera.valid() || cinfo->farCamera->getNodeMask() == 0) - endPtMat = startPtMat; - else - endPtMat = Matrix::inverse(cinfo->farCamera->getProjectionMatrix() - * windowMat); - start = start * startPtMat; - start /= start.w(); - end = end * endPtMat; - end /= end.w(); - ref_ptr picker - = new LineSegmentIntersector(Intersector::VIEW, - Vec3d(start.x(), start.y(), start.z()), - Vec3d(end.x(), end.y(), end.z())); - osgUtil::IntersectionVisitor iv(picker.get()); - const_cast(camera)->accept(iv); - if (picker->containsIntersections()) { - intersections = picker->getIntersections(); + + if (computeCameraIntersection(cinfo, ea, intersections)) return true; - } else { - break; - } } + intersections.clear(); return false; } diff --git a/src/Main/CameraGroup.hxx b/src/Main/CameraGroup.hxx index a74895e46..177782d9f 100644 --- a/src/Main/CameraGroup.hxx +++ b/src/Main/CameraGroup.hxx @@ -214,6 +214,11 @@ public: * get aspect ratio of master camera's viewport */ double getMasterAspectRatio() const; + + /** + * find the GUI camera if one is defined + */ + const CameraInfo* getGUICamera() const; protected: CameraList _cameras; osg::ref_ptr _viewer; diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index bbe5dc9fd..3f624f6bb 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -514,5 +514,12 @@ void FGGlobals::set_warp_delta( long int 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 diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 297d9c576..01f728107 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -243,7 +243,7 @@ public: inline void set_ATC_mgr( FGATCMgr *a ) {ATC_mgr = a; } 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 void set_controls( FGControls *c ) { controls = c; } diff --git a/src/Main/main.cxx b/src/Main/main.cxx index 6e70ff894..5535060d5 100644 --- a/src/Main/main.cxx +++ b/src/Main/main.cxx @@ -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 @@ -349,7 +336,7 @@ static void fgIdleFunction ( void ) { //////////////////////////////////////////////////////////////////// globals->set_matlib( new SGMaterialLib ); 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. diff --git a/src/Main/renderer.cxx b/src/Main/renderer.cxx index 6e7e81d60..864f0abab 100644 --- a/src/Main/renderer.cxx +++ b/src/Main/renderer.cxx @@ -85,6 +85,7 @@ #include