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 <Time/fg_time.hxx>
43 #include "cockpit.hxx"
51 #define SIX_SPACING (SIX_W + 5)
56 ////////////////////////////////////////////////////////////////////////
57 // Static functions for obtaining settings.
59 // These should be replaced with functions from a global facade,
60 // or BFI (Big Friendly Interface).
61 ////////////////////////////////////////////////////////////////////////
63 static char * panelGetTime (char * buf)
65 struct tm * t = FGTime::cur_time_params->getGmt();
66 sprintf(buf, " %.2d:%.2d:%.2d",
67 t->tm_hour, t->tm_min, t->tm_sec);
73 ////////////////////////////////////////////////////////////////////////
74 // Static factory functions to create textured gauges.
76 // These will be replaced first with a giant table, and then with
77 // configuration files read from an external source, but for now
78 // they're hard-coded.
79 ////////////////////////////////////////////////////////////////////////
82 #define createTexture(a) FGTextureManager::createTexture(a)
85 * Construct an airspeed indicator for a single-engine prop.
87 static FGPanelInstrument *
88 createAirspeedIndicator (int x, int y)
90 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
92 // Layer 0: gauge background.
93 inst->addLayer(0, createTexture("Textures/Panel/airspeed.rgb"));
96 // Rotates with airspeed.
97 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
98 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
99 FGSteam::get_ASI_kias,
100 30.0, 220.0, 36.0 / 20.0, -54.0);
106 * Construct an artificial horizon.
108 static FGPanelInstrument *
109 createHorizon (int x, int y)
111 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
113 // Layer 0: coloured background
114 // moves with roll only
115 inst->addLayer(0, createTexture("Textures/Panel/horizon-bg.rgb"));
116 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
118 -360.0, 360.0, -1.0, 0.0);
120 // Layer 1: floating horizon
121 // moves with roll and pitch
122 inst->addLayer(1, createTexture("Textures/Panel/horizon-float.rgb"));
123 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
125 -360.0, 360.0, -1.0, 0.0);
126 inst->addTransformation(1, FGInstrumentLayer::YSHIFT,
128 -20.0, 20.0, -(1.5 / 160.0) * SIX_W, 0.0);
131 // moves with roll only
132 inst->addLayer(2, createTexture("Textures/Panel/horizon-rim.rgb"));
133 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
135 -360.0, 360.0, -1.0, 0.0);
137 // Layer 3: glass front of gauge
138 // fixed, with markings
139 inst->addLayer(3, createTexture("Textures/Panel/horizon-fg.rgb"));
146 * Construct an altimeter.
148 static FGPanelInstrument *
149 createAltimeter (int x, int y)
151 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
153 // Layer 0: gauge background
154 inst->addLayer(0, createTexture("Textures/Panel/altimeter.rgb"));
156 // Layer 1: hundreds needle (long)
157 // moves with altitude
158 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
159 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
161 0.0, 100000.0, 360.0 / 1000.0, 0.0);
163 // Layer 2: thousands needle (short)
164 // moves with altitude
165 inst->addLayer(2, createTexture("Textures/Panel/short-needle.rgb"));
166 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
168 0.0, 100000.0, 360.0 / 10000.0, 0.0);
170 // Layer 3: ten thousands bug (outside)
171 // moves with altitude
172 inst->addLayer(3, createTexture("Textures/Panel/bug.rgb"));
173 inst->addTransformation(3, FGInstrumentLayer::ROTATION,
175 0.0, 100000.0, 360.0 / 100000.0, 0.0);
182 * Construct a turn coordinator.
184 static FGPanelInstrument *
185 createTurnCoordinator (int x, int y)
187 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
189 // Layer 0: background
190 inst->addLayer(0, createTexture("Textures/Panel/turn-bg.rgb"));
192 // Layer 1: little plane
194 inst->addLayer(1, createTexture("Textures/Panel/turn.rgb"));
195 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
196 FGSteam::get_TC_radps,
197 -30.0, 30.0, 1.0, 0.0);
199 // Layer 2: little ball
200 // moves with slip/skid
201 inst->addLayer(2, createTexture("Textures/Panel/ball.rgb"));
202 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
204 -0.1, 0.1, 450.0, 0.0);
211 * Construct a gyro compass.
213 static FGPanelInstrument *
214 createGyroCompass (int x, int y)
216 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
218 // Action: move bug counter-clockwise
219 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
220 new FGAdjustAction(FGBFI::getAPHeading,
222 -1.0, 0.0, 360.0, true));
224 // Action: move bug clockwise
225 inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
226 new FGAdjustAction(FGBFI::getAPHeading,
228 1.0, 0.0, 360.0, true));
230 // Layer 0: compass background
231 // rotates with heading
232 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
233 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
235 -360.0, 360.0, -1.0, 0.0);
237 // Layer 1: heading bug
238 // rotates with heading and AP heading
239 inst->addLayer(1, createTexture("Textures/Panel/bug.rgb"));
240 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
242 -360.0, 360.0, -1.0, 0.0);
243 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
245 -360.0, 360.0, 1.0, 0.0);
247 // Layer 2: fixed center
248 inst->addLayer(2, createTexture("Textures/Panel/gyro-fg.rgb"));
250 // Layer 3: heading knob
251 // rotates with AP heading
252 inst->addLayer(3, createTexture("Textures/Panel/heading-knob.rgb"));
253 inst->addTransformation(3, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
254 inst->addTransformation(3, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
255 inst->addTransformation(3, FGInstrumentLayer::ROTATION,
257 -360.0, 360.0, 1.0, 0.0);
264 * Construct a vertical velocity indicator.
266 static FGPanelInstrument *
267 createVerticalVelocity (int x, int y)
269 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
271 // Layer 0: gauge background
272 inst->addLayer(0, createTexture("Textures/Panel/vertical.rgb"));
275 // moves with vertical velocity
276 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
277 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
278 FGSteam::get_VSI_fps,
279 -2000.0, 2000.0, 42.0/500.0, 270.0);
286 * Construct an RPM gauge.
288 static FGPanelInstrument *
289 createRPMGauge (int x, int y)
291 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
293 // Layer 0: gauge background
294 inst->addLayer(0, createTexture("Textures/Panel/rpm.rgb"));
296 // Layer 1: long needle
297 // FIXME: moves with throttle (for now)
298 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
299 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
301 0.0, 100.0, 300.0, -150.0);
308 * Construct a flap position indicator.
310 static FGPanelInstrument *
311 createFlapIndicator (int x, int y)
313 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
315 // Layer 0: gauge background
316 inst->addLayer(0, createTexture("Textures/Panel/flaps.rgb"));
318 // Layer 1: long needle
319 // shifted over, rotates with flap position
320 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
321 inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
322 -(SMALL_W / 4) + (SMALL_W / 16));
323 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
325 0.0, 1.0, 120.0, 30.0);
330 static FGPanelInstrument *
331 createChronometer (int x, int y)
333 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
335 // Layer 0: gauge background
336 inst->addLayer(0, createTexture("Textures/Panel/clock.rgb"));
339 // displays current GMT
340 FGCharInstrumentLayer * text =
341 new FGCharInstrumentLayer(panelGetTime,
342 SMALL_W, SMALL_W, 1);
343 text->setPointSize(14);
344 text->setColor(0.2, 0.2, 0.2);
345 inst->addLayer(text);
346 inst->addTransformation(1, FGInstrumentLayer::XSHIFT, SMALL_W * -0.38);
347 inst->addTransformation(1, FGInstrumentLayer::YSHIFT, SMALL_W * -0.06);
354 * Construct control-position indicators.
356 static FGPanelInstrument *
357 createControls (int x, int y)
359 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SMALL_W, SMALL_W);
361 // Layer 0: gauge background
362 inst->addLayer(0, createTexture("Textures/Panel/controls.rgb"));
365 // moves left-right with aileron
366 inst->addLayer(1, createTexture("Textures/Panel/bug.rgb"));
367 inst->addTransformation(1, FGInstrumentLayer::XSHIFT, FGBFI::getAileron,
368 -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
371 // moves left-right with rudder
372 inst->addLayer(2, createTexture("Textures/Panel/bug.rgb"));
373 inst->addTransformation(2, FGInstrumentLayer::ROTATION, 180.0);
374 inst->addTransformation(2, FGInstrumentLayer::XSHIFT, FGBFI::getRudder,
375 -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
378 // moves up-down with elevator trim
379 inst->addLayer(3, createTexture("Textures/Panel/bug.rgb"));
380 inst->addTransformation(3, FGInstrumentLayer::ROTATION, 270.0);
381 inst->addTransformation(3, FGInstrumentLayer::YSHIFT,
382 -SMALL_W * (3.0 / 8.0));
383 inst->addTransformation(3, FGInstrumentLayer::XSHIFT, FGBFI::getElevatorTrim,
384 -1.0, 1.0, SMALL_W * .75 / 2.0, 0.0);
387 // moves up-down with elevator
388 inst->addLayer(4, createTexture("Textures/Panel/bug.rgb"));
389 inst->addTransformation(4, FGInstrumentLayer::ROTATION, 90.0);
390 inst->addTransformation(4, FGInstrumentLayer::YSHIFT,
391 -SMALL_W * (3.0 / 8.0));
392 inst->addTransformation(4, FGInstrumentLayer::XSHIFT, FGBFI::getElevator,
393 -1.0, 1.0, -SMALL_W * .75 / 2.0, 0.0);
400 * Construct a NAV1 gauge (hardwired).
402 static FGPanelInstrument *
403 createNAV1 (int x, int y)
405 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
407 // Action: increase selected radial
408 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
409 new FGAdjustAction(FGBFI::getNAV1Radial,
410 FGBFI::setNAV1Radial,
411 1.0, 0.0, 360.0, true));
413 // Action: decrease selected radial
414 inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
415 new FGAdjustAction(FGBFI::getNAV1Radial,
416 FGBFI::setNAV1Radial,
417 -1.0, 0.0, 360.0, true));
419 // Layer 0: background
420 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
421 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
422 FGBFI::getNAV1Radial,
423 -360.0, 360.0, -1.0, 0.0);
425 // Layer 1: left-right needle.
426 inst->addLayer(1, createTexture("Textures/Panel/nav-needle.rgb"));
427 inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
428 FGSteam::get_HackVOR1_deg,
429 -10.0, 10.0, SIX_W / 40.0, 0.0);
431 // Layer 2: glidescope needle
432 inst->addLayer(2, createTexture("Textures/Panel/nav-needle.rgb"));
433 inst->addTransformation(2, FGInstrumentLayer::YSHIFT,
434 FGSteam::get_HackGS_deg,
435 -1.0, 1.0, SIX_W / 5.0, 0.0);
436 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
439 // Layer 3: face with markings
440 inst->addLayer(3, createTexture("Textures/Panel/nav-face.rgb"));
442 // Layer 4: heading knob
443 // rotates with selected radial
444 inst->addLayer(4, createTexture("Textures/Panel/heading-knob.rgb"));
445 inst->addTransformation(4, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
446 inst->addTransformation(4, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
447 inst->addTransformation(4, FGInstrumentLayer::ROTATION,
448 FGBFI::getNAV1Radial,
449 -360.0, 360.0, -1.0, 0.0);
456 * Construct a NAV2 gauge.
458 static FGPanelInstrument *
459 createNAV2 (int x, int y)
461 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
463 // Action: increase selected radial
464 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
465 new FGAdjustAction(FGBFI::getNAV2Radial,
466 FGBFI::setNAV2Radial,
467 1.0, 0.0, 360.0, true));
469 // Action: decrease selected radial
470 inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
471 new FGAdjustAction(FGBFI::getNAV2Radial,
472 FGBFI::setNAV2Radial,
473 -1.0, 0.0, 360.0, true));
475 // Layer 0: background
476 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
477 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
478 FGBFI::getNAV2Radial,
479 -360.0, 360.0, -1.0, 0.0);
481 // Layer 1: left-right needle.
482 inst->addLayer(1, createTexture("Textures/Panel/nav-needle.rgb"));
483 inst->addTransformation(1, FGInstrumentLayer::XSHIFT,
484 FGSteam::get_HackVOR2_deg,
485 -10.0, 10.0, SIX_W / 40.0, 0.0);
486 // inst->addTransformation(1, FGInstrumentLayer::YSHIFT,
489 // Layer 2: face with markings.
490 inst->addLayer(2, createTexture("Textures/Panel/nav-face.rgb"));
492 // Layer 3: heading knob
493 // rotates with selected radial
494 inst->addLayer(3, createTexture("Textures/Panel/heading-knob.rgb"));
495 inst->addTransformation(3, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
496 inst->addTransformation(3, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
497 inst->addTransformation(3, FGInstrumentLayer::ROTATION,
498 FGBFI::getNAV2Radial,
499 -360.0, 360.0, -1.0, 0.0);
506 * Construct an ADF gauge (hardwired).
508 static FGPanelInstrument *
509 createADF (int x, int y)
511 FGLayeredInstrument * inst = new FGLayeredInstrument(x, y, SIX_W, SIX_W);
513 // Action: increase selected rotation
514 inst->addAction(SIX_W/2 - SIX_W/5, -SIX_W/2, SIX_W/10, SIX_W/5,
515 new FGAdjustAction(FGBFI::getADFRotation,
516 FGBFI::setADFRotation,
517 1.0, 0.0, 360.0, true));
519 // Action: decrease selected rotation
520 inst->addAction(SIX_W/2 - SIX_W/10, -SIX_W/2, SIX_W/10, SIX_W/5,
521 new FGAdjustAction(FGBFI::getADFRotation,
522 FGBFI::setADFRotation,
523 -1.0, 0.0, 360.0, true));
525 // Layer 0: background
526 inst->addLayer(0, createTexture("Textures/Panel/gyro-bg.rgb"));
527 inst->addTransformation(0, FGInstrumentLayer::ROTATION,
528 FGBFI::getADFRotation,
529 0.0, 360.0, 1.0, 0.0);
531 // Layer 1: Direction needle.
532 inst->addLayer(1, createTexture("Textures/Panel/long-needle.rgb"));
533 inst->addTransformation(1, FGInstrumentLayer::ROTATION,
534 FGSteam::get_HackADF_deg,
535 -720.0, 720.0, 1.0, 0.0);
537 // Layer 2: heading knob
538 // rotates with selected radial
539 inst->addLayer(2, createTexture("Textures/Panel/heading-knob.rgb"));
540 inst->addTransformation(2, FGInstrumentLayer::XSHIFT, SIX_W/2 - 10);
541 inst->addTransformation(2, FGInstrumentLayer::YSHIFT, -SIX_W/2 + 10);
542 inst->addTransformation(2, FGInstrumentLayer::ROTATION,
543 FGBFI::getADFRotation,
544 -360.0, 360.0, -1.0, 0.0);
550 ////////////////////////////////////////////////////////////////////////
551 // Implementation of FGTextureManager.
552 ////////////////////////////////////////////////////////////////////////
554 map<const char *,ssgTexture *> FGTextureManager::_textureMap;
557 FGTextureManager::createTexture (const char * relativePath)
561 texture = _textureMap[relativePath];
563 FGPath tpath(current_options.get_fg_root());
564 tpath.append(relativePath);
565 texture = new ssgTexture((char *)tpath.c_str(), false, false);
566 _textureMap[relativePath] = texture;
567 cerr << "Created texture " << relativePath
568 << " handle=" << texture->getHandle() << endl;
576 ////////////////////////////////////////////////////////////////////////
577 // Implementation of FGPanel.
578 ////////////////////////////////////////////////////////////////////////
580 FGPanel current_panel;
583 : _initialized(false),
590 instrument_list_type::iterator current = _instruments.begin();
591 instrument_list_type::iterator last = _instruments.end();
593 for ( ; current != last; ++current) {
600 FGPanel::addInstrument (FGPanelInstrument * instrument)
602 _instruments.push_back(instrument);
606 FGPanel::init (int x, int y, int finx, int finy)
612 _panel_h = (int)((finy - y) * 0.5768 + 1);
614 // Don't reconstruct all of the
622 _bg = createTexture("Textures/Panel/panel-bg.rgb");
624 // Chronometer alone at side
625 x = SIX_X - SIX_SPACING - 8;
626 addInstrument(createChronometer(x, y));
630 addInstrument(createAirspeedIndicator(x, y));
632 addInstrument(createHorizon(x, y));
634 addInstrument(createAltimeter(x, y));
635 x += SIX_SPACING + 20;
636 addInstrument(createNAV1(x, y));
641 addInstrument(createTurnCoordinator(x, y));
643 addInstrument(createGyroCompass(x, y));
645 addInstrument(createVerticalVelocity(x, y));
646 x += SIX_SPACING + 20;
647 addInstrument(createNAV2(x, y));
651 y -= SIX_SPACING + 10;
652 addInstrument(createControls(x, y));
654 addInstrument(createFlapIndicator(x, y));
656 addInstrument(createRPMGauge(x, y));
657 x += SIX_SPACING + 20;
659 addInstrument(createADF(x, y));
663 FGPanel::update () const
665 // Do nothing if the panel isn't visible.
669 glMatrixMode(GL_PROJECTION);
672 gluOrtho2D(_x, _x + _w, _y, _y + _h);
674 glMatrixMode(GL_MODELVIEW);
678 // Draw the background
679 glEnable(GL_TEXTURE_2D);
680 glDisable(GL_LIGHTING);
682 glEnable(GL_ALPHA_TEST);
683 glEnable(GL_COLOR_MATERIAL);
684 glColor4f(1.0, 1.0, 1.0, 1.0);
685 glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
686 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
687 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
688 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
690 glTexCoord2f(0.0, 0.0); glVertex3f(_x, _y, 0);
691 glTexCoord2f(10.0, 0.0); glVertex3f(_x + _w, _y, 0);
692 glTexCoord2f(10.0, 5.0); glVertex3f(_x + _w, _y + _panel_h, 0);
693 glTexCoord2f(0.0, 5.0); glVertex3f(_x, _y + _panel_h, 0);
696 // Draw the instruments.
697 instrument_list_type::const_iterator current = _instruments.begin();
698 instrument_list_type::const_iterator end = _instruments.end();
700 for ( ; current != end; current++) {
701 FGPanelInstrument * instr = *current;
703 glTranslated(instr->getXPos(), instr->getYPos(), 0);
707 glMatrixMode(GL_PROJECTION);
709 glMatrixMode(GL_MODELVIEW);
711 ssgForceBasicState();
712 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
716 FGPanel::setVisibility (bool visibility)
718 _visibility = visibility;
722 FGPanel::getVisibility () const
728 FGPanel::doMouseAction (int button, int updown, int x, int y)
730 // For now, ignore the release
734 x = (int)(((float)x / current_view.get_winWidth()) * _w);
735 y = (int)(_h - (((float)y / current_view.get_winHeight()) * _h));
737 for (int i = 0; i < _instruments.size(); i++) {
738 FGPanelInstrument *inst = _instruments[i];
739 int ix = inst->getXPos();
740 int iy = inst->getYPos();
741 int iw = inst->getWidth() / 2;
742 int ih = inst->getHeight() / 2;
743 if (x >= ix - iw && x < ix + iw && y >= iy - ih && y < iy + ih) {
744 cout << "Do mouse action for component " << i << '\n';
745 return inst->doMouseAction(button, updown, x - ix, y - iy);
748 cout << "Did not click on an instrument\n";
754 ////////////////////////////////////////////////////////////////////////
755 // Implementation of FGAdjustAction.
756 ////////////////////////////////////////////////////////////////////////
758 FGAdjustAction::FGAdjustAction (getter_type getter, setter_type setter,
759 double increment, double min, double max,
761 : _getter(getter), _setter(setter), _increment(increment),
762 _min(min), _max(max), _wrap(wrap)
766 FGAdjustAction::~FGAdjustAction ()
771 FGAdjustAction::doAction ()
773 double value = (*_getter)();
774 cout << "Do action; value=" << value << '\n';
777 value = (_wrap ? _max : _min);
778 } else if (value > _max) {
779 value = (_wrap ? _min : _max);
781 cout << "New value is " << value << '\n';
787 ////////////////////////////////////////////////////////////////////////
788 // Implementation of FGPanelInstrument.
789 ////////////////////////////////////////////////////////////////////////
792 FGPanelInstrument::FGPanelInstrument ()
798 FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
804 FGPanelInstrument::~FGPanelInstrument ()
806 action_list_type::iterator it = _actions.begin();
807 action_list_type::iterator last = _actions.end();
808 for ( ; it != last; it++) {
814 FGPanelInstrument::setPosition (int x, int y)
821 FGPanelInstrument::setSize (int w, int h)
828 FGPanelInstrument::getXPos () const
834 FGPanelInstrument::getYPos () const
840 FGPanelInstrument::getWidth () const
846 FGPanelInstrument::getHeight () const
852 FGPanelInstrument::addAction (int x, int y, int w, int h,
853 FGPanelAction * action)
855 FGPanelInstrument::inst_action act;
861 _actions.push_back(act);
864 // Coordinates relative to centre.
866 FGPanelInstrument::doMouseAction (int button, int updown, int x, int y)
868 action_list_type::iterator it = _actions.begin();
869 action_list_type::iterator last = _actions.end();
870 cout << "Mouse action at " << x << ',' << y << '\n';
871 for ( ; it != last; it++) {
872 cout << "Trying action at " << it->x << ',' << it->y << ','
873 << it->w <<',' << it->h << '\n';
874 if (x >= it->x && x < it->x + it->w && y >= it->y && y < it->y + it->h) {
875 it->action->doAction();
884 ////////////////////////////////////////////////////////////////////////
885 // Implementation of FGLayeredInstrument.
886 ////////////////////////////////////////////////////////////////////////
888 FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
889 : FGPanelInstrument(x, y, w, h)
893 FGLayeredInstrument::~FGLayeredInstrument ()
895 // FIXME: free layers
899 FGLayeredInstrument::draw () const
901 layer_list::const_iterator it = _layers.begin();
902 layer_list::const_iterator last = _layers.end();
910 FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
912 _layers.push_back(layer);
916 FGLayeredInstrument::addLayer (int layer, ssgTexture * texture)
918 addLayer(new FGTexturedInstrumentLayer(texture, _w, _h, layer));
922 FGLayeredInstrument::addTransformation (int layer,
923 FGInstrumentLayer::transform_type type,
924 FGInstrumentLayer::transform_func func,
925 double min, double max,
926 double factor, double offset)
928 _layers[layer]->addTransformation(type, func, min, max, factor, offset);
933 ////////////////////////////////////////////////////////////////////////
934 // Implementation of FGInstrumentLayer.
935 ////////////////////////////////////////////////////////////////////////
937 FGInstrumentLayer::FGInstrumentLayer (int w, int h, int z)
944 FGInstrumentLayer::~FGInstrumentLayer ()
946 transformation_list::iterator it = _transformations.begin();
947 transformation_list::iterator end = _transformations.end();
955 FGInstrumentLayer::transform () const
957 glTranslatef(0.0, 0.0, (_z / 100.0) + 0.1);
959 transformation_list::const_iterator it = _transformations.begin();
960 transformation_list::const_iterator last = _transformations.end();
962 transformation *t = *it;
963 double value = (t->func == 0 ? 0.0 : (*(t->func))());
964 if (value < t->min) {
966 } else if (value > t->max) {
969 value = value * t->factor + t->offset;
973 glTranslatef(value, 0.0, 0.0);
976 glTranslatef(0.0, value, 0.0);
979 glRotatef(-value, 0.0, 0.0, 1.0);
987 FGInstrumentLayer::addTransformation (transform_type type,
989 double min, double max,
990 double factor, double offset)
992 transformation *t = new transformation;
999 _transformations.push_back(t);
1004 ////////////////////////////////////////////////////////////////////////
1005 // Implementation of FGTexturedInstrumentLayer.
1006 ////////////////////////////////////////////////////////////////////////
1008 // FGTexturedInstrumentLayer::FGTexturedInstrumentLayer (const char *tname,
1009 // int w, int h, int z)
1010 // : FGInstrumentLayer(w, h, z)
1012 // setTexture(tname);
1015 FGTexturedInstrumentLayer::FGTexturedInstrumentLayer (ssgTexture * texture,
1016 int w, int h, int z)
1017 : FGInstrumentLayer(w, h, z)
1019 setTexture(texture);
1022 FGTexturedInstrumentLayer::~FGTexturedInstrumentLayer ()
1027 FGTexturedInstrumentLayer::draw () const
1034 glBindTexture(GL_TEXTURE_2D, _texture->getHandle());
1035 glBegin(GL_POLYGON);
1036 // FIXME: is this really correct
1038 glTexCoord2f(0.0, 0.0); glVertex2f(-w2, -h2);
1039 glTexCoord2f(1.0, 0.0); glVertex2f(w2, -h2);
1040 glTexCoord2f(1.0, 1.0); glVertex2f(w2, h2);
1041 glTexCoord2f(0.0, 1.0); glVertex2f(-w2, h2);
1047 // FGTexturedInstrumentLayer::setTexture (const char *textureName)
1049 // FGPath tpath(current_options.get_fg_root());
1050 // tpath.append(textureName);
1051 // ssgTexture * texture = new ssgTexture((char *)tpath.c_str(), false, false);
1052 // setTexture(texture);
1057 ////////////////////////////////////////////////////////////////////////
1058 // Implementation of FGCharInstrumentLayer.
1059 ////////////////////////////////////////////////////////////////////////
1061 FGCharInstrumentLayer::FGCharInstrumentLayer (text_func func,
1062 int w, int h, int z)
1063 : FGInstrumentLayer(w, h, z),
1066 _renderer.setFont(guiFntHandle);
1067 _renderer.setPointSize(14);
1068 _color[0] = _color[1] = _color[2] = 0.0;
1072 FGCharInstrumentLayer::~FGCharInstrumentLayer ()
1077 FGCharInstrumentLayer::draw () const
1083 _renderer.start3f(0, 0, 0);
1084 _renderer.puts((*_func)(_buf));
1086 glColor4f(1.0, 1.0, 1.0, 1.0); // FIXME
1091 FGCharInstrumentLayer::setColor (float r, float g, float b)
1100 FGCharInstrumentLayer::setPointSize (const float size)
1102 _renderer.setPointSize(size);
1106 FGCharInstrumentLayer::setFont(fntFont * font)
1108 _renderer.setFont(font);