1998-04-24 00:49:17 +00:00
|
|
|
// options.cxx -- class to handle command line options
|
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started April 1998.
|
|
|
|
//
|
2004-11-19 22:10:41 +00:00
|
|
|
// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
|
1998-04-24 00:49:17 +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
|
2006-02-21 01:16:04 +00:00
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
1998-04-24 00:49:17 +00:00
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
|
|
|
|
|
1998-04-26 05:01:19 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
#include <simgear/compiler.h>
|
2003-09-24 17:20:55 +00:00
|
|
|
#include <simgear/structure/exception.hxx>
|
2003-03-22 10:38:15 +00:00
|
|
|
#include <simgear/debug/logstream.hxx>
|
1999-03-02 01:02:31 +00:00
|
|
|
|
2002-03-20 22:15:22 +00:00
|
|
|
#include <math.h> // rint()
|
1998-04-24 00:49:17 +00:00
|
|
|
#include <stdio.h>
|
2002-03-20 22:15:22 +00:00
|
|
|
#include <stdlib.h> // atof(), atoi()
|
|
|
|
#include <string.h> // strcmp()
|
2003-02-11 21:17:36 +00:00
|
|
|
#include <algorithm>
|
1999-03-02 01:02:31 +00:00
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
#include <iostream>
|
2008-07-25 18:38:29 +00:00
|
|
|
#include <string>
|
1998-04-24 00:49:17 +00:00
|
|
|
|
2002-08-28 16:59:40 +00:00
|
|
|
#include <plib/ul.h>
|
|
|
|
|
2002-07-26 02:49:14 +00:00
|
|
|
#include <simgear/math/sg_random.h>
|
2008-07-31 12:04:32 +00:00
|
|
|
#include <simgear/props/props_io.hxx>
|
2001-03-25 14:20:12 +00:00
|
|
|
#include <simgear/misc/sgstream.hxx>
|
2002-03-16 00:18:38 +00:00
|
|
|
#include <simgear/misc/sg_path.hxx>
|
2007-05-28 05:21:45 +00:00
|
|
|
#include <simgear/scene/material/mat.hxx>
|
2001-01-13 22:06:39 +00:00
|
|
|
|
|
|
|
// #include <Include/general.hxx>
|
|
|
|
// #include <Airports/simple.hxx>
|
|
|
|
// #include <Cockpit/cockpit.hxx>
|
|
|
|
// #include <FDM/flight.hxx>
|
1998-04-24 00:49:17 +00:00
|
|
|
|
2004-01-31 19:47:45 +00:00
|
|
|
#include <Autopilot/route_mgr.hxx>
|
2001-07-19 04:53:13 +00:00
|
|
|
#include <GUI/gui.h>
|
|
|
|
|
2000-07-07 20:28:51 +00:00
|
|
|
#include "globals.hxx"
|
2001-01-13 22:06:39 +00:00
|
|
|
#include "fg_init.hxx"
|
|
|
|
#include "fg_props.hxx"
|
1999-05-06 22:16:12 +00:00
|
|
|
#include "options.hxx"
|
2003-06-11 14:18:24 +00:00
|
|
|
#include "util.hxx"
|
2001-07-22 19:51:16 +00:00
|
|
|
#include "viewmgr.hxx"
|
2009-09-19 18:41:55 +00:00
|
|
|
#include <Main/viewer.hxx>
|
2002-10-04 15:19:07 +00:00
|
|
|
|
2008-07-27 16:25:13 +00:00
|
|
|
using std::string;
|
|
|
|
using std::sort;
|
2008-08-14 18:13:39 +00:00
|
|
|
using std::cout;
|
|
|
|
using std::cerr;
|
|
|
|
using std::endl;
|
1999-03-02 01:02:31 +00:00
|
|
|
|
2008-03-15 12:10:44 +00:00
|
|
|
#ifndef VERSION
|
|
|
|
#define VERSION "CVS "__DATE__
|
|
|
|
#endif
|
1998-11-16 13:59:58 +00:00
|
|
|
|
2001-01-13 22:06:39 +00:00
|
|
|
#define NEW_DEFAULT_MODEL_HZ 120
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
FG_OPTIONS_OK = 0,
|
|
|
|
FG_OPTIONS_HELP = 1,
|
2002-08-25 22:38:20 +00:00
|
|
|
FG_OPTIONS_ERROR = 2,
|
2008-03-15 12:10:44 +00:00
|
|
|
FG_OPTIONS_EXIT = 3,
|
|
|
|
FG_OPTIONS_VERBOSE_HELP = 4,
|
|
|
|
FG_OPTIONS_SHOW_AIRCRAFT = 5
|
2001-01-13 22:06:39 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
static double
|
1998-08-27 17:01:55 +00:00
|
|
|
atof( const string& str )
|
|
|
|
{
|
|
|
|
return ::atof( str.c_str() );
|
|
|
|
}
|
|
|
|
|
2001-01-13 22:06:39 +00:00
|
|
|
static int
|
1998-08-27 17:01:55 +00:00
|
|
|
atoi( const string& str )
|
|
|
|
{
|
|
|
|
return ::atoi( str.c_str() );
|
|
|
|
}
|
1998-04-24 00:49:17 +00:00
|
|
|
|
2001-01-13 22:06:39 +00:00
|
|
|
/**
|
|
|
|
* Set a few fail-safe default property values.
|
|
|
|
*
|
|
|
|
* These should all be set in $FG_ROOT/preferences.xml, but just
|
2003-03-19 20:45:09 +00:00
|
|
|
* in case, we provide some initial sane values here. This method
|
2001-01-13 22:06:39 +00:00
|
|
|
* should be invoked *before* reading any init files.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
fgSetDefaults ()
|
1998-08-27 17:01:55 +00:00
|
|
|
{
|
2000-07-14 16:57:55 +00:00
|
|
|
// set a possibly independent location for scenery data
|
2009-03-01 16:09:45 +00:00
|
|
|
const char *envp = ::getenv( "FG_SCENERY" );
|
2000-07-14 16:57:55 +00:00
|
|
|
|
|
|
|
if ( envp != NULL ) {
|
|
|
|
// fg_root could be anywhere, so default to environmental
|
|
|
|
// variable $FG_ROOT if it is set.
|
2001-01-12 15:37:40 +00:00
|
|
|
globals->set_fg_scenery(envp);
|
2000-07-14 16:57:55 +00:00
|
|
|
} else {
|
|
|
|
// Otherwise, default to Scenery being in $FG_ROOT/Scenery
|
2001-01-12 15:37:40 +00:00
|
|
|
globals->set_fg_scenery("");
|
2000-07-14 16:57:55 +00:00
|
|
|
}
|
2002-05-01 23:13:36 +00:00
|
|
|
// Position (deliberately out of range)
|
|
|
|
fgSetDouble("/position/longitude-deg", 9999.0);
|
|
|
|
fgSetDouble("/position/latitude-deg", 9999.0);
|
2001-07-02 22:27:24 +00:00
|
|
|
fgSetDouble("/position/altitude-ft", -9999.0);
|
2001-01-12 15:37:40 +00:00
|
|
|
|
|
|
|
// Orientation
|
2007-10-04 17:14:37 +00:00
|
|
|
fgSetDouble("/orientation/heading-deg", 9999.0);
|
2007-10-04 21:52:50 +00:00
|
|
|
fgSetDouble("/orientation/roll-deg", 0.0);
|
|
|
|
fgSetDouble("/orientation/pitch-deg", 0.424);
|
2001-01-12 15:37:40 +00:00
|
|
|
|
|
|
|
// Velocities
|
2001-07-02 22:27:24 +00:00
|
|
|
fgSetDouble("/velocities/uBody-fps", 0.0);
|
|
|
|
fgSetDouble("/velocities/vBody-fps", 0.0);
|
|
|
|
fgSetDouble("/velocities/wBody-fps", 0.0);
|
|
|
|
fgSetDouble("/velocities/speed-north-fps", 0.0);
|
|
|
|
fgSetDouble("/velocities/speed-east-fps", 0.0);
|
|
|
|
fgSetDouble("/velocities/speed-down-fps", 0.0);
|
|
|
|
fgSetDouble("/velocities/airspeed-kt", 0.0);
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetDouble("/velocities/mach", 0.0);
|
2001-01-12 15:37:40 +00:00
|
|
|
|
2002-11-15 21:13:29 +00:00
|
|
|
// Presets
|
|
|
|
fgSetDouble("/sim/presets/longitude-deg", 9999.0);
|
|
|
|
fgSetDouble("/sim/presets/latitude-deg", 9999.0);
|
|
|
|
fgSetDouble("/sim/presets/altitude-ft", -9999.0);
|
|
|
|
|
2007-10-04 17:14:37 +00:00
|
|
|
fgSetDouble("/sim/presets/heading-deg", 9999.0);
|
2007-10-04 21:52:50 +00:00
|
|
|
fgSetDouble("/sim/presets/roll-deg", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/pitch-deg", 0.424);
|
2002-11-15 21:13:29 +00:00
|
|
|
|
|
|
|
fgSetString("/sim/presets/speed-set", "knots");
|
|
|
|
fgSetDouble("/sim/presets/airspeed-kt", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/mach", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/uBody-fps", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/vBody-fps", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/wBody-fps", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/speed-north-fps", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/speed-east-fps", 0.0);
|
|
|
|
fgSetDouble("/sim/presets/speed-down-fps", 0.0);
|
|
|
|
|
|
|
|
fgSetBool("/sim/presets/onground", true);
|
|
|
|
fgSetBool("/sim/presets/trim", false);
|
|
|
|
|
2001-01-12 15:37:40 +00:00
|
|
|
// Miscellaneous
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetBool("/sim/startup/game-mode", false);
|
|
|
|
fgSetBool("/sim/startup/splash-screen", true);
|
|
|
|
fgSetBool("/sim/startup/intro-music", true);
|
2001-02-26 13:58:33 +00:00
|
|
|
// we want mouse-pointer to have an undefined value if nothing is
|
|
|
|
// specified so we can do the right thing for voodoo-1/2 cards.
|
|
|
|
// fgSetString("/sim/startup/mouse-pointer", "disabled");
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetString("/sim/control-mode", "joystick");
|
|
|
|
fgSetBool("/sim/auto-coordination", false);
|
2005-11-12 14:46:00 +00:00
|
|
|
#if defined(WIN32)
|
2001-07-08 23:30:17 +00:00
|
|
|
fgSetString("/sim/startup/browser-app", "webrun.bat");
|
2005-11-12 14:46:00 +00:00
|
|
|
#elif defined(__APPLE__)
|
|
|
|
fgSetString("/sim/startup/browser-app", "open");
|
2005-11-13 10:05:58 +00:00
|
|
|
#elif defined(sgi)
|
|
|
|
fgSetString("/sim/startup/browser-app", "launchWebJumper");
|
2005-11-12 14:46:00 +00:00
|
|
|
#else
|
2005-11-13 10:20:15 +00:00
|
|
|
envp = ::getenv( "WEBBROWSER" );
|
2005-11-13 10:05:58 +00:00
|
|
|
if (!envp) envp = "netscape";
|
|
|
|
fgSetString("/sim/startup/browser-app", envp);
|
2001-07-08 23:30:17 +00:00
|
|
|
#endif
|
2003-11-25 17:10:53 +00:00
|
|
|
fgSetString("/sim/logging/priority", "alert");
|
2003-03-22 10:38:15 +00:00
|
|
|
|
2001-01-12 15:37:40 +00:00
|
|
|
// Features
|
2006-06-10 07:23:15 +00:00
|
|
|
fgSetBool("/sim/hud/color/antialiased", false);
|
2003-07-14 13:57:11 +00:00
|
|
|
fgSetBool("/sim/hud/enable3d", true);
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetBool("/sim/hud/visibility", false);
|
|
|
|
fgSetBool("/sim/panel/visibility", true);
|
2004-05-14 15:50:28 +00:00
|
|
|
fgSetBool("/sim/sound/pause", false);
|
2001-01-12 15:37:40 +00:00
|
|
|
|
|
|
|
// Flight Model options
|
2001-07-24 01:02:59 +00:00
|
|
|
fgSetString("/sim/flight-model", "jsb");
|
2001-12-06 23:10:50 +00:00
|
|
|
fgSetString("/sim/aero", "c172");
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetInt("/sim/model-hz", NEW_DEFAULT_MODEL_HZ);
|
|
|
|
fgSetInt("/sim/speed-up", 1);
|
2001-01-12 15:37:40 +00:00
|
|
|
|
|
|
|
// Rendering options
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetString("/sim/rendering/fog", "nicest");
|
|
|
|
fgSetBool("/environment/clouds/status", true);
|
|
|
|
fgSetBool("/sim/startup/fullscreen", false);
|
|
|
|
fgSetBool("/sim/rendering/shading", true);
|
|
|
|
fgSetBool("/sim/rendering/skyblend", true);
|
|
|
|
fgSetBool("/sim/rendering/textures", true);
|
2007-06-08 06:50:38 +00:00
|
|
|
fgTie( "/sim/rendering/filtering", SGGetTextureFilter, SGSetTextureFilter, false);
|
2007-05-28 05:21:45 +00:00
|
|
|
fgSetInt("/sim/rendering/filtering", 1);
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetBool("/sim/rendering/wireframe", false);
|
2003-06-22 09:45:43 +00:00
|
|
|
fgSetBool("/sim/rendering/horizon-effect", false);
|
|
|
|
fgSetBool("/sim/rendering/enhanced-lighting", false);
|
2002-12-30 21:49:56 +00:00
|
|
|
fgSetBool("/sim/rendering/distance-attenuation", false);
|
2003-09-12 21:43:01 +00:00
|
|
|
fgSetBool("/sim/rendering/specular-highlight", true);
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetInt("/sim/startup/xsize", 800);
|
|
|
|
fgSetInt("/sim/startup/ysize", 600);
|
|
|
|
fgSetInt("/sim/rendering/bits-per-pixel", 16);
|
|
|
|
fgSetString("/sim/view-mode", "pilot");
|
2002-04-18 16:51:47 +00:00
|
|
|
fgSetDouble("/sim/current-view/heading-offset-deg", 0);
|
2001-01-12 15:37:40 +00:00
|
|
|
|
|
|
|
// HUD options
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetString("/sim/startup/units", "feet");
|
|
|
|
fgSetString("/sim/hud/frame-stat-type", "tris");
|
2001-01-12 15:37:40 +00:00
|
|
|
|
|
|
|
// Time options
|
2001-01-13 22:06:39 +00:00
|
|
|
fgSetInt("/sim/startup/time-offset", 0);
|
|
|
|
fgSetString("/sim/startup/time-offset-type", "system-offset");
|
2002-02-10 04:27:56 +00:00
|
|
|
fgSetLong("/sim/time/cur-time-override", 0);
|
1998-11-25 01:33:58 +00:00
|
|
|
|
2002-01-20 03:52:36 +00:00
|
|
|
// Freeze options
|
|
|
|
fgSetBool("/sim/freeze/master", false);
|
|
|
|
fgSetBool("/sim/freeze/position", false);
|
2002-02-13 02:37:44 +00:00
|
|
|
fgSetBool("/sim/freeze/clock", false);
|
2002-01-22 15:39:51 +00:00
|
|
|
fgSetBool("/sim/freeze/fuel", false);
|
2003-03-19 20:45:09 +00:00
|
|
|
|
|
|
|
fgSetString("/sim/multiplay/callsign", "callsign");
|
|
|
|
fgSetString("/sim/multiplay/rxhost", "0");
|
|
|
|
fgSetString("/sim/multiplay/txhost", "0");
|
|
|
|
fgSetInt("/sim/multiplay/rxport", 0);
|
|
|
|
fgSetInt("/sim/multiplay/txport", 0);
|
1998-05-13 18:29:56 +00:00
|
|
|
}
|
|
|
|
|
2002-06-09 21:28:17 +00:00
|
|
|
static bool
|
|
|
|
parse_wind (const string &wind, double * min_hdg, double * max_hdg,
|
|
|
|
double * speed, double * gust)
|
|
|
|
{
|
2002-07-02 20:45:02 +00:00
|
|
|
string::size_type pos = wind.find('@');
|
2002-06-09 21:28:17 +00:00
|
|
|
if (pos == string::npos)
|
|
|
|
return false;
|
|
|
|
string dir = wind.substr(0, pos);
|
|
|
|
string spd = wind.substr(pos+1);
|
|
|
|
pos = dir.find(':');
|
|
|
|
if (pos == string::npos) {
|
|
|
|
*min_hdg = *max_hdg = atof(dir.c_str());
|
|
|
|
} else {
|
|
|
|
*min_hdg = atof(dir.substr(0,pos).c_str());
|
|
|
|
*max_hdg = atof(dir.substr(pos+1).c_str());
|
|
|
|
}
|
|
|
|
pos = spd.find(':');
|
|
|
|
if (pos == string::npos) {
|
|
|
|
*speed = *gust = atof(spd.c_str());
|
|
|
|
} else {
|
|
|
|
*speed = atof(spd.substr(0,pos).c_str());
|
|
|
|
*gust = atof(spd.substr(pos+1).c_str());
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2001-03-17 21:06:43 +00:00
|
|
|
// parse a time string ([+/-]%f[:%f[:%f]]) into hours
|
2001-01-13 22:06:39 +00:00
|
|
|
static double
|
|
|
|
parse_time(const string& time_in) {
|
1998-08-27 17:01:55 +00:00
|
|
|
char *time_str, num[256];
|
1998-04-24 00:49:17 +00:00
|
|
|
double hours, minutes, seconds;
|
|
|
|
double result = 0.0;
|
|
|
|
int sign = 1;
|
|
|
|
int i;
|
|
|
|
|
1998-08-27 17:01:55 +00:00
|
|
|
time_str = (char *)time_in.c_str();
|
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
// printf("parse_time(): %s\n", time_str);
|
|
|
|
|
|
|
|
// check for sign
|
|
|
|
if ( strlen(time_str) ) {
|
|
|
|
if ( time_str[0] == '+' ) {
|
|
|
|
sign = 1;
|
|
|
|
time_str++;
|
|
|
|
} else if ( time_str[0] == '-' ) {
|
|
|
|
sign = -1;
|
|
|
|
time_str++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// printf("sign = %d\n", sign);
|
|
|
|
|
|
|
|
// get hours
|
|
|
|
if ( strlen(time_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
|
|
|
|
num[i] = time_str[0];
|
|
|
|
time_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( time_str[0] == ':' ) {
|
|
|
|
time_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
hours = atof(num);
|
|
|
|
// printf("hours = %.2lf\n", hours);
|
|
|
|
|
1998-07-30 23:48:24 +00:00
|
|
|
result += hours;
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// get minutes
|
|
|
|
if ( strlen(time_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
|
|
|
|
num[i] = time_str[0];
|
|
|
|
time_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( time_str[0] == ':' ) {
|
|
|
|
time_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
minutes = atof(num);
|
|
|
|
// printf("minutes = %.2lf\n", minutes);
|
|
|
|
|
1998-07-30 23:48:24 +00:00
|
|
|
result += minutes / 60.0;
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// get seconds
|
|
|
|
if ( strlen(time_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (time_str[0] != ':') && (time_str[0] != '\0') ) {
|
|
|
|
num[i] = time_str[0];
|
|
|
|
time_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
seconds = atof(num);
|
|
|
|
// printf("seconds = %.2lf\n", seconds);
|
|
|
|
|
1998-07-30 23:48:24 +00:00
|
|
|
result += seconds / 3600.0;
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
|
|
|
|
2003-03-20 10:43:02 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, " parse_time() = " << sign * result );
|
2002-11-16 20:17:11 +00:00
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
return(sign * result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-03-17 21:06:43 +00:00
|
|
|
// parse a date string (yyyy:mm:dd:hh:mm:ss) into a time_t (seconds)
|
2001-01-13 22:06:39 +00:00
|
|
|
static long int
|
|
|
|
parse_date( const string& date)
|
1999-04-11 13:19:29 +00:00
|
|
|
{
|
1999-05-12 02:07:21 +00:00
|
|
|
struct tm gmt;
|
|
|
|
char * date_str, num[256];
|
|
|
|
int i;
|
|
|
|
// initialize to zero
|
|
|
|
gmt.tm_sec = 0;
|
|
|
|
gmt.tm_min = 0;
|
|
|
|
gmt.tm_hour = 0;
|
|
|
|
gmt.tm_mday = 0;
|
|
|
|
gmt.tm_mon = 0;
|
|
|
|
gmt.tm_year = 0;
|
1999-09-07 23:09:43 +00:00
|
|
|
gmt.tm_isdst = 0; // ignore daylight savings time for the moment
|
1999-05-12 02:07:21 +00:00
|
|
|
date_str = (char *)date.c_str();
|
|
|
|
// get year
|
1999-04-11 13:19:29 +00:00
|
|
|
if ( strlen(date_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
|
|
|
|
num[i] = date_str[0];
|
|
|
|
date_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( date_str[0] == ':' ) {
|
|
|
|
date_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
gmt.tm_year = atoi(num) - 1900;
|
|
|
|
}
|
1999-05-12 02:07:21 +00:00
|
|
|
// get month
|
1999-04-11 13:19:29 +00:00
|
|
|
if ( strlen(date_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
|
|
|
|
num[i] = date_str[0];
|
|
|
|
date_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( date_str[0] == ':' ) {
|
|
|
|
date_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
gmt.tm_mon = atoi(num) -1;
|
|
|
|
}
|
|
|
|
// get day
|
|
|
|
if ( strlen(date_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
|
|
|
|
num[i] = date_str[0];
|
|
|
|
date_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( date_str[0] == ':' ) {
|
|
|
|
date_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
gmt.tm_mday = atoi(num);
|
|
|
|
}
|
|
|
|
// get hour
|
|
|
|
if ( strlen(date_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
|
|
|
|
num[i] = date_str[0];
|
|
|
|
date_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( date_str[0] == ':' ) {
|
|
|
|
date_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
gmt.tm_hour = atoi(num);
|
|
|
|
}
|
|
|
|
// get minute
|
|
|
|
if ( strlen(date_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
|
|
|
|
num[i] = date_str[0];
|
|
|
|
date_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( date_str[0] == ':' ) {
|
|
|
|
date_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
gmt.tm_min = atoi(num);
|
|
|
|
}
|
|
|
|
// get second
|
|
|
|
if ( strlen(date_str) ) {
|
|
|
|
i = 0;
|
|
|
|
while ( (date_str[0] != ':') && (date_str[0] != '\0') ) {
|
|
|
|
num[i] = date_str[0];
|
|
|
|
date_str++;
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
if ( date_str[0] == ':' ) {
|
|
|
|
date_str++;
|
|
|
|
}
|
|
|
|
num[i] = '\0';
|
|
|
|
gmt.tm_sec = atoi(num);
|
|
|
|
}
|
2000-07-07 23:56:43 +00:00
|
|
|
time_t theTime = sgTimeGetGMT( gmt.tm_year, gmt.tm_mon, gmt.tm_mday,
|
|
|
|
gmt.tm_hour, gmt.tm_min, gmt.tm_sec );
|
1999-04-11 13:19:29 +00:00
|
|
|
//printf ("Date is %s\n", ctime(&theTime));
|
|
|
|
//printf ("in seconds that is %d\n", theTime);
|
|
|
|
//exit(1);
|
|
|
|
return (theTime);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-03-17 21:06:43 +00:00
|
|
|
// parse angle in the form of [+/-]ddd:mm:ss into degrees
|
2001-01-13 22:06:39 +00:00
|
|
|
static double
|
|
|
|
parse_degree( const string& degree_str) {
|
1998-08-27 17:01:55 +00:00
|
|
|
double result = parse_time( degree_str );
|
1998-07-30 23:48:24 +00:00
|
|
|
|
|
|
|
// printf("Degree = %.4f\n", result);
|
|
|
|
|
|
|
|
return(result);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2001-03-17 21:06:43 +00:00
|
|
|
// parse time offset string into seconds
|
2001-01-13 22:06:39 +00:00
|
|
|
static int
|
|
|
|
parse_time_offset( const string& time_str) {
|
1998-04-24 00:49:17 +00:00
|
|
|
int result;
|
|
|
|
|
|
|
|
// printf("time offset = %s\n", time_str);
|
|
|
|
|
1998-04-26 05:01:19 +00:00
|
|
|
#ifdef HAVE_RINT
|
1998-07-30 23:48:24 +00:00
|
|
|
result = (int)rint(parse_time(time_str) * 3600.0);
|
1998-04-26 05:01:19 +00:00
|
|
|
#else
|
1998-07-30 23:48:24 +00:00
|
|
|
result = (int)(parse_time(time_str) * 3600.0);
|
1998-04-26 05:01:19 +00:00
|
|
|
#endif
|
1998-04-24 00:49:17 +00:00
|
|
|
|
1998-07-30 23:48:24 +00:00
|
|
|
// printf("parse_time_offset(): %d\n", result);
|
1998-04-24 00:49:17 +00:00
|
|
|
|
|
|
|
return( result );
|
1998-05-06 03:16:23 +00:00
|
|
|
}
|
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
|
1998-05-13 18:29:56 +00:00
|
|
|
// Parse --fov=x.xx type option
|
2001-01-13 22:06:39 +00:00
|
|
|
static double
|
|
|
|
parse_fov( const string& arg ) {
|
1998-08-27 17:01:55 +00:00
|
|
|
double fov = atof(arg);
|
1998-05-13 18:29:56 +00:00
|
|
|
|
|
|
|
if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
|
|
|
|
if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
|
|
|
|
|
2007-12-29 21:51:39 +00:00
|
|
|
fgSetDouble("/sim/view[0]/config/default-field-of-view-deg", fov);
|
2000-11-01 23:27:32 +00:00
|
|
|
|
1998-07-30 23:48:24 +00:00
|
|
|
// printf("parse_fov(): result = %.4f\n", fov);
|
1998-05-13 18:29:56 +00:00
|
|
|
|
2000-11-01 23:27:32 +00:00
|
|
|
return fov;
|
1998-05-13 18:29:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1999-11-19 02:10:24 +00:00
|
|
|
// Parse I/O channel option
|
1998-11-16 13:59:58 +00:00
|
|
|
//
|
1999-11-19 02:10:24 +00:00
|
|
|
// Format is "--protocol=medium,direction,hz,medium_options,..."
|
|
|
|
//
|
2009-01-20 17:30:53 +00:00
|
|
|
// protocol = { native, nmea, garmin, AV400, AV400Sim, fgfs, rul, pve, etc. }
|
1999-11-19 02:10:24 +00:00
|
|
|
// medium = { serial, socket, file, etc. }
|
|
|
|
// direction = { in, out, bi }
|
|
|
|
// hz = number of times to process channel per second (floating
|
|
|
|
// point values are ok.
|
|
|
|
//
|
|
|
|
// Serial example "--nmea=serial,dir,hz,device,baud" where
|
1998-11-16 13:59:58 +00:00
|
|
|
//
|
1999-11-19 02:10:24 +00:00
|
|
|
// device = OS device name of serial line to be open()'ed
|
1998-11-16 13:59:58 +00:00
|
|
|
// baud = {300, 1200, 2400, ..., 230400}
|
1999-11-19 02:10:24 +00:00
|
|
|
//
|
2000-07-14 00:50:56 +00:00
|
|
|
// Socket exacmple "--native=socket,dir,hz,machine,port,style" where
|
2003-03-19 20:45:09 +00:00
|
|
|
//
|
1999-11-20 15:40:15 +00:00
|
|
|
// machine = machine name or ip address if client (leave empty if server)
|
1999-11-19 02:10:24 +00:00
|
|
|
// port = port, leave empty to let system choose
|
2000-07-14 00:50:56 +00:00
|
|
|
// style = tcp or udp
|
1999-11-19 02:10:24 +00:00
|
|
|
//
|
|
|
|
// File example "--garmin=file,dir,hz,filename" where
|
2003-03-19 20:45:09 +00:00
|
|
|
//
|
1999-11-19 02:10:24 +00:00
|
|
|
// filename = file system file name
|
1998-11-25 01:33:58 +00:00
|
|
|
|
2003-03-19 20:45:09 +00:00
|
|
|
static bool
|
2001-08-21 21:13:55 +00:00
|
|
|
add_channel( const string& type, const string& channel_str ) {
|
2007-05-05 09:16:59 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Channel string = " << channel_str );
|
2001-01-26 00:21:36 +00:00
|
|
|
globals->get_channel_options_list()->push_back( type + "," + channel_str );
|
1998-11-16 13:59:58 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2006-04-27 10:35:03 +00:00
|
|
|
|
|
|
|
// The parse wp and parse flight-plan options don't work anymore, because
|
2004-04-15 22:09:46 +00:00
|
|
|
// the route manager and the airport subsystems have not yet been initialized
|
2006-04-27 10:35:03 +00:00
|
|
|
// at this stage.
|
1998-11-16 13:59:58 +00:00
|
|
|
|
2001-03-17 21:06:43 +00:00
|
|
|
// Parse --wp=ID[@alt]
|
2006-04-27 10:35:03 +00:00
|
|
|
static void
|
2001-01-13 22:06:39 +00:00
|
|
|
parse_wp( const string& arg ) {
|
2004-04-19 02:24:22 +00:00
|
|
|
string_list *waypoints = globals->get_initial_waypoints();
|
|
|
|
if (!waypoints) {
|
|
|
|
waypoints = new string_list;
|
2006-04-27 10:35:03 +00:00
|
|
|
globals->set_initial_waypoints(waypoints);
|
2004-04-19 02:24:22 +00:00
|
|
|
}
|
|
|
|
waypoints->push_back(arg);
|
2000-10-12 01:08:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2000-11-28 23:38:24 +00:00
|
|
|
// Parse --flight-plan=[file]
|
2006-04-27 10:35:03 +00:00
|
|
|
static bool
|
2001-01-13 22:06:39 +00:00
|
|
|
parse_flightplan(const string& arg)
|
2000-11-28 23:38:24 +00:00
|
|
|
{
|
2006-04-27 10:35:03 +00:00
|
|
|
string_list *waypoints = globals->get_initial_waypoints();
|
|
|
|
if (!waypoints) {
|
|
|
|
waypoints = new string_list;
|
|
|
|
globals->set_initial_waypoints(waypoints);
|
|
|
|
}
|
|
|
|
|
|
|
|
sg_gzifstream in(arg.c_str());
|
|
|
|
if ( !in.is_open() )
|
|
|
|
return false;
|
|
|
|
|
|
|
|
while ( true ) {
|
|
|
|
string line;
|
|
|
|
getline( in, line, '\n' );
|
2008-07-25 07:29:20 +00:00
|
|
|
|
2006-04-27 10:35:03 +00:00
|
|
|
// catch extraneous (DOS) line ending character
|
|
|
|
if ( line[line.length() - 1] < 32 )
|
|
|
|
line = line.substr( 0, line.length()-1 );
|
|
|
|
|
|
|
|
if ( in.eof() )
|
|
|
|
break;
|
|
|
|
|
|
|
|
waypoints->push_back(line);
|
2004-04-18 18:01:10 +00:00
|
|
|
}
|
2006-04-27 10:35:03 +00:00
|
|
|
return true;
|
2000-11-28 23:38:24 +00:00
|
|
|
}
|
|
|
|
|
2006-04-27 10:35:03 +00:00
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
static int
|
|
|
|
fgOptLanguage( const char *arg )
|
|
|
|
{
|
|
|
|
globals->set_locale( fgInitLocale( arg ) );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-02-21 02:46:44 +00:00
|
|
|
static void
|
|
|
|
clearLocation ()
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/airport-id", "");
|
|
|
|
fgSetString("/sim/presets/vor-id", "");
|
|
|
|
fgSetString("/sim/presets/ndb-id", "");
|
Mathias Frhlich:
I have introduced the posibility to start directly on the carrier.
With that patch you will have a --carrrier=id argument where id can either be
the pennant number configured in the nimitz scenario or the carriers name
also configured in the carriers scenario.
Additionaly you can use --parkpos=id to select different positions on the
carrier. They are also configured in the scenario file.
That includes the switch of the whole FGInterface class to make use of the
groundcache.
That means that an aircraft no longer uses the current elevation value from
the scenery class. It rather has its own local cache of the aircrafts
environment which is setup in the common_init method of FGInterface and
updated either manually by calling
FGInterface::get_groundlevel_m(lat, lon, alt_m);
or implicitly by calling the above method in the
FGInterface::_updateGeo*Position(lat, lon, alt);
methods.
A call get_groundlevel_m rebuilds the groundcache if the request is outside
the range of the cache.
Note that for the real usage of the groundcache including the correct
information about the movement of objects and the velocity information, you
still need to set up the groundcache in the usual way like YASim and JSBSim
currently does.
If you use the native interface, you will get only static objects correctly.
But for FDM's only using one single ground level for a whole step this is IMO
sufficient.
The AIManager gets a way to return the location of a object which is placed
wrt an AI Object. At the moment it only honours AICarriers for that.
That method is a static one, which loads the scenario file for that reason and
throws it away afterwards. This looked like the aprioriate way, because the
AIManager is initialized much later in flightgears bootstrap, and I did not
find an easy way to reorder that for my needs. Since this additional load is
very small and does only happen if such a relative location is required, I
think that this is ok.
Note that moving on the carrier will only work correctly for JSBSim and YASim,
but you should now be able to start and move on every not itself moving
object with any FDM.
2005-07-03 09:39:14 +00:00
|
|
|
fgSetString("/sim/presets/carrier", "");
|
|
|
|
fgSetString("/sim/presets/parkpos", "");
|
2003-02-21 02:46:44 +00:00
|
|
|
fgSetString("/sim/presets/fix", "");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptVOR( const char * arg )
|
|
|
|
{
|
|
|
|
clearLocation();
|
|
|
|
fgSetString("/sim/presets/vor-id", arg);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptNDB( const char * arg )
|
|
|
|
{
|
|
|
|
clearLocation();
|
|
|
|
fgSetString("/sim/presets/ndb-id", arg);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
Mathias Frhlich:
I have introduced the posibility to start directly on the carrier.
With that patch you will have a --carrrier=id argument where id can either be
the pennant number configured in the nimitz scenario or the carriers name
also configured in the carriers scenario.
Additionaly you can use --parkpos=id to select different positions on the
carrier. They are also configured in the scenario file.
That includes the switch of the whole FGInterface class to make use of the
groundcache.
That means that an aircraft no longer uses the current elevation value from
the scenery class. It rather has its own local cache of the aircrafts
environment which is setup in the common_init method of FGInterface and
updated either manually by calling
FGInterface::get_groundlevel_m(lat, lon, alt_m);
or implicitly by calling the above method in the
FGInterface::_updateGeo*Position(lat, lon, alt);
methods.
A call get_groundlevel_m rebuilds the groundcache if the request is outside
the range of the cache.
Note that for the real usage of the groundcache including the correct
information about the movement of objects and the velocity information, you
still need to set up the groundcache in the usual way like YASim and JSBSim
currently does.
If you use the native interface, you will get only static objects correctly.
But for FDM's only using one single ground level for a whole step this is IMO
sufficient.
The AIManager gets a way to return the location of a object which is placed
wrt an AI Object. At the moment it only honours AICarriers for that.
That method is a static one, which loads the scenario file for that reason and
throws it away afterwards. This looked like the aprioriate way, because the
AIManager is initialized much later in flightgears bootstrap, and I did not
find an easy way to reorder that for my needs. Since this additional load is
very small and does only happen if such a relative location is required, I
think that this is ok.
Note that moving on the carrier will only work correctly for JSBSim and YASim,
but you should now be able to start and move on every not itself moving
object with any FDM.
2005-07-03 09:39:14 +00:00
|
|
|
static int
|
|
|
|
fgOptCarrier( const char * arg )
|
|
|
|
{
|
|
|
|
clearLocation();
|
|
|
|
fgSetString("/sim/presets/carrier", arg);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptParkpos( const char * arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/parkpos", arg);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-02-21 02:46:44 +00:00
|
|
|
static int
|
|
|
|
fgOptFIX( const char * arg )
|
|
|
|
{
|
|
|
|
clearLocation();
|
|
|
|
fgSetString("/sim/presets/fix", arg);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
static int
|
|
|
|
fgOptLon( const char *arg )
|
|
|
|
{
|
2003-02-21 02:46:44 +00:00
|
|
|
clearLocation();
|
2003-01-19 23:02:51 +00:00
|
|
|
fgSetDouble("/sim/presets/longitude-deg", parse_degree( arg ));
|
|
|
|
fgSetDouble("/position/longitude-deg", parse_degree( arg ));
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptLat( const char *arg )
|
|
|
|
{
|
2003-02-21 02:46:44 +00:00
|
|
|
clearLocation();
|
2003-01-19 23:02:51 +00:00
|
|
|
fgSetDouble("/sim/presets/latitude-deg", parse_degree( arg ));
|
|
|
|
fgSetDouble("/position/latitude-deg", parse_degree( arg ));
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptAltitude( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetBool("/sim/presets/onground", false);
|
|
|
|
if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
|
|
|
|
fgSetDouble("/sim/presets/altitude-ft", atof( arg ));
|
|
|
|
else
|
|
|
|
fgSetDouble("/sim/presets/altitude-ft",
|
|
|
|
atof( arg ) * SG_METER_TO_FEET);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptUBody( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/speed-set", "UVW");
|
|
|
|
if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
|
|
|
|
fgSetDouble("/sim/presets/uBody-fps", atof( arg ));
|
|
|
|
else
|
|
|
|
fgSetDouble("/sim/presets/uBody-fps",
|
|
|
|
atof( arg ) * SG_METER_TO_FEET);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptVBody( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/speed-set", "UVW");
|
|
|
|
if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
|
|
|
|
fgSetDouble("/sim/presets/vBody-fps", atof( arg ));
|
|
|
|
else
|
|
|
|
fgSetDouble("/sim/presets/vBody-fps",
|
|
|
|
atof( arg ) * SG_METER_TO_FEET);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptWBody( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/speed-set", "UVW");
|
|
|
|
if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
|
|
|
|
fgSetDouble("/sim/presets/wBody-fps", atof(arg));
|
|
|
|
else
|
|
|
|
fgSetDouble("/sim/presets/wBody-fps",
|
|
|
|
atof(arg) * SG_METER_TO_FEET);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptVNorth( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/speed-set", "NED");
|
|
|
|
if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
|
|
|
|
fgSetDouble("/sim/presets/speed-north-fps", atof( arg ));
|
|
|
|
else
|
|
|
|
fgSetDouble("/sim/presets/speed-north-fps",
|
|
|
|
atof( arg ) * SG_METER_TO_FEET);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptVEast( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/speed-set", "NED");
|
|
|
|
if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
|
|
|
|
fgSetDouble("/sim/presets/speed-east-fps", atof(arg));
|
|
|
|
else
|
|
|
|
fgSetDouble("/sim/presets/speed-east-fps",
|
|
|
|
atof(arg) * SG_METER_TO_FEET);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptVDown( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/speed-set", "NED");
|
|
|
|
if ( !strcmp(fgGetString("/sim/startup/units"), "feet") )
|
|
|
|
fgSetDouble("/sim/presets/speed-down-fps", atof(arg));
|
|
|
|
else
|
|
|
|
fgSetDouble("/sim/presets/speed-down-fps",
|
|
|
|
atof(arg) * SG_METER_TO_FEET);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptVc( const char *arg )
|
|
|
|
{
|
|
|
|
// fgSetString("/sim/presets/speed-set", "knots");
|
|
|
|
// fgSetDouble("/velocities/airspeed-kt", atof(arg.substr(5)));
|
|
|
|
fgSetString("/sim/presets/speed-set", "knots");
|
|
|
|
fgSetDouble("/sim/presets/airspeed-kt", atof(arg));
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptMach( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/speed-set", "mach");
|
|
|
|
fgSetDouble("/sim/presets/mach", atof(arg));
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptRoc( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetDouble("/velocities/vertical-speed-fps", atof(arg)/60);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptFgRoot( const char *arg )
|
|
|
|
{
|
|
|
|
globals->set_fg_root(arg);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptFgScenery( const char *arg )
|
|
|
|
{
|
|
|
|
globals->set_fg_scenery(arg);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptFov( const char *arg )
|
|
|
|
{
|
|
|
|
parse_fov( arg );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptGeometry( const char *arg )
|
|
|
|
{
|
|
|
|
bool geometry_ok = true;
|
|
|
|
int xsize = 0, ysize = 0;
|
|
|
|
string geometry = arg;
|
|
|
|
string::size_type i = geometry.find('x');
|
|
|
|
|
|
|
|
if (i != string::npos) {
|
|
|
|
xsize = atoi(geometry.substr(0, i));
|
|
|
|
ysize = atoi(geometry.substr(i+1));
|
|
|
|
} else {
|
|
|
|
geometry_ok = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( xsize <= 0 || ysize <= 0 ) {
|
|
|
|
xsize = 640;
|
|
|
|
ysize = 480;
|
|
|
|
geometry_ok = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !geometry_ok ) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Unknown geometry: " << geometry );
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
|
|
|
"Setting geometry to " << xsize << 'x' << ysize << '\n');
|
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO,
|
|
|
|
"Setting geometry to " << xsize << 'x' << ysize << '\n');
|
|
|
|
fgSetInt("/sim/startup/xsize", xsize);
|
|
|
|
fgSetInt("/sim/startup/ysize", ysize);
|
|
|
|
}
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptBpp( const char *arg )
|
|
|
|
{
|
|
|
|
string bits_per_pix = arg;
|
|
|
|
if ( bits_per_pix == "16" ) {
|
|
|
|
fgSetInt("/sim/rendering/bits-per-pixel", 16);
|
|
|
|
} else if ( bits_per_pix == "24" ) {
|
|
|
|
fgSetInt("/sim/rendering/bits-per-pixel", 24);
|
|
|
|
} else if ( bits_per_pix == "32" ) {
|
|
|
|
fgSetInt("/sim/rendering/bits-per-pixel", 32);
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "Unsupported bpp " << bits_per_pix);
|
|
|
|
}
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptTimeOffset( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetInt("/sim/startup/time-offset",
|
|
|
|
parse_time_offset( arg ));
|
|
|
|
fgSetString("/sim/startup/time-offset-type", "system-offset");
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptStartDateSys( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetInt("/sim/startup/time-offset", parse_date( arg ) );
|
|
|
|
fgSetString("/sim/startup/time-offset-type", "system");
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptStartDateLat( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetInt("/sim/startup/time-offset", parse_date( arg ) );
|
|
|
|
fgSetString("/sim/startup/time-offset-type", "latitude");
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptStartDateGmt( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetInt("/sim/startup/time-offset", parse_date( arg ) );
|
|
|
|
fgSetString("/sim/startup/time-offset-type", "gmt");
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2004-02-26 12:57:38 +00:00
|
|
|
static int
|
|
|
|
fgSetupProxy( const char *arg )
|
|
|
|
{
|
|
|
|
string options = arg;
|
|
|
|
string host, port, auth;
|
2006-12-17 18:32:56 +00:00
|
|
|
string::size_type pos;
|
2004-02-26 12:57:38 +00:00
|
|
|
|
|
|
|
host = port = auth = "";
|
|
|
|
if ((pos = options.find("@")) != string::npos)
|
|
|
|
auth = options.substr(0, pos++);
|
|
|
|
else
|
|
|
|
pos = 0;
|
|
|
|
|
|
|
|
host = options.substr(pos, options.size());
|
|
|
|
if ((pos = host.find(":")) != string::npos) {
|
|
|
|
port = host.substr(++pos, host.size());
|
|
|
|
host.erase(--pos, host.size());
|
|
|
|
}
|
|
|
|
|
|
|
|
fgSetString("/sim/presets/proxy/host", host.c_str());
|
|
|
|
fgSetString("/sim/presets/proxy/port", port.c_str());
|
|
|
|
fgSetString("/sim/presets/proxy/authentication", auth.c_str());
|
|
|
|
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
static int
|
|
|
|
fgOptTraceRead( const char *arg )
|
|
|
|
{
|
|
|
|
string name = arg;
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Tracing reads for property " << name);
|
|
|
|
fgGetNode(name.c_str(), true)
|
|
|
|
->setAttribute(SGPropertyNode::TRACE_READ, true);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-09-22 09:22:05 +00:00
|
|
|
static int
|
|
|
|
fgOptLogLevel( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/logging/classes", "all");
|
|
|
|
fgSetString("/sim/logging/priority", arg);
|
2003-09-22 09:31:36 +00:00
|
|
|
|
|
|
|
string priority = arg;
|
2003-09-22 11:35:21 +00:00
|
|
|
logbuf::set_log_classes(SG_ALL);
|
2003-09-22 09:31:36 +00:00
|
|
|
if (priority == "bulk") {
|
|
|
|
logbuf::set_log_priority(SG_BULK);
|
|
|
|
} else if (priority == "debug") {
|
|
|
|
logbuf::set_log_priority(SG_DEBUG);
|
2003-11-25 17:10:53 +00:00
|
|
|
} else if (priority == "info") {
|
2003-09-22 09:31:36 +00:00
|
|
|
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);
|
|
|
|
}
|
2003-11-25 17:10:53 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_DEBUG, "Logging priority is " << priority);
|
2003-09-22 09:31:36 +00:00
|
|
|
|
2003-09-22 09:22:05 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
static int
|
|
|
|
fgOptTraceWrite( const char *arg )
|
|
|
|
{
|
|
|
|
string name = arg;
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Tracing writes for property " << name);
|
|
|
|
fgGetNode(name.c_str(), true)
|
|
|
|
->setAttribute(SGPropertyNode::TRACE_WRITE, true);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptViewOffset( const char *arg )
|
|
|
|
{
|
|
|
|
// $$$ begin - added VS Renganathan, 14 Oct 2K
|
|
|
|
// for multi-window outside window imagery
|
|
|
|
string woffset = arg;
|
|
|
|
double default_view_offset = 0.0;
|
|
|
|
if ( woffset == "LEFT" ) {
|
|
|
|
default_view_offset = SGD_PI * 0.25;
|
|
|
|
} else if ( woffset == "RIGHT" ) {
|
|
|
|
default_view_offset = SGD_PI * 1.75;
|
|
|
|
} else if ( woffset == "CENTER" ) {
|
|
|
|
default_view_offset = 0.00;
|
|
|
|
} else {
|
|
|
|
default_view_offset = atof( woffset.c_str() ) * SGD_DEGREES_TO_RADIANS;
|
|
|
|
}
|
|
|
|
/* apparently not used (CLO, 11 Jun 2002)
|
|
|
|
FGViewer *pilot_view =
|
|
|
|
(FGViewer *)globals->get_viewmgr()->get_view( 0 ); */
|
|
|
|
// this will work without calls to the viewer...
|
|
|
|
fgSetDouble( "/sim/current-view/heading-offset-deg",
|
|
|
|
default_view_offset * SGD_RADIANS_TO_DEGREES );
|
|
|
|
// $$$ end - added VS Renganathan, 14 Oct 2K
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-06-11 14:18:24 +00:00
|
|
|
static int
|
|
|
|
fgOptVisibilityMeters( const char *arg )
|
|
|
|
{
|
|
|
|
double visibility = atof( arg );
|
|
|
|
fgDefaultWeatherValue("visibility-m", visibility);
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
static int
|
|
|
|
fgOptVisibilityMiles( const char *arg )
|
|
|
|
{
|
|
|
|
double visibility = atof( arg ) * 5280.0 * SG_FEET_TO_METER;
|
2003-06-11 14:18:24 +00:00
|
|
|
fgDefaultWeatherValue("visibility-m", visibility);
|
2003-01-19 23:02:51 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptRandomWind( const char *arg )
|
|
|
|
{
|
|
|
|
double min_hdg = sg_random() * 360.0;
|
|
|
|
double max_hdg = min_hdg + (20 - sqrt(sg_random() * 400));
|
2003-09-24 00:04:28 +00:00
|
|
|
double speed = sg_random() * sg_random() * 40;
|
2003-01-19 23:02:51 +00:00
|
|
|
double gust = speed + (10 - sqrt(sg_random() * 100));
|
2004-02-21 14:04:40 +00:00
|
|
|
fgSetupWind(min_hdg, max_hdg, speed, gust);
|
2003-01-19 23:02:51 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptWind( const char *arg )
|
|
|
|
{
|
2009-08-24 16:03:49 +00:00
|
|
|
double min_hdg = 0.0, max_hdg = 0.0, speed = 0.0, gust = 0.0;
|
2003-01-19 23:02:51 +00:00
|
|
|
if (!parse_wind( arg, &min_hdg, &max_hdg, &speed, &gust)) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "bad wind value " << arg );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
2004-02-21 14:04:40 +00:00
|
|
|
fgSetupWind(min_hdg, max_hdg, speed, gust);
|
2003-01-19 23:02:51 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-06-11 14:18:24 +00:00
|
|
|
static int
|
2003-09-01 22:58:19 +00:00
|
|
|
fgOptTurbulence( const char *arg )
|
2003-06-11 14:18:24 +00:00
|
|
|
{
|
2003-07-13 20:13:18 +00:00
|
|
|
fgDefaultWeatherValue("turbulence/magnitude-norm", atof(arg));
|
2003-06-11 14:18:24 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-09-01 22:58:19 +00:00
|
|
|
static int
|
|
|
|
fgOptCeiling( const char *arg )
|
|
|
|
{
|
|
|
|
double elevation, thickness;
|
|
|
|
string spec = arg;
|
|
|
|
string::size_type pos = spec.find(':');
|
|
|
|
if (pos == string::npos) {
|
|
|
|
elevation = atof(spec.c_str());
|
|
|
|
thickness = 2000;
|
|
|
|
} else {
|
|
|
|
elevation = atof(spec.substr(0, pos).c_str());
|
|
|
|
thickness = atof(spec.substr(pos + 1).c_str());
|
|
|
|
}
|
|
|
|
fgSetDouble("/environment/clouds/layer[0]/elevation-ft", elevation);
|
|
|
|
fgSetDouble("/environment/clouds/layer[0]/thickness-ft", thickness);
|
|
|
|
fgSetString("/environment/clouds/layer[0]/coverage", "overcast");
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
static int
|
|
|
|
fgOptWp( const char *arg )
|
|
|
|
{
|
|
|
|
parse_wp( arg );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptFlightPlan( const char *arg )
|
|
|
|
{
|
|
|
|
parse_flightplan ( arg );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptConfig( const char *arg )
|
|
|
|
{
|
|
|
|
string file = arg;
|
|
|
|
try {
|
|
|
|
readProperties(file, globals->get_props());
|
|
|
|
} catch (const sg_exception &e) {
|
|
|
|
string message = "Error loading config file: ";
|
2005-12-11 13:37:06 +00:00
|
|
|
message += e.getFormattedMessage() + e.getOrigin();
|
2003-01-19 23:02:51 +00:00
|
|
|
SG_LOG(SG_INPUT, SG_ALERT, message);
|
|
|
|
exit(2);
|
|
|
|
}
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2003-07-16 23:34:07 +00:00
|
|
|
static bool
|
|
|
|
parse_colon (const string &s, double * val1, double * val2)
|
|
|
|
{
|
|
|
|
string::size_type pos = s.find(':');
|
|
|
|
if (pos == string::npos) {
|
|
|
|
*val2 = atof(s);
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
*val1 = atof(s.substr(0, pos).c_str());
|
|
|
|
*val2 = atof(s.substr(pos+1).c_str());
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-09-10 01:29:19 +00:00
|
|
|
static int
|
|
|
|
fgOptFailure( const char * arg )
|
|
|
|
{
|
|
|
|
string a = arg;
|
|
|
|
if (a == "pitot") {
|
|
|
|
fgSetBool("/systems/pitot/serviceable", false);
|
|
|
|
} else if (a == "static") {
|
|
|
|
fgSetBool("/systems/static/serviceable", false);
|
|
|
|
} else if (a == "vacuum") {
|
|
|
|
fgSetBool("/systems/vacuum/serviceable", false);
|
|
|
|
} else if (a == "electrical") {
|
|
|
|
fgSetBool("/systems/electrical/serviceable", false);
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_INPUT, SG_ALERT, "Unknown failure mode: " << a);
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-07-16 23:34:07 +00:00
|
|
|
static int
|
|
|
|
fgOptNAV1( const char * arg )
|
|
|
|
{
|
|
|
|
double radial, freq;
|
|
|
|
if (parse_colon(arg, &radial, &freq))
|
2004-12-04 21:06:57 +00:00
|
|
|
fgSetDouble("/instrumentation/nav[0]/radials/selected-deg", radial);
|
|
|
|
fgSetDouble("/instrumentation/nav[0]/frequencies/selected-mhz", freq);
|
2003-07-16 23:34:07 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptNAV2( const char * arg )
|
|
|
|
{
|
|
|
|
double radial, freq;
|
|
|
|
if (parse_colon(arg, &radial, &freq))
|
2004-12-04 21:06:57 +00:00
|
|
|
fgSetDouble("/instrumentation/nav[1]/radials/selected-deg", radial);
|
|
|
|
fgSetDouble("/instrumentation/nav[1]/frequencies/selected-mhz", freq);
|
2003-07-16 23:34:07 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptADF( const char * arg )
|
|
|
|
{
|
|
|
|
double rot, freq;
|
|
|
|
if (parse_colon(arg, &rot, &freq))
|
2003-11-25 17:10:53 +00:00
|
|
|
fgSetDouble("/instrumentation/adf/rotation-deg", rot);
|
|
|
|
fgSetDouble("/instrumentation/adf/frequencies/selected-khz", freq);
|
2003-07-16 23:34:07 +00:00
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
fgOptDME( const char *arg )
|
|
|
|
{
|
|
|
|
string opt = arg;
|
|
|
|
if (opt == "nav1") {
|
|
|
|
fgSetInt("/instrumentation/dme/switch-position", 1);
|
|
|
|
fgSetString("/instrumentation/dme/frequencies/source",
|
2004-12-04 21:06:57 +00:00
|
|
|
"/instrumentation/nav[0]/frequencies/selected-mhz");
|
2003-07-16 23:34:07 +00:00
|
|
|
} else if (opt == "nav2") {
|
|
|
|
fgSetInt("/instrumentation/dme/switch-position", 3);
|
|
|
|
fgSetString("/instrumentation/dme/frequencies/source",
|
2004-12-04 21:06:57 +00:00
|
|
|
"/instrumentation/nav[1]/frequencies/selected-mhz");
|
2003-07-16 23:34:07 +00:00
|
|
|
} else {
|
|
|
|
fgSetInt("/instrumentation/dme/switch-position", 2);
|
|
|
|
fgSetString("/instrumentation/dme/frequencies/source",
|
|
|
|
"/instrumentation/dme/frequencies/selected-mhz");
|
|
|
|
fgSetString("/instrumentation/dme/frequencies/selected-mhz", arg);
|
|
|
|
}
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2005-10-08 11:55:18 +00:00
|
|
|
static int
|
|
|
|
fgOptLivery( const char *arg )
|
|
|
|
{
|
|
|
|
string opt = arg;
|
|
|
|
string livery_path = "livery/" + opt;
|
|
|
|
fgSetString("/sim/model/texture-path", livery_path.c_str() );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2006-05-20 12:19:33 +00:00
|
|
|
static int
|
|
|
|
fgOptScenario( const char *arg )
|
|
|
|
{
|
2006-05-20 13:29:31 +00:00
|
|
|
SGPropertyNode_ptr ai_node = fgGetNode( "/sim/ai", true );
|
2006-05-20 12:19:33 +00:00
|
|
|
vector<SGPropertyNode_ptr> scenarii = ai_node->getChildren( "scenario" );
|
|
|
|
int index = -1;
|
|
|
|
for ( size_t i = 0; i < scenarii.size(); ++i ) {
|
|
|
|
int ind = scenarii[i]->getIndex();
|
|
|
|
if ( index < ind ) {
|
|
|
|
index = ind;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
SGPropertyNode_ptr scenario = ai_node->getNode( "scenario", index + 1, true );
|
|
|
|
scenario->setStringValue( arg );
|
|
|
|
ai_node->setBoolValue( "enabled", true );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2006-05-31 07:20:10 +00:00
|
|
|
static int
|
|
|
|
fgOptRunway( const char *arg )
|
|
|
|
{
|
|
|
|
fgSetString("/sim/presets/runway", arg );
|
|
|
|
fgSetBool("/sim/presets/runway-requested", true );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2008-02-04 20:03:52 +00:00
|
|
|
static int
|
|
|
|
fgOptParking( const char *arg )
|
|
|
|
{
|
|
|
|
cerr << "Processing argument " << arg << endl;
|
|
|
|
fgSetString("/sim/presets/parking", arg );
|
|
|
|
fgSetBool ("/sim/presets/parking-requested", true );
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
2008-03-15 12:10:44 +00:00
|
|
|
static int
|
|
|
|
fgOptVersion( const char *arg )
|
|
|
|
{
|
|
|
|
cerr << VERSION << endl;
|
|
|
|
cerr << "FG_ROOT=" << globals->get_fg_root() << endl;
|
|
|
|
cerr << "FG_HOME=" << fgGetString("/sim/fg-home") << endl;
|
|
|
|
return FG_OPTIONS_EXIT;
|
|
|
|
}
|
2008-02-04 20:03:52 +00:00
|
|
|
|
2009-05-19 22:14:35 +00:00
|
|
|
static int
|
|
|
|
fgOptFpe(const char* arg)
|
|
|
|
{
|
|
|
|
// Actually handled in bootstrap.cxx
|
2009-05-21 14:49:57 +00:00
|
|
|
return FG_OPTIONS_OK;
|
2009-05-19 22:14:35 +00:00
|
|
|
}
|
|
|
|
|
2009-08-10 21:43:55 +00:00
|
|
|
static int
|
|
|
|
fgOptFgviewer(const char* arg)
|
|
|
|
{
|
|
|
|
// Actually handled in bootstrap.cxx
|
|
|
|
return FG_OPTIONS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
static map<string,size_t> fgOptionMap;
|
|
|
|
|
2003-03-22 14:52:15 +00:00
|
|
|
/*
|
|
|
|
option has_param type property b_param s_param func
|
|
|
|
|
|
|
|
where:
|
|
|
|
option : name of the option
|
|
|
|
has_param : option is --name=value if true or --name if false
|
|
|
|
type : OPTION_BOOL - property is a boolean
|
|
|
|
OPTION_STRING - property is a string
|
|
|
|
OPTION_DOUBLE - property is a double
|
|
|
|
OPTION_INT - property is an integer
|
|
|
|
OPTION_CHANNEL - name of option is the name of a channel
|
|
|
|
OPTION_FUNC - the option trigger a function
|
|
|
|
b_param : if type==OPTION_BOOL,
|
|
|
|
value set to the property (has_param is false for boolean)
|
|
|
|
s_param : if type==OPTION_STRING,
|
|
|
|
value set to the property if has_param is false
|
|
|
|
func : function called if type==OPTION_FUNC. if has_param is true,
|
|
|
|
the value is passed to the function as a string, otherwise,
|
2008-12-18 13:08:44 +00:00
|
|
|
s_param is passed.
|
2003-03-22 14:52:15 +00:00
|
|
|
|
|
|
|
For OPTION_DOUBLE and OPTION_INT, the parameter value is converted into a
|
|
|
|
double or an integer and set to the property.
|
|
|
|
|
|
|
|
For OPTION_CHANNEL, add_channel is called with the parameter value as the
|
|
|
|
argument.
|
|
|
|
*/
|
|
|
|
|
2003-01-19 23:02:51 +00:00
|
|
|
enum OptionType { OPTION_BOOL, OPTION_STRING, OPTION_DOUBLE, OPTION_INT, OPTION_CHANNEL, OPTION_FUNC };
|
|
|
|
struct OptionDesc {
|
2008-08-01 15:57:29 +00:00
|
|
|
const char *option;
|
2003-01-19 23:02:51 +00:00
|
|
|
bool has_param;
|
|
|
|
enum OptionType type;
|
2008-08-01 15:57:29 +00:00
|
|
|
const char *property;
|
2003-01-19 23:02:51 +00:00
|
|
|
bool b_param;
|
2008-08-01 15:57:29 +00:00
|
|
|
const char *s_param;
|
2003-01-19 23:02:51 +00:00
|
|
|
int (*func)( const char * );
|
|
|
|
} fgOptionArray[] = {
|
|
|
|
|
|
|
|
{"language", true, OPTION_FUNC, "", false, "", fgOptLanguage },
|
|
|
|
{"disable-game-mode", false, OPTION_BOOL, "/sim/startup/game-mode", false, "", 0 },
|
|
|
|
{"enable-game-mode", false, OPTION_BOOL, "/sim/startup/game-mode", true, "", 0 },
|
|
|
|
{"disable-splash-screen", false, OPTION_BOOL, "/sim/startup/splash-screen", false, "", 0 },
|
|
|
|
{"enable-splash-screen", false, OPTION_BOOL, "/sim/startup/splash-screen", true, "", 0 },
|
|
|
|
{"disable-intro-music", false, OPTION_BOOL, "/sim/startup/intro-music", false, "", 0 },
|
|
|
|
{"enable-intro-music", false, OPTION_BOOL, "/sim/startup/intro-music", true, "", 0 },
|
|
|
|
{"disable-mouse-pointer", false, OPTION_STRING, "/sim/startup/mouse-pointer", false, "disabled", 0 },
|
|
|
|
{"enable-mouse-pointer", false, OPTION_STRING, "/sim/startup/mouse-pointer", false, "enabled", 0 },
|
|
|
|
{"disable-random-objects", false, OPTION_BOOL, "/sim/rendering/random-objects", false, "", 0 },
|
|
|
|
{"enable-random-objects", false, OPTION_BOOL, "/sim/rendering/random-objects", true, "", 0 },
|
2009-05-29 10:26:35 +00:00
|
|
|
{"disable-real-weather-fetch", false, OPTION_BOOL, "/environment/params/real-world-weather-fetch", false, "", 0 },
|
|
|
|
{"enable-real-weather-fetch", false, OPTION_BOOL, "/environment/params/real-world-weather-fetch", true, "", 0 },
|
|
|
|
{"metar", true, OPTION_STRING, "/environment/metar/data", false, "", 0 },
|
2004-05-19 13:55:49 +00:00
|
|
|
{"disable-ai-models", false, OPTION_BOOL, "/sim/ai/enabled", false, "", 0 },
|
|
|
|
{"enable-ai-models", false, OPTION_BOOL, "/sim/ai/enabled", true, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"disable-freeze", false, OPTION_BOOL, "/sim/freeze/master", false, "", 0 },
|
|
|
|
{"enable-freeze", false, OPTION_BOOL, "/sim/freeze/master", true, "", 0 },
|
|
|
|
{"disable-fuel-freeze", false, OPTION_BOOL, "/sim/freeze/fuel", false, "", 0 },
|
|
|
|
{"enable-fuel-freeze", false, OPTION_BOOL, "/sim/freeze/fuel", true, "", 0 },
|
|
|
|
{"disable-clock-freeze", false, OPTION_BOOL, "/sim/freeze/clock", false, "", 0 },
|
|
|
|
{"enable-clock-freeze", false, OPTION_BOOL, "/sim/freeze/clock", true, "", 0 },
|
2003-07-14 13:57:11 +00:00
|
|
|
{"disable-hud-3d", false, OPTION_BOOL, "/sim/hud/enable3d", false, "", 0 },
|
|
|
|
{"enable-hud-3d", false, OPTION_BOOL, "/sim/hud/enable3d", true, "", 0 },
|
2006-06-10 07:23:15 +00:00
|
|
|
{"disable-anti-alias-hud", false, OPTION_BOOL, "/sim/hud/color/antialiased", false, "", 0 },
|
|
|
|
{"enable-anti-alias-hud", false, OPTION_BOOL, "/sim/hud/color/antialiased", true, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"control", true, OPTION_STRING, "/sim/control-mode", false, "", 0 },
|
|
|
|
{"disable-auto-coordination", false, OPTION_BOOL, "/sim/auto-coordination", false, "", 0 },
|
|
|
|
{"enable-auto-coordination", false, OPTION_BOOL, "/sim/auto-coordination", true, "", 0 },
|
|
|
|
{"browser-app", true, OPTION_STRING, "/sim/startup/browser-app", false, "", 0 },
|
|
|
|
{"disable-hud", false, OPTION_BOOL, "/sim/hud/visibility", false, "", 0 },
|
|
|
|
{"enable-hud", false, OPTION_BOOL, "/sim/hud/visibility", true, "", 0 },
|
|
|
|
{"disable-panel", false, OPTION_BOOL, "/sim/panel/visibility", false, "", 0 },
|
|
|
|
{"enable-panel", false, OPTION_BOOL, "/sim/panel/visibility", true, "", 0 },
|
2004-05-14 15:50:28 +00:00
|
|
|
{"disable-sound", false, OPTION_BOOL, "/sim/sound/pause", true, "", 0 },
|
|
|
|
{"enable-sound", false, OPTION_BOOL, "/sim/sound/pause", false, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"airport", true, OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
|
2006-05-31 07:20:10 +00:00
|
|
|
{"runway", true, OPTION_FUNC, "", false, "", fgOptRunway },
|
2003-02-21 02:46:44 +00:00
|
|
|
{"vor", true, OPTION_FUNC, "", false, "", fgOptVOR },
|
|
|
|
{"ndb", true, OPTION_FUNC, "", false, "", fgOptNDB },
|
Mathias Frhlich:
I have introduced the posibility to start directly on the carrier.
With that patch you will have a --carrrier=id argument where id can either be
the pennant number configured in the nimitz scenario or the carriers name
also configured in the carriers scenario.
Additionaly you can use --parkpos=id to select different positions on the
carrier. They are also configured in the scenario file.
That includes the switch of the whole FGInterface class to make use of the
groundcache.
That means that an aircraft no longer uses the current elevation value from
the scenery class. It rather has its own local cache of the aircrafts
environment which is setup in the common_init method of FGInterface and
updated either manually by calling
FGInterface::get_groundlevel_m(lat, lon, alt_m);
or implicitly by calling the above method in the
FGInterface::_updateGeo*Position(lat, lon, alt);
methods.
A call get_groundlevel_m rebuilds the groundcache if the request is outside
the range of the cache.
Note that for the real usage of the groundcache including the correct
information about the movement of objects and the velocity information, you
still need to set up the groundcache in the usual way like YASim and JSBSim
currently does.
If you use the native interface, you will get only static objects correctly.
But for FDM's only using one single ground level for a whole step this is IMO
sufficient.
The AIManager gets a way to return the location of a object which is placed
wrt an AI Object. At the moment it only honours AICarriers for that.
That method is a static one, which loads the scenario file for that reason and
throws it away afterwards. This looked like the aprioriate way, because the
AIManager is initialized much later in flightgears bootstrap, and I did not
find an easy way to reorder that for my needs. Since this additional load is
very small and does only happen if such a relative location is required, I
think that this is ok.
Note that moving on the carrier will only work correctly for JSBSim and YASim,
but you should now be able to start and move on every not itself moving
object with any FDM.
2005-07-03 09:39:14 +00:00
|
|
|
{"carrier", true, OPTION_FUNC, "", false, "", fgOptCarrier },
|
|
|
|
{"parkpos", true, OPTION_FUNC, "", false, "", fgOptParkpos },
|
2003-02-21 02:46:44 +00:00
|
|
|
{"fix", true, OPTION_FUNC, "", false, "", fgOptFIX },
|
2008-05-01 21:14:02 +00:00
|
|
|
{"offset-distance", true, OPTION_DOUBLE, "/sim/presets/offset-distance-nm", false, "", 0 },
|
|
|
|
{"offset-azimuth", true, OPTION_DOUBLE, "/sim/presets/offset-azimuth-deg", false, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"lon", true, OPTION_FUNC, "", false, "", fgOptLon },
|
|
|
|
{"lat", true, OPTION_FUNC, "", false, "", fgOptLat },
|
|
|
|
{"altitude", true, OPTION_FUNC, "", false, "", fgOptAltitude },
|
|
|
|
{"uBody", true, OPTION_FUNC, "", false, "", fgOptUBody },
|
|
|
|
{"vBody", true, OPTION_FUNC, "", false, "", fgOptVBody },
|
|
|
|
{"wBody", true, OPTION_FUNC, "", false, "", fgOptWBody },
|
|
|
|
{"vNorth", true, OPTION_FUNC, "", false, "", fgOptVNorth },
|
|
|
|
{"vEast", true, OPTION_FUNC, "", false, "", fgOptVEast },
|
|
|
|
{"vDown", true, OPTION_FUNC, "", false, "", fgOptVDown },
|
|
|
|
{"vc", true, OPTION_FUNC, "", false, "", fgOptVc },
|
|
|
|
{"mach", true, OPTION_FUNC, "", false, "", fgOptMach },
|
|
|
|
{"heading", true, OPTION_DOUBLE, "/sim/presets/heading-deg", false, "", 0 },
|
|
|
|
{"roll", true, OPTION_DOUBLE, "/sim/presets/roll-deg", false, "", 0 },
|
|
|
|
{"pitch", true, OPTION_DOUBLE, "/sim/presets/pitch-deg", false, "", 0 },
|
|
|
|
{"glideslope", true, OPTION_DOUBLE, "/sim/presets/glideslope-deg", false, "", 0 },
|
|
|
|
{"roc", true, OPTION_FUNC, "", false, "", fgOptRoc },
|
|
|
|
{"fg-root", true, OPTION_FUNC, "", false, "", fgOptFgRoot },
|
|
|
|
{"fg-scenery", true, OPTION_FUNC, "", false, "", fgOptFgScenery },
|
|
|
|
{"fdm", true, OPTION_STRING, "/sim/flight-model", false, "", 0 },
|
|
|
|
{"aero", true, OPTION_STRING, "/sim/aero", false, "", 0 },
|
|
|
|
{"aircraft-dir", true, OPTION_STRING, "/sim/aircraft-dir", false, "", 0 },
|
|
|
|
{"model-hz", true, OPTION_INT, "/sim/model-hz", false, "", 0 },
|
|
|
|
{"speed", true, OPTION_INT, "/sim/speed-up", false, "", 0 },
|
|
|
|
{"trim", false, OPTION_BOOL, "/sim/presets/trim", true, "", 0 },
|
|
|
|
{"notrim", false, OPTION_BOOL, "/sim/presets/trim", false, "", 0 },
|
|
|
|
{"on-ground", false, OPTION_BOOL, "/sim/presets/onground", true, "", 0 },
|
|
|
|
{"in-air", false, OPTION_BOOL, "/sim/presets/onground", false, "", 0 },
|
|
|
|
{"fog-disable", false, OPTION_STRING, "/sim/rendering/fog", false, "disabled", 0 },
|
|
|
|
{"fog-fastest", false, OPTION_STRING, "/sim/rendering/fog", false, "fastest", 0 },
|
2003-06-22 09:45:43 +00:00
|
|
|
{"fog-nicest", false, OPTION_STRING, "/sim/rendering/fog", false, "nicest", 0 },
|
|
|
|
{"disable-horizon-effect", false, OPTION_BOOL, "/sim/rendering/horizon-effect", false, "", 0 },
|
|
|
|
{"enable-horizon-effect", false, OPTION_BOOL, "/sim/rendering/horizon-effect", true, "", 0 },
|
|
|
|
{"disable-enhanced-lighting", false, OPTION_BOOL, "/sim/rendering/enhanced-lighting", false, "", 0 },
|
|
|
|
{"enable-enhanced-lighting", false, OPTION_BOOL, "/sim/rendering/enhanced-lighting", true, "", 0 },
|
|
|
|
{"disable-distance-attenuation", false, OPTION_BOOL, "/sim/rendering/distance-attenuation", false, "", 0 },
|
|
|
|
{"enable-distance-attenuation", false, OPTION_BOOL, "/sim/rendering/distance-attenuation", true, "", 0 },
|
2003-09-12 21:43:01 +00:00
|
|
|
{"disable-specular-highlight", false, OPTION_BOOL, "/sim/rendering/specular-highlight", false, "", 0 },
|
|
|
|
{"enable-specular-highlight", false, OPTION_BOOL, "/sim/rendering/specular-highlight", true, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"disable-clouds", false, OPTION_BOOL, "/environment/clouds/status", false, "", 0 },
|
|
|
|
{"enable-clouds", false, OPTION_BOOL, "/environment/clouds/status", true, "", 0 },
|
2005-06-25 11:21:18 +00:00
|
|
|
{"disable-clouds3d", false, OPTION_BOOL, "/sim/rendering/clouds3d-enable", false, "", 0 },
|
|
|
|
{"enable-clouds3d", false, OPTION_BOOL, "/sim/rendering/clouds3d-enable", true, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"fov", true, OPTION_FUNC, "", false, "", fgOptFov },
|
2005-02-25 21:20:17 +00:00
|
|
|
{"aspect-ratio-multiplier", true, OPTION_DOUBLE, "/sim/current-view/aspect-ratio-multiplier", false, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"disable-fullscreen", false, OPTION_BOOL, "/sim/startup/fullscreen", false, "", 0 },
|
|
|
|
{"enable-fullscreen", false, OPTION_BOOL, "/sim/startup/fullscreen", true, "", 0 },
|
2005-12-22 13:51:11 +00:00
|
|
|
{"disable-save-on-exit", false, OPTION_BOOL, "/sim/startup/save-on-exit", false, "", 0 },
|
|
|
|
{"enable-save-on-exit", false, OPTION_BOOL, "/sim/startup/save-on-exit", true, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"shading-flat", false, OPTION_BOOL, "/sim/rendering/shading", false, "", 0 },
|
|
|
|
{"shading-smooth", false, OPTION_BOOL, "/sim/rendering/shading", true, "", 0 },
|
|
|
|
{"disable-skyblend", false, OPTION_BOOL, "/sim/rendering/skyblend", false, "", 0 },
|
|
|
|
{"enable-skyblend", false, OPTION_BOOL, "/sim/rendering/skyblend", true, "", 0 },
|
|
|
|
{"disable-textures", false, OPTION_BOOL, "/sim/rendering/textures", false, "", 0 },
|
|
|
|
{"enable-textures", false, OPTION_BOOL, "/sim/rendering/textures", true, "", 0 },
|
2007-05-28 05:21:45 +00:00
|
|
|
{"texture-filtering", false, OPTION_INT, "/sim/rendering/filtering", 1, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"disable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", false, "", 0 },
|
|
|
|
{"enable-wireframe", false, OPTION_BOOL, "/sim/rendering/wireframe", true, "", 0 },
|
|
|
|
{"geometry", true, OPTION_FUNC, "", false, "", fgOptGeometry },
|
|
|
|
{"bpp", true, OPTION_FUNC, "", false, "", fgOptBpp },
|
|
|
|
{"units-feet", false, OPTION_STRING, "/sim/startup/units", false, "feet", 0 },
|
|
|
|
{"units-meters", false, OPTION_STRING, "/sim/startup/units", false, "meters", 0 },
|
2003-09-15 22:55:39 +00:00
|
|
|
{"timeofday", true, OPTION_STRING, "/sim/startup/time-offset-type", false, "noon", 0 },
|
2005-12-22 13:51:11 +00:00
|
|
|
{"season", true, OPTION_STRING, "/sim/startup/season", false, "summer", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"time-offset", true, OPTION_FUNC, "", false, "", fgOptTimeOffset },
|
|
|
|
{"time-match-real", false, OPTION_STRING, "/sim/startup/time-offset-type", false, "system-offset", 0 },
|
|
|
|
{"time-match-local", false, OPTION_STRING, "/sim/startup/time-offset-type", false, "latitude-offset", 0 },
|
|
|
|
{"start-date-sys", true, OPTION_FUNC, "", false, "", fgOptStartDateSys },
|
|
|
|
{"start-date-lat", true, OPTION_FUNC, "", false, "", fgOptStartDateLat },
|
|
|
|
{"start-date-gmt", true, OPTION_FUNC, "", false, "", fgOptStartDateGmt },
|
|
|
|
{"hud-tris", false, OPTION_STRING, "/sim/hud/frame-stat-type", false, "tris", 0 },
|
|
|
|
{"hud-culled", false, OPTION_STRING, "/sim/hud/frame-stat-type", false, "culled", 0 },
|
2004-11-16 19:47:11 +00:00
|
|
|
{"atcsim", true, OPTION_CHANNEL, "", false, "dummy", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"atlas", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"httpd", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
#ifdef FG_JPEG_SERVER
|
|
|
|
{"jpg-httpd", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
#endif
|
|
|
|
{"native", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"native-ctrls", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"native-fdm", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"native-gui", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"opengc", true, OPTION_CHANNEL, "", false, "", 0 },
|
2006-08-20 23:37:13 +00:00
|
|
|
{"AV400", true, OPTION_CHANNEL, "", false, "", 0 },
|
2009-01-20 17:30:53 +00:00
|
|
|
{"AV400Sim", true, OPTION_CHANNEL, "", false, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"garmin", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"nmea", true, OPTION_CHANNEL, "", false, "", 0 },
|
2003-03-25 18:47:30 +00:00
|
|
|
{"generic", true, OPTION_CHANNEL, "", false, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"props", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"telnet", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"pve", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"ray", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"rul", true, OPTION_CHANNEL, "", false, "", 0 },
|
|
|
|
{"joyclient", true, OPTION_CHANNEL, "", false, "", 0 },
|
2003-11-12 10:06:18 +00:00
|
|
|
{"jsclient", true, OPTION_CHANNEL, "", false, "", 0 },
|
2004-02-26 12:57:38 +00:00
|
|
|
{"proxy", true, OPTION_FUNC, "", false, "", fgSetupProxy },
|
2003-03-22 15:43:24 +00:00
|
|
|
{"callsign", true, OPTION_STRING, "sim/multiplay/callsign", false, "", 0 },
|
2003-03-22 14:52:15 +00:00
|
|
|
{"multiplay", true, OPTION_CHANNEL, "", false, "", 0 },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"trace-read", true, OPTION_FUNC, "", false, "", fgOptTraceRead },
|
|
|
|
{"trace-write", true, OPTION_FUNC, "", false, "", fgOptTraceWrite },
|
2003-09-22 09:22:05 +00:00
|
|
|
{"log-level", true, OPTION_FUNC, "", false, "", fgOptLogLevel },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"view-offset", true, OPTION_FUNC, "", false, "", fgOptViewOffset },
|
2003-06-11 14:18:24 +00:00
|
|
|
{"visibility", true, OPTION_FUNC, "", false, "", fgOptVisibilityMeters },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"visibility-miles", true, OPTION_FUNC, "", false, "", fgOptVisibilityMiles },
|
|
|
|
{"random-wind", false, OPTION_FUNC, "", false, "", fgOptRandomWind },
|
|
|
|
{"wind", true, OPTION_FUNC, "", false, "", fgOptWind },
|
2003-06-11 14:18:24 +00:00
|
|
|
{"turbulence", true, OPTION_FUNC, "", false, "", fgOptTurbulence },
|
2003-09-01 22:58:19 +00:00
|
|
|
{"ceiling", true, OPTION_FUNC, "", false, "", fgOptCeiling },
|
2003-01-19 23:02:51 +00:00
|
|
|
{"wp", true, OPTION_FUNC, "", false, "", fgOptWp },
|
|
|
|
{"flight-plan", true, OPTION_FUNC, "", false, "", fgOptFlightPlan },
|
|
|
|
{"config", true, OPTION_FUNC, "", false, "", fgOptConfig },
|
|
|
|
{"aircraft", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
|
2007-11-02 18:39:10 +00:00
|
|
|
{"vehicle", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
|
2003-09-10 01:29:19 +00:00
|
|
|
{"failure", true, OPTION_FUNC, "", false, "", fgOptFailure },
|
2004-12-04 21:06:57 +00:00
|
|
|
{"com1", true, OPTION_DOUBLE, "/instrumentation/comm[0]/frequencies/selected-mhz", false, "", 0 },
|
|
|
|
{"com2", true, OPTION_DOUBLE, "/instrumentation/comm[1]/frequencies/selected-mhz", false, "", 0 },
|
2003-07-16 23:34:07 +00:00
|
|
|
{"nav1", true, OPTION_FUNC, "", false, "", fgOptNAV1 },
|
|
|
|
{"nav2", true, OPTION_FUNC, "", false, "", fgOptNAV2 },
|
|
|
|
{"adf", true, OPTION_FUNC, "", false, "", fgOptADF },
|
|
|
|
{"dme", true, OPTION_FUNC, "", false, "", fgOptDME },
|
2004-10-28 09:37:21 +00:00
|
|
|
{"min-status", true, OPTION_STRING, "/sim/aircraft-min-status", false, "all", 0 },
|
2005-10-08 11:55:18 +00:00
|
|
|
{"livery", true, OPTION_FUNC, "", false, "", fgOptLivery },
|
2006-05-20 12:19:33 +00:00
|
|
|
{"ai-scenario", true, OPTION_FUNC, "", false, "", fgOptScenario },
|
2008-02-04 20:03:52 +00:00
|
|
|
{"parking-id", true, OPTION_FUNC, "", false, "", fgOptParking },
|
2008-03-15 12:10:44 +00:00
|
|
|
{"version", false, OPTION_FUNC, "", false, "", fgOptVersion },
|
2009-05-19 22:14:35 +00:00
|
|
|
{"enable-fpe", false, OPTION_FUNC, "", false, "", fgOptFpe},
|
2009-08-10 21:43:55 +00:00
|
|
|
{"fgviewer", false, OPTION_FUNC, "", false, "", fgOptFgviewer},
|
2003-01-19 23:02:51 +00:00
|
|
|
{0}
|
|
|
|
};
|
2003-03-22 14:52:15 +00:00
|
|
|
|
2000-11-28 23:38:24 +00:00
|
|
|
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
// Set a property for the --prop: option. Syntax: --prop:[<type>:]<name>=<value>
|
|
|
|
// <type> can be "double" etc. but also only the first letter "d".
|
|
|
|
// Examples: --prop:alpha=1 --prop:bool:beta=true --prop:d:gamma=0.123
|
|
|
|
static bool
|
|
|
|
set_property(const string& arg)
|
|
|
|
{
|
|
|
|
string::size_type pos = arg.find('=');
|
|
|
|
if (pos == arg.npos || pos == 0 || pos + 1 == arg.size())
|
|
|
|
return false;
|
|
|
|
|
|
|
|
string name = arg.substr(0, pos);
|
|
|
|
string value = arg.substr(pos + 1);
|
2007-07-12 14:45:46 +00:00
|
|
|
string type;
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
pos = name.find(':');
|
2007-07-12 14:45:46 +00:00
|
|
|
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
if (pos != name.npos && pos != 0 && pos + 1 != name.size()) {
|
|
|
|
type = name.substr(0, pos);
|
|
|
|
name = name.substr(pos + 1);
|
|
|
|
}
|
2007-07-12 14:45:46 +00:00
|
|
|
SGPropertyNode *n = fgGetNode(name.c_str(), true);
|
|
|
|
|
2008-07-09 15:09:23 +00:00
|
|
|
bool writable = n->getAttribute(SGPropertyNode::WRITE);
|
|
|
|
if (!writable)
|
|
|
|
n->setAttribute(SGPropertyNode::WRITE, true);
|
|
|
|
|
|
|
|
bool ret = false;
|
2007-07-12 14:45:46 +00:00
|
|
|
if (type.empty())
|
2008-07-09 15:09:23 +00:00
|
|
|
ret = n->setUnspecifiedValue(value.c_str());
|
2007-07-12 14:45:46 +00:00
|
|
|
else if (type == "s" || type == "string")
|
2008-07-09 15:09:23 +00:00
|
|
|
ret = n->setStringValue(value.c_str());
|
2007-06-28 19:23:57 +00:00
|
|
|
else if (type == "d" || type == "double")
|
2008-07-09 15:09:23 +00:00
|
|
|
ret = n->setDoubleValue(strtod(value.c_str(), 0));
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
else if (type == "f" || type == "float")
|
2008-07-09 15:09:23 +00:00
|
|
|
ret = n->setFloatValue(atof(value.c_str()));
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
else if (type == "l" || type == "long")
|
2008-07-09 15:09:23 +00:00
|
|
|
ret = n->setLongValue(strtol(value.c_str(), 0, 0));
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
else if (type == "i" || type == "int")
|
2008-07-09 15:09:23 +00:00
|
|
|
ret = n->setIntValue(atoi(value.c_str()));
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
else if (type == "b" || type == "bool")
|
2008-07-09 15:09:23 +00:00
|
|
|
ret = n->setBoolValue(value == "true" || atoi(value.c_str()) != 0);
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
|
2008-07-09 15:09:23 +00:00
|
|
|
if (!writable)
|
|
|
|
n->setAttribute(SGPropertyNode::WRITE, false);
|
|
|
|
return ret;
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-05-13 18:29:56 +00:00
|
|
|
// Parse a single option
|
2003-03-19 20:45:09 +00:00
|
|
|
static int
|
|
|
|
parse_option (const string& arg)
|
2001-01-13 22:06:39 +00:00
|
|
|
{
|
2003-01-19 23:02:51 +00:00
|
|
|
if ( fgOptionMap.size() == 0 ) {
|
|
|
|
size_t i = 0;
|
|
|
|
OptionDesc *pt = &fgOptionArray[ 0 ];
|
|
|
|
while ( pt->option != 0 ) {
|
|
|
|
fgOptionMap[ pt->option ] = i;
|
|
|
|
i += 1;
|
|
|
|
pt += 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// General Options
|
|
|
|
if ( (arg == "--help") || (arg == "-h") ) {
|
|
|
|
// help/usage request
|
|
|
|
return(FG_OPTIONS_HELP);
|
|
|
|
} else if ( (arg == "--verbose") || (arg == "-v") ) {
|
|
|
|
// verbose help/usage request
|
|
|
|
return(FG_OPTIONS_VERBOSE_HELP);
|
|
|
|
} else if ( arg.find( "--show-aircraft") == 0) {
|
|
|
|
return(FG_OPTIONS_SHOW_AIRCRAFT);
|
|
|
|
} else if ( arg.find( "--prop:" ) == 0 ) {
|
allow to specify a node type: --prop:[type:]name=value
where type is one of string (default), double, float, long, int, bool
Using only the first letter works, too.
--prop:foo=123 ... sets property foo to string 123 (old behavior)
--prop:string:foo=123 ... verbose version of above
--prop:s:foo=123 ... slightly less verbose version of above
--prop:bool:foo=1 ... makes property a bool of value 'true'
I hope this isn't considered a silly gimmick. I need this often and maybe
other developers do, too. It's useful in cases where the difference really
matters. if (getprop("/foo")), for instance, is TRUE even when the property
contains string "false", as all strings are TRUE.
2007-06-28 11:26:40 +00:00
|
|
|
if (!set_property(arg.substr(7))) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
|
2006-03-21 14:43:38 +00:00
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
2003-01-19 23:02:51 +00:00
|
|
|
} else if ( arg.find( "--" ) == 0 ) {
|
|
|
|
size_t pos = arg.find( '=' );
|
2008-03-15 12:10:44 +00:00
|
|
|
string arg_name, arg_value;
|
2003-01-19 23:02:51 +00:00
|
|
|
if ( pos == string::npos ) {
|
|
|
|
arg_name = arg.substr( 2 );
|
|
|
|
} else {
|
|
|
|
arg_name = arg.substr( 2, pos - 2 );
|
2008-03-15 12:10:44 +00:00
|
|
|
arg_value = arg.substr( pos + 1);
|
2003-01-19 23:02:51 +00:00
|
|
|
}
|
|
|
|
map<string,size_t>::iterator it = fgOptionMap.find( arg_name );
|
|
|
|
if ( it != fgOptionMap.end() ) {
|
|
|
|
OptionDesc *pt = &fgOptionArray[ it->second ];
|
|
|
|
switch ( pt->type ) {
|
|
|
|
case OPTION_BOOL:
|
|
|
|
fgSetBool( pt->property, pt->b_param );
|
|
|
|
break;
|
|
|
|
case OPTION_STRING:
|
2008-03-15 12:10:44 +00:00
|
|
|
if ( pt->has_param && !arg_value.empty() ) {
|
|
|
|
fgSetString( pt->property, arg_value.c_str() );
|
|
|
|
} else if ( !pt->has_param && arg_value.empty() ) {
|
2003-01-19 23:02:51 +00:00
|
|
|
fgSetString( pt->property, pt->s_param );
|
|
|
|
} else if ( pt->has_param ) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' does not have a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPTION_DOUBLE:
|
2008-03-15 12:10:44 +00:00
|
|
|
if ( !arg_value.empty() ) {
|
|
|
|
fgSetDouble( pt->property, atof( arg_value ) );
|
2003-01-19 23:02:51 +00:00
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPTION_INT:
|
2008-03-15 12:10:44 +00:00
|
|
|
if ( !arg_value.empty() ) {
|
|
|
|
fgSetInt( pt->property, atoi( arg_value ) );
|
2003-01-19 23:02:51 +00:00
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPTION_CHANNEL:
|
2008-03-15 12:10:44 +00:00
|
|
|
if ( pt->has_param && !arg_value.empty() ) {
|
|
|
|
add_channel( pt->option, arg_value );
|
|
|
|
} else if ( !pt->has_param && arg_value.empty() ) {
|
2003-01-19 23:02:51 +00:00
|
|
|
add_channel( pt->option, pt->s_param );
|
|
|
|
} else if ( pt->has_param ) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' does not have a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case OPTION_FUNC:
|
2008-03-15 12:10:44 +00:00
|
|
|
if ( pt->has_param && !arg_value.empty() ) {
|
|
|
|
return pt->func( arg_value.c_str() );
|
|
|
|
} else if ( !pt->has_param && arg_value.empty() ) {
|
2008-12-18 13:08:44 +00:00
|
|
|
return pt->func( pt->s_param );
|
2003-01-19 23:02:51 +00:00
|
|
|
} else if ( pt->has_param ) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' does not have a parameter" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Unknown option '" << arg << "'" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Unknown option '" << arg << "'" );
|
|
|
|
return FG_OPTIONS_ERROR;
|
|
|
|
}
|
|
|
|
|
1998-11-06 21:17:31 +00:00
|
|
|
return FG_OPTIONS_OK;
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Parse the command line options
|
2001-01-13 22:06:39 +00:00
|
|
|
void
|
2002-01-04 20:58:48 +00:00
|
|
|
fgParseArgs (int argc, char **argv)
|
|
|
|
{
|
|
|
|
bool in_options = true;
|
2002-08-25 22:38:20 +00:00
|
|
|
bool verbose = false;
|
|
|
|
bool help = false;
|
1998-04-24 00:49:17 +00:00
|
|
|
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Processing command line arguments");
|
1998-04-24 00:49:17 +00:00
|
|
|
|
2002-01-04 20:58:48 +00:00
|
|
|
for (int i = 1; i < argc; i++) {
|
|
|
|
string arg = argv[i];
|
|
|
|
|
|
|
|
if (in_options && (arg.find('-') == 0)) {
|
|
|
|
if (arg == "--") {
|
|
|
|
in_options = false;
|
|
|
|
} else {
|
|
|
|
int result = parse_option(arg);
|
2002-08-25 22:38:20 +00:00
|
|
|
if ((result == FG_OPTIONS_HELP) || (result == FG_OPTIONS_ERROR))
|
|
|
|
help = true;
|
|
|
|
|
|
|
|
else if (result == FG_OPTIONS_VERBOSE_HELP)
|
|
|
|
verbose = true;
|
2002-08-28 16:59:40 +00:00
|
|
|
|
|
|
|
else if (result == FG_OPTIONS_SHOW_AIRCRAFT) {
|
2003-09-22 11:35:21 +00:00
|
|
|
fgOptLogLevel( "alert" );
|
2003-09-15 14:07:50 +00:00
|
|
|
SGPath path( globals->get_fg_root() );
|
|
|
|
path.append("Aircraft");
|
2003-09-19 20:06:27 +00:00
|
|
|
fgShowAircraft(path, true);
|
2002-08-28 16:59:40 +00:00
|
|
|
exit(0);
|
|
|
|
}
|
2008-03-15 12:10:44 +00:00
|
|
|
|
|
|
|
else if (result == FG_OPTIONS_EXIT)
|
|
|
|
exit(0);
|
2002-01-04 20:58:48 +00:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
in_options = false;
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO,
|
|
|
|
"Reading command-line property file " << arg);
|
|
|
|
readProperties(arg, globals->get_props());
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
|
|
|
}
|
2002-01-04 20:58:48 +00:00
|
|
|
|
2002-08-25 22:38:20 +00:00
|
|
|
if (help) {
|
2003-09-22 11:35:21 +00:00
|
|
|
fgOptLogLevel( "alert" );
|
2002-08-25 22:38:20 +00:00
|
|
|
fgUsage(verbose);
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
2002-01-04 20:58:48 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Finished command line arguments");
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-08-27 17:01:55 +00:00
|
|
|
// Parse config file options
|
2001-01-13 22:06:39 +00:00
|
|
|
void
|
|
|
|
fgParseOptions (const string& path) {
|
2001-03-25 14:20:12 +00:00
|
|
|
sg_gzifstream in( path );
|
2001-05-18 16:09:39 +00:00
|
|
|
if ( !in.is_open() ) {
|
|
|
|
return;
|
|
|
|
}
|
1998-05-13 18:29:56 +00:00
|
|
|
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Processing config file: " << path );
|
1998-05-13 18:29:56 +00:00
|
|
|
|
1998-11-06 14:46:59 +00:00
|
|
|
in >> skipcomment;
|
1999-08-07 18:24:23 +00:00
|
|
|
while ( ! in.eof() ) {
|
1998-09-15 02:09:24 +00:00
|
|
|
string line;
|
2001-05-18 16:09:39 +00:00
|
|
|
getline( in, line, '\n' );
|
1998-07-22 01:27:03 +00:00
|
|
|
|
2001-05-18 16:09:39 +00:00
|
|
|
// catch extraneous (DOS) line ending character
|
2005-06-13 19:27:40 +00:00
|
|
|
int i;
|
|
|
|
for (i = line.length(); i > 0; i--)
|
|
|
|
if (line[i - 1] > 32)
|
|
|
|
break;
|
|
|
|
line = line.substr( 0, i );
|
2001-05-18 16:09:39 +00:00
|
|
|
|
1998-09-15 02:09:24 +00:00
|
|
|
if ( parse_option( line ) == FG_OPTIONS_ERROR ) {
|
2002-10-04 15:19:07 +00:00
|
|
|
cerr << endl << "Config file parse error: " << path << " '"
|
2002-09-18 16:13:08 +00:00
|
|
|
<< line << "'" << endl;
|
2001-01-13 22:06:39 +00:00
|
|
|
fgUsage();
|
1998-11-06 21:17:31 +00:00
|
|
|
exit(-1);
|
1998-05-13 18:29:56 +00:00
|
|
|
}
|
1998-11-06 14:46:59 +00:00
|
|
|
in >> skipcomment;
|
1998-05-13 18:29:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
// Print usage message
|
2001-01-13 22:06:39 +00:00
|
|
|
void
|
2002-08-25 22:38:20 +00:00
|
|
|
fgUsage (bool verbose)
|
2001-01-13 22:06:39 +00:00
|
|
|
{
|
2002-10-10 15:02:50 +00:00
|
|
|
SGPropertyNode *locale = globals->get_locale();
|
|
|
|
|
2002-06-10 23:30:23 +00:00
|
|
|
SGPropertyNode options_root;
|
|
|
|
|
2004-04-03 09:27:38 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
|
2003-03-20 10:43:02 +00:00
|
|
|
cout << endl;
|
2002-06-11 17:06:46 +00:00
|
|
|
|
2002-06-10 23:30:23 +00:00
|
|
|
try {
|
2002-11-06 18:57:31 +00:00
|
|
|
fgLoadProps("options.xml", &options_root);
|
2006-08-21 07:41:23 +00:00
|
|
|
} catch (const sg_exception &) {
|
2002-06-12 16:38:46 +00:00
|
|
|
cout << "Unable to read the help file." << endl;
|
|
|
|
cout << "Make sure the file options.xml is located in the FlightGear base directory," << endl;
|
2002-08-27 23:52:15 +00:00
|
|
|
cout << "and the location of the base directory is specified by setting $FG_ROOT or" << endl;
|
2002-06-12 16:38:46 +00:00
|
|
|
cout << "by adding --fg-root=path as a program argument." << endl;
|
|
|
|
|
2002-06-10 23:30:23 +00:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPropertyNode *options = options_root.getNode("options");
|
|
|
|
if (!options) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
|
|
|
"Error reading options.xml: <options> directive not found." );
|
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
2002-10-10 15:02:50 +00:00
|
|
|
SGPropertyNode *usage = locale->getNode(options->getStringValue("usage"));
|
2002-06-10 23:30:23 +00:00
|
|
|
if (usage) {
|
2002-06-12 16:38:46 +00:00
|
|
|
cout << "Usage: " << usage->getStringValue() << endl;
|
2002-06-10 23:30:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
vector<SGPropertyNode_ptr>section = options->getChildren("section");
|
|
|
|
for (unsigned int j = 0; j < section.size(); j++) {
|
2002-08-25 22:38:20 +00:00
|
|
|
string msg = "";
|
2002-06-10 23:30:23 +00:00
|
|
|
|
|
|
|
vector<SGPropertyNode_ptr>option = section[j]->getChildren("option");
|
|
|
|
for (unsigned int k = 0; k < option.size(); k++) {
|
|
|
|
|
|
|
|
SGPropertyNode *name = option[k]->getNode("name");
|
|
|
|
SGPropertyNode *short_name = option[k]->getNode("short");
|
2002-06-12 16:38:46 +00:00
|
|
|
SGPropertyNode *key = option[k]->getNode("key");
|
2002-06-10 23:30:23 +00:00
|
|
|
SGPropertyNode *arg = option[k]->getNode("arg");
|
2006-08-21 07:41:23 +00:00
|
|
|
bool brief = option[k]->getNode("brief") != 0;
|
2002-06-10 23:30:23 +00:00
|
|
|
|
2002-08-25 22:38:20 +00:00
|
|
|
if ((brief || verbose) && name) {
|
2002-06-11 17:06:46 +00:00
|
|
|
string tmp = name->getStringValue();
|
|
|
|
|
2002-06-12 16:38:46 +00:00
|
|
|
if (key){
|
|
|
|
tmp.append(":");
|
|
|
|
tmp.append(key->getStringValue());
|
2002-06-10 23:30:23 +00:00
|
|
|
}
|
|
|
|
if (arg) {
|
2002-06-11 17:06:46 +00:00
|
|
|
tmp.append("=");
|
|
|
|
tmp.append(arg->getStringValue());
|
2002-06-10 23:30:23 +00:00
|
|
|
}
|
2002-06-12 16:38:46 +00:00
|
|
|
if (short_name) {
|
|
|
|
tmp.append(", -");
|
|
|
|
tmp.append(short_name->getStringValue());
|
|
|
|
}
|
2007-01-02 08:32:32 +00:00
|
|
|
|
|
|
|
if (tmp.size() <= 25) {
|
|
|
|
msg+= " --";
|
|
|
|
msg += tmp;
|
|
|
|
msg.append( 27-tmp.size(), ' ');
|
|
|
|
} else {
|
|
|
|
msg += "\n --";
|
|
|
|
msg += tmp + '\n';
|
|
|
|
msg.append(32, ' ');
|
|
|
|
}
|
2002-10-10 15:02:50 +00:00
|
|
|
// There may be more than one <description> tag assosiated
|
|
|
|
// with one option
|
|
|
|
|
2007-01-02 08:32:32 +00:00
|
|
|
vector<SGPropertyNode_ptr> desc;
|
|
|
|
desc = option[k]->getChildren("description");
|
2002-10-10 15:02:50 +00:00
|
|
|
if (desc.size() > 0) {
|
|
|
|
for ( unsigned int l = 0; l < desc.size(); l++) {
|
|
|
|
|
|
|
|
// There may be more than one translation line.
|
|
|
|
|
|
|
|
string t = desc[l]->getStringValue();
|
|
|
|
SGPropertyNode *n = locale->getNode("strings");
|
|
|
|
vector<SGPropertyNode_ptr>trans_desc =
|
|
|
|
n->getChildren(t.substr(8).c_str());
|
|
|
|
|
|
|
|
for ( unsigned int m = 0; m < trans_desc.size(); m++ ) {
|
|
|
|
string t_str = trans_desc[m]->getStringValue();
|
|
|
|
|
|
|
|
if ((m > 0) || ((l > 0) && m == 0)) {
|
2007-01-02 08:32:32 +00:00
|
|
|
msg.append( 32, ' ');
|
2002-10-10 15:02:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If the string is too large to fit on the screen,
|
|
|
|
// then split it up in several pieces.
|
|
|
|
|
|
|
|
while ( t_str.size() > 47 ) {
|
|
|
|
|
|
|
|
unsigned int m = t_str.rfind(' ', 47);
|
2007-01-02 08:32:32 +00:00
|
|
|
msg += t_str.substr(0, m) + '\n';
|
|
|
|
msg.append( 32, ' ');
|
2002-10-10 15:02:50 +00:00
|
|
|
|
|
|
|
t_str.erase(t_str.begin(), t_str.begin() + m + 1);
|
|
|
|
}
|
|
|
|
msg += t_str + '\n';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2002-06-10 23:30:23 +00:00
|
|
|
}
|
|
|
|
}
|
2002-08-25 22:38:20 +00:00
|
|
|
|
2007-01-02 08:32:32 +00:00
|
|
|
SGPropertyNode *name;
|
|
|
|
name = locale->getNode(section[j]->getStringValue("name"));
|
2002-10-10 15:02:50 +00:00
|
|
|
|
2002-08-25 22:38:20 +00:00
|
|
|
if (!msg.empty() && name) {
|
|
|
|
cout << endl << name->getStringValue() << ":" << endl;
|
|
|
|
cout << msg;
|
|
|
|
msg.erase();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( !verbose ) {
|
|
|
|
cout << endl;
|
|
|
|
cout << "For a complete list of options use --help --verbose" << endl;
|
2002-06-10 23:30:23 +00:00
|
|
|
}
|
2004-04-03 09:27:38 +00:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
cout << "Hit a key to continue..." << endl;
|
|
|
|
cin.get();
|
|
|
|
#endif
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
2002-08-28 16:59:40 +00:00
|
|
|
|
2004-10-28 09:37:21 +00:00
|
|
|
// A simple function to return an integer depending on the position
|
|
|
|
// of the status string within the array in order to determine the hierarchy.
|
|
|
|
unsigned int getNumMaturity(const char * str)
|
|
|
|
{
|
|
|
|
// changes should also be reflected in $FG_ROOT/data/options.xml &
|
|
|
|
// $FG_ROOT/data/Translations/string-default.xml
|
2009-08-24 16:03:49 +00:00
|
|
|
const char* levels[] = {"alpha","beta","early-production","production"};
|
2004-10-28 09:37:21 +00:00
|
|
|
|
2009-08-24 16:03:49 +00:00
|
|
|
for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++)
|
2004-10-28 09:37:21 +00:00
|
|
|
if (strcmp(str,levels[i])==0)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2003-09-19 20:06:27 +00:00
|
|
|
static void fgSearchAircraft(const SGPath &path, string_list &aircraft,
|
|
|
|
bool recursive)
|
2004-10-28 09:37:21 +00:00
|
|
|
{
|
|
|
|
|
2002-08-28 16:59:40 +00:00
|
|
|
ulDirEnt* dire;
|
2003-09-15 14:07:50 +00:00
|
|
|
ulDir *dirp = ulOpenDir(path.str().c_str());
|
2002-08-28 16:59:40 +00:00
|
|
|
if (dirp == NULL) {
|
2005-07-03 10:27:35 +00:00
|
|
|
cerr << "Unable to open aircraft directory '" << path.str() << '\'' << endl;
|
2002-08-28 16:59:40 +00:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
while ((dire = ulReadDir(dirp)) != NULL) {
|
|
|
|
char *ptr;
|
|
|
|
|
2003-09-15 14:07:50 +00:00
|
|
|
if (dire->d_isdir) {
|
|
|
|
if (recursive && strcmp("CVS", dire->d_name)
|
|
|
|
&& strcmp(".", dire->d_name) && strcmp("..", dire->d_name))
|
|
|
|
{
|
|
|
|
SGPath next = path;
|
|
|
|
next.append(dire->d_name);
|
|
|
|
|
2003-09-19 20:06:27 +00:00
|
|
|
fgSearchAircraft(next, aircraft, true);
|
2003-09-15 14:07:50 +00:00
|
|
|
}
|
|
|
|
} else if ((ptr = strstr(dire->d_name, "-set.xml")) && (ptr[8] == '\0')) {
|
|
|
|
|
2002-08-28 16:59:40 +00:00
|
|
|
SGPath afile = path;
|
|
|
|
afile.append(dire->d_name);
|
|
|
|
|
|
|
|
*ptr = '\0';
|
|
|
|
|
|
|
|
SGPropertyNode root;
|
|
|
|
try {
|
|
|
|
readProperties(afile.str(), &root);
|
|
|
|
} catch (...) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2002-11-15 21:13:29 +00:00
|
|
|
SGPropertyNode *desc = NULL;
|
2004-10-28 09:37:21 +00:00
|
|
|
SGPropertyNode *status = NULL;
|
|
|
|
|
2002-11-15 21:13:29 +00:00
|
|
|
SGPropertyNode *node = root.getNode("sim");
|
|
|
|
if (node) {
|
2002-08-28 16:59:40 +00:00
|
|
|
desc = node->getNode("description");
|
2004-10-28 09:37:21 +00:00
|
|
|
// if a status tag is found, read it in
|
|
|
|
if (node->hasValue("status"))
|
|
|
|
status = node->getNode("status");
|
2002-11-15 21:13:29 +00:00
|
|
|
}
|
2002-08-28 16:59:40 +00:00
|
|
|
|
2007-01-02 08:32:32 +00:00
|
|
|
//additionally display status information where it is available
|
|
|
|
|
|
|
|
string descStr(" ");
|
|
|
|
descStr += dire->d_name;
|
|
|
|
if (desc) {
|
|
|
|
if (descStr.size() <= 27+3) {
|
|
|
|
descStr.append(29+3-descStr.size(), ' ');
|
|
|
|
} else {
|
|
|
|
descStr += '\n';
|
|
|
|
descStr.append( 32, ' ');
|
|
|
|
}
|
|
|
|
descStr += desc->getStringValue();
|
2003-09-15 14:07:50 +00:00
|
|
|
}
|
2007-01-02 08:32:32 +00:00
|
|
|
|
|
|
|
SGPropertyNode * required_status
|
2004-10-28 09:37:21 +00:00
|
|
|
= fgGetNode ("/sim/aircraft-min-status", true);
|
|
|
|
|
|
|
|
// If the node holds the value "all", then there wasn't any status
|
|
|
|
// level specified, so we simply go ahead and output ALL aircraft
|
|
|
|
if (strcmp(required_status->getStringValue(),"all")==0) {
|
2007-01-02 08:32:32 +00:00
|
|
|
aircraft.push_back(descStr);
|
2004-10-28 09:37:21 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// If the node doesn't hold "all" as its value, then we are supposed
|
|
|
|
// to show only aircraft meeting specific status (development status)
|
|
|
|
// requirements:
|
|
|
|
|
|
|
|
if (node->hasValue("status")) {
|
|
|
|
//Compare (minimally) required status level with actual aircraft status:
|
|
|
|
if ( getNumMaturity(status->getStringValue() ) >=
|
|
|
|
getNumMaturity(required_status->getStringValue() ) )
|
2007-01-02 08:32:32 +00:00
|
|
|
aircraft.push_back(descStr); }
|
2004-10-28 09:37:21 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2002-08-28 16:59:40 +00:00
|
|
|
}
|
|
|
|
|
2003-09-19 20:06:27 +00:00
|
|
|
ulCloseDir(dirp);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Search in the current directory, and in on directory deeper
|
|
|
|
* for <aircraft>-set.xml configuration files and show the aircaft name
|
|
|
|
* and the contents of the<description> tag in a sorted manner.
|
|
|
|
*
|
|
|
|
* @parampath the directory to search for configuration files
|
|
|
|
* @param recursive defines whether the directory should be searched recursively
|
|
|
|
*/
|
|
|
|
void fgShowAircraft(const SGPath &path, bool recursive) {
|
|
|
|
string_list aircraft;
|
|
|
|
|
|
|
|
fgSearchAircraft( path, aircraft, recursive );
|
2003-02-11 21:17:36 +00:00
|
|
|
|
2003-09-19 20:06:27 +00:00
|
|
|
sort(aircraft.begin(), aircraft.end());
|
2004-04-03 09:27:38 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
|
|
|
|
cout << "Available aircraft:" << endl;
|
2003-09-19 20:06:27 +00:00
|
|
|
for ( unsigned int i = 0; i < aircraft.size(); i++ ) {
|
2004-04-03 09:27:38 +00:00
|
|
|
cout << aircraft[i] << endl;
|
2003-09-15 14:07:50 +00:00
|
|
|
}
|
2004-03-30 09:05:05 +00:00
|
|
|
#ifdef _MSC_VER
|
2004-04-03 09:27:38 +00:00
|
|
|
cout << "Hit a key to continue..." << endl;
|
2004-03-30 09:05:05 +00:00
|
|
|
cin.get();
|
|
|
|
#endif
|
2002-08-28 16:59:40 +00:00
|
|
|
}
|