]> git.mxchange.org Git - flightgear.git/blobdiff - src/Cockpit/panel.cxx
Set the key SGModelLib callback to make aircraft-dir OSG loading work.
[flightgear.git] / src / Cockpit / panel.cxx
index 35cff0df1720416e91bcd4b922abb7e445c19372..9c39626ee6bd1dd4250047400a198064a1169b36 100644 (file)
 //  WITHOUT ANY WARRANTY; without even the implied warranty of
 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 //  General Public License for more details.
-// 
+//
 //  You should have received a copy of the GNU General Public License
 //  along with this program; if not, write to the Free Software
-//  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+//  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 //
 //  $Id$
 
+//JVK
+// On 2D panels all instruments include light sources were in night displayed
+// with a red mask (instrument light). It is not correct for light sources
+// (bulbs). There is added new layer property "emissive" (boolean) (only for
+// textured layers).
+// If a layer has to shine set it in the "instrument_def_file.xml" inside the
+// <layer> tag by adding <emissive>true</emissive> tag. When omitted the default
+// value is for backward compatibility set to false.
+
 #ifdef HAVE_CONFIG_H
 #  include <config.h>
 #endif
 
-#ifdef HAVE_WINDOWS_H          
-#  include <windows.h>
-#endif
+#include "panel.hxx"
 
 #include <stdio.h>     // sprintf
 #include <string.h>
+#include <iostream>
 
-#include <simgear/compiler.h>
+#include <osg/CullFace>
+#include <osg/Depth>
+#include <osg/Material>
+#include <osg/TexEnv>
+#include <osg/PolygonOffset>
 
-#include SG_GLU_H
+#include <simgear/compiler.h>
 
-#include <plib/ssg.h>
 #include <plib/fnt.h>
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/misc/sg_path.hxx>
+#include <simgear/scene/model/model.hxx>
+#include <osg/GLU>
 
 #include <Main/globals.hxx>
 #include <Main/fg_props.hxx>
 #include <Main/viewmgr.hxx>
 #include <Time/light.hxx>
+#include <GUI/new_gui.hxx>     // FGFontCache
+#include <Main/viewer.hxx>
+#include <Instrumentation/dclgps.hxx>
 
 #include "hud.hxx"
-#include "panel.hxx"
+
 
 #define WIN_X 0
 #define WIN_Y 0
@@ -55,7 +71,7 @@
 // The number of polygon-offset "units" to place between layers.  In
 // principle, one is supposed to be enough.  In practice, I find that
 // my hardware/driver requires many more.
-#define POFF_UNITS 4
+#define POFF_UNITS 8
 
 ////////////////////////////////////////////////////////////////////////
 // Local functions.
@@ -82,47 +98,48 @@ get_aspect_adjust (int xsize, int ysize)
 bool
 fgPanelVisible ()
 {
-     if(globals->get_current_panel() == 0)
+     const FGPanel* current = globals->get_current_panel();
+     if (current == 0)
        return false;
-     if(globals->get_current_panel()->getVisibility() == 0)
+     if (current->getVisibility() == 0)
        return false;
-     if(globals->get_viewmgr()->get_current() != 0)
+     if (globals->get_viewmgr()->get_current() != 0)
        return false;
-     if(globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS != 0)
+     if (current->getAutohide() && globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS != 0)
        return false;
      return true;
 }
 
-
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of FGTextureManager.
 ////////////////////////////////////////////////////////////////////////
 
-map<string,ssgTexture *> FGTextureManager::_textureMap;
+map<string,osg::ref_ptr<osg::Texture2D> > FGTextureManager::_textureMap;
 
