2000-02-15 03:30:01 +00:00
|
|
|
|
// panel.cxx - default, 2D single-engine prop instrument panel
|
1998-11-11 00:19:27 +00:00
|
|
|
|
//
|
2000-02-15 03:30:01 +00:00
|
|
|
|
// Written by David Megginson, started January 2000.
|
1998-11-11 00:19:27 +00:00
|
|
|
|
//
|
2000-02-15 03:30:01 +00:00
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
// License, or (at your option) any later version.
|
1999-12-23 17:37:18 +00:00
|
|
|
|
//
|
2000-02-15 03:30:01 +00:00
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
|
// 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.
|
1998-11-11 00:19:27 +00:00
|
|
|
|
//
|
2000-02-15 03:30:01 +00:00
|
|
|
|
// $Id$
|
1998-06-27 16:47:53 +00:00
|
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
# include <config.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_WINDOWS_H
|
|
|
|
|
# include <windows.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
#include <string.h>
|
1999-03-08 21:56:08 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
#include <plib/ssg.h>
|
2000-02-21 22:00:24 +00:00
|
|
|
|
#include <plib/fnt.h>
|
1998-06-27 16:47:53 +00:00
|
|
|
|
#include <GL/glut.h>
|
|
|
|
|
|
2000-02-16 23:01:03 +00:00
|
|
|
|
#include <simgear/debug/logstream.hxx>
|
|
|
|
|
#include <simgear/misc/fgpath.hxx>
|
1998-06-27 16:47:53 +00:00
|
|
|
|
#include <Main/options.hxx>
|
2000-04-27 22:45:48 +00:00
|
|
|
|
#include <Main/views.hxx>
|
2000-02-26 18:01:13 +00:00
|
|
|
|
#include <Main/bfi.hxx>
|
1999-05-13 02:10:52 +00:00
|
|
|
|
#include <Objects/texload.h>
|
2000-02-21 22:00:24 +00:00
|
|
|
|
#include <Time/fg_time.hxx>
|
1998-06-27 16:47:53 +00:00
|
|
|
|
|
1998-08-28 18:14:39 +00:00
|
|
|
|
#include "cockpit.hxx"
|
2000-02-15 03:30:01 +00:00
|
|
|
|
#include "panel.hxx"
|
2000-02-21 22:00:24 +00:00
|
|
|
|
#include "hud.hxx"
|
2000-03-21 20:51:03 +00:00
|
|
|
|
#include "steam.hxx"
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
#define SIX_X 200
|
|
|
|
|
#define SIX_Y 345
|
|
|
|
|
#define SIX_W 128
|
|
|
|
|
#define SIX_SPACING (SIX_W + 5)
|
|
|
|
|
#define SMALL_W 112
|
1998-06-27 16:47:53 +00:00
|
|
|
|
|
1998-08-28 18:14:39 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Static functions for obtaining settings.
|
|
|
|
|
//
|
|
|
|
|
// These should be replaced with functions from a global facade,
|
|
|
|
|
// or BFI (Big Friendly Interface).
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static char * panelGetTime (char * buf)
|
|
|
|
|
{
|
|
|
|
|
struct tm * t = FGTime::cur_time_params->getGmt();
|
|
|
|
|
sprintf(buf, " %.2d:%.2d:%.2d",
|
|
|
|
|
t->tm_hour, t->tm_min, t->tm_sec);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Static factory functions to create textured gauges.
|
|
|
|
|
//
|
|
|
|
|
// These will be replaced first with a giant table, and then with
|
|
|
|
|
// configuration files read from an external source, but for now
|
|
|
|
|
// they're hard-coded.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2000-02-26 18:01:13 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
#define createTexture(a) FGTextureManager::createTexture(a)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct an airspeed indicator for a single-engine prop.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createAirspeedIndicator (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: gauge background.
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/airspeed.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: needle.
|
|
|
|
|
// Rotates with airspeed.
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_ASI_kias,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
30.0, 220.0, 36.0 / 20.0, -54.0);
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct an artificial horizon.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createHorizon (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: coloured background
|
|
|
|
|
// moves with roll only
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/horizon-bg.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(0, FGInstrumentLayer::ROTATION,
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGBFI::getRoll,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 1: floating horizon
|
|
|
|
|
// moves with roll and pitch
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/horizon-float.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGBFI::getRoll,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::YSHIFT,
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGBFI::getPitch,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-20.0, 20.0, -(1.5 / 160.0) * SIX_W, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 2: rim
|
|
|
|
|
// moves with roll only
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/horizon-rim.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::ROTATION,
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGBFI::getRoll,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 3: glass front of gauge
|
|
|
|
|
// fixed, with markings
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(3, createTexture("Textures/Panel/horizon-fg.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct an altimeter.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createAltimeter (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: gauge background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/altimeter.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: hundreds needle (long)
|
|
|
|
|
// moves with altitude
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_ALT_ft,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
0.0, 100000.0, 360.0 / 1000.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 2: thousands needle (short)
|
|
|
|
|
// moves with altitude
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/short-needle.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_ALT_ft,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
0.0, 100000.0, 360.0 / 10000.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 3: ten thousands bug (outside)
|
|
|
|
|
// moves with altitude
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(3, createTexture("Textures/Panel/bug.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_ALT_ft,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
0.0, 100000.0, 360.0 / 100000.0, 0.0);
|
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a turn coordinator.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createTurnCoordinator (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/turn-bg.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: little plane
|
|
|
|
|
// moves with roll
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/turn.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_TC_radps,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-30.0, 30.0, 1.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 2: little ball
|
|
|
|
|
// moves with slip/skid
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/ball.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::ROTATION,
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
FGSteam::get_TC_rad,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-0.1, 0.1, 450.0, 0.0);
|
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a gyro compass.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createGyroCompass (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Action: move bug counter-clockwise
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
|
|
|
|
|
new FGAdjustAction(FGBFI::getAPHeading,
|
|
|
|
|
FGBFI::setAPHeading,
|
|
|
|
|
-1.0, 0.0, 360.0, true));
|
|
|
|
|
|
|
|
|
|
// Action: move bug clockwise
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
|
|
|
|
|
new FGAdjustAction(FGBFI::getAPHeading,
|
|
|
|
|
FGBFI::setAPHeading,
|
|
|
|
|
1.0, 0.0, 360.0, true));
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Layer 0: compass background
|
|
|
|
|
// rotates with heading
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(0, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_DG_deg,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 1: heading bug
|
|
|
|
|
// rotates with heading and AP heading
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/bug.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_DG_deg,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGBFI::getAPHeading,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-360.0, 360.0, 1.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 2: fixed center
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/gyro-fg.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Layer 3: heading knob
|
|
|
|
|
// rotates with AP heading
|
|
|
|
|
inst->addLayer(3, createTexture("Textures/Panel/heading-knob.rgb"));
|
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
|
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
|
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::ROTATION,
|
|
|
|
|
FGBFI::getAPHeading,
|
|
|
|
|
-360.0, 360.0, 1.0, 0.0);
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a vertical velocity indicator.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createVerticalVelocity (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: gauge background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/vertical.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: needle
|
|
|
|
|
// moves with vertical velocity
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-03-21 20:51:03 +00:00
|
|
|
|
FGSteam::get_VSI_fps,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-2000.0, 2000.0, 42.0/500.0, 270.0);
|
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct an RPM gauge.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createRPMGauge (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: gauge background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/rpm.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: long needle
|
|
|
|
|
// FIXME: moves with throttle (for now)
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGBFI::getThrottle,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
0.0, 100.0, 300.0, -150.0);
|
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct a flap position indicator.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createFlapIndicator (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: gauge background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/flaps.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: long needle
|
|
|
|
|
// shifted over, rotates with flap position
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
|
|
|
|
|
-(SMALL_W / 4) + (SMALL_W / 16));
|
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGBFI::getFlaps,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
0.0, 1.0, 120.0, 30.0);
|
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createChronometer (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: gauge background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/clock.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: text
|
|
|
|
|
// displays current GMT
|
|
|
|
|
FGCharInstrumentLayer * text =
|
|
|
|
|
new FGCharInstrumentLayer(panelGetTime,
|
|
|
|
|
SMALL_W, SMALL_W, 1);
|
|
|
|
|
text->setPointSize(14);
|
|
|
|
|
text->setColor(0.2, 0.2, 0.2);
|
|
|
|
|
inst->addLayer(text);
|
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::XSHIFT, SMALL_W * -0.38);
|
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::YSHIFT, SMALL_W * -0.06);
|
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Construct control-position indicators.
|
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createControls (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
|
|
|
|
|
|
|
|
|
|
// Layer 0: gauge background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/controls.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: bug
|
|
|
|
|
// moves left-right with aileron
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/bug.rgb"));
|
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::XSHIFT, FGBFI::getAileron,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 2: bug
|
|
|
|
|
// moves left-right with rudder
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/bug.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::ROTATION, 180.0);
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::XSHIFT, FGBFI::getRudder,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 3: bug
|
|
|
|
|
// moves up-down with elevator trim
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(3, createTexture("Textures/Panel/bug.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::ROTATION, 270.0);
|
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::YSHIFT,
|
|
|
|
|
-SMALL_W * (3.0 / 8.0));
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::XSHIFT, FGBFI::getElevatorTrim,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 4: bug
|
|
|
|
|
// moves up-down with elevator
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(4, createTexture("Textures/Panel/bug.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
inst->addTransformation(4, FGInstrumentLayer::ROTATION, 90.0);
|
|
|
|
|
inst->addTransformation(4, FGInstrumentLayer::YSHIFT,
|
|
|
|
|
-SMALL_W * (3.0 / 8.0));
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addTransformation(4, FGInstrumentLayer::XSHIFT, FGBFI::getElevator,
|
2000-02-21 22:00:24 +00:00
|
|
|
|
-1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
|
|
|
|
|
|
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
* Construct a NAV1 gauge (hardwired).
|
2000-02-21 22:00:24 +00:00
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createNAV1 (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Action: increase selected radial
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
new FGAdjustAction(FGBFI::getNAV1Radial,
|
|
|
|
|
FGBFI::setNAV1Radial,
|
2000-04-27 22:45:48 +00:00
|
|
|
|
1.0, 0.0, 360.0, true));
|
|
|
|
|
|
|
|
|
|
// Action: decrease selected radial
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
new FGAdjustAction(FGBFI::getNAV1Radial,
|
|
|
|
|
FGBFI::setNAV1Radial,
|
2000-04-27 22:45:48 +00:00
|
|
|
|
-1.0, 0.0, 360.0, true));
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Layer 0: background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
inst->addTransformation(0, FGInstrumentLayer::ROTATION,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
FGBFI::getNAV1Radial,
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
2000-04-27 22:45:48 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: left-right needle.
|
2000-03-26 17:19:39 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/nav-needle.rgb"));
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
|
|
|
|
|
FGSteam::get_HackVOR1_deg,
|
|
|
|
|
-10.0, 10.0, SIX_W / 40.0, 0.0);
|
2000-04-27 22:45:48 +00:00
|
|
|
|
|
|
|
|
|
// Layer 2: glidescope needle
|
2000-03-26 17:19:39 +00:00
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/nav-needle.rgb"));
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::YSHIFT,
|
|
|
|
|
FGSteam::get_HackGS_deg,
|
|
|
|
|
-1.0, 1.0, SIX_W / 5.0, 0.0);
|
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::ROTATION,
|
|
|
|
|
90 );
|
2000-04-27 22:45:48 +00:00
|
|
|
|
|
|
|
|
|
// Layer 3: face with markings
|
2000-03-26 17:19:39 +00:00
|
|
|
|
inst->addLayer(3, createTexture("Textures/Panel/nav-face.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Layer 4: heading knob
|
|
|
|
|
// rotates with selected radial
|
|
|
|
|
inst->addLayer(4, createTexture("Textures/Panel/heading-knob.rgb"));
|
|
|
|
|
inst->addTransformation(4, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
|
|
|
|
|
inst->addTransformation(4, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
|
|
|
|
|
inst->addTransformation(4, FGInstrumentLayer::ROTATION,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
FGBFI::getNAV1Radial,
|
2000-04-27 22:45:48 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2000-04-27 22:45:48 +00:00
|
|
|
|
* Construct a NAV2 gauge.
|
2000-02-21 22:00:24 +00:00
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createNAV2 (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Action: increase selected radial
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
new FGAdjustAction(FGBFI::getNAV2Radial,
|
|
|
|
|
FGBFI::setNAV2Radial,
|
2000-04-27 22:45:48 +00:00
|
|
|
|
1.0, 0.0, 360.0, true));
|
|
|
|
|
|
|
|
|
|
// Action: decrease selected radial
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
new FGAdjustAction(FGBFI::getNAV2Radial,
|
|
|
|
|
FGBFI::setNAV2Radial,
|
2000-04-27 22:45:48 +00:00
|
|
|
|
-1.0, 0.0, 360.0, true));
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Layer 0: background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
inst->addTransformation(0, FGInstrumentLayer::ROTATION,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
FGBFI::getNAV2Radial,
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
2000-04-27 22:45:48 +00:00
|
|
|
|
|
|
|
|
|
// Layer 1: left-right needle.
|
2000-03-26 17:19:39 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/nav-needle.rgb"));
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
|
|
|
|
|
FGSteam::get_HackVOR2_deg,
|
|
|
|
|
-10.0, 10.0, SIX_W / 40.0, 0.0);
|
2000-03-26 17:19:39 +00:00
|
|
|
|
// inst->addTransformation(1, FGInstrumentLayer::YSHIFT,
|
|
|
|
|
// -SIX_W / 4.4 );
|
2000-04-27 22:45:48 +00:00
|
|
|
|
|
|
|
|
|
// Layer 2: face with markings.
|
2000-03-26 17:19:39 +00:00
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/nav-face.rgb"));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Layer 3: heading knob
|
|
|
|
|
// rotates with selected radial
|
|
|
|
|
inst->addLayer(3, createTexture("Textures/Panel/heading-knob.rgb"));
|
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
|
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
|
|
|
|
|
inst->addTransformation(3, FGInstrumentLayer::ROTATION,
|
2000-04-30 22:21:47 +00:00
|
|
|
|
FGBFI::getNAV2Radial,
|
2000-04-27 22:45:48 +00:00
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
* Construct an ADF gauge (hardwired).
|
2000-02-21 22:00:24 +00:00
|
|
|
|
*/
|
|
|
|
|
static FGPanelInstrument *
|
2000-02-26 18:01:13 +00:00
|
|
|
|
createADF (int x, int y)
|
2000-02-21 22:00:24 +00:00
|
|
|
|
{
|
|
|
|
|
FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Action: increase selected rotation
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
|
|
|
|
|
new FGAdjustAction(FGBFI::getADFRotation,
|
|
|
|
|
FGBFI::setADFRotation,
|
|
|
|
|
1.0, 0.0, 360.0, true));
|
|
|
|
|
|
|
|
|
|
// Action: decrease selected rotation
|
|
|
|
|
inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
|
|
|
|
|
new FGAdjustAction(FGBFI::getADFRotation,
|
|
|
|
|
FGBFI::setADFRotation,
|
|
|
|
|
-1.0, 0.0, 360.0, true));
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Layer 0: background
|
2000-02-26 18:01:13 +00:00
|
|
|
|
inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
|
2000-04-27 22:45:48 +00:00
|
|
|
|
inst->addTransformation(0, FGInstrumentLayer::ROTATION,
|
|
|
|
|
FGBFI::getADFRotation,
|
|
|
|
|
0.0, 360.0, 1.0, 0.0);
|
|
|
|
|
|
|
|
|
|
// Layer 1: Direction needle.
|
NAV1 is now the ILS-28R on airport KMYF,
NAV2 is now the VOR radial 068 from MZB,
ADF is now the Compass locator on the outer marker.
This combination is more than the legally required to
fly any of KMYF-ILS-28R, KMYF-LOC-28R KMYF-NDB28.
If you don't have access to the approach plates
and would like them, let me know and I'll scan them
(and put them on the webpage area).
The approaches do work; I've checked them all out in
terms of altitude profile, centerlines and other stuff.
In real life, the radar vectoring will basically abandon you
overhead KSEE airport at 4000 ft heading 210 or so. Sometime
later you'll be turned to a heading of 260 if the controller
doesn't have too much else to do, just before you hit the
extended centerline. You can't rely on that though.
Maintain 3500ft until established, 2100 ft until the outer marker,
If non-precision, maintain 1340 until crossing the radial,
then 900 thereafter until you miss, based on time from the NDB.
The miss takes you heading 270 to intercept a radial which this
hacky implementation will not let you set up the computer for.
The hacky math implementation does not take range and/or signal
strength into account, so you can fly to San Diego from England
by following the needle indication on the ADF. It is also
fairly inaccurate math; about as accurate as the real-life signals.
When we have a _real_ radio module, I will be very happy to
throw all that code away. For now, it makes it demonstratable.
Please notice the nastiness involving the "VARY_E" constant.
This is _not_ something that will go away with the radio module.
As far as I know, we don't have a routine that calculates
magnetic variation as a function of global position.
We will need one, probably within the next two months.
2000-03-26 16:52:36 +00:00
|
|
|
|
inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
|
|
|
|
|
inst->addTransformation(1, FGInstrumentLayer::ROTATION,
|
|
|
|
|
FGSteam::get_HackADF_deg,
|
|
|
|
|
-720.0, 720.0, 1.0, 0.0);
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Layer 2: heading knob
|
|
|
|
|
// rotates with selected radial
|
|
|
|
|
inst->addLayer(2, createTexture("Textures/Panel/heading-knob.rgb"));
|
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
|
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
|
|
|
|
|
inst->addTransformation(2, FGInstrumentLayer::ROTATION,
|
|
|
|
|
FGBFI::getADFRotation,
|
|
|
|
|
-360.0, 360.0, -1.0, 0.0);
|
2000-02-21 22:00:24 +00:00
|
|
|
|
return inst;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGTextureManager.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
map<const char *,ssgTexture *> FGTextureManager::_textureMap;
|
|
|
|
|
|
|
|
|
|
ssgTexture *
|
|
|
|
|
FGTextureManager::createTexture (const char * relativePath)
|
|
|
|
|
{
|
|
|
|
|
ssgTexture *texture;
|
|
|
|
|
|
|
|
|
|
texture = _textureMap[relativePath];
|
|
|
|
|
if (texture == 0) {
|
|
|
|
|
FGPath tpath(current_options.get_fg_root());
|
|
|
|
|
tpath.append(relativePath);
|
|
|
|
|
texture = new ssgTexture((char *)tpath.c_str(), false, false);
|
|
|
|
|
_textureMap[relativePath] = texture;
|
|
|
|
|
cerr << "Created texture " << relativePath
|
|
|
|
|
<< " handle=" << texture->getHandle() << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return texture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGPanel.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
FGPanel current_panel;
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
FGPanel::FGPanel ()
|
2000-04-27 22:45:48 +00:00
|
|
|
|
: _initialized(false),
|
|
|
|
|
_visibility(false)
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-04-27 22:45:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGPanel::~FGPanel ()
|
|
|
|
|
{
|
|
|
|
|
instrument_list_type::iterator current = _instruments.begin();
|
|
|
|
|
instrument_list_type::iterator last = _instruments.end();
|
|
|
|
|
|
|
|
|
|
for ( ; current != last; ++current) {
|
|
|
|
|
delete *current;
|
|
|
|
|
*current = 0;
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
2000-04-27 22:45:48 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGPanel::addInstrument (FGPanelInstrument * instrument)
|
|
|
|
|
{
|
|
|
|
|
_instruments.push_back(instrument);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGPanel::init (int x, int y, int finx, int finy)
|
|
|
|
|
{
|
|
|
|
|
_x = x;
|
|
|
|
|
_y = y;
|
|
|
|
|
_w = finx - x;
|
|
|
|
|
_h = finy - y;
|
|
|
|
|
_panel_h = (int)((finy - y) * 0.5768 + 1);
|
2000-02-15 03:30:01 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Don't reconstruct all of the
|
|
|
|
|
// instruments.
|
|
|
|
|
if (_initialized)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
x = SIX_X;
|
|
|
|
|
y = SIX_Y;
|
2000-02-15 03:30:01 +00:00
|
|
|
|
|
2000-02-26 18:01:13 +00:00
|
|
|
|
_bg = createTexture("Textures/Panel/panel-bg.rgb");
|
2000-02-15 03:30:01 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Chronometer alone at side
|
|
|
|
|
x = SIX_X - SIX_SPACING - 8;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createChronometer(x, y));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Top row
|
|
|
|
|
x = SIX_X;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createAirspeedIndicator(x, y));
|
2000-02-15 03:30:01 +00:00
|
|
|
|
x += SIX_SPACING;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createHorizon(x, y));
|
2000-02-15 03:30:01 +00:00
|
|
|
|
x += SIX_SPACING;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createAltimeter(x, y));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
x += SIX_SPACING + 20;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createNAV1(x, y));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
|
|
|
|
|
// Middle row
|
2000-02-15 03:30:01 +00:00
|
|
|
|
x = SIX_X;
|
|
|
|
|
y -= SIX_SPACING;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createTurnCoordinator(x, y));
|
2000-02-15 03:30:01 +00:00
|
|
|
|
x += SIX_SPACING;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createGyroCompass(x, y));
|
2000-02-15 03:30:01 +00:00
|
|
|
|
x += SIX_SPACING;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createVerticalVelocity(x, y));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
x += SIX_SPACING + 20;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createNAV2(x, y));
|
2000-02-15 03:30:01 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Bottom row
|
|
|
|
|
x = SIX_X;
|
|
|
|
|
y -= SIX_SPACING + 10;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createControls(x, y));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
x += SIX_SPACING;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createFlapIndicator(x, y));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
x += SIX_SPACING;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createRPMGauge(x, y));
|
2000-02-21 22:00:24 +00:00
|
|
|
|
x += SIX_SPACING + 20;
|
|
|
|
|
y += 10;
|
2000-04-27 22:45:48 +00:00
|
|
|
|
addInstrument(createADF(x, y));
|
1998-06-27 16:47:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-04-27 22:45:48 +00:00
|
|
|
|
FGPanel::update () const
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-04-27 22:45:48 +00:00
|
|
|
|
// Do nothing if the panel isn't visible.
|
|
|
|
|
if (!_visibility)
|
|
|
|
|
return;
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
|
glPushMatrix();
|
|
|
|
|
glLoadIdentity();
|
|
|
|
|
gluOrtho2D(_x, _x + _w, _y, _y + _h);
|
|
|
|
|
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
|
glPushMatrix();
|
|
|
|
|
glLoadIdentity();
|
|
|
|
|
|
|
|
|
|
// Draw the background
|
|
|
|
|
glEnable(GL_TEXTURE_2D);
|
2000-02-21 22:00:24 +00:00
|
|
|
|
glDisable(GL_LIGHTING);
|
2000-03-17 06:16:15 +00:00
|
|
|
|
glEnable(GL_BLEND);
|
|
|
|
|
glEnable(GL_ALPHA_TEST);
|
|
|
|
|
glEnable(GL_COLOR_MATERIAL);
|
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0);
|
2000-02-21 22:00:24 +00:00
|
|
|
|
glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
|
2000-02-15 03:30:01 +00:00
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
|
|
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
2000-02-21 22:00:24 +00:00
|
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
2000-02-15 03:30:01 +00:00
|
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
|
glTexCoord2f(0.0, 0.0); glVertex3f(_x, _y, 0);
|
|
|
|
|
glTexCoord2f(10.0, 0.0); glVertex3f(_x + _w, _y, 0);
|
|
|
|
|
glTexCoord2f(10.0, 5.0); glVertex3f(_x + _w, _y + _panel_h, 0);
|
|
|
|
|
glTexCoord2f(0.0, 5.0); glVertex3f(_x, _y + _panel_h, 0);
|
|
|
|
|
glEnd();
|
|
|
|
|
|
|
|
|
|
// Draw the instruments.
|
2000-02-21 22:00:24 +00:00
|
|
|
|
instrument_list_type::const_iterator current = _instruments.begin();
|
|
|
|
|
instrument_list_type::const_iterator end = _instruments.end();
|
|
|
|
|
|
|
|
|
|
for ( ; current != end; current++) {
|
|
|
|
|
FGPanelInstrument * instr = *current;
|
|
|
|
|
glLoadIdentity();
|
|
|
|
|
glTranslated(instr->getXPos(), instr->getYPos(), 0);
|
|
|
|
|
instr->draw();
|
|
|
|
|
}
|
2000-02-15 03:30:01 +00:00
|
|
|
|
|
|
|
|
|
glMatrixMode(GL_PROJECTION);
|
|
|
|
|
glPopMatrix();
|
|
|
|
|
glMatrixMode(GL_MODELVIEW);
|
|
|
|
|
glPopMatrix();
|
2000-02-21 22:00:24 +00:00
|
|
|
|
ssgForceBasicState();
|
|
|
|
|
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
|
1999-12-23 17:37:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
void
|
|
|
|
|
FGPanel::setVisibility (bool visibility)
|
2000-02-26 18:01:13 +00:00
|
|
|
|
{
|
2000-04-27 22:45:48 +00:00
|
|
|
|
_visibility = visibility;
|
|
|
|
|
}
|
2000-02-26 18:01:13 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
bool
|
|
|
|
|
FGPanel::getVisibility () const
|
|
|
|
|
{
|
|
|
|
|
return _visibility;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
FGPanel::doMouseAction (int button, int updown, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
// For now, ignore the release
|
|
|
|
|
if (updown == 1)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
x = (int)(((float)x / current_view.get_winWidth()) * _w);
|
|
|
|
|
y = (int)(_h - (((float)y / current_view.get_winHeight()) * _h));
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < _instruments.size(); i++) {
|
|
|
|
|
FGPanelInstrument *inst = _instruments[i];
|
|
|
|
|
int ix = inst->getXPos();
|
|
|
|
|
int iy = inst->getYPos();
|
|
|
|
|
int iw = inst->getWidth() / 2;
|
|
|
|
|
int ih = inst->getHeight() / 2;
|
|
|
|
|
if (x >= ix - iw && x < ix + iw && y >= iy - ih && y < iy + ih) {
|
|
|
|
|
cout << "Do mouse action for component " << i << '\n';
|
|
|
|
|
return inst->doMouseAction(button, updown, x - ix, y - iy);
|
|
|
|
|
}
|
2000-02-26 18:01:13 +00:00
|
|
|
|
}
|
2000-04-27 22:45:48 +00:00
|
|
|
|
cout << "Did not click on an instrument\n";
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2000-02-26 18:01:13 +00:00
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGAdjustAction.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGAdjustAction::FGAdjustAction (getter_type getter, setter_type setter,
|
|
|
|
|
double increment, double min, double max,
|
|
|
|
|
bool wrap=false)
|
|
|
|
|
: _getter(getter), _setter(setter), _increment(increment),
|
|
|
|
|
_min(min), _max(max), _wrap(wrap)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGAdjustAction::~FGAdjustAction ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGAdjustAction::doAction ()
|
|
|
|
|
{
|
|
|
|
|
double value = (*_getter)();
|
|
|
|
|
cout << "Do action; value=" << value << '\n';
|
|
|
|
|
value += _increment;
|
|
|
|
|
if (value < _min) {
|
|
|
|
|
value = (_wrap ? _max : _min);
|
|
|
|
|
} else if (value > _max) {
|
|
|
|
|
value = (_wrap ? _min : _max);
|
|
|
|
|
}
|
|
|
|
|
cout << "New value is " << value << '\n';
|
|
|
|
|
(*_setter)(value);
|
2000-02-26 18:01:13 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2000-02-15 03:30:01 +00:00
|
|
|
|
// Implementation of FGPanelInstrument.
|
1999-12-23 17:37:18 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
FGPanelInstrument::FGPanelInstrument ()
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-15 03:30:01 +00:00
|
|
|
|
setPosition(0, 0);
|
|
|
|
|
setSize(0, 0);
|
1999-12-23 17:37:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
|
|
|
|
|
{
|
|
|
|
|
setPosition(x, y);
|
|
|
|
|
setSize(w, h);
|
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
FGPanelInstrument::~FGPanelInstrument ()
|
|
|
|
|
{
|
2000-04-27 22:45:48 +00:00
|
|
|
|
action_list_type::iterator it = _actions.begin();
|
|
|
|
|
action_list_type::iterator last = _actions.end();
|
|
|
|
|
for ( ; it != last; it++) {
|
|
|
|
|
delete it->action;
|
|
|
|
|
}
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGPanelInstrument::setPosition (int x, int y)
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-15 03:30:01 +00:00
|
|
|
|
_x = x;
|
|
|
|
|
_y = y;
|
1999-12-23 17:37:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
|
|
|
|
FGPanelInstrument::setSize (int w, int h)
|
|
|
|
|
{
|
|
|
|
|
_w = w;
|
|
|
|
|
_h = h;
|
|
|
|
|
}
|
1999-05-12 02:04:38 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
int
|
|
|
|
|
FGPanelInstrument::getXPos () const
|
|
|
|
|
{
|
|
|
|
|
return _x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
FGPanelInstrument::getYPos () const
|
|
|
|
|
{
|
|
|
|
|
return _y;
|
1999-01-07 19:25:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-04-27 22:45:48 +00:00
|
|
|
|
int
|
|
|
|
|
FGPanelInstrument::getWidth () const
|
|
|
|
|
{
|
|
|
|
|
return _w;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
FGPanelInstrument::getHeight () const
|
|
|
|
|
{
|
|
|
|
|
return _h;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGPanelInstrument::addAction (int x, int y, int w, int h,
|
|
|
|
|
FGPanelAction * action)
|
|
|
|
|
{
|
|
|
|
|
FGPanelInstrument::inst_action act;
|
|
|
|
|
act.x = x;
|
|
|
|
|
act.y = y;
|
|
|
|
|
act.w = w;
|
|
|
|
|
act.h = h;
|
|
|
|
|
act.action = action;
|
|
|
|
|
_actions.push_back(act);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Coordinates relative to centre.
|
|
|
|
|
bool
|
|
|
|
|
FGPanelInstrument::doMouseAction (int button, int updown, int x, int y)
|
|
|
|
|
{
|
|
|
|
|
action_list_type::iterator it = _actions.begin();
|
|
|
|
|
action_list_type::iterator last = _actions.end();
|
|
|
|
|
cout << "Mouse action at " << x << ',' << y << '\n';
|
|
|
|
|
for ( ; it != last; it++) {
|
|
|
|
|
cout << "Trying action at " << it->x << ',' << it->y << ','
|
|
|
|
|
<< it->w <<',' << it->h << '\n';
|
|
|
|
|
if (x >= it->x && x < it->x + it->w && y >= it->y && y < it->y + it->h) {
|
|
|
|
|
it->action->doAction();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
1998-08-28 18:14:39 +00:00
|
|
|
|
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Implementation of FGLayeredInstrument.
|
1999-12-23 17:37:18 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
1999-01-07 19:25:53 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
|
2000-02-15 03:30:01 +00:00
|
|
|
|
: FGPanelInstrument(x, y, w, h)
|
|
|
|
|
{
|
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGLayeredInstrument::~FGLayeredInstrument ()
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// FIXME: free layers
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGLayeredInstrument::draw () const
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
layer_list::const_iterator it = _layers.begin();
|
|
|
|
|
layer_list::const_iterator last = _layers.end();
|
|
|
|
|
while (it != last) {
|
|
|
|
|
(*it)->draw();
|
|
|
|
|
it++;
|
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
_layers.push_back(layer);
|
1998-08-28 18:14:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-26 18:01:13 +00:00
|
|
|
|
FGLayeredInstrument::addLayer (int layer, ssgTexture * texture)
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-02-26 18:01:13 +00:00
|
|
|
|
addLayer(new FGTexturedInstrumentLayer(texture, _w, _h, layer));
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
1999-01-07 19:25:53 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGLayeredInstrument::addTransformation (int layer,
|
|
|
|
|
FGInstrumentLayer::transform_type type,
|
|
|
|
|
FGInstrumentLayer::transform_func func,
|
|
|
|
|
double min, double max,
|
|
|
|
|
double factor, double offset)
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
_layers[layer]->addTransformation(type, func, min, max, factor, offset);
|
1999-01-07 19:25:53 +00:00
|
|
|
|
}
|
|
|
|
|
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Implementation of FGInstrumentLayer.
|
1999-12-23 17:37:18 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGInstrumentLayer::FGInstrumentLayer (int w, int h, int z)
|
|
|
|
|
: _w(w),
|
|
|
|
|
_h(h),
|
|
|
|
|
_z(z)
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
1999-05-06 22:16:12 +00:00
|
|
|
|
}
|
1999-02-12 01:46:29 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGInstrumentLayer::~FGInstrumentLayer ()
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-02-26 18:01:13 +00:00
|
|
|
|
transformation_list::iterator it = _transformations.begin();
|
|
|
|
|
transformation_list::iterator end = _transformations.end();
|
2000-02-21 22:00:24 +00:00
|
|
|
|
while (it != end) {
|
|
|
|
|
delete *it;
|
|
|
|
|
it++;
|
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGInstrumentLayer::transform () const
|
|
|
|
|
{
|
|
|
|
|
glTranslatef(0.0, 0.0, (_z / 100.0) + 0.1);
|
|
|
|
|
|
|
|
|
|
transformation_list::const_iterator it = _transformations.begin();
|
|
|
|
|
transformation_list::const_iterator last = _transformations.end();
|
|
|
|
|
while (it != last) {
|
|
|
|
|
transformation *t = *it;
|
|
|
|
|
double value = (t->func == 0 ? 0.0 : (*(t->func))());
|
|
|
|
|
if (value < t->min) {
|
|
|
|
|
value = t->min;
|
|
|
|
|
} else if (value > t->max) {
|
|
|
|
|
value = t->max;
|
|
|
|
|
}
|
|
|
|
|
value = value * t->factor + t->offset;
|
|
|
|
|
|
|
|
|
|
switch (t->type) {
|
|
|
|
|
case XSHIFT:
|
|
|
|
|
glTranslatef(value, 0.0, 0.0);
|
|
|
|
|
break;
|
|
|
|
|
case YSHIFT:
|
|
|
|
|
glTranslatef(0.0, value, 0.0);
|
|
|
|
|
break;
|
|
|
|
|
case ROTATION:
|
|
|
|
|
glRotatef(-value, 0.0, 0.0, 1.0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
it++;
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
1998-11-09 23:38:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGInstrumentLayer::addTransformation (transform_type type,
|
|
|
|
|
transform_func func,
|
|
|
|
|
double min, double max,
|
|
|
|
|
double factor, double offset)
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
transformation *t = new transformation;
|
|
|
|
|
t->type = type;
|
|
|
|
|
t->func = func;
|
|
|
|
|
t->min = min;
|
|
|
|
|
t->max = max;
|
|
|
|
|
t->factor = factor;
|
|
|
|
|
t->offset = offset;
|
|
|
|
|
_transformations.push_back(t);
|
1999-05-06 22:16:12 +00:00
|
|
|
|
}
|
1999-05-12 02:04:38 +00:00
|
|
|
|
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Implementation of FGTexturedInstrumentLayer.
|
1999-12-23 17:37:18 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2000-02-26 18:01:13 +00:00
|
|
|
|
// FGTexturedInstrumentLayer::FGTexturedInstrumentLayer (const char *tname,
|
|
|
|
|
// int w, int h, int z)
|
|
|
|
|
// : FGInstrumentLayer(w, h, z)
|
|
|
|
|
// {
|
|
|
|
|
// setTexture(tname);
|
|
|
|
|
// }
|
1999-05-12 02:04:38 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGTexturedInstrumentLayer::FGTexturedInstrumentLayer (ssgTexture * texture,
|
|
|
|
|
int w, int h, int z)
|
|
|
|
|
: FGInstrumentLayer(w, h, z)
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
setTexture(texture);
|
1999-05-06 22:16:12 +00:00
|
|
|
|
}
|
1999-05-12 02:04:38 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGTexturedInstrumentLayer::~FGTexturedInstrumentLayer ()
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
1999-05-06 22:16:12 +00:00
|
|
|
|
}
|
1999-05-12 02:04:38 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGTexturedInstrumentLayer::draw () const
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
int w2 = _w / 2;
|
|
|
|
|
int h2 = _h / 2;
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
glPushMatrix();
|
|
|
|
|
transform();
|
|
|
|
|
glBindTexture(GL_TEXTURE_2D, _texture->getHandle());
|
|
|
|
|
glBegin(GL_POLYGON);
|
|
|
|
|
// FIXME: is this really correct
|
|
|
|
|
// for layering?
|
|
|
|
|
glTexCoord2f(0.0, 0.0); glVertex2f(-w2, -h2);
|
|
|
|
|
glTexCoord2f(1.0, 0.0); glVertex2f(w2, -h2);
|
|
|
|
|
glTexCoord2f(1.0, 1.0); glVertex2f(w2, h2);
|
|
|
|
|
glTexCoord2f(0.0, 1.0); glVertex2f(-w2, h2);
|
|
|
|
|
glEnd();
|
|
|
|
|
glPopMatrix();
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-26 18:01:13 +00:00
|
|
|
|
// void
|
|
|
|
|
// FGTexturedInstrumentLayer::setTexture (const char *textureName)
|
|
|
|
|
// {
|
|
|
|
|
// FGPath tpath(current_options.get_fg_root());
|
|
|
|
|
// tpath.append(textureName);
|
|
|
|
|
// ssgTexture * texture = new ssgTexture((char *)tpath.c_str(), false, false);
|
|
|
|
|
// setTexture(texture);
|
|
|
|
|
// }
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2000-02-21 22:00:24 +00:00
|
|
|
|
// Implementation of FGCharInstrumentLayer.
|
2000-02-15 03:30:01 +00:00
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGCharInstrumentLayer::FGCharInstrumentLayer (text_func func,
|
|
|
|
|
int w, int h, int z)
|
|
|
|
|
: FGInstrumentLayer(w, h, z),
|
|
|
|
|
_func(func)
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
_renderer.setFont(guiFntHandle);
|
|
|
|
|
_renderer.setPointSize(14);
|
|
|
|
|
_color[0] = _color[1] = _color[2] = 0.0;
|
2000-03-17 06:16:15 +00:00
|
|
|
|
_color[3] = 1.0;
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGCharInstrumentLayer::~FGCharInstrumentLayer ()
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGCharInstrumentLayer::draw () const
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
glPushMatrix();
|
2000-03-17 06:16:15 +00:00
|
|
|
|
glColor4fv(_color);
|
2000-02-21 22:00:24 +00:00
|
|
|
|
transform();
|
|
|
|
|
_renderer.begin();
|
|
|
|
|
_renderer.start3f(0, 0, 0);
|
|
|
|
|
_renderer.puts((*_func)(_buf));
|
|
|
|
|
_renderer.end();
|
2000-03-17 06:16:15 +00:00
|
|
|
|
glColor4f(1.0, 1.0, 1.0, 1.0); // FIXME
|
2000-02-21 22:00:24 +00:00
|
|
|
|
glPopMatrix();
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGCharInstrumentLayer::setColor (float r, float g, float b)
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
_color[0] = r;
|
|
|
|
|
_color[1] = g;
|
|
|
|
|
_color[2] = b;
|
2000-03-17 06:16:15 +00:00
|
|
|
|
_color[3] = 1.0;
|
1999-12-23 17:37:18 +00:00
|
|
|
|
}
|
|
|
|
|
|
2000-02-21 22:00:24 +00:00
|
|
|
|
void
|
|
|
|
|
FGCharInstrumentLayer::setPointSize (const float size)
|
2000-02-15 03:30:01 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
_renderer.setPointSize(size);
|
2000-02-15 03:30:01 +00:00
|
|
|
|
}
|
1999-12-23 17:37:18 +00:00
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
|
void
|
2000-02-21 22:00:24 +00:00
|
|
|
|
FGCharInstrumentLayer::setFont(fntFont * font)
|
1999-12-23 17:37:18 +00:00
|
|
|
|
{
|
2000-02-21 22:00:24 +00:00
|
|
|
|
_renderer.setFont(font);
|
1999-05-06 22:16:12 +00:00
|
|
|
|
}
|
2000-02-15 03:30:01 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// end of panel.cxx
|