I'm attaching diffs to add a new FGInput module to FlightGear
(src/Input). So far, FGInput replaces most of src/Main/keyboard.cxx
(I've left a tiny stub); in the very near future, it will also take
over control of the joystick, mouse (Norm permitting), and panel
instrument interactions, so that there is a single mechanism for
configuring all input devices.
The new format should be (close to) self-explanatory by looking at the
new base-package file keyboard.xml, which is now included by
preferences.xml (I'll do the same thing for the joystick when I have a
chance). I have not managed to move all keybindings into this file
yet, but I've made a good start. I'm including Tony in the recipient
list so that he can see how bindings can use an external XML file.
This patch also adds support for multiple bindings for a single key,
special keys (i.e. keypad and function keys), and key modifiers
(shift/alt/ctrl); special keys use the PUI convention of adding 256 to
the Glut key code.
Unfortunately, everything comes with a price; in this case, I have not
yet found a general mechanism for the old (hard-coded) modal bindings,
which behaved differently depending on the autopilot state (i.e. left
rudder or move AP heading left); with my patches, this functionality
disappears, but you can still adjust the autopilot using the panel or
the GUI input dialogs.
2001-05-23 23:01:15 +00:00
|
|
|
|
// fg_props.cxx -- support for FlightGear properties.
|
2001-01-05 17:37:59 +00:00
|
|
|
|
//
|
I'm attaching diffs to add a new FGInput module to FlightGear
(src/Input). So far, FGInput replaces most of src/Main/keyboard.cxx
(I've left a tiny stub); in the very near future, it will also take
over control of the joystick, mouse (Norm permitting), and panel
instrument interactions, so that there is a single mechanism for
configuring all input devices.
The new format should be (close to) self-explanatory by looking at the
new base-package file keyboard.xml, which is now included by
preferences.xml (I'll do the same thing for the joystick when I have a
chance). I have not managed to move all keybindings into this file
yet, but I've made a good start. I'm including Tony in the recipient
list so that he can see how bindings can use an external XML file.
This patch also adds support for multiple bindings for a single key,
special keys (i.e. keypad and function keys), and key modifiers
(shift/alt/ctrl); special keys use the PUI convention of adding 256 to
the Glut key code.
Unfortunately, everything comes with a price; in this case, I have not
yet found a general mechanism for the old (hard-coded) modal bindings,
which behaved differently depending on the autopilot state (i.e. left
rudder or move AP heading left); with my patches, this functionality
disappears, but you can still adjust the autopilot using the panel or
the GUI input dialogs.
2001-05-23 23:01:15 +00:00
|
|
|
|
// Written by David Megginson, started 2000.
|
2001-01-05 17:37:59 +00:00
|
|
|
|
//
|
I'm attaching diffs to add a new FGInput module to FlightGear
(src/Input). So far, FGInput replaces most of src/Main/keyboard.cxx
(I've left a tiny stub); in the very near future, it will also take
over control of the joystick, mouse (Norm permitting), and panel
instrument interactions, so that there is a single mechanism for
configuring all input devices.
The new format should be (close to) self-explanatory by looking at the
new base-package file keyboard.xml, which is now included by
preferences.xml (I'll do the same thing for the joystick when I have a
chance). I have not managed to move all keybindings into this file
yet, but I've made a good start. I'm including Tony in the recipient
list so that he can see how bindings can use an external XML file.
This patch also adds support for multiple bindings for a single key,
special keys (i.e. keypad and function keys), and key modifiers
(shift/alt/ctrl); special keys use the PUI convention of adding 256 to
the Glut key code.
Unfortunately, everything comes with a price; in this case, I have not
yet found a general mechanism for the old (hard-coded) modal bindings,
which behaved differently depending on the autopilot state (i.e. left
rudder or move AP heading left); with my patches, this functionality
disappears, but you can still adjust the autopilot using the panel or
the GUI input dialogs.
2001-05-23 23:01:15 +00:00
|
|
|
|
// Copyright (C) 2000, 2001 David Megginson - david@megginson.com
|
2001-01-05 17:37:59 +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.
|
|
|
|
|
//
|
|
|
|
|
// 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.
|
|
|
|
|
//
|
|
|
|
|
// $Id$
|
|
|
|
|
|
2001-04-02 02:59:31 +00:00
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
|
# include <simgear/compiler.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2001-07-19 04:51:05 +00:00
|
|
|
|
#include <simgear/misc/exception.hxx>
|
|
|
|
|
|
2001-04-02 02:59:31 +00:00
|
|
|
|
#include STL_IOSTREAM
|
2001-01-05 17:37:59 +00:00
|
|
|
|
|
2001-12-11 22:40:14 +00:00
|
|
|
|
#include <ATC/ATCdisplay.hxx>
|
2001-06-05 22:13:26 +00:00
|
|
|
|
#include <Autopilot/newauto.hxx>
|
|
|
|
|
#include <Aircraft/aircraft.hxx>
|
|
|
|
|
#include <Time/tmp.hxx>
|
|
|
|
|
#include <FDM/UIUCModel/uiuc_aircraftdir.h>
|
|
|
|
|
#ifndef FG_OLD_WEATHER
|
|
|
|
|
# include <WeatherCM/FGLocalWeatherDatabase.h>
|
|
|
|
|
#else
|
|
|
|
|
# include <Weather/weather.hxx>
|
|
|
|
|
#endif
|
2001-06-26 21:59:59 +00:00
|
|
|
|
#include <Objects/matlib.hxx>
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
2001-07-19 04:51:05 +00:00
|
|
|
|
#include <GUI/gui.h>
|
|
|
|
|
|
2002-01-06 16:51:31 +00:00
|
|
|
|
#include "globals.hxx"
|
2001-06-05 22:13:26 +00:00
|
|
|
|
#include "fgfs.hxx"
|
2001-01-05 17:37:59 +00:00
|
|
|
|
#include "fg_props.hxx"
|
2001-07-24 23:51:47 +00:00
|
|
|
|
#include "viewmgr.hxx"
|
2001-01-05 17:37:59 +00:00
|
|
|
|
|
2001-04-02 02:59:31 +00:00
|
|
|
|
#if !defined(SG_HAVE_NATIVE_SGI_COMPILERS)
|
|
|
|
|
SG_USING_STD(istream);
|
|
|
|
|
SG_USING_STD(ostream);
|
|
|
|
|
#endif
|
2001-01-05 17:37:59 +00:00
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
static double getWindNorth ();
|
|
|
|
|
static double getWindEast ();
|
|
|
|
|
static double getWindDown ();
|
|
|
|
|
|
|
|
|
|
// Allow the view to be set from two axes (i.e. a joystick hat)
|
|
|
|
|
// This needs to be in FGViewer itself, somehow.
|
|
|
|
|
static double axisLong = 0.0;
|
|
|
|
|
static double axisLat = 0.0;
|
|
|
|
|
|
2001-10-05 20:27:43 +00:00
|
|
|
|
static bool winding_ccw = true; // FIXME: temporary
|
2001-07-16 04:35:35 +00:00
|
|
|
|
|
|
|
|
|
static bool fdm_data_logging = false; // FIXME: temporary
|
|
|
|
|
|
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
/**
|
|
|
|
|
* Utility function.
|
|
|
|
|
*/
|
|
|
|
|
static inline void
|
|
|
|
|
_set_view_from_axes ()
|
|
|
|
|
{
|
|
|
|
|
// Take no action when hat is centered
|
2001-06-20 20:52:10 +00:00
|
|
|
|
if ( ( axisLong < 0.01 ) &&
|
|
|
|
|
( axisLong > -0.01 ) &&
|
|
|
|
|
( axisLat < 0.01 ) &&
|
|
|
|
|
( axisLat > -0.01 )
|
|
|
|
|
)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
return;
|
|
|
|
|
|
2001-06-20 20:52:10 +00:00
|
|
|
|
double viewDir = 999;
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
2001-06-20 20:52:10 +00:00
|
|
|
|
/* Do all the quick and easy cases */
|
2001-06-05 22:13:26 +00:00
|
|
|
|
if (axisLong < 0) { // Longitudinal axis forward
|
2001-06-20 20:52:10 +00:00
|
|
|
|
if (axisLat == axisLong)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
viewDir = 45;
|
2001-06-20 20:52:10 +00:00
|
|
|
|
else if (axisLat == - axisLong)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
viewDir = 315;
|
2001-06-20 20:52:10 +00:00
|
|
|
|
else if (axisLat == 0)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
viewDir = 0;
|
|
|
|
|
} else if (axisLong > 0) { // Longitudinal axis backward
|
2001-06-20 20:52:10 +00:00
|
|
|
|
if (axisLat == - axisLong)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
viewDir = 135;
|
2001-06-20 20:52:10 +00:00
|
|
|
|
else if (axisLat == axisLong)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
viewDir = 225;
|
2001-06-20 20:52:10 +00:00
|
|
|
|
else if (axisLat == 0)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
viewDir = 180;
|
2001-06-26 22:05:11 +00:00
|
|
|
|
} else if (axisLong == 0) { // Longitudinal axis neutral
|
2001-06-05 22:13:26 +00:00
|
|
|
|
if (axisLat < 0)
|
|
|
|
|
viewDir = 90;
|
2001-06-20 20:52:10 +00:00
|
|
|
|
else if (axisLat > 0)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
viewDir = 270;
|
2001-06-20 20:52:10 +00:00
|
|
|
|
else return; /* And assertion failure maybe? */
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-20 20:52:10 +00:00
|
|
|
|
/* Do all the difficult cases */
|
|
|
|
|
if ( viewDir > 900 )
|
|
|
|
|
viewDir = SGD_RADIANS_TO_DEGREES * atan2 ( -axisLat, -axisLong );
|
|
|
|
|
if ( viewDir < -1 ) viewDir += 360;
|
|
|
|
|
|
|
|
|
|
// SG_LOG(SG_INPUT, SG_ALERT, "Joystick Lat=" << axisLat << " and Long="
|
|
|
|
|
// << axisLong << " gave angle=" << viewDir );
|
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
globals->get_current_view()->set_goal_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
|
|
|
|
|
// globals->get_current_view()->set_view_offset(viewDir*SGD_DEGREES_TO_RADIANS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Default property bindings (not yet handled by any module).
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2001-11-20 22:03:17 +00:00
|
|
|
|
struct LogClassMapping {
|
|
|
|
|
sgDebugClass c;
|
|
|
|
|
string name;
|
2001-12-09 05:20:13 +00:00
|
|
|
|
LogClassMapping(sgDebugClass cc, string nname) { c = cc; name = nname; }
|
2001-11-20 22:03:17 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
LogClassMapping log_class_mappings [] = {
|
2001-12-09 05:20:13 +00:00
|
|
|
|
LogClassMapping(SG_NONE, "none"),
|
|
|
|
|
LogClassMapping(SG_TERRAIN, "terrain"),
|
|
|
|
|
LogClassMapping(SG_ASTRO, "astro"),
|
|
|
|
|
LogClassMapping(SG_FLIGHT, "flight"),
|
|
|
|
|
LogClassMapping(SG_INPUT, "input"),
|
|
|
|
|
LogClassMapping(SG_GL, "gl"),
|
|
|
|
|
LogClassMapping(SG_VIEW, "view"),
|
|
|
|
|
LogClassMapping(SG_COCKPIT, "cockpit"),
|
|
|
|
|
LogClassMapping(SG_GENERAL, "general"),
|
|
|
|
|
LogClassMapping(SG_MATH, "math"),
|
|
|
|
|
LogClassMapping(SG_EVENT, "event"),
|
|
|
|
|
LogClassMapping(SG_AIRCRAFT, "aircraft"),
|
|
|
|
|
LogClassMapping(SG_AUTOPILOT, "autopilot"),
|
|
|
|
|
LogClassMapping(SG_IO, "io"),
|
|
|
|
|
LogClassMapping(SG_CLIPPER, "clipper"),
|
|
|
|
|
LogClassMapping(SG_NETWORK, "network"),
|
|
|
|
|
LogClassMapping(SG_UNDEFD, "")
|
2001-11-20 22:03:17 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the logging classes.
|
|
|
|
|
*/
|
|
|
|
|
static string
|
|
|
|
|
getLoggingClasses ()
|
|
|
|
|
{
|
|
|
|
|
sgDebugClass classes = logbuf::get_log_classes();
|
|
|
|
|
string result = "";
|
|
|
|
|
for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
|
|
|
|
|
if ((classes&log_class_mappings[i].c) > 0) {
|
2001-12-09 05:43:40 +00:00
|
|
|
|
if (result != (string)"")
|
2001-11-20 22:03:17 +00:00
|
|
|
|
result += '|';
|
|
|
|
|
result += log_class_mappings[i].name;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void addLoggingClass (const string &name)
|
|
|
|
|
{
|
|
|
|
|
sgDebugClass classes = logbuf::get_log_classes();
|
|
|
|
|
for (int i = 0; log_class_mappings[i].c != SG_UNDEFD; i++) {
|
|
|
|
|
if (name == log_class_mappings[i].name) {
|
|
|
|
|
logbuf::set_log_classes(sgDebugClass(classes|log_class_mappings[i].c));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "Unknown logging class: " << name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the logging classes.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setLoggingClasses (string classes)
|
|
|
|
|
{
|
|
|
|
|
logbuf::set_log_classes(SG_NONE);
|
|
|
|
|
|
|
|
|
|
if (classes == "none") {
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Disabled all logging classes");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (classes == "" || classes == "all") { // default
|
|
|
|
|
logbuf::set_log_classes(SG_ALL);
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Enabled all logging classes: "
|
|
|
|
|
<< getLoggingClasses());
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string rest = classes;
|
|
|
|
|
string name = "";
|
|
|
|
|
int sep = rest.find('|');
|
|
|
|
|
while (sep > 0) {
|
|
|
|
|
name = rest.substr(0, sep);
|
|
|
|
|
rest = rest.substr(sep+1);
|
|
|
|
|
addLoggingClass(name);
|
|
|
|
|
sep = rest.find('|');
|
|
|
|
|
}
|
|
|
|
|
addLoggingClass(rest);
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Set logging classes to "
|
|
|
|
|
<< getLoggingClasses());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the logging priority.
|
|
|
|
|
*/
|
|
|
|
|
static string
|
|
|
|
|
getLoggingPriority ()
|
|
|
|
|
{
|
|
|
|
|
switch (logbuf::get_log_priority()) {
|
|
|
|
|
case SG_BULK:
|
|
|
|
|
return "bulk";
|
|
|
|
|
case SG_DEBUG:
|
|
|
|
|
return "debug";
|
|
|
|
|
case SG_INFO:
|
|
|
|
|
return "info";
|
|
|
|
|
case SG_WARN:
|
|
|
|
|
return "warn";
|
|
|
|
|
case SG_ALERT:
|
|
|
|
|
return "alert";
|
|
|
|
|
default:
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "Internal: Unknown logging priority number: "
|
|
|
|
|
<< logbuf::get_log_priority());
|
|
|
|
|
return "unknown";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the logging priority.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setLoggingPriority (string priority)
|
|
|
|
|
{
|
|
|
|
|
if (priority == "bulk") {
|
|
|
|
|
logbuf::set_log_priority(SG_BULK);
|
|
|
|
|
} else if (priority == "debug") {
|
|
|
|
|
logbuf::set_log_priority(SG_DEBUG);
|
|
|
|
|
} else if (priority == "" || priority == "info") { // default
|
|
|
|
|
logbuf::set_log_priority(SG_INFO);
|
|
|
|
|
} else if (priority == "warn") {
|
|
|
|
|
logbuf::set_log_priority(SG_WARN);
|
|
|
|
|
} else if (priority == "alert") {
|
|
|
|
|
logbuf::set_log_priority(SG_ALERT);
|
|
|
|
|
} else {
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority);
|
|
|
|
|
}
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Logging priority is " << getLoggingPriority());
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-26 21:59:59 +00:00
|
|
|
|
|
2002-01-20 03:52:36 +00:00
|
|
|
|
#if 0
|
2001-06-26 21:59:59 +00:00
|
|
|
|
/**
|
|
|
|
|
* Get the pause state of the sim.
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getFreeze ()
|
|
|
|
|
{
|
|
|
|
|
return globals->get_freeze();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the pause state of the sim.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setFreeze (bool freeze)
|
|
|
|
|
{
|
2001-12-11 22:40:14 +00:00
|
|
|
|
globals->set_freeze(freeze);
|
|
|
|
|
if ( freeze ) {
|
|
|
|
|
// BusyCursor( 0 );
|
|
|
|
|
current_atcdisplay->CancelRepeatingMessage();
|
2002-01-15 23:39:21 +00:00
|
|
|
|
current_atcdisplay->RegisterRepeatingMessage("**** SIM IS FROZEN **** SIM IS FROZEN ****");
|
2001-12-11 22:40:14 +00:00
|
|
|
|
} else {
|
|
|
|
|
// BusyCursor( 1 );
|
|
|
|
|
current_atcdisplay->CancelRepeatingMessage();
|
|
|
|
|
}
|
2001-06-26 21:59:59 +00:00
|
|
|
|
}
|
2002-01-20 03:52:36 +00:00
|
|
|
|
#endif
|
2001-06-26 21:59:59 +00:00
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the current aircraft directory (UIUC) as a string.
|
|
|
|
|
*/
|
|
|
|
|
static string
|
|
|
|
|
getAircraftDir ()
|
|
|
|
|
{
|
|
|
|
|
return aircraft_dir;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the current aircraft directory (UIUC).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAircraftDir (string dir)
|
|
|
|
|
{
|
|
|
|
|
if (getAircraftDir() != dir) {
|
|
|
|
|
aircraft_dir = dir;
|
|
|
|
|
// needReinit(); FIXME!!
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current view offset in degrees.
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getViewOffset ()
|
|
|
|
|
{
|
|
|
|
|
return (globals->get_current_view()
|
|
|
|
|
->get_view_offset() * SGD_RADIANS_TO_DEGREES);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setViewOffset (double offset)
|
|
|
|
|
{
|
|
|
|
|
globals->get_current_view()->set_view_offset(offset * SGD_DEGREES_TO_RADIANS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double
|
|
|
|
|
getGoalViewOffset ()
|
|
|
|
|
{
|
|
|
|
|
return (globals->get_current_view()
|
|
|
|
|
->get_goal_view_offset() * SGD_RADIANS_TO_DEGREES);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setGoalViewOffset (double offset)
|
|
|
|
|
{
|
2001-07-08 23:37:14 +00:00
|
|
|
|
while ( offset < 0 ) {
|
|
|
|
|
offset += 360.0;
|
|
|
|
|
}
|
|
|
|
|
while ( offset > 360.0 ) {
|
|
|
|
|
offset -= 360.0;
|
|
|
|
|
}
|
|
|
|
|
// Snap to center if we are close
|
2001-07-11 06:00:55 +00:00
|
|
|
|
if ( fabs(offset) < 1.0 || fabs(offset) > 359.0 ) {
|
2001-07-08 23:37:14 +00:00
|
|
|
|
offset = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
globals->get_current_view()
|
|
|
|
|
->set_goal_view_offset(offset * SGD_DEGREES_TO_RADIANS);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-19 23:01:01 +00:00
|
|
|
|
/**
|
|
|
|
|
* Get the current view tilt in degrees.
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getViewTilt ()
|
|
|
|
|
{
|
|
|
|
|
return (globals->get_current_view()
|
|
|
|
|
->get_view_tilt() * SGD_RADIANS_TO_DEGREES);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setViewTilt (double tilt)
|
|
|
|
|
{
|
|
|
|
|
globals->get_current_view()->set_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double
|
|
|
|
|
getGoalViewTilt ()
|
|
|
|
|
{
|
|
|
|
|
return (globals->get_current_view()
|
|
|
|
|
->get_goal_view_tilt() * SGD_RADIANS_TO_DEGREES);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setGoalViewTilt (double tilt)
|
|
|
|
|
{
|
|
|
|
|
while ( tilt < 0 ) {
|
|
|
|
|
tilt += 360.0;
|
|
|
|
|
}
|
|
|
|
|
while ( tilt > 360.0 ) {
|
|
|
|
|
tilt -= 360.0;
|
|
|
|
|
}
|
|
|
|
|
// Snap to center if we are close
|
|
|
|
|
if ( fabs(tilt) < 1.0 || fabs(tilt) > 359.0 ) {
|
|
|
|
|
tilt = 0.0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
globals->get_current_view()
|
|
|
|
|
->set_goal_view_tilt(tilt * SGD_DEGREES_TO_RADIANS);
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
2001-07-24 23:51:47 +00:00
|
|
|
|
/**
|
|
|
|
|
* Pilot position offset from CG.
|
|
|
|
|
*/
|
|
|
|
|
static float
|
|
|
|
|
getPilotPositionXOffset ()
|
|
|
|
|
{
|
|
|
|
|
FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
|
|
|
|
|
float * offset = pilot_view->get_pilot_offset();
|
|
|
|
|
return offset[0];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setPilotPositionXOffset (float x)
|
|
|
|
|
{
|
|
|
|
|
FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
|
|
|
|
|
float * offset = pilot_view->get_pilot_offset();
|
|
|
|
|
pilot_view->set_pilot_offset(x, offset[1], offset[2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static float
|
|
|
|
|
getPilotPositionYOffset ()
|
|
|
|
|
{
|
|
|
|
|
FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
|
|
|
|
|
float * offset = pilot_view->get_pilot_offset();
|
|
|
|
|
return offset[1];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setPilotPositionYOffset (float y)
|
|
|
|
|
{
|
|
|
|
|
FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
|
|
|
|
|
float * offset = pilot_view->get_pilot_offset();
|
|
|
|
|
pilot_view->set_pilot_offset(offset[0], y, offset[2]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static float
|
|
|
|
|
getPilotPositionZOffset ()
|
|
|
|
|
{
|
|
|
|
|
FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
|
|
|
|
|
float * offset = pilot_view->get_pilot_offset();
|
|
|
|
|
return offset[2];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setPilotPositionZOffset (float z)
|
|
|
|
|
{
|
|
|
|
|
FGViewer * pilot_view = globals->get_viewmgr()->get_view(0);
|
|
|
|
|
float * offset = pilot_view->get_pilot_offset();
|
|
|
|
|
pilot_view->set_pilot_offset(offset[0], offset[1], z);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the current Zulu time.
|
|
|
|
|
*/
|
|
|
|
|
static string
|
|
|
|
|
getDateString ()
|
|
|
|
|
{
|
|
|
|
|
string out;
|
|
|
|
|
char buf[64];
|
|
|
|
|
struct tm * t = globals->get_time_params()->getGmt();
|
|
|
|
|
sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d",
|
|
|
|
|
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
|
|
|
|
|
t->tm_hour, t->tm_min, t->tm_sec);
|
|
|
|
|
out = buf;
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the current Zulu time.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setDateString (string date_string)
|
|
|
|
|
{
|
|
|
|
|
SGTime * st = globals->get_time_params();
|
|
|
|
|
struct tm * current_time = st->getGmt();
|
|
|
|
|
struct tm new_time;
|
|
|
|
|
|
|
|
|
|
// Scan for basic ISO format
|
|
|
|
|
// YYYY-MM-DDTHH:MM:SS
|
|
|
|
|
int ret = sscanf(date_string.c_str(), "%d-%d-%dT%d:%d:%d",
|
|
|
|
|
&(new_time.tm_year), &(new_time.tm_mon),
|
|
|
|
|
&(new_time.tm_mday), &(new_time.tm_hour),
|
|
|
|
|
&(new_time.tm_min), &(new_time.tm_sec));
|
|
|
|
|
|
|
|
|
|
// Be pretty picky about this, so
|
|
|
|
|
// that strange things don't happen
|
|
|
|
|
// if the save file has been edited
|
|
|
|
|
// by hand.
|
|
|
|
|
if (ret != 6) {
|
|
|
|
|
SG_LOG(SG_INPUT, SG_ALERT, "Date/time string " << date_string
|
|
|
|
|
<< " not in YYYY-MM-DDTHH:MM:SS format; skipped");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// OK, it looks like we got six
|
|
|
|
|
// values, one way or another.
|
|
|
|
|
new_time.tm_year -= 1900;
|
|
|
|
|
new_time.tm_mon -= 1;
|
|
|
|
|
|
|
|
|
|
// Now, tell flight gear to use
|
|
|
|
|
// the new time. This was far
|
|
|
|
|
// too difficult, by the way.
|
|
|
|
|
long int warp =
|
|
|
|
|
mktime(&new_time) - mktime(current_time) + globals->get_warp();
|
|
|
|
|
double lon = current_aircraft.fdm_state->get_Longitude();
|
|
|
|
|
double lat = current_aircraft.fdm_state->get_Latitude();
|
|
|
|
|
globals->set_warp(warp);
|
|
|
|
|
st->update(lon, lat, warp);
|
|
|
|
|
fgUpdateSkyAndLightingParams();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the GMT as a string.
|
|
|
|
|
*/
|
|
|
|
|
static string
|
|
|
|
|
getGMTString ()
|
|
|
|
|
{
|
|
|
|
|
string out;
|
|
|
|
|
char buf[16];
|
|
|
|
|
struct tm * t = globals->get_time_params()->getGmt();
|
|
|
|
|
sprintf(buf, " %.2d:%.2d:%.2d",
|
|
|
|
|
t->tm_hour, t->tm_min, t->tm_sec);
|
|
|
|
|
out = buf;
|
|
|
|
|
return out;
|
|
|
|
|
}
|
|
|
|
|
|
2001-06-26 21:59:59 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the texture rendering state.
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getTextures ()
|
|
|
|
|
{
|
|
|
|
|
return (material_lib.get_step() == 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the texture rendering state.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setTextures (bool textures)
|
|
|
|
|
{
|
|
|
|
|
if (textures)
|
|
|
|
|
material_lib.set_step(0);
|
|
|
|
|
else
|
|
|
|
|
material_lib.set_step(1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
/**
|
|
|
|
|
* Return the magnetic variation
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getMagVar ()
|
|
|
|
|
{
|
|
|
|
|
return globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the magnetic dip
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getMagDip ()
|
|
|
|
|
{
|
|
|
|
|
return globals->get_mag()->get_magdip() * SGD_RADIANS_TO_DEGREES;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return the current heading in degrees.
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getHeadingMag ()
|
|
|
|
|
{
|
|
|
|
|
return current_aircraft.fdm_state->get_Psi() * SGD_RADIANS_TO_DEGREES - getMagVar();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot altitude lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getAPAltitudeLock ()
|
|
|
|
|
{
|
2001-06-26 21:59:59 +00:00
|
|
|
|
return (current_autopilot->get_AltitudeEnabled() &&
|
|
|
|
|
current_autopilot->get_AltitudeMode()
|
|
|
|
|
== FGAutopilot::FG_ALTITUDE_LOCK);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot altitude lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPAltitudeLock (bool lock)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (lock)
|
|
|
|
|
current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_LOCK);
|
|
|
|
|
if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_LOCK)
|
|
|
|
|
current_autopilot->set_AltitudeEnabled(lock);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-26 21:59:59 +00:00
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot target altitude in feet.
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getAPAltitude ()
|
|
|
|
|
{
|
|
|
|
|
return current_autopilot->get_TargetAltitude() * SG_METER_TO_FEET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot target altitude in feet.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPAltitude (double altitude)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
current_autopilot->set_TargetAltitude( altitude * SG_FEET_TO_METER );
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot altitude lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getAPGSLock ()
|
|
|
|
|
{
|
2001-06-26 21:59:59 +00:00
|
|
|
|
return (current_autopilot->get_AltitudeEnabled() &&
|
|
|
|
|
(current_autopilot->get_AltitudeMode()
|
|
|
|
|
== FGAutopilot::FG_ALTITUDE_GS1));
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot altitude lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPGSLock (bool lock)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (lock)
|
|
|
|
|
current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_GS1);
|
|
|
|
|
if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_GS1)
|
|
|
|
|
current_autopilot->set_AltitudeEnabled(lock);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-06-26 21:59:59 +00:00
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot terrain lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getAPTerrainLock ()
|
|
|
|
|
{
|
|
|
|
|
return (current_autopilot->get_AltitudeEnabled() &&
|
|
|
|
|
(current_autopilot->get_AltitudeMode()
|
|
|
|
|
== FGAutopilot::FG_ALTITUDE_TERRAIN));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot terrain lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPTerrainLock (bool lock)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (lock) {
|
|
|
|
|
current_autopilot->set_AltitudeMode(FGAutopilot::FG_ALTITUDE_TERRAIN);
|
|
|
|
|
current_autopilot
|
|
|
|
|
->set_TargetAGL(current_aircraft.fdm_state->get_Altitude_AGL() *
|
|
|
|
|
SG_FEET_TO_METER);
|
|
|
|
|
cout << "Target AGL = "
|
|
|
|
|
<< current_aircraft.fdm_state->get_Altitude_AGL() * SG_FEET_TO_METER
|
|
|
|
|
<< endl;
|
|
|
|
|
}
|
|
|
|
|
if (current_autopilot->get_AltitudeMode() == FGAutopilot::FG_ALTITUDE_TERRAIN)
|
|
|
|
|
current_autopilot->set_AltitudeEnabled(lock);
|
2001-06-26 21:59:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot target altitude in feet.
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getAPClimb ()
|
|
|
|
|
{
|
|
|
|
|
return current_autopilot->get_TargetClimbRate() * SG_METER_TO_FEET;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot target altitude in feet.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPClimb (double rate)
|
|
|
|
|
{
|
|
|
|
|
current_autopilot->set_TargetClimbRate( rate * SG_FEET_TO_METER );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot heading lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getAPHeadingLock ()
|
|
|
|
|
{
|
|
|
|
|
return
|
|
|
|
|
(current_autopilot->get_HeadingEnabled() &&
|
|
|
|
|
current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot heading lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPHeadingLock (bool lock)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (lock)
|
|
|
|
|
current_autopilot->set_HeadingMode(DEFAULT_AP_HEADING_LOCK);
|
|
|
|
|
if (current_autopilot->get_HeadingMode() == DEFAULT_AP_HEADING_LOCK)
|
|
|
|
|
current_autopilot->set_HeadingEnabled(lock);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot heading bug in degrees.
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getAPHeadingBug ()
|
|
|
|
|
{
|
|
|
|
|
return current_autopilot->get_DGTargetHeading();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot heading bug in degrees.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPHeadingBug (double heading)
|
|
|
|
|
{
|
|
|
|
|
current_autopilot->set_DGTargetHeading( heading );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot wing leveler lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getAPWingLeveler ()
|
|
|
|
|
{
|
|
|
|
|
return
|
|
|
|
|
(current_autopilot->get_HeadingEnabled() &&
|
|
|
|
|
current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot wing leveler lock (true=on).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPWingLeveler (bool lock)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (lock)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
current_autopilot->set_HeadingMode(FGAutopilot::FG_TC_HEADING_LOCK);
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (current_autopilot->get_HeadingMode() == FGAutopilot::FG_TC_HEADING_LOCK)
|
|
|
|
|
current_autopilot->set_HeadingEnabled(lock);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Return true if the autopilot is locked to NAV1.
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getAPNAV1Lock ()
|
|
|
|
|
{
|
|
|
|
|
return
|
|
|
|
|
(current_autopilot->get_HeadingEnabled() &&
|
|
|
|
|
current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autopilot NAV1 lock.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPNAV1Lock (bool lock)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (lock)
|
2001-06-05 22:13:26 +00:00
|
|
|
|
current_autopilot->set_HeadingMode(FGAutopilot::FG_HEADING_NAV1);
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (current_autopilot->get_HeadingMode() == FGAutopilot::FG_HEADING_NAV1)
|
|
|
|
|
current_autopilot->set_HeadingEnabled(lock);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the autopilot autothrottle lock.
|
|
|
|
|
*/
|
|
|
|
|
static bool
|
|
|
|
|
getAPAutoThrottleLock ()
|
|
|
|
|
{
|
|
|
|
|
return current_autopilot->get_AutoThrottleEnabled();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the autothrottle lock.
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setAPAutoThrottleLock (bool lock)
|
|
|
|
|
{
|
|
|
|
|
current_autopilot->set_AutoThrottleEnabled(lock);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// kludge
|
|
|
|
|
static double
|
|
|
|
|
getAPRudderControl ()
|
|
|
|
|
{
|
|
|
|
|
if (getAPHeadingLock())
|
|
|
|
|
return current_autopilot->get_TargetHeading();
|
|
|
|
|
else
|
2001-07-22 19:51:16 +00:00
|
|
|
|
return globals->get_controls()->get_rudder();
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// kludge
|
|
|
|
|
static void
|
|
|
|
|
setAPRudderControl (double value)
|
|
|
|
|
{
|
|
|
|
|
if (getAPHeadingLock()) {
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_DEBUG, "setAPRudderControl " << value );
|
|
|
|
|
value -= current_autopilot->get_TargetHeading();
|
|
|
|
|
current_autopilot->HeadingAdjust(value < 0.0 ? -1.0 : 1.0);
|
|
|
|
|
} else {
|
2001-07-22 19:51:16 +00:00
|
|
|
|
globals->get_controls()->set_rudder(value);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// kludge
|
|
|
|
|
static double
|
|
|
|
|
getAPElevatorControl ()
|
|
|
|
|
{
|
|
|
|
|
if (getAPAltitudeLock())
|
|
|
|
|
return current_autopilot->get_TargetAltitude();
|
|
|
|
|
else
|
2001-07-22 19:51:16 +00:00
|
|
|
|
return globals->get_controls()->get_elevator();
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// kludge
|
|
|
|
|
static void
|
|
|
|
|
setAPElevatorControl (double value)
|
|
|
|
|
{
|
2002-01-14 03:14:42 +00:00
|
|
|
|
if (value != 0 && getAPAltitudeLock()) {
|
2001-06-05 22:13:26 +00:00
|
|
|
|
SG_LOG(SG_GENERAL, SG_DEBUG, "setAPElevatorControl " << value );
|
|
|
|
|
value -= current_autopilot->get_TargetAltitude();
|
|
|
|
|
current_autopilot->AltitudeAdjust(value < 0.0 ? 100.0 : -100.0);
|
|
|
|
|
} else {
|
2001-07-22 19:51:16 +00:00
|
|
|
|
globals->get_controls()->set_elevator(value);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// kludge
|
|
|
|
|
static double
|
|
|
|
|
getAPThrottleControl ()
|
|
|
|
|
{
|
|
|
|
|
if (getAPAutoThrottleLock())
|
|
|
|
|
return 0.0; // always resets
|
|
|
|
|
else
|
2001-07-22 19:51:16 +00:00
|
|
|
|
return globals->get_controls()->get_throttle(0);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// kludge
|
|
|
|
|
static void
|
|
|
|
|
setAPThrottleControl (double value)
|
|
|
|
|
{
|
|
|
|
|
if (getAPAutoThrottleLock())
|
|
|
|
|
current_autopilot->AutoThrottleAdjust(value < 0.0 ? -0.01 : 0.01);
|
|
|
|
|
else
|
2001-12-03 22:17:35 +00:00
|
|
|
|
globals->get_controls()->set_throttle(FGControls::ALL_ENGINES, value);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current visibility (meters).
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getVisibility ()
|
|
|
|
|
{
|
|
|
|
|
#ifndef FG_OLD_WEATHER
|
|
|
|
|
return WeatherDatabase->getWeatherVisibility();
|
|
|
|
|
#else
|
|
|
|
|
return current_weather.get_visibility();
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the current visibility (meters).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setVisibility (double visibility)
|
|
|
|
|
{
|
|
|
|
|
#ifndef FG_OLD_WEATHER
|
|
|
|
|
WeatherDatabase->setWeatherVisibility(visibility);
|
|
|
|
|
#else
|
|
|
|
|
current_weather.set_visibility(visibility);
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current wind north velocity (feet/second).
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getWindNorth ()
|
|
|
|
|
{
|
|
|
|
|
return current_aircraft.fdm_state->get_V_north_airmass();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the current wind north velocity (feet/second).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setWindNorth (double speed)
|
|
|
|
|
{
|
|
|
|
|
current_aircraft.fdm_state
|
|
|
|
|
->set_Velocities_Local_Airmass(speed, getWindEast(), getWindDown());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current wind east velocity (feet/second).
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getWindEast ()
|
|
|
|
|
{
|
|
|
|
|
return current_aircraft.fdm_state->get_V_east_airmass();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the current wind east velocity (feet/second).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setWindEast (double speed)
|
|
|
|
|
{
|
|
|
|
|
cout << "Set wind-east to " << speed << endl;
|
|
|
|
|
current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
|
|
|
|
|
speed,
|
|
|
|
|
getWindDown());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Get the current wind down velocity (feet/second).
|
|
|
|
|
*/
|
|
|
|
|
static double
|
|
|
|
|
getWindDown ()
|
|
|
|
|
{
|
|
|
|
|
return current_aircraft.fdm_state->get_V_down_airmass();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Set the current wind down velocity (feet/second).
|
|
|
|
|
*/
|
|
|
|
|
static void
|
|
|
|
|
setWindDown (double speed)
|
|
|
|
|
{
|
|
|
|
|
current_aircraft.fdm_state->set_Velocities_Local_Airmass(getWindNorth(),
|
|
|
|
|
getWindEast(),
|
|
|
|
|
speed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static double
|
|
|
|
|
getFOV ()
|
|
|
|
|
{
|
|
|
|
|
return globals->get_current_view()->get_fov();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setFOV (double fov)
|
|
|
|
|
{
|
2001-10-24 20:28:28 +00:00
|
|
|
|
if ( fov < 180 ) {
|
|
|
|
|
globals->get_current_view()->set_fov( fov );
|
|
|
|
|
}
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-06-26 21:59:59 +00:00
|
|
|
|
static long
|
|
|
|
|
getWarp ()
|
|
|
|
|
{
|
|
|
|
|
return globals->get_warp();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setWarp (long warp)
|
|
|
|
|
{
|
|
|
|
|
globals->set_warp(warp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static long
|
|
|
|
|
getWarpDelta ()
|
|
|
|
|
{
|
|
|
|
|
return globals->get_warp_delta();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setWarpDelta (long delta)
|
|
|
|
|
{
|
|
|
|
|
globals->set_warp_delta(delta);
|
|
|
|
|
}
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setViewAxisLong (double axis)
|
|
|
|
|
{
|
|
|
|
|
axisLong = axis;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setViewAxisLat (double axis)
|
|
|
|
|
{
|
|
|
|
|
axisLat = axis;
|
|
|
|
|
}
|
|
|
|
|
|
2001-07-16 04:35:35 +00:00
|
|
|
|
static bool
|
|
|
|
|
getWindingCCW ()
|
|
|
|
|
{
|
|
|
|
|
return winding_ccw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setWindingCCW (bool state)
|
|
|
|
|
{
|
|
|
|
|
winding_ccw = state;
|
|
|
|
|
if ( winding_ccw )
|
|
|
|
|
glFrontFace ( GL_CCW );
|
|
|
|
|
else
|
|
|
|
|
glFrontFace ( GL_CW );
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
getFullScreen ()
|
|
|
|
|
{
|
|
|
|
|
#if defined(FX) && !defined(WIN32)
|
2002-01-06 16:51:31 +00:00
|
|
|
|
return globals->get_fullscreen();
|
2001-07-16 04:35:35 +00:00
|
|
|
|
#else
|
|
|
|
|
return false;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setFullScreen (bool state)
|
|
|
|
|
{
|
|
|
|
|
#if defined(FX) && !defined(WIN32)
|
2002-01-06 16:51:31 +00:00
|
|
|
|
globals->set_fullscreen(state);
|
2001-07-16 04:35:35 +00:00
|
|
|
|
# if defined(XMESA_FX_FULLSCREEN) && defined(XMESA_FX_WINDOW)
|
2002-01-06 16:51:31 +00:00
|
|
|
|
XMesaSetFXmode( state ? XMESA_FX_FULLSCREEN : XMESA_FX_WINDOW );
|
2001-07-16 04:35:35 +00:00
|
|
|
|
# endif
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool
|
|
|
|
|
getFDMDataLogging ()
|
|
|
|
|
{
|
|
|
|
|
return fdm_data_logging;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
setFDMDataLogging (bool state)
|
|
|
|
|
{
|
|
|
|
|
// kludge; no getter or setter available
|
|
|
|
|
if (state != fdm_data_logging) {
|
|
|
|
|
fgToggleFDMdataLogging();
|
|
|
|
|
fdm_data_logging = state;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Tie the properties.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
fgInitProps ()
|
|
|
|
|
{
|
|
|
|
|
// Simulation
|
2001-11-20 22:03:17 +00:00
|
|
|
|
fgTie("/sim/logging/priority", getLoggingPriority, setLoggingPriority);
|
|
|
|
|
fgTie("/sim/logging/classes", getLoggingClasses, setLoggingClasses);
|
2002-01-20 03:52:36 +00:00
|
|
|
|
// fgTie("/sim/freeze", getFreeze, setFreeze);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/sim/aircraft-dir", getAircraftDir, setAircraftDir);
|
2001-12-06 23:28:14 +00:00
|
|
|
|
fgTie("/sim/view/offset-deg", getViewOffset, setViewOffset, false);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/sim/view/offset-deg");
|
2001-12-06 23:28:14 +00:00
|
|
|
|
fgTie("/sim/view/goal-offset-deg", getGoalViewOffset, setGoalViewOffset, false);
|
2002-01-19 23:01:01 +00:00
|
|
|
|
fgTie("/sim/view/tilt-deg", getViewTilt, setViewTilt, false);
|
|
|
|
|
fgSetArchivable("/sim/view/tilt-deg");
|
|
|
|
|
fgTie("/sim/view/goal-tilt-deg", getGoalViewTilt, setGoalViewTilt, false);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/sim/view/goal-offset-deg");
|
2001-07-24 23:51:47 +00:00
|
|
|
|
fgTie("/sim/view/pilot/x-offset-m",
|
|
|
|
|
getPilotPositionXOffset, setPilotPositionXOffset);
|
|
|
|
|
fgSetArchivable("/sim/view/pilot/x-offset-m");
|
|
|
|
|
fgTie("/sim/view/pilot/y-offset-m",
|
|
|
|
|
getPilotPositionYOffset, setPilotPositionYOffset);
|
|
|
|
|
fgSetArchivable("/sim/view/pilot/y-offset-m");
|
|
|
|
|
fgTie("/sim/view/pilot/z-offset-m",
|
|
|
|
|
getPilotPositionZOffset, setPilotPositionZOffset);
|
|
|
|
|
fgSetArchivable("/sim/view/pilot/z-offset-m");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/sim/time/gmt", getDateString, setDateString);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/sim/time/gmt");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/sim/time/gmt-string", getGMTString);
|
2001-06-26 21:59:59 +00:00
|
|
|
|
fgTie("/sim/rendering/textures", getTextures, setTextures);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
// Orientation
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/orientation/heading-magnetic-deg", getHeadingMag);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
// Autopilot
|
|
|
|
|
fgTie("/autopilot/locks/altitude", getAPAltitudeLock, setAPAltitudeLock);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/locks/altitude");
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/autopilot/settings/altitude-ft", getAPAltitude, setAPAltitude);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/settings/altitude-ft");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/autopilot/locks/glide-slope", getAPGSLock, setAPGSLock);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/locks/glide-slope");
|
2001-06-26 21:59:59 +00:00
|
|
|
|
fgTie("/autopilot/locks/terrain", getAPTerrainLock, setAPTerrainLock);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/locks/terrain");
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/autopilot/settings/climb-rate-fpm", getAPClimb, setAPClimb, false);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/settings/climb-rate-fpm");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/autopilot/locks/heading", getAPHeadingLock, setAPHeadingLock);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/locks/heading");
|
|
|
|
|
fgTie("/autopilot/settings/heading-bug-deg",
|
2002-01-14 03:14:42 +00:00
|
|
|
|
getAPHeadingBug, setAPHeadingBug);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/settings/heading-bug-deg");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/autopilot/locks/wing-leveler", getAPWingLeveler, setAPWingLeveler);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/locks/wing-leveler");
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/autopilot/locks/nav[0]", getAPNAV1Lock, setAPNAV1Lock);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/locks/nav[0]");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/autopilot/locks/auto-throttle",
|
|
|
|
|
getAPAutoThrottleLock, setAPAutoThrottleLock);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/locks/auto-throttle");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/autopilot/control-overrides/rudder",
|
|
|
|
|
getAPRudderControl, setAPRudderControl);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/control-overrides/rudder");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/autopilot/control-overrides/elevator",
|
|
|
|
|
getAPElevatorControl, setAPElevatorControl);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/control-overrides/elevator");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/autopilot/control-overrides/throttle",
|
|
|
|
|
getAPThrottleControl, setAPThrottleControl);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/autopilot/control-overrides/throttle");
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
// Environment
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/environment/visibility-m", getVisibility, setVisibility);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/environment/visibility-m");
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/environment/wind-north-fps", getWindNorth, setWindNorth);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/environment/wind-north-fps");
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/environment/wind-east-fps", getWindEast, setWindEast);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/environment/wind-east-fps");
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/environment/wind-down-fps", getWindDown, setWindDown);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/environment/wind-down-fps");
|
|
|
|
|
|
2001-07-02 22:27:24 +00:00
|
|
|
|
fgTie("/environment/magnetic-variation-deg", getMagVar);
|
|
|
|
|
fgTie("/environment/magnetic-dip-deg", getMagDip);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
|
|
|
|
|
// View
|
|
|
|
|
fgTie("/sim/field-of-view", getFOV, setFOV);
|
2001-07-12 23:35:56 +00:00
|
|
|
|
fgSetArchivable("/sim/field-of-view");
|
2001-07-02 16:44:02 +00:00
|
|
|
|
fgTie("/sim/time/warp", getWarp, setWarp, false);
|
2001-06-26 21:59:59 +00:00
|
|
|
|
fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta);
|
2001-06-05 22:13:26 +00:00
|
|
|
|
fgTie("/sim/view/axes/long", (double(*)())0, setViewAxisLong);
|
|
|
|
|
fgTie("/sim/view/axes/lat", (double(*)())0, setViewAxisLat);
|
2001-07-16 04:35:35 +00:00
|
|
|
|
|
|
|
|
|
// Misc. Temporary junk.
|
2001-10-05 20:27:43 +00:00
|
|
|
|
fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false);
|
2001-07-16 04:35:35 +00:00
|
|
|
|
fgTie("/sim/temp/full-screen", getFullScreen, setFullScreen);
|
|
|
|
|
fgTie("/sim/temp/fdm-data-logging", getFDMDataLogging, setFDMDataLogging);
|
|
|
|
|
|
2001-06-05 22:13:26 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
fgUpdateProps ()
|
|
|
|
|
{
|
|
|
|
|
_set_view_from_axes();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Save and restore.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2001-01-05 17:37:59 +00:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Save the current state of the simulator to a stream.
|
|
|
|
|
*/
|
|
|
|
|
bool
|
|
|
|
|
fgSaveFlight (ostream &output)
|
|
|
|
|
{
|
2001-07-19 04:51:05 +00:00
|
|
|
|
try {
|
|
|
|
|
writeProperties(output, globals->get_props());
|
2001-07-24 23:51:47 +00:00
|
|
|
|
} catch (const sg_exception &e) {
|
|
|
|
|
guiErrorMessage("Error saving flight: ", e);
|
2001-07-19 04:51:05 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
2001-01-05 17:37:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Restore the current state of the simulator from a stream.
|
|
|
|
|
*/
|
|
|
|
|
bool
|
|
|
|
|
fgLoadFlight (istream &input)
|
|
|
|
|
{
|
2001-01-19 22:57:24 +00:00
|
|
|
|
SGPropertyNode props;
|
2001-07-19 04:51:05 +00:00
|
|
|
|
try {
|
|
|
|
|
readProperties(input, &props);
|
2001-07-24 23:51:47 +00:00
|
|
|
|
} catch (const sg_exception &e) {
|
|
|
|
|
guiErrorMessage("Error reading saved flight: ", e);
|
2001-01-19 22:57:24 +00:00
|
|
|
|
return false;
|
|
|
|
|
}
|
2001-07-19 04:51:05 +00:00
|
|
|
|
copyProperties(&props, globals->get_props());
|
|
|
|
|
// When loading a flight, make it the
|
|
|
|
|
// new initial state.
|
|
|
|
|
globals->saveInitialState();
|
2001-05-18 20:30:36 +00:00
|
|
|
|
return true;
|
2001-01-05 17:37:59 +00:00
|
|
|
|
}
|
|
|
|
|
|
2001-08-03 00:19:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGCondition.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGCondition::FGCondition ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGCondition::~FGCondition ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGPropertyCondition.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGPropertyCondition::FGPropertyCondition (const string &propname)
|
|
|
|
|
: _node(fgGetNode(propname, true))
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGPropertyCondition::~FGPropertyCondition ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGNotCondition.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGNotCondition::FGNotCondition (FGCondition * condition)
|
|
|
|
|
: _condition(condition)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGNotCondition::~FGNotCondition ()
|
|
|
|
|
{
|
|
|
|
|
delete _condition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
FGNotCondition::test () const
|
|
|
|
|
{
|
|
|
|
|
return !(_condition->test());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGAndCondition.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGAndCondition::FGAndCondition ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGAndCondition::~FGAndCondition ()
|
|
|
|
|
{
|
2001-08-31 18:07:23 +00:00
|
|
|
|
for (unsigned int i = 0; i < _conditions.size(); i++)
|
2001-08-03 00:19:41 +00:00
|
|
|
|
delete _conditions[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
FGAndCondition::test () const
|
|
|
|
|
{
|
|
|
|
|
int nConditions = _conditions.size();
|
|
|
|
|
for (int i = 0; i < nConditions; i++) {
|
|
|
|
|
if (!_conditions[i]->test())
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGAndCondition::addCondition (FGCondition * condition)
|
|
|
|
|
{
|
|
|
|
|
_conditions.push_back(condition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGOrCondition.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGOrCondition::FGOrCondition ()
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGOrCondition::~FGOrCondition ()
|
|
|
|
|
{
|
2001-08-31 18:07:23 +00:00
|
|
|
|
for (unsigned int i = 0; i < _conditions.size(); i++)
|
2001-08-03 00:19:41 +00:00
|
|
|
|
delete _conditions[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
FGOrCondition::test () const
|
|
|
|
|
{
|
|
|
|
|
int nConditions = _conditions.size();
|
|
|
|
|
for (int i = 0; i < nConditions; i++) {
|
|
|
|
|
if (_conditions[i]->test())
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGOrCondition::addCondition (FGCondition * condition)
|
|
|
|
|
{
|
|
|
|
|
_conditions.push_back(condition);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGComparisonCondition.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
doComparison (const SGPropertyNode * left, const SGPropertyNode *right)
|
|
|
|
|
{
|
|
|
|
|
switch (left->getType()) {
|
|
|
|
|
case SGPropertyNode::BOOL: {
|
|
|
|
|
bool v1 = left->getBoolValue();
|
|
|
|
|
bool v2 = right->getBoolValue();
|
|
|
|
|
if (v1 < v2)
|
|
|
|
|
return FGComparisonCondition::LESS_THAN;
|
|
|
|
|
else if (v1 > v2)
|
|
|
|
|
return FGComparisonCondition::GREATER_THAN;
|
|
|
|
|
else
|
|
|
|
|
return FGComparisonCondition::EQUALS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SGPropertyNode::INT: {
|
|
|
|
|
int v1 = left->getIntValue();
|
|
|
|
|
int v2 = right->getIntValue();
|
|
|
|
|
if (v1 < v2)
|
|
|
|
|
return FGComparisonCondition::LESS_THAN;
|
|
|
|
|
else if (v1 > v2)
|
|
|
|
|
return FGComparisonCondition::GREATER_THAN;
|
|
|
|
|
else
|
|
|
|
|
return FGComparisonCondition::EQUALS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SGPropertyNode::LONG: {
|
|
|
|
|
long v1 = left->getLongValue();
|
|
|
|
|
long v2 = right->getLongValue();
|
|
|
|
|
if (v1 < v2)
|
|
|
|
|
return FGComparisonCondition::LESS_THAN;
|
|
|
|
|
else if (v1 > v2)
|
|
|
|
|
return FGComparisonCondition::GREATER_THAN;
|
|
|
|
|
else
|
|
|
|
|
return FGComparisonCondition::EQUALS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SGPropertyNode::FLOAT: {
|
|
|
|
|
float v1 = left->getFloatValue();
|
|
|
|
|
float v2 = right->getFloatValue();
|
|
|
|
|
if (v1 < v2)
|
|
|
|
|
return FGComparisonCondition::LESS_THAN;
|
|
|
|
|
else if (v1 > v2)
|
|
|
|
|
return FGComparisonCondition::GREATER_THAN;
|
|
|
|
|
else
|
|
|
|
|
return FGComparisonCondition::EQUALS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SGPropertyNode::DOUBLE: {
|
|
|
|
|
double v1 = left->getDoubleValue();
|
|
|
|
|
double v2 = right->getDoubleValue();
|
|
|
|
|
if (v1 < v2)
|
|
|
|
|
return FGComparisonCondition::LESS_THAN;
|
|
|
|
|
else if (v1 > v2)
|
|
|
|
|
return FGComparisonCondition::GREATER_THAN;
|
|
|
|
|
else
|
|
|
|
|
return FGComparisonCondition::EQUALS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case SGPropertyNode::STRING:
|
|
|
|
|
case SGPropertyNode::NONE:
|
|
|
|
|
case SGPropertyNode::UNSPECIFIED: {
|
|
|
|
|
string v1 = left->getStringValue();
|
|
|
|
|
string v2 = right->getStringValue();
|
|
|
|
|
if (v1 < v2)
|
|
|
|
|
return FGComparisonCondition::LESS_THAN;
|
|
|
|
|
else if (v1 > v2)
|
|
|
|
|
return FGComparisonCondition::GREATER_THAN;
|
|
|
|
|
else
|
|
|
|
|
return FGComparisonCondition::EQUALS;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
throw sg_exception("Unrecognized node type");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
FGComparisonCondition::FGComparisonCondition (Type type, bool reverse)
|
|
|
|
|
: _type(type),
|
|
|
|
|
_reverse(reverse),
|
|
|
|
|
_left_property(0),
|
|
|
|
|
_right_property(0),
|
|
|
|
|
_right_value(0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGComparisonCondition::~FGComparisonCondition ()
|
|
|
|
|
{
|
|
|
|
|
delete _right_value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
FGComparisonCondition::test () const
|
|
|
|
|
{
|
|
|
|
|
// Always fail if incompletely specified
|
|
|
|
|
if (_left_property == 0 ||
|
|
|
|
|
(_right_property == 0 && _right_value == 0))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
// Get LESS_THAN, EQUALS, or GREATER_THAN
|
|
|
|
|
int cmp =
|
|
|
|
|
doComparison(_left_property,
|
|
|
|
|
(_right_property != 0 ? _right_property : _right_value));
|
|
|
|
|
if (!_reverse)
|
|
|
|
|
return (cmp == _type);
|
|
|
|
|
else
|
|
|
|
|
return (cmp != _type);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGComparisonCondition::setLeftProperty (const string &propname)
|
|
|
|
|
{
|
|
|
|
|
_left_property = fgGetNode(propname, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGComparisonCondition::setRightProperty (const string &propname)
|
|
|
|
|
{
|
|
|
|
|
delete _right_value;
|
|
|
|
|
_right_value = 0;
|
|
|
|
|
_right_property = fgGetNode(propname, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGComparisonCondition::setRightValue (const SGPropertyNode *node)
|
|
|
|
|
{
|
|
|
|
|
_right_property = 0;
|
|
|
|
|
delete _right_value;
|
|
|
|
|
_right_value = new SGPropertyNode(*node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Read a condition and use it if necessary.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Forward declaration
|
|
|
|
|
static FGCondition * readCondition (const SGPropertyNode * node);
|
|
|
|
|
|
|
|
|
|
static FGCondition *
|
|
|
|
|
readPropertyCondition (const SGPropertyNode * node)
|
|
|
|
|
{
|
|
|
|
|
return new FGPropertyCondition(node->getStringValue());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FGCondition *
|
|
|
|
|
readNotCondition (const SGPropertyNode * node)
|
|
|
|
|
{
|
|
|
|
|
int nChildren = node->nChildren();
|
|
|
|
|
for (int i = 0; i < nChildren; i++) {
|
|
|
|
|
const SGPropertyNode * child = node->getChild(i);
|
|
|
|
|
FGCondition * condition = readCondition(child);
|
|
|
|
|
if (condition != 0)
|
|
|
|
|
return new FGNotCondition(condition);
|
|
|
|
|
}
|
|
|
|
|
SG_LOG(SG_COCKPIT, SG_ALERT, "Panel: empty 'not' condition");
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FGCondition *
|
|
|
|
|
readAndConditions (const SGPropertyNode * node)
|
|
|
|
|
{
|
|
|
|
|
FGAndCondition * andCondition = new FGAndCondition;
|
|
|
|
|
int nChildren = node->nChildren();
|
|
|
|
|
for (int i = 0; i < nChildren; i++) {
|
|
|
|
|
const SGPropertyNode * child = node->getChild(i);
|
|
|
|
|
FGCondition * condition = readCondition(child);
|
|
|
|
|
if (condition != 0)
|
|
|
|
|
andCondition->addCondition(condition);
|
|
|
|
|
}
|
|
|
|
|
return andCondition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FGCondition *
|
|
|
|
|
readOrConditions (const SGPropertyNode * node)
|
|
|
|
|
{
|
|
|
|
|
FGOrCondition * orCondition = new FGOrCondition;
|
|
|
|
|
int nChildren = node->nChildren();
|
|
|
|
|
for (int i = 0; i < nChildren; i++) {
|
|
|
|
|
const SGPropertyNode * child = node->getChild(i);
|
|
|
|
|
FGCondition * condition = readCondition(child);
|
|
|
|
|
if (condition != 0)
|
|
|
|
|
orCondition->addCondition(condition);
|
|
|
|
|
}
|
|
|
|
|
return orCondition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FGCondition *
|
|
|
|
|
readComparison (const SGPropertyNode * node,
|
|
|
|
|
FGComparisonCondition::Type type,
|
|
|
|
|
bool reverse)
|
|
|
|
|
{
|
|
|
|
|
FGComparisonCondition * condition = new FGComparisonCondition(type, reverse);
|
|
|
|
|
condition->setLeftProperty(node->getStringValue("property[0]"));
|
|
|
|
|
if (node->hasValue("property[1]"))
|
|
|
|
|
condition->setRightProperty(node->getStringValue("property[1]"));
|
|
|
|
|
else
|
|
|
|
|
condition->setRightValue(node->getChild("value", 0));
|
|
|
|
|
|
|
|
|
|
return condition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static FGCondition *
|
|
|
|
|
readCondition (const SGPropertyNode * node)
|
|
|
|
|
{
|
|
|
|
|
const string &name = node->getName();
|
|
|
|
|
if (name == "property")
|
|
|
|
|
return readPropertyCondition(node);
|
|
|
|
|
else if (name == "not")
|
|
|
|
|
return readNotCondition(node);
|
|
|
|
|
else if (name == "and")
|
|
|
|
|
return readAndConditions(node);
|
|
|
|
|
else if (name == "or")
|
|
|
|
|
return readOrConditions(node);
|
|
|
|
|
else if (name == "less-than")
|
|
|
|
|
return readComparison(node, FGComparisonCondition::LESS_THAN, false);
|
|
|
|
|
else if (name == "less-than-equals")
|
|
|
|
|
return readComparison(node, FGComparisonCondition::GREATER_THAN, true);
|
|
|
|
|
else if (name == "greater-than")
|
|
|
|
|
return readComparison(node, FGComparisonCondition::GREATER_THAN, false);
|
|
|
|
|
else if (name == "greater-than-equals")
|
|
|
|
|
return readComparison(node, FGComparisonCondition::LESS_THAN, true);
|
|
|
|
|
else if (name == "equals")
|
|
|
|
|
return readComparison(node, FGComparisonCondition::EQUALS, false);
|
|
|
|
|
else if (name == "not-equals")
|
|
|
|
|
return readComparison(node, FGComparisonCondition::EQUALS, true);
|
|
|
|
|
else
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
// Implementation of FGConditional.
|
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
FGConditional::FGConditional ()
|
|
|
|
|
: _condition (0)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
FGConditional::~FGConditional ()
|
|
|
|
|
{
|
|
|
|
|
delete _condition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
FGConditional::setCondition (FGCondition * condition)
|
|
|
|
|
{
|
|
|
|
|
delete _condition;
|
|
|
|
|
_condition = condition;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
FGConditional::test () const
|
|
|
|
|
{
|
|
|
|
|
return ((_condition == 0) || _condition->test());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The top-level is always an implicit 'and' group
|
|
|
|
|
FGCondition *
|
|
|
|
|
fgReadCondition (const SGPropertyNode * node)
|
|
|
|
|
{
|
|
|
|
|
return readAndConditions(node);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2001-01-05 17:37:59 +00:00
|
|
|
|
// end of fg_props.cxx
|