]> git.mxchange.org Git - flightgear.git/blob - src/Cockpit/panel.cxx
1. Fixed FGInput bug preventing same key from being bound separately
[flightgear.git] / src / Cockpit / panel.cxx
1 //  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 <string.h>
30
31 #include <plib/ssg.h>
32 #include <plib/fnt.h>
33
34 #include <simgear/debug/logstream.hxx>
35 #include <simgear/misc/sg_path.hxx>
36
37 #include <Main/globals.hxx>
38 #include <Main/fg_props.hxx>
39 #include <Objects/texload.h>
40 #include <Time/light.hxx>
41
42 #include "hud.hxx"
43 #include "panel.hxx"
44
45
46 bool
47 fgPanelVisible ()
48 {
49   return ((current_panel != 0) &&
50           (current_panel->getVisibility()) &&
51           (globals->get_viewmgr()->get_current() == 0) &&
52           (globals->get_current_view()->get_view_offset() == 0.0));
53 }
54
55
56 \f
57 ////////////////////////////////////////////////////////////////////////
58 // Implementation of FGTextureManager.
59 ////////////////////////////////////////////////////////////////////////
60
61 map<string,ssgTexture *> FGTextureManager::_textureMap;
62
63 ssgTexture *
64 FGTextureManager::createTexture (const string &relativePath)
65 {
66   ssgTexture * texture = _textureMap[relativePath];
67   if (texture == 0) {
68     cerr << "Texture " << relativePath << " does not yet exist" << endl;
69     SGPath tpath(globals->get_fg_root());
70     tpath.append(relativePath);
71     texture = new ssgTexture((char *)tpath.c_str(), false, false);
72     _textureMap[relativePath] = texture;
73     if (_textureMap[relativePath] == 0) 
74       cerr << "Texture *still* doesn't exist" << endl;
75     cerr << "Created texture " << relativePath
76          << " handle=" << texture->getHandle() << endl;
77   }
78
79   return texture;
80 }
81
82
83
84 \f
85 ////////////////////////////////////////////////////////////////////////
86 // Implementation of FGCropped Texture.
87 ////////////////////////////////////////////////////////////////////////
88
89
90 FGCroppedTexture::FGCroppedTexture ()
91   : _path(""), _texture(0),
92     _minX(0.0), _minY(0.0), _maxX(1.0), _maxY(1.0)
93 {
94 }
95
96
97 FGCroppedTexture::FGCroppedTexture (const string &path,
98                                     float minX, float minY,
99                                     float maxX, float maxY)
100   : _path(path), _texture(0),
101     _minX(minX), _minY(minY), _maxX(maxX), _maxY(maxY)
102 {
103 }
104
105
106 FGCroppedTexture::~FGCroppedTexture ()
107 {
108 }
109
110
111 ssgTexture *
112 FGCroppedTexture::getTexture ()
113 {
114   if (_texture == 0) {
115     _texture = FGTextureManager::createTexture(_path);
116   }
117   return _texture;
118 }
119
120
121 \f
122 ////////////////////////////////////////////////////////////////////////
123 // Implementation of FGPanel.
124 ////////////////////////////////////////////////////////////////////////
125
126 FGPanel * current_panel = NULL;
127 static fntRenderer text_renderer;
128
129
130 /**
131  * Constructor.
132  */
133 FGPanel::FGPanel (int window_x, int window_y, int window_w, int window_h)
134   : _mouseDown(false),
135     _mouseInstrument(0),
136     _winx(window_x), _winy(window_y), _winw(window_w), _winh(window_h),
137     _width(_winw), _height(int(_winh * 0.5768 + 1)),
138     _x_offset(0), _y_offset(0), _view_height(int(_winh * 0.4232)),
139     _bound(false)
140 {
141   setVisibility(fgPanelVisible());
142 }
143
144
145 /**
146  * Destructor.
147  */
148 FGPanel::~FGPanel ()
149 {
150   if (_bound)
151     unbind();
152   for (instrument_list_type::iterator it = _instruments.begin();
153        it != _instruments.end();
154        it++) {
155     delete *it;
156     *it = 0;
157   }
158 }
159
160
161 /**
162  * Add an instrument to the panel.
163  */
164 void
165 FGPanel::addInstrument (FGPanelInstrument * instrument)
166 {
167   _instruments.push_back(instrument);
168 }
169
170
171 /**
172  * Initialize the panel.
173  */
174 void
175 FGPanel::init ()
176 {
177   // NO-OP
178 }
179
180
181 /**
182  * Bind panel properties.
183  */
184 void
185 FGPanel::bind ()
186 {
187   fgTie("/sim/panel/visibility", &_visibility);
188   fgTie("/sim/panel/x-offset", &_x_offset);
189   fgTie("/sim/panel/y-offset", &_y_offset);
190   _bound = true;
191 }
192
193
194 /**
195  * Unbind panel properties.
196  */
197 void
198 FGPanel::unbind ()
199 {
200   fgUntie("/sim/panel/visibility");
201   fgUntie("/sim/panel/x-offset");
202   fgUntie("/sim/panel/y-offset");
203   _bound = false;
204 }
205
206
207 /**
208  * Update the panel.
209  */
210 void
211 FGPanel::update ()
212 {
213                                 // Do nothing if the panel isn't visible.
214   if (!fgPanelVisible())
215     return;
216
217                                 // If the mouse is down, do something
218   if (_mouseDown) {
219     _mouseDelay--;
220     if (_mouseDelay < 0) {
221       _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
222       _mouseDelay = 2;
223     }
224   }
225
226                                 // Now, draw the panel
227   glMatrixMode(GL_PROJECTION);
228   glPushMatrix();
229   glLoadIdentity();
230   gluOrtho2D(_winx, _winx + _winw, _winy, _winy + _winh);
231
232   glMatrixMode(GL_MODELVIEW);
233   glPushMatrix();
234   glLoadIdentity();
235
236   glTranslated(_x_offset, _y_offset, 0);
237
238                                 // Draw the background
239   glEnable(GL_TEXTURE_2D);
240   glDisable(GL_LIGHTING);
241   glEnable(GL_BLEND);
242   glEnable(GL_ALPHA_TEST);
243   glEnable(GL_COLOR_MATERIAL);
244   // glColor4f(1.0, 1.0, 1.0, 1.0);
245   if ( cur_light_params.sun_angle * SGD_RADIANS_TO_DEGREES < 95.0 ) {
246       glColor4fv( cur_light_params.scene_diffuse );
247   } else {
248       glColor4f(0.7, 0.2, 0.2, 1.0);
249   }
250   glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
251   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
252   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
253   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
254   glBegin(GL_POLYGON);
255   glTexCoord2f(0.0, 0.0); glVertex3f(_winx, _winy, 0);
256   glTexCoord2f(1.0, 0.0); glVertex3f(_winx + _width, _winy, 0);
257   glTexCoord2f(1.0, 1.0); glVertex3f(_winx + _width, _winy + _height, 0);
258   glTexCoord2f(0.0, 1.0); glVertex3f(_winx, _winy + _height, 0);
259   glEnd();
260
261                                 // Draw the instruments.
262   instrument_list_type::const_iterator current = _instruments.begin();
263   instrument_list_type::const_iterator end = _instruments.end();
264
265   for ( ; current != end; current++) {
266     FGPanelInstrument * instr = *current;
267     glLoadIdentity();
268     glTranslated(_x_offset, _y_offset, 0);
269     glTranslated(instr->getXPos(), instr->getYPos(), 0);
270     instr->draw();
271   }
272
273   glMatrixMode(GL_PROJECTION);
274   glPopMatrix();
275   glMatrixMode(GL_MODELVIEW);
276   glPopMatrix();
277   ssgForceBasicState();
278   glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
279 }
280
281
282 /**
283  * Set the panel's visibility.
284  */
285 void
286 FGPanel::setVisibility (bool visibility)
287 {
288   _visibility = visibility;
289 }
290
291
292 /**
293  * Return true if the panel is visible.
294  */
295 bool
296 FGPanel::getVisibility () const
297 {
298   return _visibility;
299 }
300
301
302 /**
303  * Set the panel's background texture.
304  */
305 void
306 FGPanel::setBackground (ssgTexture * texture)
307 {
308   _bg = texture;
309 }
310
311
312 /**
313  * Set the panel's x-offset.
314  */
315 void
316 FGPanel::setXOffset (int offset)
317 {
318   if (offset <= 0 && offset >= -_width + _winw)
319     _x_offset = offset;
320 }
321
322
323 /**
324  * Set the panel's y-offset.
325  */
326 void
327 FGPanel::setYOffset (int offset)
328 {
329   if (offset <= 0 && offset >= -_height)
330     _y_offset = offset;
331 }
332
333
334 /**
335  * Perform a mouse action.
336  */
337 bool
338 FGPanel::doMouseAction (int button, int updown, int x, int y)
339 {
340
341                                 // Note a released button and return
342   // cerr << "Doing mouse action\n";
343   if (updown == 1) {
344     _mouseDown = false;
345     _mouseInstrument = 0;
346     return true;
347   }
348
349                                 // Scale for the real window size.
350   x = int(((float)x / fgGetInt("/sim/startup/xsize")) * _winw);
351   y = int(_winh - (((float)y / fgGetInt("/sim/startup/ysize"))
352                    * _winh));
353
354                                 // Adjust for offsets.
355   x -= _x_offset;
356   y -= _y_offset;
357
358                                 // Search for a matching instrument.
359   for (int i = 0; i < (int)_instruments.size(); i++) {
360     FGPanelInstrument *inst = _instruments[i];
361     int ix = inst->getXPos();
362     int iy = inst->getYPos();
363     int iw = inst->getWidth() / 2;
364     int ih = inst->getHeight() / 2;
365     if (x >= ix - iw && x < ix + iw && y >= iy - ih && y < iy + ih) {
366       _mouseDown = true;
367       _mouseDelay = 20;
368       _mouseInstrument = inst;
369       _mouseButton = button;
370       _mouseX = x - ix;
371       _mouseY = y - iy;
372                                 // Always do the action once.
373       _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
374       return true;
375     }
376   }
377   return false;
378 }
379
380
381 \f
382 ////////////////////////////////////////////////////////////////////////.
383 // Implementation of FGPanelAction.
384 ////////////////////////////////////////////////////////////////////////
385
386 FGPanelAction::FGPanelAction ()
387 {
388 }
389
390 FGPanelAction::FGPanelAction (int button, int x, int y, int w, int h)
391   : _button(button), _x(x), _y(y), _w(w), _h(h)
392 {
393 }
394
395 FGPanelAction::~FGPanelAction ()
396 {
397 }
398
399
400 \f
401 ////////////////////////////////////////////////////////////////////////
402 // Implementation of FGAdjustAction.
403 ////////////////////////////////////////////////////////////////////////
404
405 FGAdjustAction::FGAdjustAction (int button, int x, int y, int w, int h,
406                                 SGValue * value, float increment, 
407                                 float min, float max, bool wrap)
408   : FGPanelAction(button, x, y, w, h),
409     _value(value), _increment(increment), _min(min), _max(max), _wrap(wrap)
410 {
411 }
412
413 FGAdjustAction::~FGAdjustAction ()
414 {
415 }
416
417 void
418 FGAdjustAction::doAction ()
419 {
420   float val = _value->getFloatValue();
421   val += _increment;
422   if (val < _min) {
423     val = (_wrap ? _max : _min);
424   } else if (val > _max) {
425     val = (_wrap ? _min : _max);
426   }
427   _value->setDoubleValue(val);
428 }
429
430
431 \f
432 ////////////////////////////////////////////////////////////////////////
433 // Implementation of FGSwapAction.
434 ////////////////////////////////////////////////////////////////////////
435
436 FGSwapAction::FGSwapAction (int button, int x, int y, int w, int h,
437                             SGValue * value1, SGValue * value2)
438   : FGPanelAction(button, x, y, w, h), _value1(value1), _value2(value2)
439 {
440 }
441
442 FGSwapAction::~FGSwapAction ()
443 {
444 }
445
446 void
447 FGSwapAction::doAction ()
448 {
449   float val = _value1->getFloatValue();
450   _value1->setDoubleValue(_value2->getFloatValue());
451   _value2->setDoubleValue(val);
452 }
453
454
455 \f
456 ////////////////////////////////////////////////////////////////////////
457 // Implementation of FGToggleAction.
458 ////////////////////////////////////////////////////////////////////////
459
460 FGToggleAction::FGToggleAction (int button, int x, int y, int w, int h,
461                                 SGValue * value)
462   : FGPanelAction(button, x, y, w, h), _value(value)
463 {
464 }
465
466 FGToggleAction::~FGToggleAction ()
467 {
468 }
469
470 void
471 FGToggleAction::doAction ()
472 {
473   _value->setBoolValue(!(_value->getBoolValue()));
474 }
475
476
477 \f
478 ////////////////////////////////////////////////////////////////////////
479 // Implementation of FGPanelTransformation.
480 ////////////////////////////////////////////////////////////////////////
481
482 FGPanelTransformation::FGPanelTransformation ()
483   : table(0)
484 {
485 }
486
487 FGPanelTransformation::~FGPanelTransformation ()
488 {
489 }
490
491
492 \f
493 ////////////////////////////////////////////////////////////////////////
494 // Implementation of FGPanelInstrument.
495 ////////////////////////////////////////////////////////////////////////
496
497
498 FGPanelInstrument::FGPanelInstrument ()
499 {
500   setPosition(0, 0);
501   setSize(0, 0);
502 }
503
504 FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
505 {
506   setPosition(x, y);
507   setSize(w, h);
508 }
509
510 FGPanelInstrument::~FGPanelInstrument ()
511 {
512   for (action_list_type::iterator it = _actions.begin();
513        it != _actions.end();
514        it++) {
515     delete *it;
516     *it = 0;
517   }
518 }
519
520 void
521 FGPanelInstrument::setPosition (int x, int y)
522 {
523   _x = x;
524   _y = y;
525 }
526
527 void
528 FGPanelInstrument::setSize (int w, int h)
529 {
530   _w = w;
531   _h = h;
532 }
533
534 int
535 FGPanelInstrument::getXPos () const
536 {
537   return _x;
538 }
539
540 int
541 FGPanelInstrument::getYPos () const
542 {
543   return _y;
544 }
545
546 int
547 FGPanelInstrument::getWidth () const
548 {
549   return _w;
550 }
551
552 int
553 FGPanelInstrument::getHeight () const
554 {
555   return _h;
556 }
557
558 void
559 FGPanelInstrument::addAction (FGPanelAction * action)
560 {
561   _actions.push_back(action);
562 }
563
564                                 // Coordinates relative to centre.
565 bool
566 FGPanelInstrument::doMouseAction (int button, int x, int y)
567 {
568   action_list_type::iterator it = _actions.begin();
569   action_list_type::iterator last = _actions.end();
570   for ( ; it != last; it++) {
571     if ((*it)->inArea(button, x, y)) {
572       (*it)->doAction();
573       return true;
574     }
575   }
576   return false;
577 }
578
579
580 \f
581 ////////////////////////////////////////////////////////////////////////
582 // Implementation of FGLayeredInstrument.
583 ////////////////////////////////////////////////////////////////////////
584
585 FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
586   : FGPanelInstrument(x, y, w, h)
587 {
588 }
589
590 FGLayeredInstrument::~FGLayeredInstrument ()
591 {
592   for (layer_list::iterator it = _layers.begin(); it != _layers.end(); it++) {
593     delete *it;
594     *it = 0;
595   }
596 }
597
598 void
599 FGLayeredInstrument::draw ()
600 {
601   for (int i = 0; i < (int)_layers.size(); i++) {
602     glPushMatrix();
603     glTranslatef(0.0, 0.0, (i / 100.0) + 0.1);
604     _layers[i]->draw();
605     glPopMatrix();
606   }
607 }
608
609 int
610 FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
611 {
612   int n = _layers.size();
613   if (layer->getWidth() == -1) {
614     layer->setWidth(getWidth());
615   }
616   if (layer->getHeight() == -1) {
617     layer->setHeight(getHeight());
618   }
619   _layers.push_back(layer);
620   return n;
621 }
622
623 int
624 FGLayeredInstrument::addLayer (FGCroppedTexture &texture,
625                                int w, int h)
626 {
627   return addLayer(new FGTexturedLayer(texture, w, h));
628 }
629
630 void
631 FGLayeredInstrument::addTransformation (FGPanelTransformation * transformation)
632 {
633   int layer = _layers.size() - 1;
634   _layers[layer]->addTransformation(transformation);
635 }
636
637
638 \f
639 ////////////////////////////////////////////////////////////////////////
640 // Implementation of FGInstrumentLayer.
641 ////////////////////////////////////////////////////////////////////////
642
643 FGInstrumentLayer::FGInstrumentLayer (int w, int h)
644   : _w(w),
645     _h(h)
646 {
647 }
648
649 FGInstrumentLayer::~FGInstrumentLayer ()
650 {
651   for (transformation_list::iterator it = _transformations.begin();
652        it != _transformations.end();
653        it++) {
654     delete *it;
655     *it = 0;
656   }
657 }
658
659 void
660 FGInstrumentLayer::transform () const
661 {
662   transformation_list::const_iterator it = _transformations.begin();
663   transformation_list::const_iterator last = _transformations.end();
664   while (it != last) {
665     FGPanelTransformation *t = *it;
666     float val = (t->value == 0 ? 0.0 : t->value->getFloatValue());
667     if (val < t->min) {
668       val = t->min;
669     } else if (val > t->max) {
670       val = t->max;
671     }
672     if(t->table==0) {
673         val = val * t->factor + t->offset;
674     } else {
675         val = t->table->interpolate(val) * t->factor + t->offset;
676     }
677
678     switch (t->type) {
679     case FGPanelTransformation::XSHIFT:
680       glTranslatef(val, 0.0, 0.0);
681       break;
682     case FGPanelTransformation::YSHIFT:
683       glTranslatef(0.0, val, 0.0);
684       break;
685     case FGPanelTransformation::ROTATION:
686       glRotatef(-val, 0.0, 0.0, 1.0);
687       break;
688     }
689     it++;
690   }
691 }
692
693 void
694 FGInstrumentLayer::addTransformation (FGPanelTransformation * transformation)
695 {
696   _transformations.push_back(transformation);
697 }
698
699
700 \f
701 ////////////////////////////////////////////////////////////////////////
702 // Implementation of FGTexturedLayer.
703 ////////////////////////////////////////////////////////////////////////
704
705
706 FGTexturedLayer::FGTexturedLayer (const FGCroppedTexture &texture, int w, int h)
707   : FGInstrumentLayer(w, h)
708 {
709   setTexture(texture);
710 }
711
712
713 FGTexturedLayer::~FGTexturedLayer ()
714 {
715 }
716
717
718 void
719 FGTexturedLayer::draw ()
720 {
721   int w2 = _w / 2;
722   int h2 = _h / 2;
723
724   transform();
725   glBindTexture(GL_TEXTURE_2D, _texture.getTexture()->getHandle());
726   glBegin(GL_POLYGON);
727
728                                 // From Curt: turn on the panel
729                                 // lights after sundown.
730   if ( cur_light_params.sun_angle * SGD_RADIANS_TO_DEGREES < 95.0 ) {
731       glColor4fv( cur_light_params.scene_diffuse );
732   } else {
733       glColor4f(0.7, 0.2, 0.2, 1.0);
734   }
735
736
737   glTexCoord2f(_texture.getMinX(), _texture.getMinY()); glVertex2f(-w2, -h2);
738   glTexCoord2f(_texture.getMaxX(), _texture.getMinY()); glVertex2f(w2, -h2);
739   glTexCoord2f(_texture.getMaxX(), _texture.getMaxY()); glVertex2f(w2, h2);
740   glTexCoord2f(_texture.getMinX(), _texture.getMaxY()); glVertex2f(-w2, h2);
741   glEnd();
742 }
743
744
745 \f
746 ////////////////////////////////////////////////////////////////////////
747 // Implementation of FGTextLayer.
748 ////////////////////////////////////////////////////////////////////////
749
750 FGTextLayer::FGTextLayer (int w, int h)
751   : FGInstrumentLayer(w, h), _pointSize(14.0)
752 {
753   _then.stamp();
754   _color[0] = _color[1] = _color[2] = 0.0;
755   _color[3] = 1.0;
756 }
757
758 FGTextLayer::~FGTextLayer ()
759 {
760   chunk_list::iterator it = _chunks.begin();
761   chunk_list::iterator last = _chunks.end();
762   for ( ; it != last; it++) {
763     delete *it;
764   }
765 }
766
767 void
768 FGTextLayer::draw ()
769 {
770   glPushMatrix();
771   glColor4fv(_color);
772   transform();
773   text_renderer.setFont(guiFntHandle);
774   text_renderer.setPointSize(_pointSize);
775   text_renderer.begin();
776   text_renderer.start3f(0, 0, 0);
777
778   _now.stamp();
779   if (_now - _then > 100000) {
780     recalc_value();
781     _then = _now;
782   }
783   text_renderer.puts((char *)(_value.c_str()));
784
785   text_renderer.end();
786   glColor4f(1.0, 1.0, 1.0, 1.0);        // FIXME
787   glPopMatrix();
788 }
789
790 void
791 FGTextLayer::addChunk (FGTextLayer::Chunk * chunk)
792 {
793   _chunks.push_back(chunk);
794 }
795
796 void
797 FGTextLayer::setColor (float r, float g, float b)
798 {
799   _color[0] = r;
800   _color[1] = g;
801   _color[2] = b;
802   _color[3] = 1.0;
803 }
804
805 void
806 FGTextLayer::setPointSize (float size)
807 {
808   _pointSize = size;
809 }
810
811 void
812 FGTextLayer::setFont(fntFont * font)
813 {
814   text_renderer.setFont(font);
815 }
816
817
818 void
819 FGTextLayer::recalc_value () const
820 {
821   _value = "";
822   chunk_list::const_iterator it = _chunks.begin();
823   chunk_list::const_iterator last = _chunks.end();
824   for ( ; it != last; it++) {
825     _value += (*it)->getValue();
826   }
827 }
828
829
830 \f
831 ////////////////////////////////////////////////////////////////////////
832 // Implementation of FGTextLayer::Chunk.
833 ////////////////////////////////////////////////////////////////////////
834
835 FGTextLayer::Chunk::Chunk (const string &text, const string &fmt)
836   : _type(FGTextLayer::TEXT), _fmt(fmt)
837 {
838   _text = text;
839   if (_fmt == "") 
840     _fmt = "%s";
841 }
842
843 FGTextLayer::Chunk::Chunk (ChunkType type, const SGValue * value,
844                            const string &fmt, float mult)
845   : _type(type), _fmt(fmt), _mult(mult)
846 {
847   if (_fmt == "") {
848     if (type == TEXT_VALUE)
849       _fmt = "%s";
850     else
851       _fmt = "%.2f";
852   }
853   _value = value;
854 }
855
856 const char *
857 FGTextLayer::Chunk::getValue () const
858 {
859   switch (_type) {
860   case TEXT:
861     sprintf(_buf, _fmt.c_str(), _text.c_str());
862     return _buf;
863   case TEXT_VALUE:
864     sprintf(_buf, _fmt.c_str(), _value->getStringValue().c_str());
865     break;
866   case DOUBLE_VALUE:
867     sprintf(_buf, _fmt.c_str(), _value->getFloatValue() * _mult);
868     break;
869   }
870   return _buf;
871 }
872
873
874 \f
875 ////////////////////////////////////////////////////////////////////////
876 // Implementation of FGSwitchLayer.
877 ////////////////////////////////////////////////////////////////////////
878
879 FGSwitchLayer::FGSwitchLayer (int w, int h, const SGValue * value,
880                               FGInstrumentLayer * layer1,
881                               FGInstrumentLayer * layer2)
882   : FGInstrumentLayer(w, h), _value(value), _layer1(layer1), _layer2(layer2)
883 {
884 }
885
886 FGSwitchLayer::~FGSwitchLayer ()
887 {
888   delete _layer1;
889   delete _layer2;
890 }
891
892 void
893 FGSwitchLayer::draw ()
894 {
895   transform();
896   if (_value->getBoolValue()) {
897     _layer1->draw();
898   } else {
899     _layer2->draw();
900   }
901 }
902
903 \f
904 // end of panel.cxx