-ssgTexture *
-FGTextureManager::createTexture (const string &relativePath)
+osg::Texture2D*
+FGTextureManager::createTexture (const string &relativePath, bool staticTexture)
 {
-  ssgTexture * texture = _textureMap[relativePath];
+  osg::Texture2D* texture = _textureMap[relativePath].get();
   if (texture == 0) {
-    SG_LOG( SG_COCKPIT, SG_DEBUG,
-            "Texture " << relativePath << " does not yet exist" );
-    SGPath tpath(globals->get_fg_root());
-    tpath.append(relativePath);
-    texture = new ssgTexture((char *)tpath.c_str(), false, false);
+    SGPath tpath = globals->resolve_aircraft_path(relativePath);
+    texture = SGLoadTexture2D(staticTexture, tpath);
+
     _textureMap[relativePath] = texture;
-    if (_textureMap[relativePath] == 0
+    if (!_textureMap[relativePath].valid()
       SG_LOG( SG_COCKPIT, SG_ALERT, "Texture *still* doesn't exist" );
-    SG_LOG( SG_COCKPIT, SG_DEBUG, "Created texture " << relativePath
-            << " handle=" << texture->getHandle() );
+    SG_LOG( SG_COCKPIT, SG_DEBUG, "Created texture " << relativePath );
   }
 
   return texture;
 }
 
 
-
+void FGTextureManager::addTexture(const string &relativePath,
+                                  osg::Texture2D* texture)
+{
+    _textureMap[relativePath] = texture;
+}
 \f
 ////////////////////////////////////////////////////////////////////////
 // Implementation of FGCropped Texture.
@@ -150,13 +167,16 @@ FGCroppedTexture::~FGCroppedTexture ()
 }
 
 
-ssgTexture *
+osg::StateSet*
 FGCroppedTexture::getTexture ()
 {
   if (_texture == 0) {
-    _texture = FGTextureManager::createTexture(_path);
+    _texture = new osg::StateSet;
+    _texture->setTextureAttribute(0, FGTextureManager::createTexture(_path));
+    _texture->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
+    _texture->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE));
   }
-  return _texture;
+  return _texture.get();
 }
 
 
@@ -166,9 +186,8 @@ FGCroppedTexture::getTexture ()
 ////////////////////////////////////////////////////////////////////////
 
 static fntRenderer text_renderer;
-static fntTexFont *default_font = 0;
-static fntTexFont *led_font = 0;
 static sgVec4 panel_color;
