+
+ 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));
+}
+
+/**
+ * Handle repeatable mouse events. Called from update() and from
+ * fgUpdate3DPanels(). This functionality needs to move into the
+ * input subsystem. Counting a tick every two frames is clumsy...
+ */
+void FGPanel::updateMouseDelay()
+{
+ if (_mouseDown) {
+ _mouseDelay--;
+ if (_mouseDelay < 0) {
+ _mouseInstrument->doMouseAction(_mouseButton, 0, _mouseX, _mouseY);
+ _mouseDelay = 2;
+ }
+ }
+}
+
+
+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.
+ static osg::ref_ptr<osg::StateSet> panelStateSet;
+ if (!panelStateSet.valid()) {
+ panelStateSet = new osg::StateSet;
+ panelStateSet->setAttributeAndModes(new osg::PolygonOffset(-1, -POFF_UNITS));
+ panelStateSet->setTextureAttribute(0, new osg::TexEnv);
+
+ // Draw the background
+ panelStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
+ 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));
+ material->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(1, 1, 1, 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));
+ 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));
+ }
+ if ( _enable_depth_test )
+ panelStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
+ else
+ panelStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
+ state.pushStateSet(panelStateSet.get());
+ state.apply();
+ state.setActiveTextureUnit(0);
+ state.setClientActiveTextureUnit(0);
+
+ FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
+ sgCopyVec4( panel_color, l->scene_diffuse().data());
+ if ( fgGetDouble("/systems/electrical/outputs/instrument-lights") > 1.0 ) {
+ if ( panel_color[0] < 0.7 ) panel_color[0] = 0.7;
+ if ( panel_color[1] < 0.2 ) panel_color[1] = 0.2;
+ if ( panel_color[2] < 0.2 ) panel_color[2] = 0.2;
+ }
+ glColor4fv( panel_color );
+ if (_bg != 0) {
+ state.pushStateSet(_bg.get());
+ state.apply();
+ state.setActiveTextureUnit(0);
+ state.setClientActiveTextureUnit(0);
+
+ glBegin(GL_POLYGON);
+ glTexCoord2f(0.0, 0.0); glVertex2f(WIN_X, WIN_Y);
+ glTexCoord2f(1.0, 0.0); glVertex2f(WIN_X + _width, WIN_Y);
+ glTexCoord2f(1.0, 1.0); glVertex2f(WIN_X + _width, WIN_Y + _height);
+ glTexCoord2f(0.0, 1.0); glVertex2f(WIN_X, WIN_Y + _height);
+ glEnd();
+ state.popStateSet();
+ state.apply();
+ state.setActiveTextureUnit(0);
+ state.setClientActiveTextureUnit(0);