1 // sp_panel.cxx - default, 2D single-engine prop instrument panel
3 // Written by David Megginson, started January 2000.
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.
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.
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.
29 #include <simgear/debug/logstream.hxx>
30 #include <Main/bfi.hxx>
31 #include <Time/fg_time.hxx>
35 #include "radiostack.hxx"
37 // Macros for instrument sizes
38 // (these aren't used consistently
39 // anyway, and should probably be
44 #define SIX_SPACING (SIX_W + 5)
47 #define createTexture(a) FGTextureManager::createTexture(a)
51 ////////////////////////////////////////////////////////////////////////
52 // Static functions for obtaining settings.
54 // These are all temporary, and should be moved somewhere else
55 // as soon as convenient.
56 ////////////////////////////////////////////////////////////////////////
58 static char * panelGetTime ()
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);
67 static bool panelGetNAV1TO ()
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);
78 fabs(heading - var - radial);
79 return (offset <= 20.0 || offset >= 340.0);
86 static bool panelGetNAV1FROM ()
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);
97 fabs(heading - var - radial);
98 return (offset >= 160.0 && offset <= 200.0);
105 static bool panelGetNAV2TO ()
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);
116 fabs(heading - var - radial);
117 return (offset <= 20.0 || offset >= 340.0);
124 static bool panelGetNAV2FROM ()
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);
135 fabs(heading - var - radial);
136 return (offset >= 160.0 && offset <= 200.0);
145 ////////////////////////////////////////////////////////////////////////
146 // Special class for magnetic compass ribbon layer.
147 ////////////////////////////////////////////////////////////////////////
149 class MagRibbon : public FGTexturedLayer
152 MagRibbon (int w, int h);
153 virtual ~MagRibbon () {}
155 virtual void draw () const;
158 MagRibbon::MagRibbon (int w, int h)
159 : FGTexturedLayer(createTexture("Textures/Panel/compass-ribbon.rgb"), w, h)
164 MagRibbon::draw () const
166 double heading = FGSteam::get_MH_deg();
167 double xoffset, yoffset;
169 while (heading >= 360.0) {
172 while (heading < 0.0) {
176 if (heading >= 60.0 && heading <= 180.0) {
177 xoffset = heading / 240.0;
179 } else if (heading >= 150.0 && heading <= 270.0) {
180 xoffset = (heading - 90.0) / 240.0;
182 } else if (heading >= 240.0 && heading <= 360.0) {
183 xoffset = (heading - 180.0) / 240.0;
188 xoffset = (heading - 270.0) / 240.0;
192 xoffset = 1.0 - xoffset;
193 // Adjust to put the number in the centre
196 setTextureCoords(xoffset, yoffset, xoffset + 0.5, yoffset + 0.25);
197 FGTexturedLayer::draw();
202 ////////////////////////////////////////////////////////////////////////
203 // Static factory functions to create textured gauges.
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 ////////////////////////////////////////////////////////////////////////
212 * Construct a magnetic (wet) compass.
214 static FGPanelInstrument *
215 createMagneticCompass (int x, int y)
217 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W/2);
219 inst->addLayer(new MagRibbon(int(SIX_W*0.8), int(SIX_W*0.2)));
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);
229 * Construct an airspeed indicator for a single-engine prop.
231 static FGPanelInstrument *
232 createAirspeedIndicator (int x, int y)
234 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
236 // Layer 0: gauge background.
237 inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
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);
254 * Construct an artificial horizon.
256 static FGPanelInstrument *
257 createHorizon (int x, int y)
259 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
261 // Layer 0: coloured background
262 // moves with roll only
263 inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
265 inst->addTransformation(FGInstrumentLayer::ROTATION,
267 -360.0, 360.0, -1.0, 0.0);
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,
276 -360.0, 360.0, -1.0, 0.0);
277 inst->addTransformation(FGInstrumentLayer::YSHIFT,
279 -20.0, 20.0, -(1.5 / 160.0) * SIX_W, 0.0);
282 // moves with roll only
283 inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
285 inst->addTransformation(FGInstrumentLayer::ROTATION,
287 -360.0, 360.0, -1.0, 0.0);
289 // Layer 3: glass front of gauge
290 // fixed, with markings
291 inst->addLayer(createTexture("Textures/Panel/faces-2.rgb"), -1, -1,
299 * Construct an altimeter.
301 static FGPanelInstrument *
302 createAltimeter (int x, int y)
304 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
306 // Layer 0: gauge background
307 inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
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,
317 0.0, 100000.0, 360.0 / 1000.0, 0.0);
318 inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
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,
327 0.0, 100000.0, 360.0 / 10000.0, 0.0);
328 inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W/8.0);
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,
337 0.0, 100000.0, 360.0 / 100000.0, 0.0);
338 inst->addTransformation(FGInstrumentLayer::YSHIFT, (SIX_W/2.0) - 4);
345 * Construct a turn coordinator.
347 static FGPanelInstrument *
348 createTurnCoordinator (int x, int y)
350 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
352 // Layer 0: background
353 inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
356 // Layer 1: little plane
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,
363 -2.5, 2.5, 20.0, 0.0);
364 inst->addTransformation(FGInstrumentLayer::YSHIFT, int(SIX_W * 0.0625));
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,
373 -0.1, 0.1, -450.0, 0.0);
374 inst->addTransformation(FGInstrumentLayer::YSHIFT, -(SIX_W/4) + 4);
381 * Construct a gyro compass.
383 static FGPanelInstrument *
384 createGyroCompass (int x, int y)
386 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
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));
406 // Layer 0: compass background
407 // rotates with heading
408 inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
410 inst->addTransformation(FGInstrumentLayer::ROTATION,
411 FGBFI::getHeadingMag,
412 -720.0, 720.0, -1.0, 0.0);
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);
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);
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);
448 * Construct a vertical velocity indicator.
450 static FGPanelInstrument *
451 createVerticalVelocity (int x, int y)
453 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
455 // Layer 0: gauge background
456 inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
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);
474 * Construct an RPM gauge.
476 static FGPanelInstrument *
477 createRPMGauge (int x, int y)
479 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
481 // Layer 0: gauge background
482 inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
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,
492 0.0, 100.0, 300.0, -150.0);
493 inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
500 * Construct a flap position indicator.
502 static FGPanelInstrument *
503 createFlapIndicator (int x, int y)
505 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
507 // Layer 0: gauge background
508 inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
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,
520 0.0, 1.0, 120.0, 30.0);
521 inst->addTransformation(FGInstrumentLayer::YSHIFT, SIX_W * 12.0/64.0);
528 * Construct a digital chronometer.
530 static FGPanelInstrument *
531 createChronometer (int x, int y)
533 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
535 // Layer 0: gauge background
536 inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
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);
554 * Construct control-position indicators.
556 static FGPanelInstrument *
557 createControls (int x, int y)
559 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
561 // Layer 0: gauge background
562 inst->addLayer(createTexture("Textures/Panel/faces-3.rgb"), -1, -1,
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);
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);
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);
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);
613 * Construct a NAV1 gauge (hardwired).
615 static FGPanelInstrument *
616 createNAV1 (int x, int y)
618 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
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));
639 inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
641 inst->addTransformation(FGInstrumentLayer::ROTATION,
642 FGBFI::getNAV1SelRadial,
643 -360.0, 360.0, -1.0, 0.0);
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));
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);
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));
665 FGTexturedLayer * off =
666 new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
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"),
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"),
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);
682 inst->addTransformation(FGInstrumentLayer::YSHIFT, -int(SIX_W*0.1875));
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);
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,
707 * Construct a NAV2 gauge.
709 static FGPanelInstrument *
710 createNAV2 (int x, int y)
712 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
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));
733 inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
735 inst->addTransformation(FGInstrumentLayer::ROTATION,
736 FGBFI::getNAV2SelRadial,
737 -360.0, 360.0, -1.0, 0.0);
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));
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);
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));
759 FGTexturedLayer * off =
760 new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
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"),
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"),
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);
776 inst->addTransformation(FGInstrumentLayer::YSHIFT, -int(SIX_W*0.1875));
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);
791 * Construct an ADF gauge.
793 static FGPanelInstrument *
794 createADF (int x, int y)
796 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
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));
816 // Layer 0: background
817 inst->addLayer(createTexture("Textures/Panel/faces-1.rgb"), -1, -1,
819 inst->addTransformation(FGInstrumentLayer::ROTATION,
820 FGBFI::getADFRotation,
821 0.0, 360.0, 1.0, 0.0);
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);
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);
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);
852 * Create Nav-Com radio 1.
854 static FGPanelInstrument *
855 createNavCom1 (int x, int y)
857 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
859 // Use the button to swap standby and active
861 inst->addAction(0, int(SIX_W * .375), -SIX_W/4, SIX_W/4, SIX_W/4,
862 new FGSwapAction(FGBFI::getNAV1Freq,
864 FGBFI::getNAV1AltFreq,
865 FGBFI::setNAV1AltFreq));
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));
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);
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);
906 * Create Nav-Com radio 2.
908 static FGPanelInstrument *
909 createNavCom2 (int x, int y)
911 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
913 // Use the button to swap standby and active
915 inst->addAction(0, int(SIX_W * .375), -SIX_W/4, SIX_W/4, SIX_W/4,
916 new FGSwapAction(FGBFI::getNAV2Freq,
918 FGBFI::getNAV2AltFreq,
919 FGBFI::setNAV2AltFreq));
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));
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);
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);
962 static FGPanelInstrument *
963 createADFRadio (int x, int y)
965 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/2);
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,
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,
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,
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,
987 25.0, 100.0, 1299, true));
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);
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);
1008 * Construct the autopilot.
1012 createAP (int x, int y)
1014 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W*2, SIX_W/4);
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));
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));
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));
1031 // Layer: AP background
1032 FGTexturedLayer * layer;
1033 layer = new FGTexturedLayer(createTexture("Textures/Panel/radios-1.rgb"),
1035 0.0, 0.375, 1.0, 0.5);
1036 inst->addLayer(layer);
1038 // Display HDG button
1039 FGTexturedLayer *l1 =
1040 new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
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"),
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);
1050 inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W * 0.5);
1052 // Display NAV button
1054 new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1056 39.0/128.0, 106.0/128.0, 54.0/128.0, 116.0/128.0);
1058 new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1060 22.0/128.0, 106.0/128.0, 37.0/128.0, 116.0/128.0);
1062 new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPNAV1Lock, l1, l2);
1064 inst->addTransformation(FGInstrumentLayer::XSHIFT, -SIX_W * 0.25);
1066 // Display ALT button
1068 new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1070 39.0/128.0, 82.0/128.0, 54.0/128.0, 92.0/128.0);
1072 new FGTexturedLayer(createTexture("Textures/Panel/misc-1.rgb"),
1074 22.0/128.0, 82.0/128.0, 37.0/128.0, 92.0/128.0);
1076 new FGSwitchLayer(SIX_W/4, SIX_W/8, FGBFI::getAPAltitudeLock, l1, l2);
1083 createDME (int x, int y)
1085 FGLayeredInstrument * inst =
1086 new FGLayeredInstrument(x, y, int(SIX_W * 0.75), int(SIX_W * 0.25));
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);
1095 // Layer: current distance
1097 FGTextLayer * text1 = new FGTextLayer(SIX_W/2, SIX_W/4);
1098 text1->addChunk(new FGTextLayer::Chunk(FGBFI::getNAV1DistDME, "%05.1f",
1100 text1->setPointSize(12);
1101 text1->setColor(1.0, 0.5, 0.0);
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);
1108 FGSwitchLayer * sw =
1109 new FGSwitchLayer(SIX_W/2, SIX_W/4, FGBFI::getNAV1DMEInRange,
1113 inst->addTransformation(FGInstrumentLayer::XSHIFT, -20);
1114 inst->addTransformation(FGInstrumentLayer::YSHIFT, -6);
1121 ////////////////////////////////////////////////////////////////////////
1122 // Construct a panel for a small, single-prop plane.
1123 ////////////////////////////////////////////////////////////////////////
1126 fgCreateSmallSinglePropPanel (int xpos, int ypos, int finx, int finy)
1128 int w = finx - xpos;
1129 int h = finy - ypos;
1130 FGPanel * panel = new FGPanel(xpos, ypos, w, h);
1136 // Set the background texture
1137 panel->setBackground(createTexture("Textures/Panel/panel-bg.rgb"));
1139 // Mag compass at top.
1140 panel->addInstrument(createMagneticCompass((w / 2),
1141 int(h * 0.5768) + (SIX_W / 8)));
1143 // Chronometer alone at side
1144 x = SIX_X - SIX_SPACING - 8;
1145 panel->addInstrument(createChronometer(x, y));
1149 panel->addInstrument(createAirspeedIndicator(x, y));
1151 panel->addInstrument(createHorizon(x, y));
1153 panel->addInstrument(createAltimeter(x, y));
1154 x += SIX_SPACING + 20;
1155 panel->addInstrument(createNAV1(x, y));
1160 panel->addInstrument(createTurnCoordinator(x, y));
1162 panel->addInstrument(createGyroCompass(x, y));
1164 panel->addInstrument(createVerticalVelocity(x, y));
1165 x += SIX_SPACING + 20;
1166 panel->addInstrument(createNAV2(x, y));
1170 y -= SIX_SPACING + 10;
1171 panel->addInstrument(createControls(x, y));
1173 panel->addInstrument(createFlapIndicator(x, y));
1175 panel->addInstrument(createRPMGauge(x, y));
1176 x += SIX_SPACING + 20;
1178 panel->addInstrument(createADF(x, y));
1181 x = SIX_X + (SIX_SPACING * 5);
1183 panel->addInstrument(createDME(x, y));
1184 y -= (int)(SIX_W * 0.375);
1185 panel->addInstrument(createNavCom1(x, y));
1187 panel->addInstrument(createNavCom2(x, y));
1189 panel->addInstrument(createADFRadio(x, y));
1190 y -= (int)(SIX_W * 0.375);
1191 panel->addInstrument(createAP(x, y));
1196 // end of sp_panel.cxx