]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/sp_panel.cxx
Replaced Durk's mymath.* with plib/sg.h (contributed by Durk).
[flightgear.git] / src / Cockpit / sp_panel.cxx
1 //  sp_panel.cxx - default, 2D single-engine prop instrument panel
2 //
3 //  Written by David Megginson, started January 2000.
4 //
5 //  This program is free software; you can redistribute it and/or
6 //  modify it under the terms of the GNU General Public License as
7 //  published by the Free Software Foundation; either version 2 of the
8 //  License, or (at your option) any later version.
9 // 
10 //  This program is distributed in the hope that it will be useful, but
11 //  WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 //  General Public License for more details.
14 // 
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 //
19 //  $Id$
20
21 #ifdef HAVE_CONFIG_H
22 #  include <config.h>
23 #endif
24
25 #ifdef HAVE_WINDOWS_H          
26 #  include <windows.h>
27 #endif
28
29 #include <simgear/debug/logstream.hxx>
30 #include <Main/bfi.hxx>
31 #include <Time/fg_time.hxx>
32
33 #include "panel.hxx"
34 #include "steam.hxx"
35 #include "radiostack.hxx"
36
37                                 // Macros for instrument sizes
38                                 // (these aren't used consistently
39                                 // anyway, and should probably be
40                                 // removed).
41 #define SIX_X 200
42 #define SIX_Y 345
43 #define SIX_W 128
44 #define SIX_SPACING (SIX_W + 5)
45 #define SMALL_W 112
46
47 #define createTexture(a) FGTextureManager::createTexture(a)
48
49
50 \f
51 ////////////////////////////////////////////////////////////////////////
52 // Static functions for obtaining settings.
53 //
54 // These are all temporary, and should be moved somewhere else
55 // as soon as convenient.
56 ////////////////////////////////////////////////////////////////////////
57
58 static char * panelGetTime ()
59 {
60   static char buf[1024];        // FIXME: not thread-safe
61   struct tm * t = FGTime::cur_time_params->getGmt();
62   sprintf(buf, " %.2d:%.2d:%.2d",
63           t->tm_hour, t->tm_min, t->tm_sec);
64   return buf;
65 }
66
67 static bool panelGetNAV1TO ()
68 {
69   if (current_radiostack->get_nav1_inrange()) {
70     double heading = current_radiostack->get_nav1_heading();
71     double radial = current_radiostack->get_nav1_radial();
72     double var = FGBFI::getMagVar();
73     if (current_radiostack->get_nav1_loc()) {
74       double offset = fabs(heading - radial);
75       return (offset<= 8.0 || offset >= 352.0);
76     } else {
77       double offset =
78         fabs(heading - var - radial);
79       return (offset <= 20.0 || offset >= 340.0);
80     }
81   } else {
82     return false;
83   }
84 }
85
86 static bool panelGetNAV1FROM ()
87 {
88   if (current_radiostack->get_nav1_inrange()) {
89     double heading = current_radiostack->get_nav1_heading();
90     double radial = current_radiostack->get_nav1_radial();
91     double var = FGBFI::getMagVar();
92     if (current_radiostack->get_nav1_loc()) {
93       double offset = fabs(heading - radial);
94       return (offset >= 172.0 && offset<= 188.0);
95     } else {
96       double offset =
97         fabs(heading - var - radial);
98       return (offset >= 160.0 && offset <= 200.0);
99     }
100   } else {
101     return false;
102   }
103 }
104
105 static bool panelGetNAV2TO ()
106 {
107   if (current_radiostack->get_nav2_inrange()) {
108     double heading = current_radiostack->get_nav2_heading();
109     double radial = current_radiostack->get_nav2_radial();
110     double var = FGBFI::getMagVar();
111     if (current_radiostack->get_nav2_loc()) {
112       double offset = fabs(heading - radial);
113       return (offset<= 8.0 || offset >= 352.0);
114     } else {
115       double offset =
116         fabs(heading - var - radial);
117       return (offset <= 20.0 || offset >= 340.0);
118     }
119   } else {
120     return false;
121   }
122 }
123
124 static bool panelGetNAV2FROM ()
125 {
126   if (current_radiostack->get_nav2_inrange()) {
127     double heading = current_radiostack->get_nav2_heading();
128     double radial = current_radiostack->get_nav2_radial();
129     double var = FGBFI::getMagVar();
130     if (current_radiostack->get_nav2_loc()) {
131       double offset = fabs(heading - radial);
132       return (offset >= 172.0 && offset<= 188.0);
133     } else {
134       double offset =
135         fabs(heading - var - radial);
136       return (offset >= 160.0 && offset <= 200.0);
137     }
138   } else {
139     return false;
140   }
141 }
142
143
144 \f
145 ////////////////////////////////////////////////////////////////////////
146 // Special class for magnetic compass ribbon layer.
147 ////////////////////////////////////////////////////////////////////////
148
149 class MagRibbon : public FGTexturedLayer
150 {
151 public:
152   MagRibbon (int w, int h);
153   virtual ~MagRibbon () {}
154
155   virtual void draw () const;
156 };
157
158 MagRibbon::MagRibbon (int w, int h)
159   : FGTexturedLayer(createTexture("Textures/Panel/compass-ribbon.rgb"), w, h)
160 {
161 }
162
163 void
164 MagRibbon::draw () const
165 {
166   double heading = FGSteam::get_MH_deg();
167   double xoffset, yoffset;
168
169   while (heading >= 360.0) {
170     heading -= 360.0;
171   }
172   while (heading < 0.0) {
173     heading += 360.0;
174   }
175
176   if (heading >= 60.0 && heading <= 180.0) {
177     xoffset = heading / 240.0;
178     yoffset = 0.75;
179   } else if (heading >= 150.0 && heading <= 270.0) {
180     xoffset = (heading - 90.0) / 240.0;
181     yoffset = 0.50;
182   } else if (heading >= 240.0 && heading <= 360.0) {
183     xoffset = (heading - 180.0) / 240.0;
184     yoffset = 0.25;
185   } else {
186     if (heading < 270.0)
187       heading += 360.0;
188     xoffset = (heading - 270.0) / 240.0;
189     yoffset = 0.0;
190   }
191
192   xoffset = 1.0 - xoffset;
193                                 // Adjust to put the number in the centre
194   xoffset -= 0.25;
195
196   setTextureCoords(xoffset, yoffset, xoffset + 0.5, yoffset + 0.25);
197   FGTexturedLayer::draw();
198 }
199
200
201 \f
202 ////////////////////////////////////////////////////////////////////////
203 // Static factory functions to create textured gauges.
204 //
205 // These will be replaced first with a giant table, and then with
206 // configuration files read from an external source, but for now
207 // they're hard-coded.
208 ////////////////////////////////////////////////////////////////////////
209
210
211 /**
212  * Construct a magnetic (wet) compass.
213  */
214 static FGPanelInstrument *
215 createMagneticCompass (int x, int y)
216 {
217   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W/2);
218
219   inst->addLayer(new MagRibbon(int(SIX_W*0.8), int(SIX_W*0.2)));
220
221   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
222                  int(SIX_W * (80.0/80.0)), int(SIX_W * (24.0/80.0)),
223                  48.0/128.0, 0.0, 1.0, 24.0/128.0);
224
225   return inst;
226 }
227
228 /**
229  * Construct an airspeed indicator for a single-engine prop.
230  */
231 static FGPanelInstrument *
232 createAirspeedIndicator (int x, int y)
233 {
234   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
235
236                                 // Layer 0: gauge background.
237   inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
238                                0, 0.5, 0.5, 1.0);
239
240                                 // Layer 1: needle.
241                                 // Rotates with airspeed.
242   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
243                  int(SIX_W*(5.0/64.0)), int(SIX_W*(7.0/16.0)),
244                  102.0/128.0, 100.0/128.0, 107.0/128.0, 1.0);
245   inst->addTransformation(FGInstrumentLayer::ROTATION,
246                           FGSteam::get_ASI_kias,
247                           30.0, 220.0, 36.0 / 20.0, -54.0);
248   inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
249   return inst;
250 }
251
252
253 /**
254  * Construct an artificial horizon.
255  */
256 static FGPanelInstrument *
257 createHorizon (int x, int y)
258 {
259   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
260
261                                 // Layer 0: coloured background
262                                 // moves with roll only
263   inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
264                  0.5, 0.5, 1.0, 1.0);
265   inst->addTransformation(FGInstrumentLayer::ROTATION,
266                           FGBFI::getRoll,
267                           -360.0, 360.0, -1.0, 0.0);
268
269                                 // Layer 1: floating horizon
270                                 // moves with roll and pitch
271   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
272                  int(SIX_W * (13.0/16.0)), int(SIX_W * (33.0/64.0)),
273                  15.0/32.0, 54.0/128.0, 28.0/32.0, 87.0/128.0);
274   inst->addTransformation(FGInstrumentLayer::ROTATION,
275                           FGBFI::getRoll,
276                           -360.0, 360.0, -1.0, 0.0);
277   inst->addTransformation(FGInstrumentLayer::YSHIFT,
278                           FGBFI::getPitch,
279                           -20.0, 20.0, -(1.5 / 160.0) * SIX_W, 0.0);
280
281                                 // Layer 2: rim
282                                 // moves with roll only
283   inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
284                  0, 0, 0.5, 0.5);
285   inst->addTransformation(FGInstrumentLayer::ROTATION,
286                           FGBFI::getRoll,
287                           -360.0, 360.0, -1.0, 0.0);
288
289                                 // Layer 3: glass front of gauge
290                                 // fixed, with markings
291   inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
292                  0.5, 0, 1.0, 0.5);
293
294   return inst;
295 }
296
297
298 /**
299  * Construct an altimeter.
300  */
301 static FGPanelInstrument *
302 createAltimeter (int x, int y)
303 {
304   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
305
306                                 // Layer 0: gauge background
307   inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
308                  0.5, 0.5, 1.0, 1.0);
309
310                                 // Layer 1: hundreds needle (long)
311                                 // moves with altitude
312   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
313                  int(SIX_W*(5.0/64.0)), int(SIX_W*(7.0/16.0)),
314                  102.0/128.0, 100.0/128.0, 107.0/128.0, 1.0);
315   inst->addTransformation(FGInstrumentLayer::ROTATION,
316                           FGSteam::get_ALT_ft,
317                           0.0, 100000.0, 360.0 / 1000.0, 0.0);
318   inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
319
320                                 // Layer 2: thousands needle (short)
321                                 // moves with altitude
322   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
323                  int(SIX_W * (6.0/64.0)), int(SIX_W * (18.0/64.0)),
324                  (107.0/128.0), (110.0/128.0), (113.0/128.0), 1.0);
325   inst->addTransformation(FGInstrumentLayer::ROTATION,
326                           FGSteam::get_ALT_ft,
327                           0.0, 100000.0, 360.0 / 10000.0, 0.0);
328   inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W/8.0);
329
330                                 // Layer 3: ten thousands bug (outside)
331                                 // moves with altitude
332   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
333                  int(SIX_W * (4.0/64.0)), int(SIX_W * (4.0/64.0)),
334                  (108.0/128.0), (104.0/128.0), (112.0/128.0), (108.0/128.0));
335   inst->addTransformation(FGInstrumentLayer::ROTATION,
336                           FGSteam::get_ALT_ft,
337                           0.0, 100000.0, 360.0 / 100000.0, 0.0);
338   inst->addTransformation(FGInstrumentLayer::YSHIFT, (SIX_W/2.0) - 4);
339
340   return inst;
341 }
342
343
344 /**
345  * Construct a turn coordinator.
346  */
347 static FGPanelInstrument *
348 createTurnCoordinator (int x, int y)
349 {
350   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
351
352                                 // Layer 0: background
353   inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
354                  0.5, 0, 1.0, 0.5);
355
356                                 // Layer 1: little plane
357                                 // moves with roll
358   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
359                  int(SIX_W * 0.75), int(SIX_W * 0.25),
360                  0.0, 3.0/8.0, 3.0/8.0, 0.5);
361   inst->addTransformation(FGInstrumentLayer::ROTATION,
362                           FGSteam::get_TC_std,
363                           -2.5, 2.5, 20.0, 0.0);
364   inst->addTransformation(FGInstrumentLayer::YSHIFT, int(SIX_W * 0.0625));
365
366                                 // Layer 2: little ball
367                                 // moves with slip/skid
368   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
369                  int(SIX_W * (4.0/64.0)), int(SIX_W * (4.0/64.0)),
370                  (108.0/128.0), (100.0/128.0), (112.0/128.0), (104.0/128.0));
371   inst->addTransformation(FGInstrumentLayer::ROTATION,
372                           FGSteam::get_TC_rad,
373                           -0.1, 0.1, -450.0, 0.0);
374   inst->addTransformation(FGInstrumentLayer::YSHIFT, -(SIX_W/4) + 4);
375
376   return inst;
377 }
378
379
380 /**
381  * Construct a gyro compass.
382  */
383 static FGPanelInstrument *
384 createGyroCompass (int x, int y)
385 {
386   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
387
388                                 // Action: move heading bug
389   inst->addAction(0, SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
390                   new FGAdjustAction(FGBFI::getAPHeadingMag,
391                                      FGBFI::setAPHeadingMag,
392                                      -1.0, -360.0, 360.0, true));
393   inst->addAction(0, SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
394                   new FGAdjustAction(FGBFI::getAPHeadingMag,
395                                      FGBFI::setAPHeadingMag,
396                                      1.0, -360.0, 360.0, true));
397   inst->addAction(1, SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
398                   new FGAdjustAction(FGBFI::getAPHeadingMag,
399                                      FGBFI::setAPHeadingMag,
400                                      -5.0, -360.0, 360.0, true));
401   inst->addAction(1, SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
402                   new FGAdjustAction(FGBFI::getAPHeadingMag,
403                                      FGBFI::setAPHeadingMag,
404                                      5.0, -360.0, 360.0, true));
405
406                                 // Layer 0: compass background
407                                 // rotates with heading
408   inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
409                  0, 0.5, 0.5, 1.0);
410   inst->addTransformation(FGInstrumentLayer::ROTATION,
411                           FGBFI::getHeadingMag,
412                           -720.0, 720.0, -1.0, 0.0);
413
414                                 // Layer 1: heading bug
415                                 // rotates with heading and AP heading
416   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
417                  int(SIX_W * (4.0/64.0)), int(SIX_W * (4.0/64.0)),
418                  (108.0/128.0), (104.0/128.0), (112.0/128.0), (108.0/128.0));
419   inst->addTransformation(FGInstrumentLayer::ROTATION,
420                           FGBFI::getHeadingMag,
421                           -720.0, 720.0, -1.0, 0.0);
422   inst->addTransformation(FGInstrumentLayer::ROTATION,
423                           FGBFI::getAPHeadingMag,
424                           -720.0, 720.0, 1.0, 0.0);
425   inst->addTransformation(FGInstrumentLayer::YSHIFT, (SIX_W/2.0) - 4);
426
427                                 // Layer 2: fixed center
428   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
429                  int(SIX_W * 0.625), int(SIX_W * 0.625),
430                  15.0/32.0, 11.0/16.0, 25.0/32.0, 1.0);
431
432                                 // Layer 3: heading knob
433                                 // rotates with AP heading
434   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
435                  int(SIX_W * (21.0/112.0)), int(SIX_W * (21.0/112.0)),
436                  0, (64.0/128.0), (21.0/128.0), (85.0/128.0));
437   inst->addTransformation(FGInstrumentLayer::XSHIFT, SIX_W/2 - 10); 
438   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
439   inst->addTransformation(FGInstrumentLayer::ROTATION,
440                           FGBFI::getAPHeadingMag,
441                           -360.0, 360.0, 1.0, 0.0);
442
443   return inst;
444 }
445
446
447 /**
448  * Construct a vertical velocity indicator.
449  */
450 static FGPanelInstrument *
451 createVerticalVelocity (int x, int y)
452 {
453   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
454
455                                 // Layer 0: gauge background
456   inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
457                  0, 0, 0.5, 0.5);
458
459                                 // Layer 1: needle
460                                 // moves with vertical velocity
461   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
462                  int(SIX_W*(5.0/64.0)), int(SIX_W*(7.0/16.0)),
463                  102.0/128.0, 100.0/128.0, 107.0/128.0, 1.0);
464   inst->addTransformation(FGInstrumentLayer::ROTATION,
465                           FGSteam::get_VSI_fps,
466                           -2000.0, 2000.0, 42.0/500.0, 270.0);
467   inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
468
469   return inst;
470 }
471
472
473 /**
474  * Construct an RPM gauge.
475  */
476 static FGPanelInstrument *
477 createRPMGauge (int x, int y)
478 {
479   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
480
481                                 // Layer 0: gauge background
482   inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
483                  0, 0.5, 0.5, 1.0);
484
485                                 // Layer 1: long needle
486                                 // FIXME: moves with throttle (for now)
487   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
488                  int(SIX_W*(5.0/64.0)), int(SIX_W*(7.0/16.0)),
489                  102.0/128.0, 100.0/128.0, 107.0/128.0, 1.0);
490   inst->addTransformation(FGInstrumentLayer::ROTATION,
491                           FGBFI::getThrottle,
492                           0.0, 100.0, 300.0, -150.0);
493   inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
494
495   return inst;
496 }
497
498
499 /**
500  * Construct a flap position indicator.
501  */
502 static FGPanelInstrument *
503 createFlapIndicator (int x, int y)
504 {
505   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
506
507                                 // Layer 0: gauge background
508   inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
509                  0.5, 0.5, 1.0, 1.0);
510
511                                 // Layer 1: long needle
512                                 // shifted over, rotates with flap position
513   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
514                  int(SIX_W*(5.0/64.0)), int(SIX_W*(7.0/16.0)),
515                  102.0/128.0, 100.0/128.0, 107.0/128.0, 1.0);
516   inst->addTransformation(FGInstrumentLayer::XSHIFT,
517                           -(SMALL_W / 4) + (SMALL_W / 16));
518   inst->addTransformation(FGInstrumentLayer::ROTATION,
519                           FGBFI::getFlaps,
520                           0.0, 1.0, 120.0, 30.0);
521   inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
522
523   return inst;
524 }
525
526
527 /**
528  * Construct a digital chronometer.
529  */
530 static FGPanelInstrument *
531 createChronometer (int x, int y)
532 {
533   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
534
535                                 // Layer 0: gauge background
536   inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
537                  0.5, 0, 1.0, 0.5);
538
539                                 // Layer 1: text
540                                 // displays current GMT
541   FGTextLayer * text = new FGTextLayer(SMALL_W, SMALL_W);
542   text->addChunk(new FGTextLayer::Chunk(panelGetTime));
543   text->setPointSize(14);
544   text->setColor(0.2, 0.2, 0.2);
545   inst->addLayer(text);
546   inst->addTransformation(FGInstrumentLayer::XSHIFT, SMALL_W * -0.38);
547   inst->addTransformation(FGInstrumentLayer::YSHIFT, SMALL_W * -0.06);
548
549   return inst;
550 }
551
552
553 /**
554  * Construct control-position indicators.
555  */
556 static FGPanelInstrument *
557 createControls (int x, int y)
558 {
559   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
560
561                                 // Layer 0: gauge background
562   inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
563                  0, 0, 0.5, 0.5);
564
565                                 // Layer 1: bug
566                                 // moves left-right with aileron
567   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
568                  int(SIX_W * (4.0/64.0)), int(SIX_W * (4.0/64.0)),
569                  (108.0/128.0), (104.0/128.0), (112.0/128.0), (108.0/128.0));
570   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getAileron,
571                           -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
572   inst->addTransformation(FGInstrumentLayer::YSHIFT, (SIX_W/2.0) - 12);
573
574                                 // Layer 2: bug
575                                 // moves left-right with rudder
576   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
577                  int(SIX_W * (4.0/64.0)), int(SIX_W * (4.0/64.0)),
578                  (108.0/128.0), (104.0/128.0), (112.0/128.0), (108.0/128.0));
579   inst->addTransformation(FGInstrumentLayer::ROTATION, 180.0);
580   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getRudder,
581                           -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
582   inst->addTransformation(FGInstrumentLayer::YSHIFT, (SIX_W/2.0) - 12);
583
584                                 // Layer 3: bug
585                                 // moves up-down with elevator trim
586   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
587                  int(SIX_W * (4.0/64.0)), int(SIX_W * (4.0/64.0)),
588                  (108.0/128.0), (104.0/128.0), (112.0/128.0), (108.0/128.0));
589   inst->addTransformation(FGInstrumentLayer::ROTATION, 270.0);
590   inst->addTransformation(FGInstrumentLayer::YSHIFT,
591                           -SMALL_W * (3.0 / 8.0));
592   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getElevatorTrim,
593                           -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
594   inst->addTransformation(FGInstrumentLayer::YSHIFT, (SIX_W/2.0) - 12);
595
596                                 // Layer 4: bug
597                                 // moves up-down with elevator
598   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
599                  int(SIX_W * (4.0/64.0)), int(SIX_W * (4.0/64.0)),
600                  (108.0/128.0), (104.0/128.0), (112.0/128.0), (108.0/128.0));
601   inst->addTransformation(FGInstrumentLayer::ROTATION, 90.0);
602   inst->addTransformation(FGInstrumentLayer::YSHIFT,
603                           -SMALL_W * (3.0 / 8.0));
604   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getElevator,
605                           -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
606   inst->addTransformation(FGInstrumentLayer::YSHIFT, (SIX_W/2.0) - 12);
607
608   return inst;
609 }
610
611
612 /**
613  * Construct a NAV1 gauge (hardwired).
614  */
615 static FGPanelInstrument *
616 createNAV1 (int x, int y)
617 {
618   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
619
620                                 // Action: change selected radial.
621   inst->addAction(0, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
622                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
623                                      FGBFI::setNAV1SelRadial,
624                                      1.0, 0.0, 360.0, true));
625   inst->addAction(0, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
626                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
627                                      FGBFI::setNAV1SelRadial,
628                                      -1.0, 0.0, 360.0, true));
629   inst->addAction(1, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
630                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
631                                      FGBFI::setNAV1SelRadial,
632                                      5.0, 0.0, 360.0, true));
633   inst->addAction(1, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
634                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
635                                      FGBFI::setNAV1SelRadial,
636                                      -5.0, 0.0, 360.0, true));
637
638                                 // Layer: background
639   inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
640                  0, 0.5, 0.5, 1.0);
641   inst->addTransformation(FGInstrumentLayer::ROTATION,
642                           FGBFI::getNAV1SelRadial,
643                           -360.0, 360.0, -1.0, 0.0);
644
645                                 // Layer 3: face with markings
646   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
647                  SIX_W/2, int(SIX_W * (5.0 / 8.0)),
648                  0, 0, 0.25, (5.0 / 16.0));
649
650                                 // Layer: OBS knob
651                                 // rotates with selected radial
652   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
653                  int(SIX_W * (21.0/112.0)), int(SIX_W * (21.0/112.0)),
654                  0.0, (86.0/128.0), (21.0/128.0), (107.0/128.0));
655   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W/2 + 10); 
656   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
657   inst->addTransformation(FGInstrumentLayer::ROTATION,
658                           FGBFI::getNAV1SelRadial,
659                           -360.0, 360.0, 1.0, 0.0);
660
661                                 // Layer: TO/FROM flag
662   int flag_w = int(SIX_W * (8.0/64.0));
663   int flag_h = int(SIX_W * (6.0/64.0));
664
665   FGTexturedLayer * off =
666     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
667                         flag_w, flag_h,
668                         120.0/128.0, 0.5, 1.0, 70.0/128.0);
669   FGTexturedLayer * from =
670     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
671                         flag_w, flag_h,
672                         120.0/128.0, 80.0/128.0, 1.0, 86.0/128.0);
673   FGTexturedLayer * to =
674     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
675                         flag_w, flag_h,
676                         120.0/128.0, 74.0/128.0, 1.0, 80.0/128.0);
677   FGSwitchLayer * sw1 =
678     new FGSwitchLayer(flag_w, flag_h, panelGetNAV1FROM, from, off);
679   FGSwitchLayer * sw2 =
680     new FGSwitchLayer(flag_w, flag_h, panelGetNAV1TO, to, sw1);
681   inst->addLayer(sw2);
682   inst->addTransformation(FGInstrumentLayer::YSHIFT, -int(SIX_W*0.1875));
683
684                                 // Layer: left-right needle.
685   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
686                  SIX_W * (2.0/64.0), SIX_W/2,
687                  (56.0/128.0), 0.5, (58.0/128.0), 1.0);
688   inst->addTransformation(FGInstrumentLayer::XSHIFT,
689                           FGSteam::get_HackVOR1_deg,
690                           -10.0, 10.0, SIX_W / 40.0, 0.0);
691
692                                 // Layer: glidescope needle
693   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
694                  SIX_W * (2.0/64.0), SIX_W/2,
695                  (56.0/128.0), 0.5, (58.0/128.0), 1.0);
696   inst->addTransformation(FGInstrumentLayer::YSHIFT,
697                           FGSteam::get_HackGS_deg,
698                           -1.0, 1.0, SIX_W / 5.0, 0.0);
699   inst->addTransformation(FGInstrumentLayer::ROTATION,
700                           90 );
701
702   return inst;
703 }
704
705
706 /**
707  * Construct a NAV2 gauge.
708  */
709 static FGPanelInstrument *
710 createNAV2 (int x, int y)
711 {
712   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
713
714                                 // Action: change selected radial.
715   inst->addAction(0, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
716                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
717                                      FGBFI::setNAV2SelRadial,
718                                      1.0, 0.0, 360.0, true));
719   inst->addAction(0, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
720                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
721                                      FGBFI::setNAV2SelRadial,
722                                      -1.0, 0.0, 360.0, true));
723   inst->addAction(1, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
724                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
725                                      FGBFI::setNAV2SelRadial,
726                                      5.0, 0.0, 360.0, true));
727   inst->addAction(1, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
728                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
729                                      FGBFI::setNAV2SelRadial,
730                                      -5.0, 0.0, 360.0, true));
731
732                                 // Layer: background
733   inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
734                  0, 0.5, 0.5, 1.0);
735   inst->addTransformation(FGInstrumentLayer::ROTATION,
736                           FGBFI::getNAV2SelRadial,
737                           -360.0, 360.0, -1.0, 0.0);
738
739                                 // Layer: face with markings.
740   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
741                  SIX_W/2, int(SIX_W * (5.0 / 8.0)),
742                  0, 0, 0.25, (5.0 / 16.0));
743
744                                 // Layer: OBS knob
745                                 // rotates with selected radial
746   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
747                  int(SIX_W * (21.0/112.0)), int(SIX_W * (21.0/112.0)),
748                  0.0, (86.0/128.0), (21.0/128.0), (107.0/128.0));
749   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W/2 + 10); 
750   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
751   inst->addTransformation(FGInstrumentLayer::ROTATION,
752                           FGBFI::getNAV2SelRadial,
753                           -360.0, 360.0, 1.0, 0.0);
754
755                                 // Layer: TO/FROM flag
756   int flag_w = int(SIX_W * (8.0/64.0));
757   int flag_h = int(SIX_W * (6.0/64.0));
758
759   FGTexturedLayer * off =
760     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
761                         flag_w, flag_h,
762                         120.0/128.0, 0.5, 1.0, 70.0/128.0);
763   FGTexturedLayer * from =
764     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
765                         flag_w, flag_h,
766                         120.0/128.0, 80.0/128.0, 1.0, 86.0/128.0);
767   FGTexturedLayer * to =
768     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
769                         flag_w, flag_h,
770                         120.0/128.0, 74.0/128.0, 1.0, 80.0/128.0);
771   FGSwitchLayer * sw1 =
772     new FGSwitchLayer(flag_w, flag_h, panelGetNAV2FROM, from, off);
773   FGSwitchLayer * sw2 =
774     new FGSwitchLayer(flag_w, flag_h, panelGetNAV2TO, to, sw1);
775   inst->addLayer(sw2);
776   inst->addTransformation(FGInstrumentLayer::YSHIFT, -int(SIX_W*0.1875));
777
778                                 // Layer: left-right needle.
779   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
780                  SIX_W * (2.0/64.0), SIX_W/2,
781                  (56.0/128.0), 0.5, (58.0/128.0), 1.0);
782   inst->addTransformation(FGInstrumentLayer::XSHIFT,
783                           FGSteam::get_HackVOR2_deg,
784                           -10.0, 10.0, SIX_W / 40.0, 0.0);
785
786   return inst;
787 }
788
789
790 /**
791  * Construct an ADF gauge.
792  */
793 static FGPanelInstrument *
794 createADF (int x, int y)
795 {
796   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
797
798                                 // Action: change selected rotation.
799   inst->addAction(0, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
800                   new FGAdjustAction(FGBFI::getADFRotation,
801                                      FGBFI::setADFRotation,
802                                      -1.0, 0.0, 360.0, true));
803   inst->addAction(0, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
804                   new FGAdjustAction(FGBFI::getADFRotation,
805                                      FGBFI::setADFRotation,
806                                      1.0, 0.0, 360.0, true));
807   inst->addAction(1, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
808                   new FGAdjustAction(FGBFI::getADFRotation,
809                                      FGBFI::setADFRotation,
810                                      -5.0, 0.0, 360.0, true));
811   inst->addAction(1, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
812                   new FGAdjustAction(FGBFI::getADFRotation,
813                                      FGBFI::setADFRotation,
814                                      5.0, 0.0, 360.0, true));
815
816                                 // Layer 0: background
817   inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
818                  0, 0.5, 0.5, 1.0);
819   inst->addTransformation(FGInstrumentLayer::ROTATION,
820                           FGBFI::getADFRotation,
821                           0.0, 360.0, 1.0, 0.0);
822
823                                 // Layer 1: Direction needle.
824   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
825                  SIX_W * (6.0/64.0), SIX_W * (40.0/64.0),
826                  (120.0/128.0), (88.0/128.0), 1.0, 1.0);
827   inst->addTransformation(FGInstrumentLayer::ROTATION,
828                           FGSteam::get_HackADF_deg,
829                           -720.0, 720.0, 1.0, 0.0);
830
831                                 // Layer 2: heading knob
832                                 // rotates with selected radial
833   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
834                  int(SIX_W * (21.0/112.0)), int(SIX_W * (21.0/112.0)),
835                  0.0, (107.0/128.0), (21.0/128.0), 1.0);
836   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W/2 + 10); 
837   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
838   inst->addTransformation(FGInstrumentLayer::ROTATION,
839                           FGBFI::getADFRotation,
840                           -360.0, 360.0, -1.0, 0.0);
841
842                                 // Layer 3: airplace at centre
843   inst->addLayer(createTexture("Textures/Panel/misc-1.rgb"),
844                  int(SIX_W * (20.0/64.0)), int(SIX_W * (16.0/64.0)),
845                  102.0/128.0, 32.0/128.0, 1.0, 48.0/128.0);
846
847   return inst;
848 }
849
850
851 /**
852  * Create Nav-Com radio 1.
853  */
854 static FGPanelInstrument *
855 createNavCom1 (int x, int y)
856 {
857   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
858
859                                 // Use the button to swap standby and active
860                                 // NAV frequencies
861   inst->addAction(0, int(SIX_W * .375), -SIX_W/4, SIX_W/4, SIX_W/4,
862                   new FGSwapAction(FGBFI::getNAV1Freq,
863                                    FGBFI::setNAV1Freq,
864                                    FGBFI::getNAV1AltFreq,
865                                    FGBFI::setNAV1AltFreq));
866
867                                 // Use the knob to tune the standby NAV
868   inst->addAction(0, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
869                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
870                                      FGBFI::setNAV1AltFreq,
871                                      -0.05, 108.0, 117.95, true));
872   inst->addAction(0, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
873                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
874                                      FGBFI::setNAV1AltFreq,
875                                      0.05, 108.0, 117.95, true));
876   inst->addAction(1, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
877                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
878                                      FGBFI::setNAV1AltFreq,
879                                      -0.5, 108.0, 117.95, true));
880   inst->addAction(1, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
881                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
882                                      FGBFI::setNAV1AltFreq,
883                                      0.5, 108.0, 117.95, true));
884
885                                 // Layer 0: background
886   FGTexturedLayer * layer =
887     new FGTexturedLayer(createTexture("Textures/Panel/radios-1.rgb"),
888                         SIX_W*2, SIX_W/2, 0.0, 0.75, 1.0, 1.0);
889   inst->addLayer(layer);
890
891                                 // Layer 1: NAV frequencies
892   FGTextLayer * text = new FGTextLayer(SIX_W*2, SMALL_W/2);
893   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV1Freq, "%.2f"));
894   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV1AltFreq, "%7.2f"));
895   text->setPointSize(14);
896   text->setColor(1.0, 0.5, 0.0);
897   inst->addLayer(text);
898   inst->addTransformation(FGInstrumentLayer::XSHIFT, 3);
899   inst->addTransformation(FGInstrumentLayer::YSHIFT, 5);
900
901   return inst;
902 }
903
904
905 /**
906  * Create Nav-Com radio 2.
907  */
908 static FGPanelInstrument *
909 createNavCom2 (int x, int y)
910 {
911   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
912
913                                 // Use the button to swap standby and active
914                                 // NAV frequencies
915   inst->addAction(0, int(SIX_W * .375), -SIX_W/4, SIX_W/4, SIX_W/4,
916                   new FGSwapAction(FGBFI::getNAV2Freq,
917                                    FGBFI::setNAV2Freq,
918                                    FGBFI::getNAV2AltFreq,
919                                    FGBFI::setNAV2AltFreq));
920
921                                 // Use the knob to tune the standby NAV
922   inst->addAction(0, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
923                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
924                                      FGBFI::setNAV2AltFreq,
925                                      -0.05, 108.0, 117.95, true));
926   inst->addAction(0, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
927                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
928                                      FGBFI::setNAV2AltFreq,
929                                      0.05, 108.0, 117.95, true));
930   inst->addAction(1, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
931                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
932                                      FGBFI::setNAV2AltFreq,
933                                      -0.5, 108.0, 117.95, true));
934   inst->addAction(1, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
935                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
936                                      FGBFI::setNAV2AltFreq,
937                                      0.5, 108.0, 117.95, true));
938
939                                 // Layer 0: background
940   FGTexturedLayer * layer =
941     new FGTexturedLayer(createTexture("Textures/Panel/radios-1.rgb"),
942                         SIX_W*2, SIX_W/2, 0.0, 0.75, 1.0, 1.0);
943   inst->addLayer(layer);
944
945                                 // Layer 1: NAV frequencies
946   FGTextLayer * text = new FGTextLayer(SIX_W*2, SIX_W/2);
947   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV2Freq, "%.2f"));
948   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV2AltFreq, "%7.2f"));
949   text->setPointSize(14);
950   text->setColor(1.0, 0.5, 0.0);
951   inst->addLayer(text);
952   inst->addTransformation(FGInstrumentLayer::XSHIFT, 3);
953   inst->addTransformation(FGInstrumentLayer::YSHIFT, 5);
954
955   return inst;
956 }
957
958
959 /**
960  * Create ADF radio.
961  */
962 static FGPanelInstrument *
963 createADFRadio (int x, int y)
964 {
965   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
966
967                                 // Use the knob to tune the standby NAV
968   inst->addAction(0, int(SIX_W * 0.7), int(-SIX_W * 0.07),
969                   int(SIX_W * 0.09), int(SIX_W * 0.14),
970                   new FGAdjustAction(FGBFI::getADFFreq,
971                                      FGBFI::setADFFreq,
972                                      -1.0, 100.0, 1299, true));
973   inst->addAction(0, int(SIX_W * 0.79), int(-SIX_W * 0.07),
974                   int(SIX_W * 0.09), int(SIX_W * 0.14),
975                   new FGAdjustAction(FGBFI::getADFFreq,
976                                      FGBFI::setADFFreq,
977                                      1.0, 100.0, 1299, true));
978   inst->addAction(1, int(SIX_W * 0.7), int(-SIX_W * 0.07),
979                   int(SIX_W * 0.09), int(SIX_W * 0.14),
980                   new FGAdjustAction(FGBFI::getADFFreq,
981                                      FGBFI::setADFFreq,
982                                      -25.0, 100.0, 1299, true));
983   inst->addAction(1, int(SIX_W * 0.79), int(-SIX_W * 0.07),
984                   int(SIX_W * 0.09), int(SIX_W * 0.14),
985                   new FGAdjustAction(FGBFI::getADFFreq,
986                                      FGBFI::setADFFreq,
987                                      25.0, 100.0, 1299, true));
988
989                                 // Layer 0: background
990   FGTexturedLayer * layer =
991     new FGTexturedLayer(createTexture("Textures/Panel/radios-1.rgb"),
992                         SIX_W*2, SIX_W/2, 0.0, 0.5, 1.0, 0.75);
993   inst->addLayer(layer);
994
995                                 // Layer: ADF frequency
996   FGTextLayer * text = new FGTextLayer(SIX_W*2, SIX_W/2);
997   text->addChunk(new FGTextLayer::Chunk(FGBFI::getADFFreq, "%4.0f"));
998   text->setPointSize(14);
999   text->setColor(1.0, 0.5, 0.0);
1000   inst->addLayer(text);
1001   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W + 18);
1002
1003   return inst;
1004 }
1005
1006
1007 /**
1008  * Construct the autopilot.
1009  */
1010
1011 FGPanelInstrument *
1012 createAP (int x, int y)
1013 {
1014   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/4);
1015
1016                                 // Action: select HDG button
1017   inst->addAction(0, int(-SIX_W*0.6125), -SIX_W/16, SIX_W/4, SIX_W/8,
1018                   new FGToggleAction(FGBFI::getAPHeadingLock,
1019                                      FGBFI::setAPHeadingLock));
1020
1021                                 // Action: select NAV button
1022   inst->addAction(0, int(-SIX_W*0.3625), -SIX_W/16, SIX_W/4, SIX_W/8,
1023                   new FGToggleAction(FGBFI::getAPNAV1Lock,
1024                                      FGBFI::setAPNAV1Lock));
1025
1026                                 // Action: select ALT button
1027   inst->addAction(0, int(-SIX_W*0.1125), -SIX_W/16, SIX_W/4, SIX_W/8,
1028                   new FGToggleAction(FGBFI::getAPAltitudeLock,
1029                                      FGBFI::setAPAltitudeLock));
1030
1031                                 // Layer: AP background
1032   FGTexturedLayer * layer;
1033   layer = new FGTexturedLayer(createTexture("Textures/Panel/radios-1.rgb"),
1034                               SIX_W*2, SIX_W/4,
1035                               0.0, 0.375, 1.0, 0.5);
1036   inst->addLayer(layer);
1037
1038                                 // Display HDG button
1039   FGTexturedLayer *l1 =
1040     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1041                         SIX_W/4, SIX_W/8,
1042                         39.0/128.0, 118.0/128.0, 54.0/128.0, 1.0);
1043   FGTexturedLayer *l2 =
1044     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1045                         SIX_W/4, SIX_W/8,
1046                         22.0/128.0, 118.0/128.0, 37.0/128.0, 1.0);
1047   FGSwitchLayer * sw =
1048     new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPHeadingLock, l1, l2);
1049   inst->addLayer(sw);
1050   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W * 0.5);
1051
1052                                 // Display NAV button
1053   l1 =
1054     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1055                         SIX_W/4, SIX_W/8,
1056                         39.0/128.0, 106.0/128.0, 54.0/128.0, 116.0/128.0);
1057   l2 =
1058     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1059                         SIX_W/4, SIX_W/8,
1060                         22.0/128.0, 106.0/128.0, 37.0/128.0, 116.0/128.0);
1061   sw =
1062     new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPNAV1Lock, l1, l2);
1063   inst->addLayer(sw);
1064   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W * 0.25);
1065
1066                                 // Display ALT button
1067   l1 =
1068     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1069                         SIX_W/4, SIX_W/8,
1070                         39.0/128.0, 82.0/128.0, 54.0/128.0, 92.0/128.0);
1071   l2 =
1072     new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1073                         SIX_W/4, SIX_W/8,
1074                         22.0/128.0, 82.0/128.0, 37.0/128.0, 92.0/128.0);
1075   sw =
1076     new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPAltitudeLock, l1, l2);
1077   inst->addLayer(sw);
1078
1079   return inst;
1080 }
1081
1082 FGPanelInstrument * 
1083 createDME (int x, int y)
1084 {
1085   FGLayeredInstrument * inst =
1086     new FGLayeredInstrument(x, y, int(SIX_W * 0.75), int(SIX_W * 0.25));
1087
1088                                 // Layer: background
1089   FGTexturedLayer * layer =
1090     new FGTexturedLayer(createTexture("Textures/Panel/radios-1.rgb"),
1091                         int(SIX_W * 0.75), int(SIX_W * 0.25),
1092                         0.0, 0.25, 0.375, 0.375);
1093   inst->addLayer(layer);
1094
1095                                 // Layer: current distance
1096
1097   FGTextLayer * text1 = new FGTextLayer(SIX_W/2, SIX_W/4);
1098   text1->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV1DistDME, "%05.1f",
1099                                          METER_TO_NM));
1100   text1->setPointSize(12);
1101   text1->setColor(1.0, 0.5, 0.0);
1102
1103   FGTextLayer * text2 = new FGTextLayer(SIX_W/2, SIX_W/4);
1104   text2->addChunk(new FGTextLayer::Chunk("---.-"));
1105   text2->setPointSize(12);
1106   text2->setColor(1.0, 0.5, 0.0);
1107
1108   FGSwitchLayer * sw =
1109     new FGSwitchLayer(SIX_W/2, SIX_W/4, FGBFI::getNAV1DMEInRange,
1110                       text1, text2);
1111
1112   inst->addLayer(sw);
1113   inst->addTransformation(FGInstrumentLayer::XSHIFT, -20);
1114   inst->addTransformation(FGInstrumentLayer::YSHIFT, -6);
1115
1116   return inst;
1117 }
1118
1119
1120 \f
1121 ////////////////////////////////////////////////////////////////////////
1122 // Construct a panel for a small, single-prop plane.
1123 ////////////////////////////////////////////////////////////////////////
1124
1125 FGPanel *
1126 fgCreateSmallSinglePropPanel (int xpos, int ypos, int finx, int finy)
1127 {
1128   int w = finx - xpos;
1129   int h = finy - ypos;
1130   FGPanel * panel = new FGPanel(xpos, ypos, w, h);
1131   int x, y;
1132
1133   x = SIX_X;
1134   y = SIX_Y;
1135
1136                                 // Set the background texture
1137   panel->setBackground(createTexture("Textures/Panel/panel-bg.rgb"));
1138
1139                                 // Mag compass at top.
1140   panel->addInstrument(createMagneticCompass((w / 2),
1141                                              int(h * 0.5768) + (SIX_W / 8)));
1142
1143                                 // Chronometer alone at side
1144   x = SIX_X - SIX_SPACING - 8;
1145   panel->addInstrument(createChronometer(x, y));
1146
1147                                 // Top row
1148   x = SIX_X;
1149   panel->addInstrument(createAirspeedIndicator(x, y));
1150   x += SIX_SPACING;
1151   panel->addInstrument(createHorizon(x, y));
1152   x += SIX_SPACING;
1153   panel->addInstrument(createAltimeter(x, y));
1154   x += SIX_SPACING + 20;
1155   panel->addInstrument(createNAV1(x, y));
1156
1157                                 // Middle row
1158   x = SIX_X;
1159   y -= SIX_SPACING;
1160   panel->addInstrument(createTurnCoordinator(x, y));
1161   x += SIX_SPACING;
1162   panel->addInstrument(createGyroCompass(x, y));
1163   x += SIX_SPACING;
1164   panel->addInstrument(createVerticalVelocity(x, y));
1165   x += SIX_SPACING + 20;
1166   panel->addInstrument(createNAV2(x, y));
1167
1168                                 // Bottom row
1169   x = SIX_X;
1170   y -= SIX_SPACING + 10;
1171   panel->addInstrument(createControls(x, y));
1172   x += SIX_SPACING;
1173   panel->addInstrument(createFlapIndicator(x, y));
1174   x += SIX_SPACING;
1175   panel->addInstrument(createRPMGauge(x, y));
1176   x += SIX_SPACING + 20;
1177   y += 10;
1178   panel->addInstrument(createADF(x, y));
1179
1180                                 // Radio stack
1181   x = SIX_X + (SIX_SPACING * 5);
1182   y = SIX_Y;
1183   panel->addInstrument(createDME(x, y));
1184   y -= (int)(SIX_W * 0.375);
1185   panel->addInstrument(createNavCom1(x, y));
1186   y -= SIX_W / 2;
1187   panel->addInstrument(createNavCom2(x, y));
1188   y -= SIX_W / 2;
1189   panel->addInstrument(createADFRadio(x, y));
1190   y -= (int)(SIX_W * 0.375);
1191   panel->addInstrument(createAP(x, y));
1192
1193   return panel;
1194 }
1195
1196 // end of sp_panel.cxx