1
0
Fork 0
flightgear/src/Cockpit/panel.cxx

953 lines
20 KiB
C++
Raw Normal View History

2000-02-15 03:30:01 +00:00
// panel.cxx - default, 2D single-engine prop instrument panel
//
2000-02-15 03:30:01 +00:00
// Written by David Megginson, started January 2000.
//
2000-02-15 03:30:01 +00:00
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of the
// License, or (at your option) any later version.
//
2000-02-15 03:30:01 +00:00
// This program is distributed in the hope that it will be useful, but
// WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
2000-02-15 03:30:01 +00:00
// $Id$
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
2000-02-15 03:30:01 +00:00
#include <string.h>
2000-02-15 03:30:01 +00:00
#include <plib/ssg.h>
#include <plib/fnt.h>
2000-02-16 23:01:03 +00:00
#include <simgear/debug/logstream.hxx>
#include <simgear/misc/sg_path.hxx>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
#include <Main/viewmgr.hxx>
#include <Objects/texload.h>
#include <Time/light.hxx>
#include "hud.hxx"
#include "panel.hxx"
#define WIN_X 0
#define WIN_Y 0
#define WIN_W 1024
#define WIN_H 768
#ifdef NONE
#pragma warn A sloppy coder has defined NONE as a macro!!!
#undef NONE
#endif
////////////////////////////////////////////////////////////////////////
// Local functions.
////////////////////////////////////////////////////////////////////////
/**
* Calculate the aspect adjustment for the panel.
*/
static float
get_aspect_adjust (int xsize, int ysize)
{
float ideal_aspect = float(WIN_W) / float(WIN_H);
float real_aspect = float(xsize) / float(ysize);
return (real_aspect / ideal_aspect);
}
////////////////////////////////////////////////////////////////////////
// Global functions.
////////////////////////////////////////////////////////////////////////
bool
fgPanelVisible ()
{
return ((current_panel != 0) &&
(current_panel->getVisibility()) &&
2000-11-03 23:04:23 +00:00
(globals->get_viewmgr()->get_current() == 0) &&
(globals->get_current_view()->get_view_offset() == 0.0));
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGTextureManager.
////////////////////////////////////////////////////////////////////////
map<string,ssgTexture *> FGTextureManager::_textureMap;
ssgTexture *
FGTextureManager::createTexture (const string &relativePath)
{
ssgTexture * texture = _textureMap[relativePath];
if (texture == 0) {
2001-06-01 17:55:49 +00:00
SG_LOG( SG_COCKPIT, SG_DEBUG,
"Texture " << relativePath << " does not yet exist" );
SGPath tpath(globals->get_fg_root());
tpath.append(relativePath);
texture = new ssgTexture((char *)tpath.c_str(), false, false);
_textureMap[relativePath] = texture;
if (_textureMap[relativePath] == 0)
2001-06-01 17:55:49 +00:00
SG_LOG( SG_COCKPIT, SG_ALERT, "Texture *still* doesn't exist" );
SG_LOG( SG_COCKPIT, SG_DEBUG, "Created texture " << relativePath
<< " handle=" << texture->getHandle() );
}
return texture;
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGCropped Texture.
////////////////////////////////////////////////////////////////////////
FGCroppedTexture::FGCroppedTexture ()
: _path(""), _texture(0),
_minX(0.0), _minY(0.0), _maxX(1.0), _maxY(1.0)
{
}
FGCroppedTexture::FGCroppedTexture (const string &path,
float minX, float minY,
float maxX, float maxY)
: _path(path), _texture(0),
_minX(minX), _minY(minY), _maxX(maxX), _maxY(maxY)
{
}
FGCroppedTexture::~FGCroppedTexture ()
{
}
ssgTexture *
FGCroppedTexture::getTexture ()
{
if (_texture == 0) {
_texture = FGTextureManager::createTexture(_path);
}
return _texture;
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGPanel.
////////////////////////////////////////////////////////////////////////
FGPanel * current_panel = NULL;
static fntRenderer text_renderer;
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Constructor.
*/
FGPanel::FGPanel ()
: _mouseDown(false),
_mouseInstrument(0),
_width(WIN_W), _height(int(WIN_H * 0.5768 + 1)),
_x_offset(0), _y_offset(0), _view_height(int(WIN_H * 0.4232)),
_bound(false),
_xsize_node(fgGetNode("/sim/startup/xsize", true)),
_ysize_node(fgGetNode("/sim/startup/ysize", true))
2000-02-15 03:30:01 +00:00
{
setVisibility(fgPanelVisible());
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Destructor.
*/
FGPanel::~FGPanel ()
{
if (_bound)
unbind();
for (instrument_list_type::iterator it = _instruments.begin();
it != _instruments.end();
it++) {
delete *it;
*it = 0;
2000-02-15 03:30:01 +00:00
}
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Add an instrument to the panel.
*/
void
FGPanel::addInstrument (FGPanelInstrument * instrument)
{
_instruments.push_back(instrument);
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Initialize the panel.
*/
void
FGPanel::init ()
{
// NO-OP
}
/**
* Bind panel properties.
*/
void
FGPanel::bind ()
{
fgTie("/sim/panel/visibility", &_visibility);
fgSetArchivable("/sim/panel/visibility");
fgTie("/sim/panel/x-offset", &_x_offset);
fgSetArchivable("/sim/panel/x-offset");
fgTie("/sim/panel/y-offset", &_y_offset);
fgSetArchivable("/sim/panel/y-offset");
_bound = true;
}
/**
* Unbind panel properties.
*/
void
FGPanel::unbind ()
{
fgUntie("/sim/panel/visibility");
fgUntie("/sim/panel/x-offset");
fgUntie("/sim/panel/y-offset");
_bound = false;
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Update the panel.
*/
2000-02-15 03:30:01 +00:00
void
FGPanel::update ()
2000-02-15 03:30:01 +00:00
{
// Do nothing if the panel isn't visible.
if (!fgPanelVisible())
return;
// If the mouse is down, do something
if (_mouseDown) {
_mouseDelay--;
if (_mouseDelay < 0) {
_mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
_mouseDelay = 2;
}
}
// Now, draw the panel
float aspect_adjust = get_aspect_adjust(_xsize_node->getIntValue(),
_ysize_node->getIntValue());
if (aspect_adjust <1.0)
update(WIN_X, int(WIN_W * aspect_adjust), WIN_Y, WIN_H);
else
update(WIN_X, WIN_W, WIN_Y, int(WIN_H / aspect_adjust));
}
void
FGPanel::update (GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh)
{
2000-02-15 03:30:01 +00:00
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
gluOrtho2D(winx, winx + winw, winy, winy + winh); /* right side up */
// gluOrtho2D(winx + winw, winx, winy + winh, winy); /* up side down */
2000-02-15 03:30:01 +00:00
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
glTranslated(_x_offset, _y_offset, 0);
2000-02-15 03:30:01 +00:00
// Draw the background
glEnable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
2000-03-17 06:16:15 +00:00
glEnable(GL_BLEND);
glEnable(GL_ALPHA_TEST);
glEnable(GL_COLOR_MATERIAL);
2000-05-27 06:40:55 +00:00
// glColor4f(1.0, 1.0, 1.0, 1.0);
2001-03-24 04:48:44 +00:00
if ( cur_light_params.sun_angle * SGD_RADIANS_TO_DEGREES < 95.0 ) {
2000-05-27 06:40:55 +00:00
glColor4fv( cur_light_params.scene_diffuse );
} else {
glColor4f(0.7, 0.2, 0.2, 1.0);
}
glBindTexture(GL_TEXTURE_2D, _bg->getHandle());
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
2000-02-15 03:30:01 +00:00
glBegin(GL_POLYGON);
glTexCoord2f(0.0, 0.0); glVertex3f(WIN_X, WIN_Y, 0);
glTexCoord2f(1.0, 0.0); glVertex3f(WIN_X + _width, WIN_Y, 0);
glTexCoord2f(1.0, 1.0); glVertex3f(WIN_X + _width, WIN_Y + _height, 0);
glTexCoord2f(0.0, 1.0); glVertex3f(WIN_X, WIN_Y + _height, 0);
2000-02-15 03:30:01 +00:00
glEnd();
// Draw the instruments.
instrument_list_type::const_iterator current = _instruments.begin();
instrument_list_type::const_iterator end = _instruments.end();
for ( ; current != end; current++) {
FGPanelInstrument * instr = *current;
glLoadIdentity();
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
glTranslated(_x_offset, _y_offset, 0);
glTranslated(instr->getXPos(), instr->getYPos(), 0);
instr->draw();
}
2000-02-15 03:30:01 +00:00
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
ssgForceBasicState();
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Set the panel's visibility.
*/
void
FGPanel::setVisibility (bool visibility)
{
_visibility = visibility;
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Return true if the panel is visible.
*/
bool
FGPanel::getVisibility () const
{
return _visibility;
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Set the panel's background texture.
*/
void
FGPanel::setBackground (ssgTexture * texture)
{
_bg = texture;
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
/**
* Set the panel's x-offset.
*/
void
FGPanel::setXOffset (int offset)
{
if (offset <= 0 && offset >= -_width + WIN_W)
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
_x_offset = offset;
}
/**
* Set the panel's y-offset.
*/
void
FGPanel::setYOffset (int offset)
{
if (offset <= 0 && offset >= -_height)
_y_offset = offset;
}
/**
* Perform a mouse action.
*/
bool
FGPanel::doMouseAction (int button, int updown, int x, int y)
{
// FIXME: this same code appears in update()
int xsize = _xsize_node->getIntValue();
int ysize = _ysize_node->getIntValue();
float aspect_adjust = get_aspect_adjust(xsize, ysize);
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
// Note a released button and return
// cerr << "Doing mouse action\n";
if (updown == 1) {
_mouseDown = false;
_mouseInstrument = 0;
return true;
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
// Scale for the real window size.
if (aspect_adjust < 1.0) {
x = int(((float)x / xsize) * WIN_W * aspect_adjust);
y = int(WIN_H - ((float(y) / ysize) * WIN_H));
} else {
x = int(((float)x / xsize) * WIN_W);
y = int((WIN_H - ((float(y) / ysize) * WIN_H)) / aspect_adjust);
}
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
// Adjust for offsets.
x -= _x_offset;
y -= _y_offset;
David Megginson writes: I have a scrollable panel working (it didn't take long in the end). A panel can now be much wider or higher than the available area, and the user can scroll around using [Shift]F5, [Shift]F6, [Shift]F7, and [Shift]F8. The user can also scroll the panel down to get a bigger external view. Mouse clicks seem still to be working correctly. To set the panel's (virtual) height and width, use the panel file's /w and /h properties in a panel XML file; to set the initial x- and y- offsets (untested), use the panel file's /x-offset and /y-offset properties; to set the initial height of the external view (untested and optional), use the panel file's /view-height property. Note that none of these show up in the regular FGFS property manager. Unfortunately, these patches will not affect your initialization problems with the property manager -- I'm having a hard time tracking them down because I cannot reproduce them. I have also made some patches to main.cxx and views.cxx to do two things: 1. Expand or shrink the external view as the panel moves up and down. 2. Set the window ratio correctly, so that we don't get an oval sun and flat clouds when the panel is visible (the problem before was integer division, so I added casts). Unfortunately, the window ratio is not set properly at start-up -- there are too many dependencies, and I haven't figured that part out yet. As soon as you hide and redisplay the panel or move it vertically (i.e. force fgReshape to be called), you'll see the correct ratio.
2000-10-06 21:16:01 +00:00
// Search for a matching instrument.
2000-09-13 21:51:07 +00:00
for (int i = 0; i < (int)_instruments.size(); i++) {
FGPanelInstrument *inst = _instruments[i];
int ix = inst->getXPos();
int iy = inst->getYPos();
int iw = inst->getWidth() / 2;
int ih = inst->getHeight() / 2;
if (x >= ix - iw && x < ix + iw && y >= iy - ih && y < iy + ih) {
_mouseDown = true;
_mouseDelay = 20;
_mouseInstrument = inst;
_mouseButton = button;
_mouseX = x - ix;
_mouseY = y - iy;
// Always do the action once.
_mouseInstrument->doMouseAction(_mouseButton, _mouseX, _mouseY);
return true;
}
}
return false;
}
////////////////////////////////////////////////////////////////////////.
// Implementation of FGPanelAction.
////////////////////////////////////////////////////////////////////////
FGPanelAction::FGPanelAction ()
{
}
FGPanelAction::FGPanelAction (int button, int x, int y, int w, int h)
: _button(button), _x(x), _y(y), _w(w), _h(h)
{
}
FGPanelAction::~FGPanelAction ()
{
}
void
FGPanelAction::addBinding (const FGBinding &binding)
{
_bindings.push_back(binding);
}
void
FGPanelAction::doAction ()
{
if (test()) {
int nBindings = _bindings.size();
for (int i = 0; i < nBindings; i++) {
_bindings[i].fire();
}
}
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGPanelTransformation.
////////////////////////////////////////////////////////////////////////
FGPanelTransformation::FGPanelTransformation ()
2001-05-15 23:08:25 +00:00
: table(0)
{
}
FGPanelTransformation::~FGPanelTransformation ()
{
}
////////////////////////////////////////////////////////////////////////
2000-02-15 03:30:01 +00:00
// Implementation of FGPanelInstrument.
////////////////////////////////////////////////////////////////////////
2000-02-15 03:30:01 +00:00
FGPanelInstrument::FGPanelInstrument ()
{
2000-02-15 03:30:01 +00:00
setPosition(0, 0);
setSize(0, 0);
}
2000-02-15 03:30:01 +00:00
FGPanelInstrument::FGPanelInstrument (int x, int y, int w, int h)
{
setPosition(x, y);
setSize(w, h);
}
2000-02-15 03:30:01 +00:00
FGPanelInstrument::~FGPanelInstrument ()
{
for (action_list_type::iterator it = _actions.begin();
it != _actions.end();
it++) {
delete *it;
*it = 0;
}
2000-02-15 03:30:01 +00:00
}
void
FGPanelInstrument::setPosition (int x, int y)
{
2000-02-15 03:30:01 +00:00
_x = x;
_y = y;
}
2000-02-15 03:30:01 +00:00
void
FGPanelInstrument::setSize (int w, int h)
{
_w = w;
_h = h;
}
2000-02-15 03:30:01 +00:00
int
FGPanelInstrument::getXPos () const
{
return _x;
}
int
FGPanelInstrument::getYPos () const
{
return _y;
1999-01-07 19:25:53 +00:00
}
int
FGPanelInstrument::getWidth () const
{
return _w;
}
int
FGPanelInstrument::getHeight () const
{
return _h;
}
void
FGPanelInstrument::addAction (FGPanelAction * action)
{
_actions.push_back(action);
}
// Coordinates relative to centre.
bool
FGPanelInstrument::doMouseAction (int button, int x, int y)
{
if (test()) {
action_list_type::iterator it = _actions.begin();
action_list_type::iterator last = _actions.end();
for ( ; it != last; it++) {
if ((*it)->inArea(button, x, y)) {
(*it)->doAction();
return true;
}
}
}
return false;
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGLayeredInstrument.
////////////////////////////////////////////////////////////////////////
1999-01-07 19:25:53 +00:00
FGLayeredInstrument::FGLayeredInstrument (int x, int y, int w, int h)
2000-02-15 03:30:01 +00:00
: FGPanelInstrument(x, y, w, h)
{
}
FGLayeredInstrument::~FGLayeredInstrument ()
2000-02-15 03:30:01 +00:00
{
for (layer_list::iterator it = _layers.begin(); it != _layers.end(); it++) {
delete *it;
*it = 0;
}
2000-02-15 03:30:01 +00:00
}
2000-02-15 03:30:01 +00:00
void
FGLayeredInstrument::draw ()
{
if (test()) {
for (int i = 0; i < (int)_layers.size(); i++) {
glPushMatrix();
glTranslatef(0.0, 0.0, (i / 100.0) + 0.1);
_layers[i]->draw();
glPopMatrix();
}
}
}
int
FGLayeredInstrument::addLayer (FGInstrumentLayer *layer)
{
int n = _layers.size();
if (layer->getWidth() == -1) {
layer->setWidth(getWidth());
}
if (layer->getHeight() == -1) {
layer->setHeight(getHeight());
}
_layers.push_back(layer);
return n;
}
int
FGLayeredInstrument::addLayer (FGCroppedTexture &texture,
2000-09-13 21:51:07 +00:00
int w, int h)
2000-02-15 03:30:01 +00:00
{
return addLayer(new FGTexturedLayer(texture, w, h));
2000-02-15 03:30:01 +00:00
}
1999-01-07 19:25:53 +00:00
2000-02-15 03:30:01 +00:00
void
FGLayeredInstrument::addTransformation (FGPanelTransformation * transformation)
2000-02-15 03:30:01 +00:00
{
int layer = _layers.size() - 1;
_layers[layer]->addTransformation(transformation);
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGInstrumentLayer.
////////////////////////////////////////////////////////////////////////
FGInstrumentLayer::FGInstrumentLayer (int w, int h)
: _w(w),
_h(h)
2000-02-15 03:30:01 +00:00
{
1999-05-06 22:16:12 +00:00
}
1999-02-12 01:46:29 +00:00
FGInstrumentLayer::~FGInstrumentLayer ()
2000-02-15 03:30:01 +00:00
{
for (transformation_list::iterator it = _transformations.begin();
it != _transformations.end();
it++) {
delete *it;
*it = 0;
}
}
2000-02-15 03:30:01 +00:00
void
FGInstrumentLayer::transform () const
{
transformation_list::const_iterator it = _transformations.begin();
transformation_list::const_iterator last = _transformations.end();
while (it != last) {
FGPanelTransformation *t = *it;
if (t->test()) {
float val = (t->node == 0 ? 0.0 : t->node->getFloatValue());
if (val < t->min) {
val = t->min;
} else if (val > t->max) {
val = t->max;
}
if(t->table==0) {
2001-05-15 23:08:25 +00:00
val = val * t->factor + t->offset;
} else {
2001-05-15 23:08:25 +00:00
val = t->table->interpolate(val) * t->factor + t->offset;
}
switch (t->type) {
case FGPanelTransformation::XSHIFT:
glTranslatef(val, 0.0, 0.0);
break;
case FGPanelTransformation::YSHIFT:
glTranslatef(0.0, val, 0.0);
break;
case FGPanelTransformation::ROTATION:
glRotatef(-val, 0.0, 0.0, 1.0);
break;
}
}
it++;
2000-02-15 03:30:01 +00:00
}
1998-11-09 23:38:50 +00:00
}
2000-02-15 03:30:01 +00:00
void
FGInstrumentLayer::addTransformation (FGPanelTransformation * transformation)
{
_transformations.push_back(transformation);
1999-05-06 22:16:12 +00:00
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGGroupLayer.
////////////////////////////////////////////////////////////////////////
FGGroupLayer::FGGroupLayer ()
{
}
FGGroupLayer::~FGGroupLayer ()
{
for (int i = 0; i < _layers.size(); i++)
delete _layers[i];
}
void
FGGroupLayer::draw ()
{
if (test()) {
int nLayers = _layers.size();
for (int i = 0; i < nLayers; i++)
_layers[i]->draw();
}
}
void
FGGroupLayer::addLayer (FGInstrumentLayer * layer)
{
_layers.push_back(layer);
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGTexturedLayer.
////////////////////////////////////////////////////////////////////////
FGTexturedLayer::FGTexturedLayer (const FGCroppedTexture &texture, int w, int h)
: FGInstrumentLayer(w, h)
{
setTexture(texture);
1999-05-06 22:16:12 +00:00
}
FGTexturedLayer::~FGTexturedLayer ()
{
1999-05-06 22:16:12 +00:00
}
2000-02-15 03:30:01 +00:00
void
FGTexturedLayer::draw ()
{
if (test()) {
int w2 = _w / 2;
int h2 = _h / 2;
transform();
glBindTexture(GL_TEXTURE_2D, _texture.getTexture()->getHandle());
glBegin(GL_POLYGON);
// From Curt: turn on the panel
// lights after sundown.
if ( cur_light_params.sun_angle * SGD_RADIANS_TO_DEGREES < 95.0 ) {
2000-05-27 06:40:55 +00:00
glColor4fv( cur_light_params.scene_diffuse );
} else {
2000-05-27 06:40:55 +00:00
glColor4f(0.7, 0.2, 0.2, 1.0);
}
glTexCoord2f(_texture.getMinX(), _texture.getMinY()); glVertex2f(-w2, -h2);
glTexCoord2f(_texture.getMaxX(), _texture.getMinY()); glVertex2f(w2, -h2);
glTexCoord2f(_texture.getMaxX(), _texture.getMaxY()); glVertex2f(w2, h2);
glTexCoord2f(_texture.getMinX(), _texture.getMaxY()); glVertex2f(-w2, h2);
glEnd();
}
2000-02-15 03:30:01 +00:00
}
2000-02-15 03:30:01 +00:00
////////////////////////////////////////////////////////////////////////
// Implementation of FGTextLayer.
2000-02-15 03:30:01 +00:00
////////////////////////////////////////////////////////////////////////
FGTextLayer::FGTextLayer (int w, int h)
2000-09-13 21:51:07 +00:00
: FGInstrumentLayer(w, h), _pointSize(14.0)
2000-02-15 03:30:01 +00:00
{
_then.stamp();
_color[0] = _color[1] = _color[2] = 0.0;
2000-03-17 06:16:15 +00:00
_color[3] = 1.0;
2000-02-15 03:30:01 +00:00
}
FGTextLayer::~FGTextLayer ()
2000-02-15 03:30:01 +00:00
{
chunk_list::iterator it = _chunks.begin();
chunk_list::iterator last = _chunks.end();
for ( ; it != last; it++) {
delete *it;
}
2000-02-15 03:30:01 +00:00
}
void
FGTextLayer::draw ()
2000-02-15 03:30:01 +00:00
{
if (test()) {
glPushMatrix();
glColor4fv(_color);
transform();
text_renderer.setFont(guiFntHandle);
text_renderer.setPointSize(_pointSize);
text_renderer.begin();
text_renderer.start3f(0, 0, 0);
_now.stamp();
if (_now - _then > 100000) {
recalc_value();
_then = _now;
}
text_renderer.puts((char *)(_value.c_str()));
text_renderer.end();
glColor4f(1.0, 1.0, 1.0, 1.0); // FIXME
glPopMatrix();
}
2000-02-15 03:30:01 +00:00
}
2000-02-15 03:30:01 +00:00
void
FGTextLayer::addChunk (FGTextLayer::Chunk * chunk)
{
_chunks.push_back(chunk);
}
void
FGTextLayer::setColor (float r, float g, float b)
{
_color[0] = r;
_color[1] = g;
_color[2] = b;
2000-03-17 06:16:15 +00:00
_color[3] = 1.0;
}
void
2000-09-13 21:51:07 +00:00
FGTextLayer::setPointSize (float size)
2000-02-15 03:30:01 +00:00
{
2000-09-13 21:51:07 +00:00
_pointSize = size;
2000-02-15 03:30:01 +00:00
}
2000-02-15 03:30:01 +00:00
void
FGTextLayer::setFont(fntFont * font)
{
text_renderer.setFont(font);
}
void
FGTextLayer::recalc_value () const
{
_value = "";
chunk_list::const_iterator it = _chunks.begin();
chunk_list::const_iterator last = _chunks.end();
for ( ; it != last; it++) {
_value += (*it)->getValue();
}
1999-05-06 22:16:12 +00:00
}
2000-02-15 03:30:01 +00:00
////////////////////////////////////////////////////////////////////////
// Implementation of FGTextLayer::Chunk.
////////////////////////////////////////////////////////////////////////
2000-09-13 21:51:07 +00:00
FGTextLayer::Chunk::Chunk (const string &text, const string &fmt)
: _type(FGTextLayer::TEXT), _fmt(fmt)
{
2000-09-13 21:51:07 +00:00
_text = text;
if (_fmt == "")
_fmt = "%s";
}
FGTextLayer::Chunk::Chunk (ChunkType type, const SGPropertyNode * node,
2000-09-13 21:51:07 +00:00
const string &fmt, float mult)
: _type(type), _fmt(fmt), _mult(mult)
{
2000-09-13 21:51:07 +00:00
if (_fmt == "") {
if (type == TEXT_VALUE)
_fmt = "%s";
else
_fmt = "%.2f";
}
_node = node;
}
2000-09-13 21:51:07 +00:00
const char *
FGTextLayer::Chunk::getValue () const
{
if (test()) {
switch (_type) {
case TEXT:
sprintf(_buf, _fmt.c_str(), _text.c_str());
return _buf;
case TEXT_VALUE:
sprintf(_buf, _fmt.c_str(), _node->getStringValue().c_str());
break;
case DOUBLE_VALUE:
sprintf(_buf, _fmt.c_str(), _node->getFloatValue() * _mult);
break;
}
return _buf;
} else {
return "";
}
}
////////////////////////////////////////////////////////////////////////
// Implementation of FGSwitchLayer.
////////////////////////////////////////////////////////////////////////
FGSwitchLayer::FGSwitchLayer (int w, int h, const SGPropertyNode * node,
FGInstrumentLayer * layer1,
FGInstrumentLayer * layer2)
: FGInstrumentLayer(w, h), _node(node), _layer1(layer1), _layer2(layer2)
{
}
FGSwitchLayer::~FGSwitchLayer ()
{
delete _layer1;
delete _layer2;
}
void
FGSwitchLayer::draw ()
{
if (test()) {
transform();
if (_node->getBoolValue()) {
_layer1->draw();
} else {
_layer2->draw();
}
}
}
2000-02-15 03:30:01 +00:00
// end of panel.cxx