//
// Written by Curtis Olson, started April 1998.
//
-// Copyright (C) 1998 Curtis L. Olson - curt@me.umn.edu
+// Copyright (C) 1998 Curtis L. Olson - http://www.flightgear.org/~curt
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
-// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
//
// $Id$
#endif
#include <simgear/compiler.h>
-#include <simgear/misc/exception.hxx>
+#include <simgear/structure/exception.hxx>
#include <simgear/debug/logstream.hxx>
#include <math.h> // rint()
#include <string.h> // strcmp()
#include <algorithm>
-#include STL_STRING
+#include <iostream>
+#include <string>
#include <plib/ul.h>
#include <simgear/math/sg_random.h>
+#include <simgear/props/props_io.hxx>
#include <simgear/misc/sgstream.hxx>
#include <simgear/misc/sg_path.hxx>
-#include <simgear/route/route.hxx>
-#include <simgear/route/waypoint.hxx>
+#include <simgear/scene/material/mat.hxx>
// #include <Include/general.hxx>
// #include <Airports/simple.hxx>
// #include <Cockpit/cockpit.hxx>
// #include <FDM/flight.hxx>
-// #include <FDM/UIUCModel/uiuc_aircraftdir.h>
-#ifdef FG_NETWORK_OLK
-# include <NetworkOLK/network.h>
-#endif
+#include <Autopilot/route_mgr.hxx>
#include <GUI/gui.h>
#include "globals.hxx"
#include "viewmgr.hxx"
-SG_USING_STD(string);
-SG_USING_STD(sort);
-SG_USING_NAMESPACE(std);
+using std::string;
+using std::sort;
+using std::cout;
+using std::cerr;
+using std::endl;
+#ifndef VERSION
+#define VERSION "CVS "__DATE__
+#endif
#define NEW_DEFAULT_MODEL_HZ 120
FG_OPTIONS_OK = 0,
FG_OPTIONS_HELP = 1,
FG_OPTIONS_ERROR = 2,
- FG_OPTIONS_VERBOSE_HELP = 3,
- FG_OPTIONS_SHOW_AIRCRAFT = 4
+ FG_OPTIONS_EXIT = 3,
+ FG_OPTIONS_VERBOSE_HELP = 4,
+ FG_OPTIONS_SHOW_AIRCRAFT = 5
};
static double
atof( const string& str )
{
-
-#ifdef __MWERKS__
- // -dw- if ::atof is called, then we get an infinite loop
- return std::atof( str.c_str() );
-#else
return ::atof( str.c_str() );
-#endif
}
static int
atoi( const string& str )
{
-#ifdef __MWERKS__
- // -dw- if ::atoi is called, then we get an infinite loop
- return std::atoi( str.c_str() );
-#else
return ::atoi( str.c_str() );
-#endif
}
-
/**
* Set a few fail-safe default property values.
*
fgSetDouble("/position/altitude-ft", -9999.0);
// Orientation
- fgSetDouble("/orientation/heading-deg", 270);
- fgSetDouble("/orientation/roll-deg", 0);
+ fgSetDouble("/orientation/heading-deg", 9999.0);
+ fgSetDouble("/orientation/roll-deg", 0.0);
fgSetDouble("/orientation/pitch-deg", 0.424);
// Velocities
fgSetDouble("/sim/presets/latitude-deg", 9999.0);
fgSetDouble("/sim/presets/altitude-ft", -9999.0);
- fgSetDouble("/sim/presets/heading-deg", 270);
- fgSetDouble("/sim/presets/roll-deg", 0);
+ fgSetDouble("/sim/presets/heading-deg", 9999.0);
+ fgSetDouble("/sim/presets/roll-deg", 0.0);
fgSetDouble("/sim/presets/pitch-deg", 0.424);
fgSetString("/sim/presets/speed-set", "knots");
// fgSetString("/sim/startup/mouse-pointer", "disabled");
fgSetString("/sim/control-mode", "joystick");
fgSetBool("/sim/auto-coordination", false);
-#if !defined(WIN32)
- fgSetString("/sim/startup/browser-app", "netscape");
-#else
+#if defined(WIN32)
fgSetString("/sim/startup/browser-app", "webrun.bat");
+#elif defined(__APPLE__)
+ fgSetString("/sim/startup/browser-app", "open");
+#elif defined(sgi)
+ fgSetString("/sim/startup/browser-app", "launchWebJumper");
+#else
+ envp = ::getenv( "WEBBROWSER" );
+ if (!envp) envp = "netscape";
+ fgSetString("/sim/startup/browser-app", envp);
#endif
- fgSetString("/sim/logging/priority", "warn");
+ fgSetString("/sim/logging/priority", "alert");
// Features
- fgSetBool("/sim/hud/antialiased", false);
+ fgSetBool("/sim/hud/color/antialiased", false);
fgSetBool("/sim/hud/enable3d", true);
fgSetBool("/sim/hud/visibility", false);
fgSetBool("/sim/panel/visibility", true);
- fgSetBool("/sim/sound/audible", true);
+ fgSetBool("/sim/sound/pause", false);
// Flight Model options
fgSetString("/sim/flight-model", "jsb");
fgSetBool("/sim/rendering/shading", true);
fgSetBool("/sim/rendering/skyblend", true);
fgSetBool("/sim/rendering/textures", true);
+ fgTie( "/sim/rendering/filtering", SGGetTextureFilter, SGSetTextureFilter, false);
+ fgSetInt("/sim/rendering/filtering", 1);
fgSetBool("/sim/rendering/wireframe", false);
fgSetBool("/sim/rendering/horizon-effect", false);
fgSetBool("/sim/rendering/enhanced-lighting", false);
fgSetString("/sim/startup/time-offset-type", "system-offset");
fgSetLong("/sim/time/cur-time-override", 0);
- fgSetBool("/sim/networking/network-olk", false);
- fgSetString("/sim/networking/call-sign", "Johnny");
-
// Freeze options
fgSetBool("/sim/freeze/master", false);
fgSetBool("/sim/freeze/position", false);
fgSetBool("/sim/freeze/clock", false);
fgSetBool("/sim/freeze/fuel", false);
-#ifdef FG_MPLAYER_AS
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);
-#endif
-
}
static bool
if ( fov < FG_FOV_MIN ) { fov = FG_FOV_MIN; }
if ( fov > FG_FOV_MAX ) { fov = FG_FOV_MAX; }
- fgSetDouble("/sim/current-view/field-of-view", fov);
+ fgSetDouble("/sim/view[0]/config/default-field-of-view-deg", fov);
// printf("parse_fov(): result = %.4f\n", fov);
//
// Format is "--protocol=medium,direction,hz,medium_options,..."
//
-// protocol = { native, nmea, garmin, fgfs, rul, pve, etc. }
+// protocol = { native, nmea, garmin, AV400, fgfs, rul, pve, etc. }
// medium = { serial, socket, file, etc. }
// direction = { in, out, bi }
// hz = number of times to process channel per second (floating
static bool
add_channel( const string& type, const string& channel_str ) {
SG_LOG(SG_GENERAL, SG_INFO, "Channel string = " << channel_str );
-
globals->get_channel_options_list()->push_back( type + "," + channel_str );
-
- // cout << "here" << endl;
-
return true;
}
-static void
-setup_wind (double min_hdg, double max_hdg, double speed, double gust)
-{
- // Initialize to a reasonable state
- fgDefaultWeatherValue("wind-from-heading-deg", min_hdg);
- fgDefaultWeatherValue("wind-speed-kt", speed);
-
- SG_LOG(SG_GENERAL, SG_INFO, "WIND: " << min_hdg << '@' <<
- speed << " knots" << endl);
-
- // Now, add some variety to the layers
- min_hdg += 10;
- if (min_hdg > 360)
- min_hdg -= 360;
- speed *= 1.2;
- fgSetDouble("/environment/config/boundary/entry[1]/wind-from-heading-deg",
- min_hdg);
- fgSetDouble("/environment/config/boundary/entry[1]/wind-speed-kt",
- speed);
-
- min_hdg += 20;
- if (min_hdg > 360)
- min_hdg -= 360;
- speed *= 1.5;
- fgSetDouble("/environment/config/aloft/entry[0]/wind-from-heading-deg",
- min_hdg);
- fgSetDouble("/environment/config/aloft/entry[0]/wind-speed-kt",
- speed);
-
- min_hdg += 10;
- if (min_hdg > 360)
- min_hdg -= 360;
- speed *= 1.2;
- fgSetDouble("/environment/config/aloft/entry[1]/wind-from-heading-deg",
- min_hdg);
- fgSetDouble("/environment/config/aloft/entry[1]/wind-speed-kt",
- speed);
-
- min_hdg += 10;
- if (min_hdg > 360)
- min_hdg -= 360;
- speed *= 1.2;
- fgSetDouble("/environment/config/aloft/entry[2]/wind-from-heading-deg",
- min_hdg);
- fgSetDouble("/environment/config/aloft/entry[2]/wind-speed-kt",
- speed);
-
-#ifdef FG_WEATHERCM
- // convert to fps
- speed *= SG_NM_TO_METER * SG_METER_TO_FEET * (1.0/3600);
- while (min_hdg > 360)
- min_hdg -= 360;
- while (min_hdg <= 0)
- min_hdg += 360;
- min_hdg *= SGD_DEGREES_TO_RADIANS;
- fgSetDouble("/environment/wind-from-north-fps", speed * cos(dir));
- fgSetDouble("/environment/wind-from-east-fps", speed * sin(dir));
-#endif // FG_WEATHERCM
-}
-
+// The parse wp and parse flight-plan options don't work anymore, because
+// the route manager and the airport subsystems have not yet been initialized
+// at this stage.
// Parse --wp=ID[@alt]
-static bool
+static void
parse_wp( const string& arg ) {
- string id, alt_str;
- double alt = 0.0;
-
- string::size_type pos = arg.find( "@" );
- if ( pos != string::npos ) {
- id = arg.substr( 0, pos );
- alt_str = arg.substr( pos + 1 );
- // cout << "id str = " << id << " alt str = " << alt_str << endl;
- alt = atof( alt_str.c_str() );
- if ( !strcmp(fgGetString("/sim/startup/units"), "feet") ) {
- alt *= SG_FEET_TO_METER;
- }
- } else {
- id = arg;
- }
-
- FGAirport a;
- if ( fgFindAirportID( id, &a ) ) {
- SGWayPoint wp( a.longitude, a.latitude, alt, SGWayPoint::WGS84, id );
- globals->get_route()->add_waypoint( wp );
-
- return true;
- } else {
- return false;
+ string_list *waypoints = globals->get_initial_waypoints();
+ if (!waypoints) {
+ waypoints = new string_list;
+ globals->set_initial_waypoints(waypoints);
}
+ waypoints->push_back(arg);
}
// Parse --flight-plan=[file]
-static bool
+static bool
parse_flightplan(const string& arg)
{
- sg_gzifstream in(arg.c_str());
- if ( !in.is_open() ) {
- return false;
+ string_list *waypoints = globals->get_initial_waypoints();
+ if (!waypoints) {
+ waypoints = new string_list;
+ globals->set_initial_waypoints(waypoints);
}
- while ( true ) {
- string line;
-#if defined( macintosh )
- getline( in, line, '\r' );
-#else
- getline( in, line, '\n' );
-#endif
+ sg_gzifstream in(arg.c_str());
+ if ( !in.is_open() )
+ return false;
+
+ while ( true ) {
+ string line;
+ getline( in, line, '\n' );
// catch extraneous (DOS) line ending character
- if ( line[line.length() - 1] < 32 ) {
+ if ( line[line.length() - 1] < 32 )
line = line.substr( 0, line.length()-1 );
- }
- if ( in.eof() ) {
- break;
- }
- parse_wp(line);
- }
+ if ( in.eof() )
+ break;
+ waypoints->push_back(line);
+ }
return true;
}
+
static int
fgOptLanguage( const char *arg )
{
fgSetString("/sim/presets/airport-id", "");
fgSetString("/sim/presets/vor-id", "");
fgSetString("/sim/presets/ndb-id", "");
+ fgSetString("/sim/presets/carrier", "");
+ fgSetString("/sim/presets/parkpos", "");
fgSetString("/sim/presets/fix", "");
}
return FG_OPTIONS_OK;
}
+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;
+}
+
static int
fgOptFIX( const char * arg )
{
return FG_OPTIONS_OK;
}
-#ifdef FG_NETWORK_OLK
static int
-fgOptNetHud( const char *arg )
+fgSetupProxy( const char *arg )
{
- fgSetBool("/sim/hud/net-display", true);
- net_hud_display = 1; // FIXME
+ string options = arg;
+ string host, port, auth;
+ string::size_type pos;
+
+ 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;
}
-#endif
static int
fgOptTraceRead( const char *arg )
fgSetString("/sim/logging/priority", arg);
string priority = arg;
+ logbuf::set_log_classes(SG_ALL);
if (priority == "bulk") {
logbuf::set_log_priority(SG_BULK);
} else if (priority == "debug") {
logbuf::set_log_priority(SG_DEBUG);
- } else if (priority.empty() || priority == "info") { // default
+ } else if (priority == "info") {
logbuf::set_log_priority(SG_INFO);
} else if (priority == "warn") {
logbuf::set_log_priority(SG_WARN);
} else {
SG_LOG(SG_GENERAL, SG_WARN, "Unknown logging priority " << priority);
}
- SG_LOG(SG_GENERAL, SG_INFO, "Logging priority is " << priority);
+ SG_LOG(SG_GENERAL, SG_DEBUG, "Logging priority is " << priority);
return FG_OPTIONS_OK;
}
{
double min_hdg = sg_random() * 360.0;
double max_hdg = min_hdg + (20 - sqrt(sg_random() * 400));
- double speed = 40 - sqrt(sg_random() * 1600.0);
+ double speed = sg_random() * sg_random() * 40;
double gust = speed + (10 - sqrt(sg_random() * 100));
- setup_wind(min_hdg, max_hdg, speed, gust);
+ fgSetupWind(min_hdg, max_hdg, speed, gust);
return FG_OPTIONS_OK;
}
SG_LOG( SG_GENERAL, SG_ALERT, "bad wind value " << arg );
return FG_OPTIONS_ERROR;
}
- setup_wind(min_hdg, max_hdg, speed, gust);
+ fgSetupWind(min_hdg, max_hdg, speed, gust);
return FG_OPTIONS_OK;
}
readProperties(file, globals->get_props());
} catch (const sg_exception &e) {
string message = "Error loading config file: ";
- message += e.getFormattedMessage();
+ message += e.getFormattedMessage() + e.getOrigin();
SG_LOG(SG_INPUT, SG_ALERT, message);
exit(2);
}
{
double radial, freq;
if (parse_colon(arg, &radial, &freq))
- fgSetDouble("/radios/nav[0]/radials/selected-deg", radial);
- fgSetDouble("/radios/nav[0]/frequencies/selected-mhz", freq);
+ fgSetDouble("/instrumentation/nav[0]/radials/selected-deg", radial);
+ fgSetDouble("/instrumentation/nav[0]/frequencies/selected-mhz", freq);
return FG_OPTIONS_OK;
}
{
double radial, freq;
if (parse_colon(arg, &radial, &freq))
- fgSetDouble("/radios/nav[1]/radials/selected-deg", radial);
- fgSetDouble("/radios/nav[1]/frequencies/selected-mhz", freq);
+ fgSetDouble("/instrumentation/nav[1]/radials/selected-deg", radial);
+ fgSetDouble("/instrumentation/nav[1]/frequencies/selected-mhz", freq);
return FG_OPTIONS_OK;
}
{
double rot, freq;
if (parse_colon(arg, &rot, &freq))
- fgSetDouble("/radios/kr-87/inputs/rotation-deg", rot);
- fgSetDouble("/radios/kr-87/outputs/selected-khz", freq);
+ fgSetDouble("/instrumentation/adf/rotation-deg", rot);
+ fgSetDouble("/instrumentation/adf/frequencies/selected-khz", freq);
return FG_OPTIONS_OK;
}
if (opt == "nav1") {
fgSetInt("/instrumentation/dme/switch-position", 1);
fgSetString("/instrumentation/dme/frequencies/source",
- "/radios/nav[0]/frequencies/selected-mhz");
+ "/instrumentation/nav[0]/frequencies/selected-mhz");
} else if (opt == "nav2") {
fgSetInt("/instrumentation/dme/switch-position", 3);
fgSetString("/instrumentation/dme/frequencies/source",
- "/radios/nav[1]/frequencies/selected-mhz");
+ "/instrumentation/nav[1]/frequencies/selected-mhz");
} else {
fgSetInt("/instrumentation/dme/switch-position", 2);
fgSetString("/instrumentation/dme/frequencies/source",
return FG_OPTIONS_OK;
}
+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;
+}
+
+static int
+fgOptScenario( const char *arg )
+{
+ SGPropertyNode_ptr ai_node = fgGetNode( "/sim/ai", true );
+ 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;
+}
+
+static int
+fgOptRunway( const char *arg )
+{
+ fgSetString("/sim/presets/runway", arg );
+ fgSetBool("/sim/presets/runway-requested", true );
+ return FG_OPTIONS_OK;
+}
+
+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;
+}
+
+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;
+}
+
static map<string,size_t> fgOptionMap;
/*
enum OptionType { OPTION_BOOL, OPTION_STRING, OPTION_DOUBLE, OPTION_INT, OPTION_CHANNEL, OPTION_FUNC };
struct OptionDesc {
- char *option;
+ const char *option;
bool has_param;
enum OptionType type;
- char *property;
+ const char *property;
bool b_param;
- char *s_param;
+ const char *s_param;
int (*func)( const char * );
} fgOptionArray[] = {
{"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 },
+ {"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 },
+ {"disable-ai-models", false, OPTION_BOOL, "/sim/ai/enabled", false, "", 0 },
+ {"enable-ai-models", false, OPTION_BOOL, "/sim/ai/enabled", true, "", 0 },
{"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-clock-freeze", false, OPTION_BOOL, "/sim/freeze/clock", true, "", 0 },
{"disable-hud-3d", false, OPTION_BOOL, "/sim/hud/enable3d", false, "", 0 },
{"enable-hud-3d", false, OPTION_BOOL, "/sim/hud/enable3d", true, "", 0 },
- {"disable-anti-alias-hud", false, OPTION_BOOL, "/sim/hud/antialiased", false, "", 0 },
- {"enable-anti-alias-hud", false, OPTION_BOOL, "/sim/hud/antialiased", true, "", 0 },
+ {"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 },
{"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 },
{"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 },
- {"disable-sound", false, OPTION_BOOL, "/sim/sound/audible", false, "", 0 },
- {"enable-sound", false, OPTION_BOOL, "/sim/sound/audible", true, "", 0 },
+ {"disable-sound", false, OPTION_BOOL, "/sim/sound/pause", true, "", 0 },
+ {"enable-sound", false, OPTION_BOOL, "/sim/sound/pause", false, "", 0 },
{"airport", true, OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
- {"airport-id", true, OPTION_STRING, "/sim/presets/airport-id", false, "", 0 },
- {"runway", true, OPTION_STRING, "/sim/presets/runway", false, "", 0 },
+ {"runway", true, OPTION_FUNC, "", false, "", fgOptRunway },
{"vor", true, OPTION_FUNC, "", false, "", fgOptVOR },
{"ndb", true, OPTION_FUNC, "", false, "", fgOptNDB },
+ {"carrier", true, OPTION_FUNC, "", false, "", fgOptCarrier },
+ {"parkpos", true, OPTION_FUNC, "", false, "", fgOptParkpos },
{"fix", true, OPTION_FUNC, "", false, "", fgOptFIX },
- {"offset-distance", true, OPTION_DOUBLE, "/sim/presets/offset-distance", false, "", 0 },
- {"offset-azimuth", true, OPTION_DOUBLE, "/sim/presets/offset-azimuth", false, "", 0 },
+ {"offset-distance", true, OPTION_DOUBLE, "/sim/presets/offset-distance-nm", false, "", 0 },
+ {"offset-azimuth", true, OPTION_DOUBLE, "/sim/presets/offset-azimuth-deg", false, "", 0 },
{"lon", true, OPTION_FUNC, "", false, "", fgOptLon },
{"lat", true, OPTION_FUNC, "", false, "", fgOptLat },
{"altitude", true, OPTION_FUNC, "", false, "", fgOptAltitude },
{"enable-specular-highlight", false, OPTION_BOOL, "/sim/rendering/specular-highlight", true, "", 0 },
{"disable-clouds", false, OPTION_BOOL, "/environment/clouds/status", false, "", 0 },
{"enable-clouds", false, OPTION_BOOL, "/environment/clouds/status", true, "", 0 },
-#ifdef FG_USE_CLOUDS_3D
- {"disable-clouds3d", false, OPTION_BOOL, "/sim/rendering/clouds3d", false, "", 0 },
- {"enable-clouds3d", false, OPTION_BOOL, "/sim/rendering/clouds3d", true, "", 0 },
-#endif
+ {"disable-clouds3d", false, OPTION_BOOL, "/sim/rendering/clouds3d-enable", false, "", 0 },
+ {"enable-clouds3d", false, OPTION_BOOL, "/sim/rendering/clouds3d-enable", true, "", 0 },
{"fov", true, OPTION_FUNC, "", false, "", fgOptFov },
+ {"aspect-ratio-multiplier", true, OPTION_DOUBLE, "/sim/current-view/aspect-ratio-multiplier", false, "", 0 },
{"disable-fullscreen", false, OPTION_BOOL, "/sim/startup/fullscreen", false, "", 0 },
{"enable-fullscreen", false, OPTION_BOOL, "/sim/startup/fullscreen", true, "", 0 },
+ {"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 },
{"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 },
+ {"texture-filtering", false, OPTION_INT, "/sim/rendering/filtering", 1, "", 0 },
{"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 },
{"units-feet", false, OPTION_STRING, "/sim/startup/units", false, "feet", 0 },
{"units-meters", false, OPTION_STRING, "/sim/startup/units", false, "meters", 0 },
{"timeofday", true, OPTION_STRING, "/sim/startup/time-offset-type", false, "noon", 0 },
+ {"season", true, OPTION_STRING, "/sim/startup/season", false, "summer", 0 },
{"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-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 },
- {"atc610x", true, OPTION_CHANNEL, "", false, "dummy", 0 },
+ {"atcsim", true, OPTION_CHANNEL, "", false, "dummy", 0 },
{"atlas", true, OPTION_CHANNEL, "", false, "", 0 },
{"httpd", true, OPTION_CHANNEL, "", false, "", 0 },
#ifdef FG_JPEG_SERVER
{"native-fdm", true, OPTION_CHANNEL, "", false, "", 0 },
{"native-gui", true, OPTION_CHANNEL, "", false, "", 0 },
{"opengc", true, OPTION_CHANNEL, "", false, "", 0 },
+ {"AV400", true, OPTION_CHANNEL, "", false, "", 0 },
{"garmin", true, OPTION_CHANNEL, "", false, "", 0 },
{"nmea", true, OPTION_CHANNEL, "", false, "", 0 },
{"generic", true, OPTION_CHANNEL, "", false, "", 0 },
{"ray", true, OPTION_CHANNEL, "", false, "", 0 },
{"rul", true, OPTION_CHANNEL, "", false, "", 0 },
{"joyclient", true, OPTION_CHANNEL, "", false, "", 0 },
-#ifdef FG_NETWORK_OLK
- {"disable-network-olk", false, OPTION_BOOL, "/sim/networking/olk", false, "", 0 },
- {"enable-network-olk", false, OPTION_BOOL, "/sim/networking/olk", true, "", 0 },
- {"net-hud", false, OPTION_FUNC, "", false, "", fgOptNetHud },
- {"net-id", true, OPTION_STRING, "sim/networking/call-sign", false, "", 0 },
-#endif
-#ifdef FG_MPLAYER_AS
+ {"jsclient", true, OPTION_CHANNEL, "", false, "", 0 },
+ {"proxy", true, OPTION_FUNC, "", false, "", fgSetupProxy },
{"callsign", true, OPTION_STRING, "sim/multiplay/callsign", false, "", 0 },
{"multiplay", true, OPTION_CHANNEL, "", false, "", 0 },
-#endif
{"trace-read", true, OPTION_FUNC, "", false, "", fgOptTraceRead },
{"trace-write", true, OPTION_FUNC, "", false, "", fgOptTraceWrite },
{"log-level", true, OPTION_FUNC, "", false, "", fgOptLogLevel },
{"flight-plan", true, OPTION_FUNC, "", false, "", fgOptFlightPlan },
{"config", true, OPTION_FUNC, "", false, "", fgOptConfig },
{"aircraft", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
+ {"vehicle", true, OPTION_STRING, "/sim/aircraft", false, "", 0 },
{"failure", true, OPTION_FUNC, "", false, "", fgOptFailure },
- {"com1", true, OPTION_DOUBLE, "/radios/comm[0]/frequencies/selected-mhz", false, "", 0 },
- {"com2", true, OPTION_DOUBLE, "/radios/comm[1]/frequencies/selected-mhz", false, "", 0 },
+ {"com1", true, OPTION_DOUBLE, "/instrumentation/comm[0]/frequencies/selected-mhz", false, "", 0 },
+ {"com2", true, OPTION_DOUBLE, "/instrumentation/comm[1]/frequencies/selected-mhz", false, "", 0 },
{"nav1", true, OPTION_FUNC, "", false, "", fgOptNAV1 },
{"nav2", true, OPTION_FUNC, "", false, "", fgOptNAV2 },
{"adf", true, OPTION_FUNC, "", false, "", fgOptADF },
{"dme", true, OPTION_FUNC, "", false, "", fgOptDME },
+ {"min-status", true, OPTION_STRING, "/sim/aircraft-min-status", false, "all", 0 },
+ {"livery", true, OPTION_FUNC, "", false, "", fgOptLivery },
+ {"ai-scenario", true, OPTION_FUNC, "", false, "", fgOptScenario },
+ {"parking-id", true, OPTION_FUNC, "", false, "", fgOptParking },
+ {"version", false, OPTION_FUNC, "", false, "", fgOptVersion },
{0}
};
+// 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);
+ string type;
+ pos = name.find(':');
+
+ if (pos != name.npos && pos != 0 && pos + 1 != name.size()) {
+ type = name.substr(0, pos);
+ name = name.substr(pos + 1);
+ }
+ SGPropertyNode *n = fgGetNode(name.c_str(), true);
+
+ bool writable = n->getAttribute(SGPropertyNode::WRITE);
+ if (!writable)
+ n->setAttribute(SGPropertyNode::WRITE, true);
+
+ bool ret = false;
+ if (type.empty())
+ ret = n->setUnspecifiedValue(value.c_str());
+ else if (type == "s" || type == "string")
+ ret = n->setStringValue(value.c_str());
+ else if (type == "d" || type == "double")
+ ret = n->setDoubleValue(strtod(value.c_str(), 0));
+ else if (type == "f" || type == "float")
+ ret = n->setFloatValue(atof(value.c_str()));
+ else if (type == "l" || type == "long")
+ ret = n->setLongValue(strtol(value.c_str(), 0, 0));
+ else if (type == "i" || type == "int")
+ ret = n->setIntValue(atoi(value.c_str()));
+ else if (type == "b" || type == "bool")
+ ret = n->setBoolValue(value == "true" || atoi(value.c_str()) != 0);
+
+ if (!writable)
+ n->setAttribute(SGPropertyNode::WRITE, false);
+ return ret;
+}
+
+
// Parse a single option
static int
parse_option (const string& arg)
} else if ( arg.find( "--show-aircraft") == 0) {
return(FG_OPTIONS_SHOW_AIRCRAFT);
} else if ( arg.find( "--prop:" ) == 0 ) {
- string assign = arg.substr(7);
- string::size_type pos = assign.find('=');
- if ( pos == arg.npos || pos == 0 ) {
- SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
- return FG_OPTIONS_ERROR;
- }
- string name = assign.substr(0, pos);
- string value = assign.substr(pos + 1);
- fgSetString(name.c_str(), value.c_str());
- // SG_LOG(SG_GENERAL, SG_INFO, "Setting default value of property "
- // << name << " to \"" << value << '"');
+ if (!set_property(arg.substr(7))) {
+ SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg );
+ return FG_OPTIONS_ERROR;
+ }
} else if ( arg.find( "--" ) == 0 ) {
size_t pos = arg.find( '=' );
- string arg_name;
+ string arg_name, arg_value;
if ( pos == string::npos ) {
arg_name = arg.substr( 2 );
} else {
arg_name = arg.substr( 2, pos - 2 );
+ arg_value = arg.substr( pos + 1);
}
map<string,size_t>::iterator it = fgOptionMap.find( arg_name );
if ( it != fgOptionMap.end() ) {
fgSetBool( pt->property, pt->b_param );
break;
case OPTION_STRING:
- if ( pt->has_param && pos != string::npos ) {
- fgSetString( pt->property, arg.substr( pos + 1 ).c_str() );
- } else if ( !pt->has_param && pos == string::npos ) {
+ if ( pt->has_param && !arg_value.empty() ) {
+ fgSetString( pt->property, arg_value.c_str() );
+ } else if ( !pt->has_param && arg_value.empty() ) {
fgSetString( pt->property, pt->s_param );
} else if ( pt->has_param ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
}
break;
case OPTION_DOUBLE:
- if ( pos != string::npos ) {
- fgSetDouble( pt->property, atof( arg.substr( pos + 1 ) ) );
+ if ( !arg_value.empty() ) {
+ fgSetDouble( pt->property, atof( arg_value ) );
} else {
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
return FG_OPTIONS_ERROR;
}
break;
case OPTION_INT:
- if ( pos != string::npos ) {
- fgSetInt( pt->property, atoi( arg.substr( pos + 1 ) ) );
+ if ( !arg_value.empty() ) {
+ fgSetInt( pt->property, atoi( arg_value ) );
} else {
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
return FG_OPTIONS_ERROR;
}
break;
case OPTION_CHANNEL:
- if ( pt->has_param && pos != string::npos ) {
- add_channel( pt->option, arg.substr( pos + 1 ) );
- } else if ( !pt->has_param && pos == string::npos ) {
+ if ( pt->has_param && !arg_value.empty() ) {
+ add_channel( pt->option, arg_value );
+ } else if ( !pt->has_param && arg_value.empty() ) {
add_channel( pt->option, pt->s_param );
} else if ( pt->has_param ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
}
break;
case OPTION_FUNC:
- if ( pt->has_param && pos != string::npos ) {
- return pt->func( arg.substr( pos + 1 ).c_str() );
- } else if ( !pt->has_param && pos == string::npos ) {
+ if ( pt->has_param && !arg_value.empty() ) {
+ return pt->func( arg_value.c_str() );
+ } else if ( !pt->has_param && arg_value.empty() ) {
return pt->func( 0 );
} else if ( pt->has_param ) {
SG_LOG( SG_GENERAL, SG_ALERT, "Option '" << arg << "' needs a parameter" );
verbose = true;
else if (result == FG_OPTIONS_SHOW_AIRCRAFT) {
+ fgOptLogLevel( "alert" );
SGPath path( globals->get_fg_root() );
path.append("Aircraft");
fgShowAircraft(path, true);
exit(0);
}
+
+ else if (result == FG_OPTIONS_EXIT)
+ exit(0);
}
} else {
in_options = false;
}
if (help) {
+ fgOptLogLevel( "alert" );
fgUsage(verbose);
exit(0);
}
SG_LOG( SG_GENERAL, SG_INFO, "Processing config file: " << path );
in >> skipcomment;
-#ifndef __MWERKS__
while ( ! in.eof() ) {
-#else
- char c = '\0';
- while ( in.get(c) && c != '\0' ) {
- in.putback(c);
-#endif
string line;
-
-#if defined( macintosh )
- getline( in, line, '\r' );
-#else
getline( in, line, '\n' );
-#endif
// catch extraneous (DOS) line ending character
- if ( line[line.length() - 1] < 32 ) {
- line = line.substr( 0, line.length()-1 );
- }
+ int i;
+ for (i = line.length(); i > 0; i--)
+ if (line[i - 1] > 32)
+ break;
+ line = line.substr( 0, i );
if ( parse_option( line ) == FG_OPTIONS_ERROR ) {
cerr << endl << "Config file parse error: " << path << " '"
SGPropertyNode options_root;
+ SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
cout << endl;
try {
fgLoadProps("options.xml", &options_root);
- } catch (const sg_exception &ex) {
+ } catch (const sg_exception &) {
cout << "Unable to read the help file." << endl;
cout << "Make sure the file options.xml is located in the FlightGear base directory," << endl;
cout << "and the location of the base directory is specified by setting $FG_ROOT or" << endl;
SGPropertyNode *short_name = option[k]->getNode("short");
SGPropertyNode *key = option[k]->getNode("key");
SGPropertyNode *arg = option[k]->getNode("arg");
- bool brief = option[k]->getNode("brief");
+ bool brief = option[k]->getNode("brief") != 0;
if ((brief || verbose) && name) {
string tmp = name->getStringValue();
tmp.append(", -");
tmp.append(short_name->getStringValue());
}
-
- char cstr[96];
+
if (tmp.size() <= 25) {
- snprintf(cstr, 96, " --%-27s", tmp.c_str());
+ msg+= " --";
+ msg += tmp;
+ msg.append( 27-tmp.size(), ' ');
} else {
- snprintf(cstr, 96, "\n --%s\n%32c", tmp.c_str(), ' ');
+ msg += "\n --";
+ msg += tmp + '\n';
+ msg.append(32, ' ');
}
-
// There may be more than one <description> tag assosiated
// with one option
- msg += cstr;
- vector<SGPropertyNode_ptr>desc =
- option[k]->getChildren("description");
-
+ vector<SGPropertyNode_ptr> desc;
+ desc = option[k]->getChildren("description");
if (desc.size() > 0) {
for ( unsigned int l = 0; l < desc.size(); l++) {
string t_str = trans_desc[m]->getStringValue();
if ((m > 0) || ((l > 0) && m == 0)) {
- snprintf(cstr, 96, "%32c", ' ');
- msg += cstr;
-
+ msg.append( 32, ' ');
}
// If the string is too large to fit on the screen,
while ( t_str.size() > 47 ) {
unsigned int m = t_str.rfind(' ', 47);
- msg += t_str.substr(0, m);
- snprintf(cstr, 96, "\n%32c", ' ');
- msg += cstr;
+ msg += t_str.substr(0, m) + '\n';
+ msg.append( 32, ' ');
t_str.erase(t_str.begin(), t_str.begin() + m + 1);
}
}
}
- SGPropertyNode *name =
- locale->getNode(section[j]->getStringValue("name"));
+ SGPropertyNode *name;
+ name = locale->getNode(section[j]->getStringValue("name"));
if (!msg.empty() && name) {
cout << endl << name->getStringValue() << ":" << endl;
cout << endl;
cout << "For a complete list of options use --help --verbose" << endl;
}
+#ifdef _MSC_VER
+ cout << "Hit a key to continue..." << endl;
+ cin.get();
+#endif
}
+// 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
+ const char levels[][20]= {"alpha","beta","early-production","production",0};
+
+ for (unsigned int i=0; i<(sizeof(levels)/sizeof(levels[0])-1);i++)
+ if (strcmp(str,levels[i])==0)
+ return i;
+
+ return 0;
+};
+
+
static void fgSearchAircraft(const SGPath &path, string_list &aircraft,
bool recursive)
-{
+{
+
ulDirEnt* dire;
ulDir *dirp = ulOpenDir(path.str().c_str());
if (dirp == NULL) {
- cerr << "Unable to open aircraft directory." << endl;
+ cerr << "Unable to open aircraft directory '" << path.str() << '\'' << endl;
exit(-1);
}
}
SGPropertyNode *desc = NULL;
+ SGPropertyNode *status = NULL;
+
SGPropertyNode *node = root.getNode("sim");
if (node) {
desc = node->getNode("description");
+ // if a status tag is found, read it in
+ if (node->hasValue("status"))
+ status = node->getNode("status");
}
- char cstr[96];
- if (strlen(dire->d_name) <= 27) {
- snprintf(cstr, 96, " %-27s %s", dire->d_name,
- (desc) ? desc->getStringValue() : "" );
-
- } else {
- snprintf(cstr, 96, " %-27s\n%32c%s", dire->d_name, ' ',
- (desc) ? desc->getStringValue() : "" );
+ //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();
}
-
- aircraft.push_back(cstr);
- }
+
+ SGPropertyNode * required_status
+ = 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) {
+ aircraft.push_back(descStr);
+ }
+ 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() ) )
+ aircraft.push_back(descStr); }
+
+ }
+
+
+ }
}
ulCloseDir(dirp);
}
-
/*
* Search in the current directory, and in on directory deeper
* for <aircraft>-set.xml configuration files and show the aircaft name
fgSearchAircraft( path, aircraft, recursive );
sort(aircraft.begin(), aircraft.end());
+ SG_LOG( SG_GENERAL, SG_ALERT, "" ); // To popup the console on Windows
cout << "Available aircraft:" << endl;
for ( unsigned int i = 0; i < aircraft.size(); i++ ) {
cout << aircraft[i] << endl;
}
+#ifdef _MSC_VER
+ cout << "Hit a key to continue..." << endl;
+ cin.get();
+#endif
}