+static sgVec4 emissive_panel_color = {1,1,1,1};
 
 /**
  * Constructor.
@@ -220,28 +239,6 @@ FGPanel::addInstrument (FGPanelInstrument * instrument)
 void
 FGPanel::init ()
 {
-    SGPath base_path;
-    char* envp = ::getenv( "FG_FONTS" );
-    if ( envp != NULL ) {
-        base_path.set( envp );
-    } else {
-        base_path.set( globals->get_fg_root() );
-       base_path.append( "Fonts" );
-    }
-
-    SGPath fntpath;
-
-    // Install the default font
-    fntpath = base_path;
-    fntpath.append( "typewriter.txf" );
-    default_font = new fntTexFont ;
-    default_font -> load ( (char *)fntpath.c_str() ) ;
-
-    // Install the LED font
-    fntpath = base_path;
-    fntpath.append( "led.txf" );
-    led_font = new fntTexFont ;
-    led_font -> load ( (char *)fntpath.c_str() ) ;
 }
 
 
@@ -267,11 +264,52 @@ FGPanel::unbind ()
 }
 
 
+void
+FGPanel::update (double dt)
+{
+  std::cout << "OSGFIXME" << std::endl;
+}
+
+void
+FGPanel::update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
+{
+                               // 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();
+  glLoadIdentity();
+  if ( _flipx->getBoolValue() ) {
+    gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */
+  } else {
+    gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */
+  }
+  
+  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 (double dt)
+FGPanel::update (osg::State& state)
 {
                                // Do nothing if the panel isn't visible.
     if ( !fgPanelVisible() ) {
@@ -284,9 +322,9 @@ FGPanel::update (double dt)
     float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(),
                                             _ysize_node->getIntValue());
     if (aspect_adjust <1.0)
-        update(WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H);
+        update(state, WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H);
     else
-        update(WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust));
+        update(state, WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust));
 }
 
 /**
@@ -307,90 +345,44 @@ void FGPanel::updateMouseDelay()
 
 
 void
-FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
-{
-                               // 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();
-
-#if 0
-  if (_jitter->getFloatValue() != 0.0) {
-    double a_x_pilot = current_aircraft.fdm_state->get_A_X_pilot();
-    double a_y_pilot = current_aircraft.fdm_state->get_A_Y_pilot();
-    double a_z_pilot = current_aircraft.fdm_state->get_A_Z_pilot();
-
-    double a_zx_pilot = a_z_pilot - a_x_pilot;
-    
-    int x_adjust = int(sqrt(fabs(a_y_pilot) * _jitter->getFloatValue())) *
-                  (a_y_pilot < 0 ? -1 : 1);
-    int y_adjust = int(sqrt(fabs(a_zx_pilot) * _jitter->getFloatValue())) *
-                  (a_zx_pilot < 0 ? -1 : 1);
-
-                               // adjustments in screen coordinates
-    x_offset += x_adjust;
-    y_offset += y_adjust;
-  }
-#endif
-
-  glMatrixMode(GL_PROJECTION);
-  glPushMatrix();
-  glLoadIdentity();
-  if ( _flipx->getBoolValue() ) {
-    gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */
-  } else {
-    gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */
-  }
-  
-  glMatrixMode(GL_MODELVIEW);
-  glPushMatrix();
-  glLoadIdentity();
-  
-  glTranslated(x_offset, y_offset, 0);
-  
-  draw();
-
-  glMatrixMode(GL_PROJECTION);
-  glPopMatrix();
-  glMatrixMode(GL_MODELVIEW);
-  glPopMatrix();
-
-  ssgForceBasicState();
-  glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
-}
-
-void
-FGPanel::draw()
+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.
-  glEnable(GL_POLYGON_OFFSET_FILL);
-  glPolygonOffset(-1, -POFF_UNITS);
-
-  // save some state
-  glPushAttrib( GL_COLOR_BUFFER_BIT | GL_ENABLE_BIT | GL_LIGHTING_BIT
-                | GL_TEXTURE_BIT | GL_PIXEL_MODE_BIT | GL_CULL_FACE 
-                | GL_DEPTH_BUFFER_BIT );
-
-  // Draw the background
-  glEnable(GL_TEXTURE_2D);
-  glDisable(GL_LIGHTING);
-  glEnable(GL_BLEND);
-  glEnable(GL_ALPHA_TEST);
-  glEnable(GL_COLOR_MATERIAL);
-  glEnable(GL_CULL_FACE);
-  glCullFace(GL_BACK);
-  if( _enable_depth_test )
-      glDepthFunc(GL_ALWAYS);
+  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
-    glDisable(GL_DEPTH_TEST);
+    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());
+  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;
@@ -398,68 +390,138 @@ FGPanel::draw()
   }
   glColor4fv( panel_color );
   if (_bg != 0) {
-    glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
-    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-    // glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-    glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+    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);
+
   } else {
     for (int i = 0; i < 4; i ++) {
       // top row of textures...(1,3,5,7)
-      glBindTexture(GL_TEXTURE_2D, _mbg[i*2]->getHandle());
-      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+      state.pushStateSet(_mbg[i*2].get());
+      state.apply();
+      state.setActiveTextureUnit(0);
+      state.setClientActiveTextureUnit(0);
+
       glBegin(GL_POLYGON);
       glTexCoord2f(0.0, 0.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y + (_height/2));
       glTexCoord2f(1.0, 0.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y + (_height/2));
       glTexCoord2f(1.0, 1.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y + _height);
       glTexCoord2f(0.0, 1.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y + _height);
       glEnd();
+      state.popStateSet();
+      state.apply();
+      state.setActiveTextureUnit(0);
+      state.setClientActiveTextureUnit(0);
+
       // bottom row of textures...(2,4,6,8)
-      glBindTexture(GL_TEXTURE_2D, _mbg[(i*2)+1]->getHandle());
-      glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
+      state.pushStateSet(_mbg[i*2+1].get());
+      state.apply();
+      state.setActiveTextureUnit(0);
+      state.setClientActiveTextureUnit(0);
+
       glBegin(GL_POLYGON);
       glTexCoord2f(0.0, 0.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y);
       glTexCoord2f(1.0, 0.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y);
       glTexCoord2f(1.0, 1.0); glVertex2f(WIN_X + (_width/4) * (i+1), WIN_Y + (_height/2));
       glTexCoord2f(0.0, 1.0); glVertex2f(WIN_X + (_width/4) * i, WIN_Y + (_height/2));
       glEnd();
+      state.popStateSet();
+      state.apply();
+      state.setActiveTextureUnit(0);
+      state.setClientActiveTextureUnit(0);
+
     }
   }
 
   // Draw the instruments.
