]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/sp_panel.cxx
ADF tuner fixes so that it goes from 100 to 1299 without decimal steps.
[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
36                                 // Macros for instrument sizes
37                                 // (these aren't used consistently
38                                 // anyway, and should probably be
39                                 // removed).
40 #define SIX_X 200
41 #define SIX_Y 345
42 #define SIX_W 128
43 #define SIX_SPACING (SIX_W + 5)
44 #define SMALL_W 112
45
46
47 \f
48 ////////////////////////////////////////////////////////////////////////
49 // Static functions for obtaining settings.
50 ////////////////////////////////////////////////////////////////////////
51
52 static char * panelGetTime ()
53 {
54   static char buf[1024];        // FIXME: not thread-safe
55   struct tm * t = FGTime::cur_time_params->getGmt();
56   sprintf(buf, " %.2d:%.2d:%.2d",
57           t->tm_hour, t->tm_min, t->tm_sec);
58   return buf;
59 }
60
61
62 \f
63 ////////////////////////////////////////////////////////////////////////
64 // Static factory functions to create textured gauges.
65 //
66 // These will be replaced first with a giant table, and then with
67 // configuration files read from an external source, but for now
68 // they're hard-coded.
69 ////////////////////////////////////////////////////////////////////////
70
71
72 #define createTexture(a) FGTextureManager::createTexture(a)
73
74 /**
75  * Construct an airspeed indicator for a single-engine prop.
76  */
77 static FGPanelInstrument *
78 createAirspeedIndicator (int x, int y)
79 {
80   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
81
82                                 // Layer 0: gauge background.
83   inst->addLayer(createTexture("Textures/Panel/airspeed.rgb"));
84
85                                 // Layer 1: needle.
86                                 // Rotates with airspeed.
87   inst->addLayer(createTexture("Textures/Panel/long-needle.rgb"));
88   inst->addTransformation(FGInstrumentLayer::ROTATION,
89                           FGSteam::get_ASI_kias,
90                           30.0, 220.0, 36.0 / 20.0, -54.0);
91   return inst;
92 }
93
94
95 /**
96  * Construct an artificial horizon.
97  */
98 static FGPanelInstrument *
99 createHorizon (int x, int y)
100 {
101   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
102
103                                 // Layer 0: coloured background
104                                 // moves with roll only
105   inst->addLayer(createTexture("Textures/Panel/horizon-bg.rgb"));
106   inst->addTransformation(FGInstrumentLayer::ROTATION,
107                           FGBFI::getRoll,
108                           -360.0, 360.0, -1.0, 0.0);
109
110                                 // Layer 1: floating horizon
111                                 // moves with roll and pitch
112   inst->addLayer(createTexture("Textures/Panel/horizon-float.rgb"));
113   inst->addTransformation(FGInstrumentLayer::ROTATION,
114                           FGBFI::getRoll,
115                           -360.0, 360.0, -1.0, 0.0);
116   inst->addTransformation(FGInstrumentLayer::YSHIFT,
117                           FGBFI::getPitch,
118                           -20.0, 20.0, -(1.5 / 160.0) * SIX_W, 0.0);
119
120                                 // Layer 2: rim
121                                 // moves with roll only
122   inst->addLayer(createTexture("Textures/Panel/horizon-rim.rgb"));
123   inst->addTransformation(FGInstrumentLayer::ROTATION,
124                           FGBFI::getRoll,
125                           -360.0, 360.0, -1.0, 0.0);
126
127                                 // Layer 3: glass front of gauge
128                                 // fixed, with markings
129   inst->addLayer(createTexture("Textures/Panel/horizon-fg.rgb"));
130
131   return inst;
132 }
133
134
135 /**
136  * Construct an altimeter.
137  */
138 static FGPanelInstrument *
139 createAltimeter (int x, int y)
140 {
141   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
142
143                                 // Layer 0: gauge background
144   inst->addLayer(createTexture("Textures/Panel/altimeter.rgb"));
145
146                                 // Layer 1: hundreds needle (long)
147                                 // moves with altitude
148   inst->addLayer(createTexture("Textures/Panel/long-needle.rgb"));
149   inst->addTransformation(FGInstrumentLayer::ROTATION,
150                           FGSteam::get_ALT_ft,
151                           0.0, 100000.0, 360.0 / 1000.0, 0.0);
152
153                                 // Layer 2: thousands needle (short)
154                                 // moves with altitude
155   inst->addLayer(createTexture("Textures/Panel/short-needle.rgb"));
156   inst->addTransformation(FGInstrumentLayer::ROTATION,
157                           FGSteam::get_ALT_ft,
158                           0.0, 100000.0, 360.0 / 10000.0, 0.0);
159
160                                 // Layer 3: ten thousands bug (outside)
161                                 // moves with altitude
162   inst->addLayer(createTexture("Textures/Panel/bug.rgb"));
163   inst->addTransformation(FGInstrumentLayer::ROTATION,
164                           FGSteam::get_ALT_ft,
165                           0.0, 100000.0, 360.0 / 100000.0, 0.0);
166
167   return inst;
168 }
169
170
171 /**
172  * Construct a turn coordinator.
173  */
174 static FGPanelInstrument *
175 createTurnCoordinator (int x, int y)
176 {
177   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
178
179                                 // Layer 0: background
180   inst->addLayer(createTexture("Textures/Panel/turn-bg.rgb"));
181
182                                 // Layer 1: little plane
183                                 // moves with roll
184   inst->addLayer(createTexture("Textures/Panel/turn.rgb"));
185   inst->addTransformation(FGInstrumentLayer::ROTATION,
186                           FGSteam::get_TC_std,
187                           -2.5, 2.5, 20.0, 0.0);
188
189                                 // Layer 2: little ball
190                                 // moves with slip/skid
191   inst->addLayer(createTexture("Textures/Panel/ball.rgb"));
192   inst->addTransformation(FGInstrumentLayer::ROTATION,
193                           FGSteam::get_TC_rad,
194                           -0.1, 0.1, -450.0, 0.0);
195
196   return inst;
197 }
198
199
200 /**
201  * Construct a gyro compass.
202  */
203 static FGPanelInstrument *
204 createGyroCompass (int x, int y)
205 {
206   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
207
208                                 // Action: move heading bug
209   inst->addAction(0, SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
210                   new FGAdjustAction(FGBFI::getAPHeading,
211                                      FGBFI::setAPHeading,
212                                      -1.0, -360.0, 360.0, true));
213   inst->addAction(0, SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
214                   new FGAdjustAction(FGBFI::getAPHeading,
215                                      FGBFI::setAPHeading,
216                                      1.0, -360.0, 360.0, true));
217   inst->addAction(1, SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
218                   new FGAdjustAction(FGBFI::getAPHeading,
219                                      FGBFI::setAPHeading,
220                                      -5.0, -360.0, 360.0, true));
221   inst->addAction(1, SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
222                   new FGAdjustAction(FGBFI::getAPHeading,
223                                      FGBFI::setAPHeading,
224                                      5.0, -360.0, 360.0, true));
225
226                                 // Layer 0: compass background
227                                 // rotates with heading
228   inst->addLayer(createTexture("Textures/Panel/gyro-bg.rgb"));
229   inst->addTransformation(FGInstrumentLayer::ROTATION,
230                           FGSteam::get_MH_deg,
231                           -720.0, 720.0, -1.0, 0.0);
232
233                                 // Layer 1: heading bug
234                                 // rotates with heading and AP heading
235   inst->addLayer(createTexture("Textures/Panel/bug.rgb"));
236   inst->addTransformation(FGInstrumentLayer::ROTATION,
237                           FGSteam::get_MH_deg,
238                           -720.0, 720.0, -1.0, 0.0);
239   inst->addTransformation(FGInstrumentLayer::ROTATION,
240                           FGBFI::getAPHeading,
241                           -720.0, 720.0, 1.0, 0.0);
242
243                                 // Layer 2: fixed center
244   inst->addLayer(createTexture("Textures/Panel/gyro-fg.rgb"));
245
246                                 // Layer 3: heading knob
247                                 // rotates with AP heading
248   inst->addLayer(new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
249                                      SIX_W/4, SIX_W/4, 0.0, 0.25, 0.25, 0.5));
250   inst->addTransformation(FGInstrumentLayer::XSHIFT, SIX_W/2 - 10); 
251   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
252   inst->addTransformation(FGInstrumentLayer::ROTATION,
253                           FGBFI::getAPHeading,
254                           -360.0, 360.0, 1.0, 0.0);
255
256   return inst;
257 }
258
259
260 /**
261  * Construct a vertical velocity indicator.
262  */
263 static FGPanelInstrument *
264 createVerticalVelocity (int x, int y)
265 {
266   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
267
268                                 // Layer 0: gauge background
269   inst->addLayer(createTexture("Textures/Panel/vertical.rgb"));
270
271                                 // Layer 1: needle
272                                 // moves with vertical velocity
273   inst->addLayer(createTexture("Textures/Panel/long-needle.rgb"));
274   inst->addTransformation(FGInstrumentLayer::ROTATION,
275                           FGSteam::get_VSI_fps,
276                           -2000.0, 2000.0, 42.0/500.0, 270.0);
277
278   return inst;
279 }
280
281
282 /**
283  * Construct an RPM gauge.
284  */
285 static FGPanelInstrument *
286 createRPMGauge (int x, int y)
287 {
288   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
289
290                                 // Layer 0: gauge background
291   inst->addLayer(createTexture("Textures/Panel/rpm.rgb"));
292
293                                 // Layer 1: long needle
294                                 // FIXME: moves with throttle (for now)
295   inst->addLayer(createTexture("Textures/Panel/long-needle.rgb"));
296   inst->addTransformation(FGInstrumentLayer::ROTATION,
297                           FGBFI::getThrottle,
298                           0.0, 100.0, 300.0, -150.0);
299
300   return inst;
301 }
302
303
304 /**
305  * Construct a flap position indicator.
306  */
307 static FGPanelInstrument *
308 createFlapIndicator (int x, int y)
309 {
310   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
311
312                                 // Layer 0: gauge background
313   inst->addLayer(createTexture("Textures/Panel/flaps.rgb"));
314
315                                 // Layer 1: long needle
316                                 // shifted over, rotates with flap position
317   inst->addLayer(createTexture("Textures/Panel/long-needle.rgb"));
318   inst->addTransformation(FGInstrumentLayer::XSHIFT,
319                           -(SMALL_W / 4) + (SMALL_W / 16));
320   inst->addTransformation(FGInstrumentLayer::ROTATION,
321                           FGBFI::getFlaps,
322                           0.0, 1.0, 120.0, 30.0);
323
324   return inst;
325 }
326
327 static FGPanelInstrument *
328 createChronometer (int x, int y)
329 {
330   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
331
332                                 // Layer 0: gauge background
333   inst->addLayer(createTexture("Textures/Panel/clock.rgb"));
334
335                                 // Layer 1: text
336                                 // displays current GMT
337   FGTextLayer * text = new FGTextLayer(SMALL_W, SMALL_W);
338   text->addChunk(new FGTextLayer::Chunk(panelGetTime));
339   text->setPointSize(14);
340   text->setColor(0.2, 0.2, 0.2);
341   inst->addLayer(text);
342   inst->addTransformation(FGInstrumentLayer::XSHIFT, SMALL_W * -0.38);
343   inst->addTransformation(FGInstrumentLayer::YSHIFT, SMALL_W * -0.06);
344
345   return inst;
346 }
347
348
349 /**
350  * Construct control-position indicators.
351  */
352 static FGPanelInstrument *
353 createControls (int x, int y)
354 {
355   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
356
357                                 // Layer 0: gauge background
358   inst->addLayer(createTexture("Textures/Panel/controls.rgb"));
359
360                                 // Layer 1: bug
361                                 // moves left-right with aileron
362   inst->addLayer(createTexture("Textures/Panel/bug.rgb"));
363   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getAileron,
364                           -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
365
366                                 // Layer 2: bug
367                                 // moves left-right with rudder
368   inst->addLayer(createTexture("Textures/Panel/bug.rgb"));
369   inst->addTransformation(FGInstrumentLayer::ROTATION, 180.0);
370   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getRudder,
371                           -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
372
373                                 // Layer 3: bug
374                                 // moves up-down with elevator trim
375   inst->addLayer(createTexture("Textures/Panel/bug.rgb"));
376   inst->addTransformation(FGInstrumentLayer::ROTATION, 270.0);
377   inst->addTransformation(FGInstrumentLayer::YSHIFT,
378                           -SMALL_W * (3.0 / 8.0));
379   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getElevatorTrim,
380                           -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
381
382                                 // Layer 4: bug
383                                 // moves up-down with elevator
384   inst->addLayer(createTexture("Textures/Panel/bug.rgb"));
385   inst->addTransformation(FGInstrumentLayer::ROTATION, 90.0);
386   inst->addTransformation(FGInstrumentLayer::YSHIFT,
387                           -SMALL_W * (3.0 / 8.0));
388   inst->addTransformation(FGInstrumentLayer::XSHIFT, FGBFI::getElevator,
389                           -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
390
391   return inst;
392 }
393
394
395 /**
396  * Construct a NAV1 gauge (hardwired).
397  */
398 static FGPanelInstrument *
399 createNAV1 (int x, int y)
400 {
401   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
402
403                                 // Action: change selected radial.
404   inst->addAction(0, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
405                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
406                                      FGBFI::setNAV1SelRadial,
407                                      1.0, 0.0, 360.0, true));
408   inst->addAction(0, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
409                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
410                                      FGBFI::setNAV1SelRadial,
411                                      -1.0, 0.0, 360.0, true));
412   inst->addAction(1, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
413                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
414                                      FGBFI::setNAV1SelRadial,
415                                      5.0, 0.0, 360.0, true));
416   inst->addAction(1, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
417                   new FGAdjustAction(FGBFI::getNAV1SelRadial,
418                                      FGBFI::setNAV1SelRadial,
419                                      -5.0, 0.0, 360.0, true));
420
421                                 // Layer 0: background
422   inst->addLayer(createTexture("Textures/Panel/gyro-bg.rgb"));
423   inst->addTransformation(FGInstrumentLayer::ROTATION,
424                           FGBFI::getNAV1SelRadial,
425                           -360.0, 360.0, -1.0, 0.0);
426
427                                 // Layer 1: left-right needle.
428   inst->addLayer(createTexture("Textures/Panel/nav-needle.rgb"));
429   inst->addTransformation(FGInstrumentLayer::XSHIFT,
430                           FGSteam::get_HackVOR1_deg,
431                           -10.0, 10.0, SIX_W / 40.0, 0.0);
432
433                                 // Layer 2: glidescope needle
434   inst->addLayer(createTexture("Textures/Panel/nav-needle.rgb"));
435   inst->addTransformation(FGInstrumentLayer::YSHIFT,
436                           FGSteam::get_HackGS_deg,
437                           -1.0, 1.0, SIX_W / 5.0, 0.0);
438   inst->addTransformation(FGInstrumentLayer::ROTATION,
439                           90 );
440
441                                 // Layer 3: face with markings
442   inst->addLayer(createTexture("Textures/Panel/nav-face.rgb"));
443
444                                 // Layer 4: heading knob
445                                 // rotates with selected radial
446   FGTexturedLayer * layer =
447     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
448                         SIX_W/4, SIX_W/4, 0.0, 0.5, 0.25, 0.75);
449   inst->addLayer(layer);
450   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W/2 + 10); 
451   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
452   inst->addTransformation(FGInstrumentLayer::ROTATION,
453                           FGBFI::getNAV1SelRadial,
454                           -360.0, 360.0, 1.0, 0.0);
455
456   return inst;
457 }
458
459
460 /**
461  * Construct a NAV2 gauge.
462  */
463 static FGPanelInstrument *
464 createNAV2 (int x, int y)
465 {
466   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
467
468                                 // Action: change selected radial.
469   inst->addAction(0, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
470                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
471                                      FGBFI::setNAV2SelRadial,
472                                      1.0, 0.0, 360.0, true));
473   inst->addAction(0, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
474                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
475                                      FGBFI::setNAV2SelRadial,
476                                      -1.0, 0.0, 360.0, true));
477   inst->addAction(1, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
478                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
479                                      FGBFI::setNAV2SelRadial,
480                                      5.0, 0.0, 360.0, true));
481   inst->addAction(1, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
482                   new FGAdjustAction(FGBFI::getNAV2SelRadial,
483                                      FGBFI::setNAV2SelRadial,
484                                      -5.0, 0.0, 360.0, true));
485
486                                 // Layer 0: background
487   inst->addLayer(createTexture("Textures/Panel/gyro-bg.rgb"));
488   inst->addTransformation(FGInstrumentLayer::ROTATION,
489                           FGBFI::getNAV2SelRadial,
490                           -360.0, 360.0, -1.0, 0.0);
491
492                                 // Layer 1: left-right needle.
493   inst->addLayer(createTexture("Textures/Panel/nav-needle.rgb"));
494   inst->addTransformation(FGInstrumentLayer::XSHIFT,
495                           FGSteam::get_HackVOR2_deg,
496                           -10.0, 10.0, SIX_W / 40.0, 0.0);
497 //   inst->addTransformation(FGInstrumentLayer::YSHIFT,
498 //                        -SIX_W / 4.4 );
499
500                                 // Layer 2: face with markings.
501   inst->addLayer(createTexture("Textures/Panel/nav-face.rgb"));
502
503                                 // Layer 3: heading knob
504                                 // rotates with selected radial
505   FGTexturedLayer * layer =
506     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
507                         SIX_W/4, SIX_W/4, 0.0, 0.5, 0.25, 0.75);
508   inst->addLayer(layer);
509   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W/2 + 10); 
510   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
511   inst->addTransformation(FGInstrumentLayer::ROTATION,
512                           FGBFI::getNAV2SelRadial,
513                           -360.0, 360.0, 1.0, 0.0);
514
515   return inst;
516 }
517
518
519 /**
520  * Construct an ADF gauge.
521  */
522 static FGPanelInstrument *
523 createADF (int x, int y)
524 {
525   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
526
527                                 // Action: change selected rotation.
528   inst->addAction(0, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
529                   new FGAdjustAction(FGBFI::getADFRotation,
530                                      FGBFI::setADFRotation,
531                                      -1.0, 0.0, 360.0, true));
532   inst->addAction(0, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
533                   new FGAdjustAction(FGBFI::getADFRotation,
534                                      FGBFI::setADFRotation,
535                                      1.0, 0.0, 360.0, true));
536   inst->addAction(1, -SIX_W/2, -SIX_W/2, SIX_W/10, SIX_W/5,
537                   new FGAdjustAction(FGBFI::getADFRotation,
538                                      FGBFI::setADFRotation,
539                                      -5.0, 0.0, 360.0, true));
540   inst->addAction(1, -SIX_W/2 + SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
541                   new FGAdjustAction(FGBFI::getADFRotation,
542                                      FGBFI::setADFRotation,
543                                      5.0, 0.0, 360.0, true));
544
545                                 // Layer 0: background
546   inst->addLayer(createTexture("Textures/Panel/gyro-bg.rgb"));
547   inst->addTransformation(FGInstrumentLayer::ROTATION,
548                           FGBFI::getADFRotation,
549                           0.0, 360.0, 1.0, 0.0);
550
551                                 // Layer 1: Direction needle.
552   inst->addLayer(createTexture("Textures/Panel/long-needle.rgb"));
553   inst->addTransformation(FGInstrumentLayer::ROTATION,
554                           FGSteam::get_HackADF_deg,
555                           -720.0, 720.0, 1.0, 0.0);
556
557                                 // Layer 2: heading knob
558                                 // rotates with selected radial
559   FGTexturedLayer * layer =
560     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
561                         SIX_W/4, SIX_W/4, 0.0, 0.75, 0.25, 1.0);
562   inst->addLayer(layer);
563   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W/2 + 10); 
564   inst->addTransformation(FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10); 
565   inst->addTransformation(FGInstrumentLayer::ROTATION,
566                           FGBFI::getADFRotation,
567                           -360.0, 360.0, -1.0, 0.0);
568   return inst;
569 }
570
571
572 /**
573  * Create Nav-Com radio 1.
574  */
575 static FGPanelInstrument *
576 createNavCom1 (int x, int y)
577 {
578   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
579
580                                 // Use the button to swap standby and active
581                                 // NAV frequencies
582   inst->addAction(0, SIX_W * .375, -SIX_W/4, SIX_W/4, SIX_W/4,
583                   new FGSwapAction(FGBFI::getNAV1Freq,
584                                    FGBFI::setNAV1Freq,
585                                    FGBFI::getNAV1AltFreq,
586                                    FGBFI::setNAV1AltFreq));
587
588                                 // Use the knob to tune the standby NAV
589   inst->addAction(0, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
590                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
591                                      FGBFI::setNAV1AltFreq,
592                                      -0.05, 108.0, 117.95, true));
593   inst->addAction(0, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
594                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
595                                      FGBFI::setNAV1AltFreq,
596                                      0.05, 108.0, 117.95, true));
597   inst->addAction(1, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
598                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
599                                      FGBFI::setNAV1AltFreq,
600                                      -0.5, 108.0, 117.95, true));
601   inst->addAction(1, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
602                   new FGAdjustAction(FGBFI::getNAV1AltFreq,
603                                      FGBFI::setNAV1AltFreq,
604                                      0.5, 108.0, 117.95, true));
605
606                                 // Layer 0: background
607   FGTexturedLayer * layer =
608     new FGTexturedLayer(createTexture("Textures/Panel/radios.rgb"),
609                         SIX_W*2, SIX_W/2, 0.0, 0.75, 1.0, 1.0);
610   inst->addLayer(layer);
611
612                                 // Layer 1: NAV frequencies
613   FGTextLayer * text = new FGTextLayer(SIX_W*2, SMALL_W/2);
614   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV1Freq, "%.2f"));
615   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV1AltFreq, "%7.2f"));
616   text->setPointSize(14);
617   text->setColor(1.0, 0.5, 0.0);
618   inst->addLayer(text);
619   inst->addTransformation(FGInstrumentLayer::XSHIFT, 3);
620   inst->addTransformation(FGInstrumentLayer::YSHIFT, 5);
621
622   return inst;
623 }
624
625
626 /**
627  * Create Nav-Com radio 2.
628  */
629 static FGPanelInstrument *
630 createNavCom2 (int x, int y)
631 {
632   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
633
634                                 // Use the button to swap standby and active
635                                 // NAV frequencies
636   inst->addAction(0, SIX_W * .375, -SIX_W/4, SIX_W/4, SIX_W/4,
637                   new FGSwapAction(FGBFI::getNAV2Freq,
638                                    FGBFI::setNAV2Freq,
639                                    FGBFI::getNAV2AltFreq,
640                                    FGBFI::setNAV2AltFreq));
641
642                                 // Use the knob to tune the standby NAV
643   inst->addAction(0, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
644                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
645                                      FGBFI::setNAV2AltFreq,
646                                      -0.05, 108.0, 117.95, true));
647   inst->addAction(0, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
648                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
649                                      FGBFI::setNAV2AltFreq,
650                                      0.05, 108.0, 117.95, true));
651   inst->addAction(1, SIX_W-SIX_W/4, -SIX_W/4, SIX_W/8, SIX_W/4,
652                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
653                                      FGBFI::setNAV2AltFreq,
654                                      -0.5, 108.0, 117.95, true));
655   inst->addAction(1, SIX_W-SIX_W/8, -SIX_W/4, SIX_W/8, SIX_W/4,
656                   new FGAdjustAction(FGBFI::getNAV2AltFreq,
657                                      FGBFI::setNAV2AltFreq,
658                                      0.5, 108.0, 117.95, true));
659
660                                 // Layer 0: background
661   FGTexturedLayer * layer =
662     new FGTexturedLayer(createTexture("Textures/Panel/radios.rgb"),
663                         SIX_W*2, SIX_W/2, 0.0, 0.75, 1.0, 1.0);
664   inst->addLayer(layer);
665
666                                 // Layer 1: NAV frequencies
667   FGTextLayer * text = new FGTextLayer(SIX_W*2, SIX_W/2);
668   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV2Freq, "%.2f"));
669   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV2AltFreq, "%7.2f"));
670   text->setPointSize(14);
671   text->setColor(1.0, 0.5, 0.0);
672   inst->addLayer(text);
673   inst->addTransformation(FGInstrumentLayer::XSHIFT, 3);
674   inst->addTransformation(FGInstrumentLayer::YSHIFT, 5);
675
676   return inst;
677 }
678
679
680 /**
681  * Create ADF radio.
682  */
683 static FGPanelInstrument *
684 createADFRadio (int x, int y)
685 {
686   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
687
688                                 // Use the knob to tune the standby NAV
689   inst->addAction(0, SIX_W * 0.7, -SIX_W * 0.07, SIX_W * 0.09, SIX_W * 0.14,
690                   new FGAdjustAction(FGBFI::getADFFreq,
691                                      FGBFI::setADFFreq,
692                                      -1.0, 100.0, 1299, true));
693   inst->addAction(0, SIX_W * 0.79, -SIX_W * 0.07, SIX_W * 0.09, SIX_W * 0.14,
694                   new FGAdjustAction(FGBFI::getADFFreq,
695                                      FGBFI::setADFFreq,
696                                      1.0, 100.0, 1299, true));
697   inst->addAction(1, SIX_W * 0.7, -SIX_W * 0.07, SIX_W * 0.09, SIX_W * 0.14,
698                   new FGAdjustAction(FGBFI::getADFFreq,
699                                      FGBFI::setADFFreq,
700                                      -25.0, 100.0, 1299, true));
701   inst->addAction(1, SIX_W * 0.79, -SIX_W * 0.07, SIX_W * 0.09, SIX_W * 0.14,
702                   new FGAdjustAction(FGBFI::getADFFreq,
703                                      FGBFI::setADFFreq,
704                                      25.0, 100.0, 1299, true));
705
706                                 // Layer 0: background
707   FGTexturedLayer * layer =
708     new FGTexturedLayer(createTexture("Textures/Panel/radios.rgb"),
709                         SIX_W*2, SIX_W/2, 0.0, 0.5, 1.0, 0.75);
710   inst->addLayer(layer);
711
712                                 // Layer: ADF frequency
713   FGTextLayer * text = new FGTextLayer(SIX_W*2, SIX_W/2);
714   text->addChunk(new FGTextLayer::Chunk(FGBFI::getADFFreq, "%4.0f"));
715   text->setPointSize(14);
716   text->setColor(1.0, 0.5, 0.0);
717   inst->addLayer(text);
718   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W + 18);
719
720   return inst;
721 }
722
723
724 /**
725  * Construct the autopilot.
726  */
727
728 FGPanelInstrument *
729 createAP (int x, int y)
730 {
731   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/4);
732
733                                 // Action: select HDG button
734   inst->addAction(0, -SIX_W*0.6125, -SIX_W/16, SIX_W/4, SIX_W/8,
735                   new FGToggleAction(FGBFI::getAPHeadingLock,
736                                      FGBFI::setAPHeadingLock));
737
738                                 // Action: select NAV button
739   inst->addAction(0, -SIX_W*0.3625, -SIX_W/16, SIX_W/4, SIX_W/8,
740                   new FGToggleAction(FGBFI::getAPNAV1Lock,
741                                      FGBFI::setAPNAV1Lock));
742
743                                 // Action: select ALT button
744   inst->addAction(0, -SIX_W*0.1125, -SIX_W/16, SIX_W/4, SIX_W/8,
745                   new FGToggleAction(FGBFI::getAPAltitudeLock,
746                                      FGBFI::setAPAltitudeLock));
747
748                                 // Layer: AP background
749   FGTexturedLayer * layer;
750   layer = new FGTexturedLayer(createTexture("Textures/Panel/radios.rgb"),
751                               SIX_W*2, SIX_W/4,
752                               0.0, 0.375, 1.0, 0.5);
753   inst->addLayer(layer);
754
755                                 // Display HDG button
756   FGTexturedLayer *l1 =
757     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
758                         SIX_W/4, SIX_W/8,
759                         7.0/16.0, 27.0/32.0, 9.0/16.0, 15.0/16.0);
760   FGTexturedLayer *l2 =
761     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
762                         SIX_W/4, SIX_W/8,
763                         1.0/4.0, 27.0/32.0, 3.0/8.0, 15.0/16.0);
764   FGSwitchLayer * sw =
765     new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPHeadingLock, l1, l2);
766   inst->addLayer(sw);
767   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W * 0.5);
768
769                                 // Display NAV button
770   l1 =
771     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
772                         SIX_W/4, SIX_W/8,
773                         7.0/16.0, 3.0/4.0, 9.0/16.0, 27.0/32.0);
774   l2 =
775     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
776                         SIX_W/4, SIX_W/8,
777                         1.0/4.0, 3.0/4.0, 3.0/8.0, 27.0/32.0);
778   sw =
779     new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPNAV1Lock, l1, l2);
780   inst->addLayer(sw);
781   inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W * 0.25);
782
783                                 // Display ALT button
784   l1 =
785     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
786                         SIX_W/4, SIX_W/8,
787                         7.0/16.0, 9.0/16.0, 9.0/16.0, 21.0/32.0);
788   l2 =
789     new FGTexturedLayer(createTexture("Textures/Panel/knobs.rgb"),
790                         SIX_W/4, SIX_W/8,
791                         1.0/4.0, 9.0/16.0, 3.0/8.0, 21.0/32.0);
792   sw =
793     new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPAltitudeLock, l1, l2);
794   inst->addLayer(sw);
795
796   return inst;
797 }
798
799 FGPanelInstrument * 
800 createDME (int x, int y)
801 {
802   FGLayeredInstrument * inst = new FGLayeredInstrument(x, y,
803                                                        SIX_W * 0.75,
804                                                        SIX_W * 0.25);
805
806                                 // Layer: background
807   FGTexturedLayer * layer =
808     new FGTexturedLayer(createTexture("Textures/Panel/radios.rgb"),
809                         SIX_W * 0.75, SIX_W * 0.25,
810                         0.0, 0.25, 0.375, 0.375);
811   inst->addLayer(layer);
812
813                                 // Layer: current distance
814   FGTextLayer * text = new FGTextLayer(SIX_W/2, SIX_W/4);
815   text->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV1Dist, "%05.1f",
816                                         METER_TO_NM));
817   text->setPointSize(14);
818   text->setColor(1.0, 0.5, 0.0);
819   inst->addLayer(text);
820   inst->addTransformation(FGInstrumentLayer::XSHIFT, -20);
821   inst->addTransformation(FGInstrumentLayer::YSHIFT, -6);
822
823   return inst;
824 }
825
826
827 \f
828 ////////////////////////////////////////////////////////////////////////
829 // Construct a panel for a small, single-prop plane.
830 ////////////////////////////////////////////////////////////////////////
831
832 FGPanel *
833 fgCreateSmallSinglePropPanel (int x, int y, int finx, int finy)
834 {
835   FGPanel * panel = new FGPanel(x, y, finx - x, finy - y);
836
837   x = SIX_X;
838   y = SIX_Y;
839
840                                 // Set the background texture
841   panel->setBackground(createTexture("Textures/Panel/panel-bg.rgb"));
842
843                                 // Chronometer alone at side
844   x = SIX_X - SIX_SPACING - 8;
845   panel->addInstrument(createChronometer(x, y));
846
847                                 // Top row
848   x = SIX_X;
849   panel->addInstrument(createAirspeedIndicator(x, y));
850   x += SIX_SPACING;
851   panel->addInstrument(createHorizon(x, y));
852   x += SIX_SPACING;
853   panel->addInstrument(createAltimeter(x, y));
854   x += SIX_SPACING + 20;
855   panel->addInstrument(createNAV1(x, y));
856
857                                 // Middle row
858   x = SIX_X;
859   y -= SIX_SPACING;
860   panel->addInstrument(createTurnCoordinator(x, y));
861   x += SIX_SPACING;
862   panel->addInstrument(createGyroCompass(x, y));
863   x += SIX_SPACING;
864   panel->addInstrument(createVerticalVelocity(x, y));
865   x += SIX_SPACING + 20;
866   panel->addInstrument(createNAV2(x, y));
867
868                                 // Bottom row
869   x = SIX_X;
870   y -= SIX_SPACING + 10;
871   panel->addInstrument(createControls(x, y));
872   x += SIX_SPACING;
873   panel->addInstrument(createFlapIndicator(x, y));
874   x += SIX_SPACING;
875   panel->addInstrument(createRPMGauge(x, y));
876   x += SIX_SPACING + 20;
877   y += 10;
878   panel->addInstrument(createADF(x, y));
879
880                                 // Radio stack
881   x = SIX_X + (SIX_SPACING * 5);
882   y = SIX_Y;
883   panel->addInstrument(createDME(x, y));
884   y -= (int)(SIX_W * 0.375);
885   panel->addInstrument(createNavCom1(x, y));
886   y -= SIX_W / 2;
887   panel->addInstrument(createNavCom2(x, y));
888   y -= SIX_W / 2;
889   panel->addInstrument(createADFRadio(x, y));
890   y -= (int)(SIX_W * 0.375);
891   panel->addInstrument(createAP(x, y));
892
893   return panel;
894 }
895
896 // end of sp_panel.cxx