1 // 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.
35 #include <simgear/debug/logstream.hxx>
36 #include <simgear/misc/fgpath.hxx>
37 #include <Main/options.hxx>
38 #include <Main/views.hxx>
39 #include <Main/bfi.hxx>
40 #include <Objects/texload.h>
41 #include <Autopilot/autopilot.hxx>
42 #include <Time/fg_time.hxx>
44 #include "cockpit.hxx"
49 extern fgAPDataPtr APDataGlobal;
54 #define SIX_SPACING (SIX_W + 5)
59 ////////////////////////////////////////////////////////////////////////
60 // Static functions for obtaining settings.
62 // These should be replaced with functions from a global facade,
63 // or BFI (Big Friendly Interface).
64 ////////////////////////////////////////////////////////////////////////
66 static char * panelGetTime (char * buf)
68 struct tm * t = FGTime::cur_time_params->getGmt();
69 sprintf(buf, " %.2d:%.2d:%.2d",
70 t->tm_hour, t->tm_min, t->tm_sec);
76 ////////////////////////////////////////////////////////////////////////
77 // Static factory functions to create textured gauges.
79 // These will be replaced first with a giant table, and then with
80 // configuration files read from an external source, but for now
81 // they're hard-coded.
82 ////////////////////////////////////////////////////////////////////////
85 #define createTexture(a) FGTextureManager::createTexture(a)
88 * Construct an airspeed indicator for a single-engine prop.
90 static FGPanelInstrument *
91 createAirspeedIndicator (int x, int y)
93 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
95 // Layer 0: gauge background.
96 inst->addLayer(0, createTexture("Textures/Panel/airspeed.rgb"));
99 // Rotates with airspeed.
100 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
101 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
102 FGSteam::get_ASI_kias,
103 30.0, 220.0, 36.0 / 20.0, -54.0);
109 * Construct an artificial horizon.
111 static FGPanelInstrument *
112 createHorizon (int x, int y)
114 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
116 // Layer 0: coloured background
117 // moves with roll only
118 inst->addLayer(0, createTexture("Textures/Panel/horizon-bg.rgb"));
119 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
121 -360.0, 360.0, -1.0, 0.0);
123 // Layer 1: floating horizon
124 // moves with roll and pitch
125 inst->addLayer(1, createTexture("Textures/Panel/horizon-float.rgb"));
126 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
128 -360.0, 360.0, -1.0, 0.0);
129 inst->addTransformation(1, FGInstrumentLayer::YSHIFT,
131 -20.0, 20.0, -(1.5 / 160.0) * SIX_W, 0.0);
134 // moves with roll only
135 inst->addLayer(2, createTexture("Textures/Panel/horizon-rim.rgb"));
136 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
138 -360.0, 360.0, -1.0, 0.0);
140 // Layer 3: glass front of gauge
141 // fixed, with markings
142 inst->addLayer(3, createTexture("Textures/Panel/horizon-fg.rgb"));
149 * Construct an altimeter.
151 static FGPanelInstrument *
152 createAltimeter (int x, int y)
154 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
156 // Layer 0: gauge background
157 inst->addLayer(0, createTexture("Textures/Panel/altimeter.rgb"));
159 // Layer 1: hundreds needle (long)
160 // moves with altitude
161 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
162 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
164 0.0, 100000.0, 360.0 / 1000.0, 0.0);
166 // Layer 2: thousands needle (short)
167 // moves with altitude
168 inst->addLayer(2, createTexture("Textures/Panel/short-needle.rgb"));
169 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
171 0.0, 100000.0, 360.0 / 10000.0, 0.0);
173 // Layer 3: ten thousands bug (outside)
174 // moves with altitude
175 inst->addLayer(3, createTexture("Textures/Panel/bug.rgb"));
176 inst->addTransformation(3, FGInstrumentLayer::ROTATION,
178 0.0, 100000.0, 360.0 / 100000.0, 0.0);
185 * Construct a turn coordinator.
187 static FGPanelInstrument *
188 createTurnCoordinator (int x, int y)
190 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
192 // Layer 0: background
193 inst->addLayer(0, createTexture("Textures/Panel/turn-bg.rgb"));
195 // Layer 1: little plane
197 inst->addLayer(1, createTexture("Textures/Panel/turn.rgb"));
198 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
199 FGSteam::get_TC_radps,
200 -30.0, 30.0, 1.0, 0.0);
202 // Layer 2: little ball
203 // moves with slip/skid
204 inst->addLayer(2, createTexture("Textures/Panel/ball.rgb"));
205 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
207 -0.1, 0.1, 450.0, 0.0);
214 * Construct a gyro compass.
216 static FGPanelInstrument *
217 createGyroCompass (int x, int y)
219 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
221 // Action: move bug counter-clockwise
222 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
223 new FGAdjustAction(FGBFI::getAPHeading,
225 -1.0, 0.0, 360.0, true));
227 // Action: move bug clockwise
228 inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
229 new FGAdjustAction(FGBFI::getAPHeading,
231 1.0, 0.0, 360.0, true));
233 // Layer 0: compass background
234 // rotates with heading
235 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
236 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
238 -360.0, 360.0, -1.0, 0.0);
240 // Layer 1: heading bug
241 // rotates with heading and AP heading
242 inst->addLayer(1, createTexture("Textures/Panel/bug.rgb"));
243 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
245 -360.0, 360.0, -1.0, 0.0);
246 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
248 -360.0, 360.0, 1.0, 0.0);
250 // Layer 2: fixed center
251 inst->addLayer(2, createTexture("Textures/Panel/gyro-fg.rgb"));
253 // Layer 3: heading knob
254 // rotates with AP heading
255 inst->addLayer(3, createTexture("Textures/Panel/heading-knob.rgb"));
256 inst->addTransformation(3, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
257 inst->addTransformation(3, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
258 inst->addTransformation(3, FGInstrumentLayer::ROTATION,
260 -360.0, 360.0, 1.0, 0.0);
267 * Construct a vertical velocity indicator.
269 static FGPanelInstrument *
270 createVerticalVelocity (int x, int y)
272 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
274 // Layer 0: gauge background
275 inst->addLayer(0, createTexture("Textures/Panel/vertical.rgb"));
278 // moves with vertical velocity
279 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
280 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
281 FGSteam::get_VSI_fps,
282 -2000.0, 2000.0, 42.0/500.0, 270.0);
289 * Construct an RPM gauge.
291 static FGPanelInstrument *
292 createRPMGauge (int x, int y)
294 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
296 // Layer 0: gauge background
297 inst->addLayer(0, createTexture("Textures/Panel/rpm.rgb"));
299 // Layer 1: long needle
300 // FIXME: moves with throttle (for now)
301 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
302 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
304 0.0, 100.0, 300.0, -150.0);
311 * Construct a flap position indicator.
313 static FGPanelInstrument *
314 createFlapIndicator (int x, int y)
316 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
318 // Layer 0: gauge background
319 inst->addLayer(0, createTexture("Textures/Panel/flaps.rgb"));
321 // Layer 1: long needle
322 // shifted over, rotates with flap position
323 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
324 inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
325 -(SMALL_W / 4) + (SMALL_W / 16));
326 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
328 0.0, 1.0, 120.0, 30.0);
333 static FGPanelInstrument *
334 createChronometer (int x, int y)
336 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
338 // Layer 0: gauge background
339 inst->addLayer(0, createTexture("Textures/Panel/clock.rgb"));
342 // displays current GMT
343 FGCharInstrumentLayer * text =
344 new FGCharInstrumentLayer(panelGetTime,
345 SMALL_W, SMALL_W, 1);
346 text->setPointSize(14);
347 text->setColor(0.2, 0.2, 0.2);
348 inst->addLayer(text);
349 inst->addTransformation(1, FGInstrumentLayer::XSHIFT, SMALL_W * -0.38);
350 inst->addTransformation(1, FGInstrumentLayer::YSHIFT, SMALL_W * -0.06);
357 * Construct control-position indicators.
359 static FGPanelInstrument *
360 createControls (int x, int y)
362 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
364 // Layer 0: gauge background
365 inst->addLayer(0, createTexture("Textures/Panel/controls.rgb"));
368 // moves left-right with aileron
369 inst->addLayer(1, createTexture("Textures/Panel/bug.rgb"));
370 inst->addTransformation(1, FGInstrumentLayer::XSHIFT, FGBFI::getAileron,
371 -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
374 // moves left-right with rudder
375 inst->addLayer(2, createTexture("Textures/Panel/bug.rgb"));
376 inst->addTransformation(2, FGInstrumentLayer::ROTATION, 180.0);
377 inst->addTransformation(2, FGInstrumentLayer::XSHIFT, FGBFI::getRudder,
378 -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
381 // moves up-down with elevator trim
382 inst->addLayer(3, createTexture("Textures/Panel/bug.rgb"));
383 inst->addTransformation(3, FGInstrumentLayer::ROTATION, 270.0);
384 inst->addTransformation(3, FGInstrumentLayer::YSHIFT,
385 -SMALL_W * (3.0 / 8.0));
386 inst->addTransformation(3, FGInstrumentLayer::XSHIFT, FGBFI::getElevatorTrim,
387 -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
390 // moves up-down with elevator
391 inst->addLayer(4, createTexture("Textures/Panel/bug.rgb"));
392 inst->addTransformation(4, FGInstrumentLayer::ROTATION, 90.0);
393 inst->addTransformation(4, FGInstrumentLayer::YSHIFT,
394 -SMALL_W * (3.0 / 8.0));
395 inst->addTransformation(4, FGInstrumentLayer::XSHIFT, FGBFI::getElevator,
396 -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
403 * Construct a NAV1 gauge (hardwired).
405 static FGPanelInstrument *
406 createNAV1 (int x, int y)
408 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
410 // Action: increase selected radial
411 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
412 new FGAdjustAction(FGBFI::getNAV1SelRadial,
413 FGBFI::setNAV1SelRadial,
414 1.0, 0.0, 360.0, true));
416 // Action: decrease selected radial
417 inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
418 new FGAdjustAction(FGBFI::getNAV1SelRadial,
419 FGBFI::setNAV1SelRadial,
420 -1.0, 0.0, 360.0, true));
422 // Layer 0: background
423 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
424 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
425 FGBFI::getNAV1SelRadial,
426 -360.0, 360.0, -1.0, 0.0);
428 // Layer 1: left-right needle.
429 inst->addLayer(1, createTexture("Textures/Panel/nav-needle.rgb"));
430 inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
431 FGSteam::get_HackVOR1_deg,
432 -10.0, 10.0, SIX_W / 40.0, 0.0);
434 // Layer 2: glidescope needle
435 inst->addLayer(2, createTexture("Textures/Panel/nav-needle.rgb"));
436 inst->addTransformation(2, FGInstrumentLayer::YSHIFT,
437 FGSteam::get_HackGS_deg,
438 -1.0, 1.0, SIX_W / 5.0, 0.0);
439 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
442 // Layer 3: face with markings
443 inst->addLayer(3, createTexture("Textures/Panel/nav-face.rgb"));
445 // Layer 4: heading knob
446 // rotates with selected radial
447 inst->addLayer(4, createTexture("Textures/Panel/heading-knob.rgb"));
448 inst->addTransformation(4, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
449 inst->addTransformation(4, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
450 inst->addTransformation(4, FGInstrumentLayer::ROTATION,
451 FGBFI::getNAV1SelRadial,
452 -360.0, 360.0, -1.0, 0.0);
459 * Construct a NAV2 gauge.
461 static FGPanelInstrument *
462 createNAV2 (int x, int y)
464 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
466 // Action: increase selected radial
467 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
468 new FGAdjustAction(FGBFI::getNAV2SelRadial,
469 FGBFI::setNAV2SelRadial,
470 1.0, 0.0, 360.0, true));
472 // Action: decrease selected radial
473 inst->addAction(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));
478 // Layer 0: background
479 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
480 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
481 FGBFI::getNAV2SelRadial,
482 -360.0, 360.0, -1.0, 0.0);
484 // Layer 1: left-right needle.
485 inst->addLayer(1, createTexture("Textures/Panel/nav-needle.rgb"));
486 inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
487 FGSteam::get_HackVOR2_deg,
488 -10.0, 10.0, SIX_W / 40.0, 0.0);
489 // inst->addTransformation(1, FGInstrumentLayer::YSHIFT,
492 // Layer 2: face with markings.
493 inst->addLayer(2, createTexture("Textures/Panel/nav-face.rgb"));
495 // Layer 3: heading knob
496 // rotates with selected radial
497 inst->addLayer(3, createTexture("Textures/Panel/heading-knob.rgb"));
498 inst->addTransformation(3, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
499 inst->addTransformation(3, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
500 inst->addTransformation(3, FGInstrumentLayer::ROTATION,
501 FGBFI::getNAV2SelRadial,
502 -360.0, 360.0, -1.0, 0.0);
509 * Construct an ADF gauge (hardwired).
511 static FGPanelInstrument *
512 createADF (int x, int y)
514 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
516 // Action: increase selected rotation
517 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
518 new FGAdjustAction(FGBFI::getADFRotation,
519 FGBFI::setADFRotation,
520 1.0, 0.0, 360.0, true));
522 // Action: decrease selected rotation
523 inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
524 new FGAdjustAction(FGBFI::getADFRotation,
525 FGBFI::setADFRotation,
526 -1.0, 0.0, 360.0, true));
528 // Layer 0: background
529 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
530 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
531 FGBFI::getADFRotation,
532 0.0, 360.0, 1.0, 0.0);
534 // Layer 1: Direction needle.
535 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
536 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
537 FGSteam::get_HackADF_deg,
538 -720.0, 720.0, 1.0, 0.0);
540 // Layer 2: heading knob
541 // rotates with selected radial
542 inst->addLayer(2, createTexture("Textures/Panel/heading-knob.rgb"));
543 inst->addTransformation(2, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
544 inst->addTransformation(2, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
545 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
546 FGBFI::getADFRotation,
547 -360.0, 360.0, -1.0, 0.0);
553 ////////////////////////////////////////////////////////////////////////
554 // Implementation of FGTextureManager.
555 ////////////////////////////////////////////////////////////////////////
557 map<const char *,ssgTexture *> FGTextureManager::_textureMap;
560 FGTextureManager::createTexture (const char * relativePath)
564 texture = _textureMap[relativePath];
566 FGPath tpath(current_options.get_fg_root());
567 tpath.append(relativePath);
568 texture = new ssgTexture((char *)tpath.c_str(), false, false);
569 _textureMap[relativePath] = texture;
570 cerr << "Created texture " << relativePath
571 << " handle=" << texture->getHandle() << endl;
579 ////////////////////////////////////////////////////////////////////////
580 // Implementation of FGPanel.
581 ////////////////////////////////////////////////////////////////////////
583 FGPanel current_panel;
586 : _initialized(false),
593 instrument_list_type::iterator current = _instruments.begin();
594 instrument_list_type::iterator last = _instruments.end();
596 for ( ; current != last; ++current) {
603 FGPanel::addInstrument (FGPanelInstrument * instrument)
605 _instruments.push_back(instrument);
609 FGPanel::init (int x, int y, int finx, int finy)
615 _panel_h = (int)((finy - y) * 0.5768 + 1);
617 // Don't reconstruct all of the
625 _bg = createTexture("Textures/Panel/panel-bg.rgb");
627 // Chronometer alone at side
628 x = SIX_X - SIX_SPACING - 8;
629 addInstrument(createChronometer(x, y));
633 addInstrument(createAirspeedIndicator(x, y));
635 addInstrument(createHorizon(x, y));
637 addInstrument(createAltimeter(x, y));
638 x += SIX_SPACING + 20;
639 addInstrument(createNAV1(x, y));
644 addInstrument(createTurnCoordinator(x, y));
646 addInstrument(createGyroCompass(x, y));
648 addInstrument(createVerticalVelocity(x, y));
649 x += SIX_SPACING + 20;
650 addInstrument(createNAV2(x, y));
654 y -= SIX_SPACING + 10;
655 addInstrument(createControls(x, y));
657 addInstrument(createFlapIndicator(x, y));
659 addInstrument(createRPMGauge(x, y));
660 x += SIX_SPACING + 20;
662 addInstrument(createADF(x, y));
666 FGPanel::update () const
668 // Do nothing if the panel isn't visible.
672 glMatrixMode(GL_PROJECTION);
675 gluOrtho2D(_x, _x + _w, _y, _y + _h);
677 glMatrixMode(GL_MODELVIEW);
681 // Draw the background
682 glEnable(GL_TEXTURE_2D);
683 glDisable(GL_LIGHTING);
685 glEnable(GL_ALPHA_TEST);
686 glEnable(GL_COLOR_MATERIAL);
687 glColor4f(1.0, 1.0, 1.0, 1.0);
688 glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
689 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
690 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
691 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
693 glTexCoord2f(0.0, 0.0); glVertex3f(_x, _y, 0);
694 glTexCoord2f(10.0, 0.0); glVertex3f(_x + _w, _y, 0);
695 glTexCoord2f(10.0, 5.0); glVertex3f(_x + _w, _y + _panel_h, 0);
696 glTexCoord2f(0.0, 5.0); glVertex3f(_x, _y + _panel_h, 0);
699 // Draw the instruments.
700 instrument_list_type::const_iterator current = _instruments.begin();
701 instrument_list_type::const_iterator end = _instruments.end();
703 for ( ; current != end; current++) {
704 FGPanelInstrument * instr = *current;
706 glTranslated(instr->getXPos(), instr->getYPos(), 0);
710 glMatrixMode(GL_PROJECTION);
712 glMatrixMode(GL_MODELVIEW);
714 ssgForceBasicState();
715 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
719 FGPanel::setVisibility (bool visibility)
721 _visibility = visibility;
725 FGPanel::getVisibility () const
731 FGPanel::doMouseAction (int button, int updown, int x, int y)
733 // For now, ignore the release
737 x = (int)(((float)x / current_view.get_winWidth()) * _w);
738 y = (int)(_h - (((float)y / current_view.get_winHeight()) * _h));
740 for (int i = 0; i < _instruments.size(); i++) {
741 FGPanelInstrument *inst = _instruments[i];
742 int ix = inst->getXPos();
743 int iy = inst->getYPos();
744 int iw = inst->getWidth() / 2;
745 int ih = inst->getHeight() / 2;
746 if (x >= ix - iw && x < ix + iw && y >= iy - ih && y < iy + ih) {
747 cout << "Do mouse action for component " << i << '\n';
748 return inst->doMouseAction(button, updown, x - ix, y - iy);
751 cout << "Did not click on an instrument\n";
757 ////////////////////////////////////////////////////////////////////////
758 // Implementation of FGAdjustAction.
759 ////////////////////////////////////////////////////////////////////////
761 FGAdjustAction::FGAdjustAction (getter_type getter, setter_type setter,
762 double increment, double min, double max,
764 : _getter(getter), _setter(setter), _increment(increment),
765 _min(min), _max(max), _wrap(wrap)
769 FGAdjustAction::~FGAdjustAction ()
774 FGAdjustAction::doAction ()
776 double value = (*_getter)();
777 cout << "Do action; value=" << value << '\n';
780 value = (_wrap ? _max : _min);
781 } else if (value > _max) {
782 value = (_wrap ? _min : _max);
784 cout << "New value is " << value << '\n';
790 ////////////////////////////////////////////////////////////////////////
791 // Implementation of FGPanelInstrument.
792 ////////////////////////////////////////////////////////////////////////
795 FGPanelInstrument::FGPanelInstrument ()
801 FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
807 FGPanelInstrument::~FGPanelInstrument ()
809 action_list_type::iterator it = _actions.begin();
810 action_list_type::iterator last = _actions.end();
811 for ( ; it != last; it++) {
817 FGPanelInstrument::setPosition (int x, int y)
824 FGPanelInstrument::setSize (int w, int h)
831 FGPanelInstrument::getXPos () const
837 FGPanelInstrument::getYPos () const
843 FGPanelInstrument::getWidth () const
849 FGPanelInstrument::getHeight () const
855 FGPanelInstrument::addAction (int x, int y, int w, int h,
856 FGPanelAction * action)
858 FGPanelInstrument::inst_action act;
864 _actions.push_back(act);
867 // Coordinates relative to centre.
869 FGPanelInstrument::doMouseAction (int button, int updown, int x, int y)
871 action_list_type::iterator it = _actions.begin();
872 action_list_type::iterator last = _actions.end();
873 cout << "Mouse action at " << x << ',' << y << '\n';
874 for ( ; it != last; it++) {
875 cout << "Trying action at " << it->x << ',' << it->y << ','
876 << it->w <<',' << it->h << '\n';
877 if (x >= it->x && x < it->x + it->w && y >= it->y && y < it->y + it->h) {
878 it->action->doAction();
887 ////////////////////////////////////////////////////////////////////////
888 // Implementation of FGLayeredInstrument.
889 ////////////////////////////////////////////////////////////////////////
891 FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
892 : FGPanelInstrument(x, y, w, h)
896 FGLayeredInstrument::~FGLayeredInstrument ()
898 // FIXME: free layers
902 FGLayeredInstrument::draw () const
904 layer_list::const_iterator it = _layers.begin();
905 layer_list::const_iterator last = _layers.end();
913 FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
915 _layers.push_back(layer);
919 FGLayeredInstrument::addLayer (int layer, ssgTexture * texture)
921 addLayer(new FGTexturedInstrumentLayer(texture, _w, _h, layer));
925 FGLayeredInstrument::addTransformation (int layer,
926 FGInstrumentLayer::transform_type type,
927 FGInstrumentLayer::transform_func func,
928 double min, double max,
929 double factor, double offset)
931 _layers[layer]->addTransformation(type, func, min, max, factor, offset);
936 ////////////////////////////////////////////////////////////////////////
937 // Implementation of FGInstrumentLayer.
938 ////////////////////////////////////////////////////////////////////////
940 FGInstrumentLayer::FGInstrumentLayer (int w, int h, int z)
947 FGInstrumentLayer::~FGInstrumentLayer ()
949 transformation_list::iterator it = _transformations.begin();
950 transformation_list::iterator end = _transformations.end();
958 FGInstrumentLayer::transform () const
960 glTranslatef(0.0, 0.0, (_z / 100.0) + 0.1);
962 transformation_list::const_iterator it = _transformations.begin();
963 transformation_list::const_iterator last = _transformations.end();
965 transformation *t = *it;
966 double value = (t->func == 0 ? 0.0 : (*(t->func))());
967 if (value < t->min) {
969 } else if (value > t->max) {
972 value = value * t->factor + t->offset;
976 glTranslatef(value, 0.0, 0.0);
979 glTranslatef(0.0, value, 0.0);
982 glRotatef(-value, 0.0, 0.0, 1.0);
990 FGInstrumentLayer::addTransformation (transform_type type,
992 double min, double max,
993 double factor, double offset)
995 transformation *t = new transformation;
1002 _transformations.push_back(t);
1007 ////////////////////////////////////////////////////////////////////////
1008 // Implementation of FGTexturedInstrumentLayer.
1009 ////////////////////////////////////////////////////////////////////////
1011 // FGTexturedInstrumentLayer::FGTexturedInstrumentLayer (const char *tname,
1012 // int w, int h, int z)
1013 // : FGInstrumentLayer(w, h, z)
1015 // setTexture(tname);
1018 FGTexturedInstrumentLayer::FGTexturedInstrumentLayer (ssgTexture * texture,
1019 int w, int h, int z)
1020 : FGInstrumentLayer(w, h, z)
1022 setTexture(texture);
1025 FGTexturedInstrumentLayer::~FGTexturedInstrumentLayer ()
1030 FGTexturedInstrumentLayer::draw () const
1037 glBindTexture(GL_TEXTURE_2D, _texture->getHandle());
1038 glBegin(GL_POLYGON);
1039 // FIXME: is this really correct
1041 glTexCoord2f(0.0, 0.0); glVertex2f(-w2, -h2);
1042 glTexCoord2f(1.0, 0.0); glVertex2f(w2, -h2);
1043 glTexCoord2f(1.0, 1.0); glVertex2f(w2, h2);
1044 glTexCoord2f(0.0, 1.0); glVertex2f(-w2, h2);
1050 // FGTexturedInstrumentLayer::setTexture (const char *textureName)
1052 // FGPath tpath(current_options.get_fg_root());
1053 // tpath.append(textureName);
1054 // ssgTexture * texture = new ssgTexture((char *)tpath.c_str(), false, false);
1055 // setTexture(texture);
1060 ////////////////////////////////////////////////////////////////////////
1061 // Implementation of FGCharInstrumentLayer.
1062 ////////////////////////////////////////////////////////////////////////
1064 FGCharInstrumentLayer::FGCharInstrumentLayer (text_func func,
1065 int w, int h, int z)
1066 : FGInstrumentLayer(w, h, z),
1069 _renderer.setFont(guiFntHandle);
1070 _renderer.setPointSize(14);
1071 _color[0] = _color[1] = _color[2] = 0.0;
1075 FGCharInstrumentLayer::~FGCharInstrumentLayer ()
1080 FGCharInstrumentLayer::draw () const
1086 _renderer.start3f(0, 0, 0);
1087 _renderer.puts((*_func)(_buf));
1089 glColor4f(1.0, 1.0, 1.0, 1.0); // FIXME
1094 FGCharInstrumentLayer::setColor (float r, float g, float b)
1103 FGCharInstrumentLayer::setPointSize (const float size)
1105 _renderer.setPointSize(size);
1109 FGCharInstrumentLayer::setFont(fntFont * font)
1111 _renderer.setFont(font);