+  // Syd Adams: added instrument clipping
   instrument_list_type::const_iterator current = _instruments.begin();
   instrument_list_type::const_iterator end = _instruments.end();
 
+  GLdouble blx[4]={1.0,0.0,0.0,0.0};
+  GLdouble bly[4]={0.0,1.0,0.0,0.0};
+  GLdouble urx[4]={-1.0,0.0,0.0,0.0};
+  GLdouble ury[4]={0.0,-1.0,0.0,0.0};
+
   for ( ; current != end; current++) {
     FGPanelInstrument * instr = *current;
     glPushMatrix();
     glTranslated(instr->getXPos(), instr->getYPos(), 0);
-    instr->draw();
+
+    int ix= instr->getWidth();
+    int iy= instr->getHeight();
+    glPushMatrix();
+    glTranslated(-ix/2,-iy/2,0);
+    glClipPlane(GL_CLIP_PLANE0,blx);
+    glClipPlane(GL_CLIP_PLANE1,bly);
+    glEnable(GL_CLIP_PLANE0);
+    glEnable(GL_CLIP_PLANE1);
+
+    glTranslated(ix,iy,0);
+    glClipPlane(GL_CLIP_PLANE2,urx);
+    glClipPlane(GL_CLIP_PLANE3,ury);
+    glEnable(GL_CLIP_PLANE2);
+    glEnable(GL_CLIP_PLANE3);
+    glPopMatrix();
+    instr->draw(state);
+
     glPopMatrix();
   }
 
+  glDisable(GL_CLIP_PLANE0);
+  glDisable(GL_CLIP_PLANE1);
+  glDisable(GL_CLIP_PLANE2);
+  glDisable(GL_CLIP_PLANE3);
+
+  state.popStateSet();
+  state.apply();
+  state.setActiveTextureUnit(0);
+  state.setClientActiveTextureUnit(0);
+
+
   // 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") ) {
-    glDisable(GL_TEXTURE_2D);
+    static osg::ref_ptr<osg::StateSet> hotspotStateSet;
+    if (!hotspotStateSet.valid()) {
+      hotspotStateSet = new osg::StateSet;
+      hotspotStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF);
+      hotspotStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
+    }
+
+    state.pushStateSet(hotspotStateSet.get());
+    state.apply();
+    state.setActiveTextureUnit(0);
+    state.setClientActiveTextureUnit(0);
+
+
+    glPushAttrib(GL_ENABLE_BIT);
+    glDisable(GL_COLOR_MATERIAL);
     glColor3f(1, 1, 0);
     
     for ( unsigned int i = 0; i < _instruments.size(); i++ )
-      _instruments[i]->drawHotspots();
-  }
+      _instruments[i]->drawHotspots(state);
 
+    glPopAttrib();
 
-  // restore some original state
-  if( _enable_depth_test )
-    glDepthFunc(GL_LESS);
-  glPopAttrib();
-  glPolygonOffset(0, 0);
-  glDisable(GL_POLYGON_OFFSET_FILL);
+    state.popStateSet();
+    state.apply();
+    state.setActiveTextureUnit(0);
+    state.setClientActiveTextureUnit(0);
+
+  }
 }
 
 /**
@@ -486,19 +548,28 @@ FGPanel::getVisibility () const
  * Set the panel's background texture.
  */
 void
