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.
34 #include <simgear/debug/logstream.hxx>
35 #include <simgear/misc/fgpath.hxx>
36 #include <Main/options.hxx>
37 #include <Main/views.hxx>
38 #include <Objects/texload.h>
45 ////////////////////////////////////////////////////////////////////////
46 // Implementation of FGTextureManager.
47 ////////////////////////////////////////////////////////////////////////
49 map<string,ssgTexture *> FGTextureManager::_textureMap;
52 FGTextureManager::createTexture (const string &relativePath)
54 ssgTexture * texture = _textureMap[relativePath];
56 cerr << "Texture " << relativePath << " does not yet exist" << endl;
57 FGPath tpath(current_options.get_fg_root());
58 tpath.append(relativePath);
59 texture = new ssgTexture((char *)tpath.c_str(), false, false);
60 _textureMap[relativePath] = texture;
61 if (_textureMap[relativePath] == 0)
62 cerr << "Texture *still* doesn't exist" << endl;
63 cerr << "Created texture " << relativePath
64 << " handle=" << texture->getHandle() << endl;
72 ////////////////////////////////////////////////////////////////////////
73 // Implementation of FGPanel.
74 ////////////////////////////////////////////////////////////////////////
76 FGPanel * current_panel = NULL;
78 FGPanel::FGPanel (int x, int y, int w, int h)
81 _x(x), _y(y), _w(w), _h(h)
83 setVisibility(current_options.get_panel_status());
84 _panel_h = (int)(h * 0.5768 + 1);
89 instrument_list_type::iterator current = _instruments.begin();
90 instrument_list_type::iterator last = _instruments.end();
92 for ( ; current != last; ++current) {
99 FGPanel::addInstrument (FGPanelInstrument * instrument)
101 _instruments.push_back(instrument);
105 FGPanel::update () const
107 // Do nothing if the panel isn't visible.
111 // If the mouse is down, do something
114 if (_mouseDelay < 0) {
115 _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
120 // Now, draw the panel
121 glMatrixMode(GL_PROJECTION);
124 gluOrtho2D(_x, _x + _w, _y, _y + _h);
126 glMatrixMode(GL_MODELVIEW);
130 // Draw the background
131 glEnable(GL_TEXTURE_2D);
132 glDisable(GL_LIGHTING);
134 glEnable(GL_ALPHA_TEST);
135 glEnable(GL_COLOR_MATERIAL);
136 // glColor4f(1.0, 1.0, 1.0, 1.0);
137 if ( cur_light_params.sun_angle * RAD_TO_DEG < 95.0 ) {
138 glColor4fv( cur_light_params.scene_diffuse );
140 glColor4f(0.7, 0.2, 0.2, 1.0);
142 glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
143 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
144 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
145 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
147 glTexCoord2f(0.0, 0.0); glVertex3f(_x, _y, 0);
148 glTexCoord2f(10.0, 0.0); glVertex3f(_x + _w, _y, 0);
149 glTexCoord2f(10.0, 5.0); glVertex3f(_x + _w, _y + _panel_h, 0);
150 glTexCoord2f(0.0, 5.0); glVertex3f(_x, _y + _panel_h, 0);
153 // Draw the instruments.
154 instrument_list_type::const_iterator current = _instruments.begin();
155 instrument_list_type::const_iterator end = _instruments.end();
157 for ( ; current != end; current++) {
158 FGPanelInstrument * instr = *current;
160 glTranslated(instr->getXPos(), instr->getYPos(), 0);
164 glMatrixMode(GL_PROJECTION);
166 glMatrixMode(GL_MODELVIEW);
168 ssgForceBasicState();
169 glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
173 FGPanel::setVisibility (bool visibility)
175 _visibility = visibility;
179 FGPanel::getVisibility () const
185 FGPanel::setBackground (ssgTexture * texture)
191 FGPanel::doMouseAction (int button, int updown, int x, int y)
193 // Note a released button and return
194 // cerr << "Doing mouse action\n";
197 _mouseInstrument = 0;
201 x = (int)(((float)x / current_view.get_winWidth()) * _w);
202 y = (int)(_h - (((float)y / current_view.get_winHeight()) * _h));
204 for (int i = 0; i < _instruments.size(); i++) {
205 FGPanelInstrument *inst = _instruments[i];
206 int ix = inst->getXPos();
207 int iy = inst->getYPos();
208 int iw = inst->getWidth() / 2;
209 int ih = inst->getHeight() / 2;
210 if (x >= ix - iw && x < ix + iw && y >= iy - ih && y < iy + ih) {
211 // cout << "Do mouse action for component " << i << '\n';
214 _mouseInstrument = inst;
215 _mouseButton = button;
218 // Always do the action once.
219 _mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
223 // cout << "Did not click on an instrument\n";
229 ////////////////////////////////////////////////////////////////////////
230 // Implementation of FGAdjustAction.
231 ////////////////////////////////////////////////////////////////////////
233 FGAdjustAction::FGAdjustAction (SGValue * value, float increment,
234 float min, float max, bool wrap=false)
235 : _value(value), _increment(increment), _min(min), _max(max), _wrap(wrap)
239 FGAdjustAction::~FGAdjustAction ()
244 FGAdjustAction::doAction ()
246 float val = _value->getFloatValue();
247 // cout << "Do action; value=" << value << '\n';
250 val = (_wrap ? _max : _min);
251 } else if (val > _max) {
252 val = (_wrap ? _min : _max);
254 // cout << "New value is " << value << '\n';
255 _value->setDoubleValue(val);
260 ////////////////////////////////////////////////////////////////////////
261 // Implementation of FGSwapAction.
262 ////////////////////////////////////////////////////////////////////////
264 FGSwapAction::FGSwapAction (SGValue * value1, SGValue * value2)
265 : _value1(value1), _value2(value2)
269 FGSwapAction::~FGSwapAction ()
274 FGSwapAction::doAction ()
276 float val = _value1->getFloatValue();
277 _value1->setDoubleValue(_value2->getFloatValue());
278 _value2->setDoubleValue(val);
283 ////////////////////////////////////////////////////////////////////////
284 // Implementation of FGToggleAction.
285 ////////////////////////////////////////////////////////////////////////
287 FGToggleAction::FGToggleAction (SGValue * value)
292 FGToggleAction::~FGToggleAction ()
297 FGToggleAction::doAction ()
299 _value->setBoolValue(!(_value->getBoolValue()));
304 ////////////////////////////////////////////////////////////////////////
305 // Implementation of FGPanelInstrument.
306 ////////////////////////////////////////////////////////////////////////
309 FGPanelInstrument::FGPanelInstrument ()
315 FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
321 FGPanelInstrument::~FGPanelInstrument ()
323 action_list_type::iterator it = _actions.begin();
324 action_list_type::iterator last = _actions.end();
325 for ( ; it != last; it++) {
331 FGPanelInstrument::setPosition (int x, int y)
338 FGPanelInstrument::setSize (int w, int h)
345 FGPanelInstrument::getXPos () const
351 FGPanelInstrument::getYPos () const
357 FGPanelInstrument::getWidth () const
363 FGPanelInstrument::getHeight () const
369 FGPanelInstrument::addAction (int button, int x, int y, int w, int h,
370 FGPanelAction * action)
372 FGPanelInstrument::inst_action act;
379 _actions.push_back(act);
382 // Coordinates relative to centre.
384 FGPanelInstrument::doMouseAction (int button, int x, int y)
386 action_list_type::iterator it = _actions.begin();
387 action_list_type::iterator last = _actions.end();
388 // cout << "Mouse action at " << x << ',' << y << '\n';
389 for ( ; it != last; it++) {
390 // cout << "Trying action at " << it->x << ',' << it->y << ','
391 // << it->w <<',' << it->h << '\n';
392 if (button == it->button &&
393 x >= it->x && x < it->x + it->w && y >= it->y && y < it->y + it->h) {
394 it->action->doAction();
403 ////////////////////////////////////////////////////////////////////////
404 // Implementation of FGLayeredInstrument.
405 ////////////////////////////////////////////////////////////////////////
407 FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
408 : FGPanelInstrument(x, y, w, h)
412 FGLayeredInstrument::~FGLayeredInstrument ()
414 // FIXME: free layers
418 FGLayeredInstrument::draw ()
420 for (int i = 0; i < _layers.size(); i++) {
422 glTranslatef(0.0, 0.0, (i / 100.0) + 0.1);
429 FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
431 int n = _layers.size();
432 if (layer->getWidth() == -1) {
433 layer->setWidth(getWidth());
435 if (layer->getHeight() == -1) {
436 layer->setHeight(getHeight());
438 _layers.push_back(layer);
443 FGLayeredInstrument::addLayer (CroppedTexture &texture,
444 int w = -1, int h = -1)
446 return addLayer(new FGTexturedLayer(texture, w, h));
450 FGLayeredInstrument::addTransformation (FGInstrumentLayer::transform_type type,
451 const SGValue * value,
452 float min, float max,
453 float factor, float offset)
455 int layer = _layers.size() - 1;
456 _layers[layer]->addTransformation(type, value, min, max, factor, offset);
460 FGLayeredInstrument::addTransformation (FGInstrumentLayer::transform_type type,
463 addTransformation(type, 0, 0.0, 0.0, 1.0, offset);
468 ////////////////////////////////////////////////////////////////////////
469 // Implementation of FGInstrumentLayer.
470 ////////////////////////////////////////////////////////////////////////
472 FGInstrumentLayer::FGInstrumentLayer (int w, int h)
478 FGInstrumentLayer::~FGInstrumentLayer ()
480 transformation_list::iterator it = _transformations.begin();
481 transformation_list::iterator end = _transformations.end();
489 FGInstrumentLayer::transform () const
491 transformation_list::const_iterator it = _transformations.begin();
492 transformation_list::const_iterator last = _transformations.end();
494 transformation *t = *it;
495 float val = (t->value == 0 ? 0.0 : t->value->getFloatValue());
498 } else if (val > t->max) {
501 val = val * t->factor + t->offset;
505 glTranslatef(val, 0.0, 0.0);
508 glTranslatef(0.0, val, 0.0);
511 glRotatef(-val, 0.0, 0.0, 1.0);
519 FGInstrumentLayer::addTransformation (transform_type type,
520 const SGValue * value,
521 float min, float max,
522 float factor, float offset)
524 transformation *t = new transformation;
531 _transformations.push_back(t);
536 ////////////////////////////////////////////////////////////////////////
537 // Implementation of FGTexturedLayer.
538 ////////////////////////////////////////////////////////////////////////
541 FGTexturedLayer::FGTexturedLayer (CroppedTexture &texture, int w, int h)
542 : FGInstrumentLayer(w, h)
548 FGTexturedLayer::~FGTexturedLayer ()
554 FGTexturedLayer::draw ()
560 glBindTexture(GL_TEXTURE_2D, _texture->texture->getHandle());
562 if ( cur_light_params.sun_angle * RAD_TO_DEG < 95.0 ) {
563 glColor4fv( cur_light_params.scene_diffuse );
565 glColor4f(0.7, 0.2, 0.2, 1.0);
567 glTexCoord2f(_texture->minX, _texture->minY); glVertex2f(-w2, -h2);
568 glTexCoord2f(_texture->maxX, _texture->minY); glVertex2f(w2, -h2);
569 glTexCoord2f(_texture->maxX, _texture->maxY); glVertex2f(w2, h2);
570 glTexCoord2f(_texture->minX, _texture->maxY); glVertex2f(-w2, h2);
576 ////////////////////////////////////////////////////////////////////////
577 // Implementation of FGTextLayer.
578 ////////////////////////////////////////////////////////////////////////
580 FGTextLayer::FGTextLayer (int w, int h, Chunk * chunk1, Chunk * chunk2,
582 : FGInstrumentLayer(w, h)
584 _color[0] = _color[1] = _color[2] = 0.0;
594 FGTextLayer::~FGTextLayer ()
596 chunk_list::iterator it = _chunks.begin();
597 chunk_list::iterator last = _chunks.end();
598 for ( ; it != last; it++) {
609 _renderer.setFont(guiFntHandle);
610 _renderer.setPointSize(14);
612 _renderer.start3f(0, 0, 0);
614 // Render each of the chunks.
615 chunk_list::const_iterator it = _chunks.begin();
616 chunk_list::const_iterator last = _chunks.end();
617 for ( ; it != last; it++) {
618 _renderer.puts((*it)->getValue());
622 glColor4f(1.0, 1.0, 1.0, 1.0); // FIXME
627 FGTextLayer::addChunk (FGTextLayer::Chunk * chunk)
629 _chunks.push_back(chunk);
633 FGTextLayer::setColor (float r, float g, float b)
642 FGTextLayer::setPointSize (const float size)
644 _renderer.setPointSize(size);
648 FGTextLayer::setFont(fntFont * font)
650 _renderer.setFont(font);
655 ////////////////////////////////////////////////////////////////////////
656 // Implementation of FGTextLayer::Chunk.
657 ////////////////////////////////////////////////////////////////////////
659 FGTextLayer::Chunk::Chunk (char * text, char * fmt = "%s")
660 : _type(FGTextLayer::TEXT), _fmt(fmt)
665 FGTextLayer::Chunk::Chunk (ChunkType type, const SGValue * value,
666 char * fmt = 0, float mult = 1.0)
667 : _type(type), _fmt(fmt), _mult(mult)
670 if (type == TEXT_VALUE)
675 _value._value = value;
679 FGTextLayer::Chunk::getValue () const
683 sprintf(_buf, _fmt, _value._text);
686 sprintf(_buf, _fmt, _value._value->getStringValue().c_str());
689 sprintf(_buf, _fmt, _value._value->getFloatValue() * _mult);
697 ////////////////////////////////////////////////////////////////////////
698 // Implementation of FGSwitchLayer.
699 ////////////////////////////////////////////////////////////////////////
701 FGSwitchLayer::FGSwitchLayer (int w, int h, const SGValue * value,
702 FGInstrumentLayer * layer1,
703 FGInstrumentLayer * layer2)
704 : FGInstrumentLayer(w, h), _value(value), _layer1(layer1), _layer2(layer2)
708 FGSwitchLayer::~FGSwitchLayer ()
715 FGSwitchLayer::draw ()
718 if (_value->getBoolValue()) {