Andy Ross writes:
> OK, I *finally* got a chance this weekend to sit down and crank on
> FlightGear code.  It's been a while.  Attached are three patches for
> review.  Complete files for Curt are available at:
> http://www.plausible.org/fgfs-andy-2002Oct26.tar.gz.
> 
> The first is [ bleep :-) ]
> 
> The second adds angular rate information to the FDM output properties.
> I needed this to get autostabilization working on the Harrier model
> (more on this soon in a post to the flightmodel list).  Very
> trivial.

This is added.

> The biggest and coolest patch ...

Andy, very cool, almost works reliably.  Definitely a huge addition to
the 3d panels, great work!

I did notice on rare occasion some areas were getting mismapped.
I.e. I couldn't click on the wing leveler, but I could click the other
autopilot buttons.  Another time I was trying to switch the DME
between nav1 and nav2 and my right engine died ... looks like the
magneto switch mistakenly grabbed the click.  But most of the time the
stuff works great!

> ... adds mouse sensitivity to the 3D
> cockpits, so we can finally work the radios.  This ended up requiring
> significant modifications outside of the 3D cockpit code.  Stuff folks
> will want to look at:
> 
> + The list of all "3D" cockpits is stored statically in the
>    panelnode.cxx file.  This is clumsy, and won't migrate well to a
>    multiple-aircraft feature.  Really, there should be a per-model list
>    of 3D panels, but I couldn't find a clean place to put this.  The
>    only handle you get back after parsing a model is a generic ssg
>    node, to which I obviously can't add panel-specific methods.
> 
> + The aircraft model is parsed *very* early in the initialization
>    order.  Earlier, in fact, than the static list of allowable command
>    bindings is built in fgInitCommands().  This is bad, as it means
>    that mouse bindings on the instruments can't work yet.  I moved the
>    call to fgInitCommands, but someone should look carefully to see
>    that I picked the right place.  There's a lot of initialization
>    code, and I got a little lost in there... :)
> 
> + I added yet another "update" hook to the fgRenderFrame routine to
>    hook the updates for the 3D panels.  This is only required for
>    "mouse press delay", and it's a fairly clumsy mechanism based on
>    frame rate instead of real time.  There appears to be delay handling
>    already in place in the Input stuff, and there's a discussion going
>    on about different mouse behavior right now.  Maybe this is a good
>    time to unify these two (now three) approaches?
> 
> Anyway, try it out and see what breaks.
> 
> Andy
> 
> -- 
> Andrew J. Ross                NextBus Information Systems
> Senior Software Engineer      Emeryville, CA
> [EMAIL PROTECTED]              http://www.nextbus.com
> "Men go crazy in conflagrations.  They only get better one by one."
>   - Sting (misquoted)
> Index: src/Cockpit/hud.cxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Cockpit/hud.cxx,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 hud.cxx
> --- src/Cockpit/hud.cxx       10 Sep 2002 01:13:59 -0000      1.1.1.1
> +++ src/Cockpit/hud.cxx       26 Oct 2002 22:05:24 -0000
> @@ -171,6 +171,8 @@
>  static instr_item * readCard ( const SGPropertyNode * node);
>  static instr_item * readLabel( const SGPropertyNode * node);
>  static instr_item * readTBI( const SGPropertyNode * node);
> +static void drawHUD();
> +static void fgUpdateHUDVirtual();
>  //$$$ end   - added, Neetha, 28 Nov 2k
>  
>  void fgHUDalphaInit( void );
> @@ -310,6 +312,11 @@
>      nadir                    = node->getIntValue("nadir");  //suma
>      hat                              = node->getIntValue("hat");
>  
> +    // The factor assumes a base of 55 degrees per 640 pixels.
> +    // Invert to convert the "compression" factor to a
> +    // pixels-per-degree number.
> +    if(factor == 0) factor = 1;
> +    factor = (640./55.) / factor;
>  
>      SG_LOG(SG_INPUT, SG_INFO, "Done reading instrument " << name);
>       
> @@ -1038,7 +1045,12 @@
>  // all C++.
>  //
>  void fgUpdateHUD( void ) {
> -     
> +
> +    if(1) {
> +        fgUpdateHUDVirtual();
> +        return;
> +    }
> +    
>      static const float normal_aspect = float(640) / float(480);
>      // note: aspect_ratio is Y/X
>      float current_aspect = 1.0f/globals->get_current_view()->get_aspect_ratio();
> @@ -1053,9 +1065,78 @@
>      }
>  }
>  
> +void fgUpdateHUDVirtual()
> +{
> +    FGViewer* view = globals->get_current_view();
> +
> +    // Standard fgfs projection, with essentially meaningless clip
> +    // planes (we'll map the whole HUD plane to z=-1)
> +    glMatrixMode(GL_PROJECTION);
> +    glPushMatrix();
> +    glLoadIdentity();
> +    gluPerspective(view->get_v_fov(), 1/view->get_aspect_ratio(), 0.1, 10);
> +
> +    glMatrixMode(GL_MODELVIEW);
> +    glPushMatrix();
> +    glLoadIdentity();
> +
> +    // Standard fgfs view direction computation
> +    float lookat[3];
> +    lookat[0] = -sin(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
> +    lookat[1] = tan(SG_DEGREES_TO_RADIANS * view->getPitchOffset_deg());
> +    lookat[2] = -cos(SG_DEGREES_TO_RADIANS * view->getHeadingOffset_deg());
> +    if(fabs(lookat[1]) > 9999) lookat[1] = 9999; // FPU sanity
> +    gluLookAt(0, 0, 0, lookat[0], lookat[1], lookat[2], 0, 1, 0);
> +
> +    // Map the -1:1 square to a 55.0x41.25 degree wide patch at z=1.
> +    // This is the default fgfs field of view, which the HUD files are
> +    // written to assume.
> +    float dx = 0.52056705; // tan(55/2)
> +    float dy = dx * 0.75;  // assumes 4:3 aspect ratio
> +    float m[16];
> +    m[0] = dx; m[4] =  0; m[ 8] = 0; m[12] = 0;
> +    m[1] =  0; m[5] = dy; m[ 9] = 0; m[13] = 0;
> +    m[2] =  0; m[6] =  0; m[10] = 1; m[14] = 0;
> +    m[3] =  0; m[7] =  0; m[11] = 0; m[15] = 1;
> +    glMultMatrixf(m);
> +    
> +    // Convert the 640x480 "HUD standard" coordinate space to a square
> +    // about the origin in the range [-1:1] at depth of -1
> +    glScalef(1./320, 1./240, 1);
> +    glTranslatef(-320, -240, -1);
> +    
> +    // Do the deed
> +    drawHUD();
> +
> +    // Clean up our mess
> +    glMatrixMode(GL_PROJECTION);
> +    glPopMatrix();
> +    glMatrixMode(GL_MODELVIEW);
> +    glPopMatrix();
> +}
> +
>  void fgUpdateHUD( GLfloat x_start, GLfloat y_start,
>                    GLfloat x_end, GLfloat y_end )
>  {
> +    glMatrixMode(GL_PROJECTION);
> +    glPushMatrix();
> +    glLoadIdentity();
> +    gluOrtho2D(x_start, x_end, y_start, y_end);
> +
> +    glMatrixMode(GL_MODELVIEW);
> +    glPushMatrix();
> +    glLoadIdentity();
> +
> +    drawHUD();
> +
> +    glMatrixMode(GL_PROJECTION);
> +    glPopMatrix();
> +    glMatrixMode(GL_MODELVIEW);
> +    glPopMatrix();
> +}
> +
> +void drawHUD()
> +{
>      int brightness;
>      // int day_night_sw = current_aircraft.controls->day_night_switch;
>      int day_night_sw = global_day_night_switch;
> @@ -1075,15 +1156,6 @@
>      brightness = pHUDInstr->get_brightness();
>      // brightness = HUD_deque.at(0)->get_brightness();
>  
> -    glMatrixMode(GL_PROJECTION);
> -    glPushMatrix();
> -
> -    glLoadIdentity();
> -    gluOrtho2D(x_start, x_end, y_start, y_end);
> -    glMatrixMode(GL_MODELVIEW);
> -    glPushMatrix();
> -    glLoadIdentity();
> -
>      glDisable(GL_DEPTH_TEST);
>      glDisable(GL_LIGHTING);
>  
> @@ -1235,9 +1307,5 @@
>  
>      glEnable(GL_DEPTH_TEST);
>      glEnable(GL_LIGHTING);
> -    glMatrixMode(GL_PROJECTION);
> -    glPopMatrix();
> -    glMatrixMode(GL_MODELVIEW);
> -    glPopMatrix();
>  }
>  
> Index: src/FDM/flight.cxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/FDM/flight.cxx,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 flight.cxx
> --- src/FDM/flight.cxx        10 Sep 2002 01:14:00 -0000      1.1.1.1
> +++ src/FDM/flight.cxx        26 Oct 2002 22:03:38 -0000
> @@ -323,6 +323,15 @@
>       &FGInterface::set_Psi_deg);
>    fgSetArchivable("/orientation/heading-deg");
>  
> +  // Body-axis "euler rates" (rotation speed, but in a funny
> +  // representation).
> +  fgTie("/orientation/roll-rate-degps", this,
> +     &FGInterface::get_Phi_dot_degps);
> +  fgTie("/orientation/pitch-rate-degps", this,
> +     &FGInterface::get_Theta_dot_degps);
> +  fgTie("/orientation/yaw-rate-degps", this,
> +     &FGInterface::get_Psi_dot_degps);
> +
>                               // Calibrated airspeed
>    fgTie("/velocities/airspeed-kt", this,
>       &FGInterface::get_V_calibrated_kts,
> Index: src/FDM/flight.hxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/FDM/flight.hxx,v
> retrieving revision 1.2
> diff -u -r1.2 flight.hxx
> --- src/FDM/flight.hxx        28 Sep 2002 04:01:34 -0000      1.2
> +++ src/FDM/flight.hxx        26 Oct 2002 22:03:40 -0000
> @@ -839,6 +839,9 @@
>      inline double get_Phi_dot() const { return euler_rates_v[0]; }
>      inline double get_Theta_dot() const { return euler_rates_v[1]; }
>      inline double get_Psi_dot() const { return euler_rates_v[2]; }
> +    inline double get_Phi_dot_degps() const { return euler_rates_v[0] * 
>SGD_RADIANS_TO_DEGREES; }
> +    inline double get_Theta_dot_degps() const { return euler_rates_v[1] * 
>SGD_RADIANS_TO_DEGREES; }
> +    inline double get_Psi_dot_degps() const { return euler_rates_v[2] * 
>SGD_RADIANS_TO_DEGREES; }
>  
>      // inline double * get_Geocentric_rates_v() { return geocentric_rates_v; }
>      inline double get_Latitude_dot() const { return geocentric_rates_v[0]; }
> ? src/Main/main.cxx-save
> Index: src/Cockpit/panel.cxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Cockpit/panel.cxx,v
> retrieving revision 1.2
> diff -u -r1.2 panel.cxx
> --- src/Cockpit/panel.cxx     28 Sep 2002 03:57:37 -0000      1.2
> +++ src/Cockpit/panel.cxx     27 Oct 2002 04:31:56 -0000
> @@ -279,14 +279,7 @@
>          return;
>      }
>  
> -                             // If the mouse is down, do something
> -    if (_mouseDown) {
> -        _mouseDelay--;
> -        if (_mouseDelay < 0) {
> -            _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
> -            _mouseDelay = 2;
> -        }
> -    }
> +    updateMouseDelay();
>  
>                               // Now, draw the panel
>      float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(),
> @@ -297,6 +290,22 @@
>          update(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, _mouseX, _mouseY);
> +            _mouseDelay = 2;
> +        }
> +    }
> +}
> +
>  
>  void
>  FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
> @@ -494,38 +503,21 @@
>  }
>  
>  /**
> - * Perform a mouse action.
> + * Handle a mouse action in panel-local (not screen) coordinates.
> + * Used by the 3D panel code in Model/panelnode.cxx, in situations
> + * where the panel doesn't control its own screen location.
>   */
>  bool
> -FGPanel::doMouseAction (int button, int updown, int x, int y)
> +FGPanel::doLocalMouseAction(int button, int updown, int x, int y)
>  {
> -                             // FIXME: this same code appears in update()
> -  int xsize = _xsize_node->getIntValue();
> -  int ysize = _ysize_node->getIntValue();
> -  float aspect_adjust = get_aspect_adjust(xsize, ysize);
> -
> -                             // Note a released button and return
> -  // cerr << "Doing mouse action\n";
> +  // Note a released button and return
>    if (updown == 1) {
>      _mouseDown = false;
>      _mouseInstrument = 0;
>      return false;
>    }
>  
> -                             // Scale for the real window size.
> -  if (aspect_adjust < 1.0) {
> -    x = int(((float)x / xsize) * WIN_W * aspect_adjust);
> -    y = int(WIN_H - ((float(y) / ysize) * WIN_H));
> -  } else {
> -    x = int(((float)x / xsize) * WIN_W);
> -    y = int((WIN_H - ((float(y) / ysize) * WIN_H)) / aspect_adjust);
> -  }
> -
> -                             // Adjust for offsets.
> -  x -= _x_offset;
> -  y -= _y_offset;
> -
> -                             // Search for a matching instrument.
> +  // Search for a matching instrument.
>    for (int i = 0; i < (int)_instruments.size(); i++) {
>      FGPanelInstrument *inst = _instruments[i];
>      int ix = inst->getXPos();
> @@ -539,12 +531,41 @@
>        _mouseButton = button;
>        _mouseX = x - ix;
>        _mouseY = y - iy;
> -                             // Always do the action once.
> +      // Always do the action once.
>        return _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
>      }
>    }
>    return false;
>  }
> +
> +/**
> + * Perform a mouse action.
> + */
> +bool
> +FGPanel::doMouseAction (int button, int updown, int x, int y)
> +{
> +                             // FIXME: this same code appears in update()
> +  int xsize = _xsize_node->getIntValue();
> +  int ysize = _ysize_node->getIntValue();
> +  float aspect_adjust = get_aspect_adjust(xsize, ysize);
> +
> +                             // Scale for the real window size.
> +  if (aspect_adjust < 1.0) {
> +    x = int(((float)x / xsize) * WIN_W * aspect_adjust);
> +    y = int(WIN_H - ((float(y) / ysize) * WIN_H));
> +  } else {
> +    x = int(((float)x / xsize) * WIN_W);
> +    y = int((WIN_H - ((float(y) / ysize) * WIN_H)) / aspect_adjust);
> +  }
> +
> +                             // Adjust for offsets.
> +  x -= _x_offset;
> +  y -= _y_offset;
> +
> +  // Having fixed up the coordinates, fall through to the local
> +  // coordinate handler.
> +  doLocalMouseAction(button, updown, x, y);
> +} 
>  
>  
>  
> Index: src/Cockpit/panel.hxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Cockpit/panel.hxx,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 panel.hxx
> --- src/Cockpit/panel.hxx     10 Sep 2002 01:14:00 -0000      1.1.1.1
> +++ src/Cockpit/panel.hxx     27 Oct 2002 04:31:57 -0000
> @@ -145,6 +145,8 @@
>    virtual void update (double dt);
>    virtual void update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh);
>  
> +  virtual void updateMouseDelay();
> +
>                               // transfer pointer ownership!!!
>    virtual void addInstrument (FGPanelInstrument * instrument);
>  
> @@ -180,6 +182,7 @@
>  
>                               // Handle a mouse click.
>    virtual bool doMouseAction (int button, int updown, int x, int y);
> +  virtual bool doLocalMouseAction(int button, int updown, int x, int y);
>  
>  private:
>    void setupVirtualCockpit();
> Index: src/Input/input.cxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Input/input.cxx,v
> retrieving revision 1.3
> diff -u -r1.3 input.cxx
> --- src/Input/input.cxx       26 Oct 2002 01:19:23 -0000      1.3
> +++ src/Input/input.cxx       27 Oct 2002 04:32:44 -0000
> @@ -54,6 +54,7 @@
>  #include <Cockpit/panel.hxx>
>  #include <Cockpit/panel_io.hxx>
>  #include <GUI/gui.h>
> +#include <Model/panelnode.hxx>
>  
>  #include <Main/globals.hxx>
>  #include <Main/fg_props.hxx>
> @@ -378,7 +379,9 @@
>      if (puMouse(b, updown, x, y))
>        return;
>      else if ((current_panel != 0) &&
> -          current_panel->doMouseAction(b, updown, x, y))
> +             current_panel->doMouseAction(b, updown, x, y))
> +      return;
> +    else if (fgHandle3DPanelMouseEvent(b, updown, x, y))
>        return;
>    }
>  
> Index: src/Main/fg_init.cxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Main/fg_init.cxx,v
> retrieving revision 1.14
> diff -u -r1.14 fg_init.cxx
> --- src/Main/fg_init.cxx      10 Oct 2002 18:39:52 -0000      1.14
> +++ src/Main/fg_init.cxx      27 Oct 2002 04:32:46 -0000
> @@ -1125,12 +1125,6 @@
>          globals->get_AI_mgr()->init();
>      }
>  
> -    ////////////////////////////////////////////////////////////////////
> -    // Initialize the built-in commands.
> -    ////////////////////////////////////////////////////////////////////
> -    fgInitCommands();
> -
> -
>  #ifdef ENABLE_AUDIO_SUPPORT
>      ////////////////////////////////////////////////////////////////////
>      // Initialize the sound subsystem.
> Index: src/Main/main.cxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Main/main.cxx,v
> retrieving revision 1.33
> diff -u -r1.33 main.cxx
> --- src/Main/main.cxx 24 Oct 2002 14:05:40 -0000      1.33
> +++ src/Main/main.cxx 27 Oct 2002 04:32:49 -0000
> @@ -107,6 +107,7 @@
>  #include <Model/model.hxx>
>  #include <Model/modelmgr.hxx>
>  #include <Main/location.hxx>
> +#include <Model/panelnode.hxx>
>  #ifdef FG_NETWORK_OLK
>  #include <NetworkOLK/network.h>
>  #endif
> @@ -133,6 +134,7 @@
>  #include <FDM/ADA.hxx>
>  #include <Scenery/tileentry.hxx>
>  
> +#include "fg_commands.hxx"
>  
>  // #define FG_EXPERIMENTAL_LIGHTING
>  #ifdef FG_EXPERIMENTAL_LIGHTING
> @@ -840,6 +842,7 @@
>       if ( current_panel != NULL ) {
>           current_panel->update(delta_time_sec);
>       }
> +        fgUpdate3DPanels();
>  
>       // We can do translucent menus, so why not. :-)
>       menus->apply();
> @@ -1636,6 +1639,11 @@
>      globals->set_scenery( new FGScenery );
>      globals->get_scenery()->init();
>      globals->get_scenery()->bind();
> +
> +    ////////////////////////////////////////////////////////////////////
> +    // Initialize the property-based built-in commands
> +    ////////////////////////////////////////////////////////////////////
> +    fgInitCommands();
>  
>      ////////////////////////////////////////////////////////////////////
>      // Initialize the general model subsystem.
> Index: src/Model/panelnode.cxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Model/panelnode.cxx,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 panelnode.cxx
> --- src/Model/panelnode.cxx   10 Sep 2002 01:14:08 -0000      1.1.1.1
> +++ src/Model/panelnode.cxx   27 Oct 2002 04:32:49 -0000
> @@ -1,3 +1,8 @@
> +#include <vector>
> +
> +#include <GL/gl.h>
> +#include <plib/sg.h>
> +
>  #ifdef HAVE_CONFIG_H
>  #  include <config.h>
>  #endif
> @@ -5,15 +10,43 @@
>  #include <Main/fg_props.hxx>
>  #include <Cockpit/panel.hxx>
>  #include <Cockpit/panel_io.hxx>
> -#include <GL/gl.h>
>  #include "panelnode.hxx"
>  
> +// Static (!) handling for all 3D panels in the program.  Very
> +// clumsy.  Replace with per-aircraft handling.
> +vector<FGPanelNode*> all_3d_panels;
> +bool fgHandle3DPanelMouseEvent(int button, int updown, int x, int y)
> +{
> +    for(int i=0; i<all_3d_panels.size(); i++)
> +        if(all_3d_panels[i]->doMouseAction(button, updown, x, y))
> +            return true;
> +    return false;
> +}
> +
> +void fgUpdate3DPanels()
> +{
> +    for(int i=0; i<all_3d_panels.size(); i++)
> +        all_3d_panels[i]->getPanel()->updateMouseDelay();
> +}
> +
>  FGPanelNode::FGPanelNode(SGPropertyNode* props)
>  {
>      // Make an FGPanel object.  But *don't* call init() or bind() on
>      // it -- those methods touch static state.
>      _panel = fgReadPanel(props->getStringValue("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!`
> +    _panel->init();
> +
> +    // Initialize the matrices to the identity.  PLib prints warnings
> +    // when trying to invert singular matrices (e.g. when not using a
> +    // 3D panel).
> +    for(int i=0; i<4; i++)
> +        for(int j=0; j<4; j++)
> +            _lastModelview[4*i+j] = _lastProjection[4*i+j] = i==j ? 1 : 0;
> +
>      // Read out the pixel-space info
>      _xmax = _panel->getWidth();
>      _ymax = _panel->getHeight();
> @@ -34,7 +67,7 @@
>      _bottomRight[1] = pt->getFloatValue("y-m");
>      _bottomRight[2] = pt->getFloatValue("z-m");
>  
> -    // Now generate out 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
>      // vector u goes from a to b, v from a to c, and w is a
>      // perpendicular cross product.
> @@ -74,6 +107,9 @@
>                     (cz-a[2])*(cz-a[2]));
>      bsphere.setCenter(cx, cy, cz);
>      bsphere.setRadius(r);
> +
> +    // All done.  Add us to the list
> +    all_3d_panels.push_back(this);
>  }
>  
>  FGPanelNode::~FGPanelNode()
> @@ -92,13 +128,60 @@
>      glMatrixMode(GL_MODELVIEW);
>      glPushMatrix();
>      glMultMatrixf(_xform);
> +
> +    // Grab the matrix state, so that we can get back from screen
> +    // coordinates to panel coordinates when the user clicks the
> +    // mouse.
> +    glGetFloatv(GL_MODELVIEW_MATRIX, _lastModelview);
> +    glGetFloatv(GL_PROJECTION_MATRIX, _lastProjection);
> +    glGetIntegerv(GL_VIEWPORT, _lastViewport);
> +
>      _panel->draw();
> +
> +
>      glPopMatrix();
>  }
>  
> +bool FGPanelNode::doMouseAction(int button, int updown, int x, int y)
> +{
> +    // Covert the screen coordinates to viewport coordinates in the
> +    // range [0:1], then transform to OpenGL "post projection" coords
> +    // in [-1:1].  Remember the difference in Y direction!
> +    float vx = (x + 0.5 - _lastViewport[0]) / _lastViewport[2];
> +    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
> +    // screen, one in the near field and one in the far field.
> +    sgVec3 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
> +    // transformation.  Remember to w-normalize the vectors!
> +    sgMat4 m;
> +    sgMultMat4(m, *(sgMat4*)_lastProjection, *(sgMat4*)_lastModelview);
> +    sgInvertMat4(m);
> +
> +    sgFullXformPnt3(a, m);
> +    sgFullXformPnt3(b, m);
> +
> +    // 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);
> +}
> +
>  void FGPanelNode::die()
>  {
>      SG_LOG(SG_ALL,SG_ALERT,"Unimplemented function called on FGPanelNode");
> -    *(int*)0=0;
> +    exit(1);
>  }
>  
> Index: src/Model/panelnode.hxx
> ===================================================================
> RCS file: /var/cvs/FlightGear-0.9/FlightGear/src/Model/panelnode.hxx,v
> retrieving revision 1.1.1.1
> diff -u -r1.1.1.1 panelnode.hxx
> --- src/Model/panelnode.hxx   10 Sep 2002 01:14:08 -0000      1.1.1.1
> +++ src/Model/panelnode.hxx   27 Oct 2002 04:32:49 -0000
> @@ -8,6 +8,12 @@
>  // many methods, mostly involved with modelling and runtime
>  // inspection, are unimplemented.
>  
> +// Static mouse handler for all FGPanelNodes.  Very clumsy; this
> +// 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 ssgLeaf 
>  {
>  protected:
> @@ -18,7 +24,9 @@
>      virtual ~FGPanelNode();
>  
>      virtual void draw();
> -    void mouseEvent(int button, int updown, int x, int y);
> +    bool doMouseAction(int button, int updown, int x, int y);
> +
> +    FGPanel* getPanel() { return _panel; }
>  
>      virtual void recalcBSphere() { bsphere_is_invalid = 0; }
>  

-- 
Curtis Olson   IVLab / HumanFIRST Program       FlightGear Project
Twin Cities    [EMAIL PROTECTED]                  [EMAIL PROTECTED]
Minnesota      http://www.menet.umn.edu/~curt   http://www.flightgear.org

_______________________________________________
Flightgear-devel mailing list
[EMAIL PROTECTED]
http://mail.flightgear.org/mailman/listinfo/flightgear-devel

Reply via email to