-FGPanel::setBackground (ssgTexture * texture)
+FGPanel::setBackground (osg::Texture2D* texture)
 {
-  _bg = texture;
+  osg::StateSet* stateSet = new osg::StateSet;
+  stateSet->setTextureAttribute(0, texture);
+  stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
+  stateSet->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE));
+  _bg = stateSet;
 }
 
 /**
  * Set the panel's multiple background textures.
  */
 void
-FGPanel::setMultiBackground (ssgTexture * texture, int idx)
+FGPanel::setMultiBackground (osg::Texture2D* texture, int idx)
 {
   _bg = 0;
-  _mbg[idx] = texture;
+
+  osg::StateSet* stateSet = new osg::StateSet;
+  stateSet->setTextureAttribute(0, texture);
+  stateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::ON);
+  stateSet->setTextureAttribute(0, new osg::TexEnv(osg::TexEnv::MODULATE));
+  _mbg[idx] = stateSet;
 }
 
 /**
@@ -619,7 +690,7 @@ FGPanelAction::~FGPanelAction ()
 }
 
 void
-FGPanelAction::addBinding (FGBinding * binding, int updown)
+FGPanelAction::addBinding (SGBinding * binding, int updown)
 {
   _bindings[updown].push_back(binding);
 }
@@ -686,7 +757,7 @@ FGPanelInstrument::~FGPanelInstrument ()
 }
 
 void
-FGPanelInstrument::drawHotspots()
+FGPanelInstrument::drawHotspots(osg::State& state)
 {
   for ( unsigned int i = 0; i < _actions.size(); i++ ) {
     FGPanelAction* a = _actions[i];
@@ -784,14 +855,14 @@ FGLayeredInstrument::~FGLayeredInstrument ()
 }
 
 void
-FGLayeredInstrument::draw ()
+FGLayeredInstrument::draw (osg::State& state)
 {
   if (!test())
     return;
   
   for (int i = 0; i < (int)_layers.size(); i++) {
     glPushMatrix();
-    _layers[i]->draw();
+    _layers[i]->draw(state);
     glPopMatrix();
   }
 }
@@ -841,9 +912,9 @@ FGSpecialInstrument::~FGSpecialInstrument ()
 }
 
 void
-FGSpecialInstrument::draw ()
+FGSpecialInstrument::draw (osg::State& state)
 {
-  complex->draw();
+  complex->draw(state);
 }
 
 
@@ -886,7 +957,7 @@ FGInstrumentLayer::transform () const
        val = t->max;
       }
 
-      if(t->table==0) {
+      if (t->table==0) {
        val = val * t->factor + t->offset;
       } else {
        val = t->table->interpolate(val) * t->factor + t->offset;
@@ -931,13 +1002,13 @@ FGGroupLayer::~FGGroupLayer ()
 }
 
 void
-FGGroupLayer::draw ()
+FGGroupLayer::draw (osg::State& state)
 {
   if (test()) {
     transform();
     int nLayers = _layers.size();
     for (int i = 0; i < nLayers; i++)
-      _layers[i]->draw();
+      _layers[i]->draw(state);
   }
 }
 
@@ -955,7 +1026,8 @@ FGGroupLayer::addLayer (FGInstrumentLayer * layer)
 
 
 FGTexturedLayer::FGTexturedLayer (const FGCroppedTexture &texture, int w, int h)
-  : FGInstrumentLayer(w, h)
+  : FGInstrumentLayer(w, h),
+    _emissive(false)
 {
   setTexture(texture);
 }
@@ -967,25 +1039,38 @@ FGTexturedLayer::~FGTexturedLayer ()
 
 
 void
-FGTexturedLayer::draw ()
+FGTexturedLayer::draw (osg::State& state)
 {
   if (test()) {
     int w2 = _w / 2;
     int h2 = _h / 2;
     
     transform();
-    glBindTexture(GL_TEXTURE_2D, _texture.getTexture()->getHandle());
+    state.pushStateSet(_texture.getTexture());
+    state.apply();
+    state.setActiveTextureUnit(0);
+    state.setClientActiveTextureUnit(0);
+
     glBegin(GL_POLYGON);
-    
+
+    if (_emissive) {
+      glColor4fv( emissive_panel_color );
+    } else {
                                // From Curt: turn on the panel
                                // lights after sundown.
-    glColor4fv( panel_color );
+      glColor4fv( panel_color );
+    }
 
     glTexCoord2f(_texture.getMinX(), _texture.getMinY()); glVertex2f(-w2, -h2);
     glTexCoord2f(_texture.getMaxX(), _texture.getMinY()); glVertex2f(w2, -h2);
     glTexCoord2f(_texture.getMaxX(), _texture.getMaxY()); glVertex2f(w2, h2);
     glTexCoord2f(_texture.getMinX(), _texture.getMaxY()); glVertex2f(-w2, h2);
     glEnd();
+    state.popStateSet();
+    state.apply();
+    state.setActiveTextureUnit(0);
+    state.setClientActiveTextureUnit(0);
+
   }
 }
 
@@ -996,7 +1081,7 @@ FGTexturedLayer::draw ()
 ////////////////////////////////////////////////////////////////////////
 
 FGTextLayer::FGTextLayer (int w, int h)
-  : FGInstrumentLayer(w, h), _pointSize(14.0), _font_name("default")
+  : FGInstrumentLayer(w, h), _pointSize(14.0), _font_name("Helvetica.txf")
 {
   _then.stamp();
   _color[0] = _color[1] = _color[2] = 0.0;
@@ -1013,22 +1098,26 @@ FGTextLayer::~FGTextLayer ()
 }
 
 void
-FGTextLayer::draw ()
+FGTextLayer::draw (osg::State& state)
 {
   if (test()) {
     glColor4fv(_color);
     transform();
-    if ( _font_name == "led" && led_font != 0) {
-       text_renderer.setFont(led_font);
-    } else {
-       text_renderer.setFont(guiFntHandle);
+
+    FGFontCache *fc = globals->get_fontcache();
+    fntFont* font = fc->getTexFont(_font_name.c_str());
+    if (!font) {
+        return; // don't crash on missing fonts
     }
+    
+    text_renderer.setFont(font);
+
     text_renderer.setPointSize(_pointSize);
     text_renderer.begin();
     text_renderer.start3f(0, 0, 0);
 
     _now.stamp();
-    long diff = _now - _then;
+    double diff = (_now - _then).toUSecs();
 
     if (diff > 100000 || diff < 0 ) {
       // ( diff < 0 ) is a sanity check and indicates our time stamp
@@ -1081,7 +1170,12 @@ FGTextLayer::setPointSize (float size)
 void
 FGTextLayer::setFontName(const string &name)
 {
-  _font_name = name;
+  _font_name = name + ".txf";
+  FGFontCache *fc = globals->get_fontcache();
+  fntFont* font = fc->getTexFont(_font_name.c_str());
+  if (!font) {
+      SG_LOG(SG_GENERAL, SG_WARN, "unable to find font:" << name);
+  }
 }
 
 
@@ -1167,14 +1261,14 @@ FGSwitchLayer::FGSwitchLayer ()
 }
 
 void
-FGSwitchLayer::draw ()
+FGSwitchLayer::draw (osg::State& state)
 {
   if (test()) {
     transform();
     int nLayers = _layers.size();
     for (int i = 0; i < nLayers; i++) {
       if (_layers[i]->test()) {
-          _layers[i]->draw();
+          _layers[i]->draw(state);
           return;
       }
     }
@@ -1183,6 +1277,3 @@ FGSwitchLayer::draw ()
 
 \f
 // end of panel.cxx
-
-
-