2001-07-02 22:14:09 +00:00
|
|
|
// fg_init.cxx -- Flight Gear top level initialization routines
|
1998-04-25 15:11:10 +00:00
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started August 1997.
|
|
|
|
//
|
2004-11-19 22:10:41 +00:00
|
|
|
// Copyright (C) 1997 Curtis L. Olson - http://www.flightgear.org/~curt
|
1998-04-25 15:11:10 +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-25 15:11:10 +00:00
|
|
|
//
|
|
|
|
// $Id$
|
1997-08-23 01:46:20 +00:00
|
|
|
|
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
1998-04-22 13:25:39 +00:00
|
|
|
|
1997-08-23 01:46:20 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
2002-10-04 13:20:53 +00:00
|
|
|
#include <string.h> // strcmp()
|
1998-07-22 21:40:43 +00:00
|
|
|
|
2010-01-23 22:26:30 +00:00
|
|
|
#ifdef _WIN32
|
2008-10-01 15:03:53 +00:00
|
|
|
# include <io.h> // isatty()
|
|
|
|
# define isatty _isatty
|
2007-06-16 21:35:16 +00:00
|
|
|
#endif
|
2001-03-22 04:02:11 +00:00
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
#include <simgear/compiler.h>
|
1999-02-26 22:08:34 +00:00
|
|
|
|
2008-07-25 18:38:29 +00:00
|
|
|
#include <string>
|
2009-12-05 14:25:31 +00:00
|
|
|
#include <boost/algorithm/string/compare.hpp>
|
|
|
|
#include <boost/algorithm/string/predicate.hpp>
|
1997-08-23 01:46:20 +00:00
|
|
|
|
2000-02-15 03:30:01 +00:00
|
|
|
#include <simgear/constants.h>
|
2000-02-16 23:01:03 +00:00
|
|
|
#include <simgear/debug/logstream.hxx>
|
2003-09-24 17:20:55 +00:00
|
|
|
#include <simgear/structure/exception.hxx>
|
|
|
|
#include <simgear/structure/event_mgr.hxx>
|
2011-11-19 14:37:49 +00:00
|
|
|
#include <simgear/structure/SGPerfMon.hxx>
|
2001-03-25 14:20:12 +00:00
|
|
|
#include <simgear/misc/sg_path.hxx>
|
2010-07-06 20:06:50 +00:00
|
|
|
#include <simgear/misc/sg_dir.hxx>
|
2010-10-20 16:54:16 +00:00
|
|
|
#include <simgear/misc/sgstream.hxx>
|
2011-07-18 09:09:43 +00:00
|
|
|
#include <simgear/misc/strutils.hxx>
|
2011-07-30 09:47:28 +00:00
|
|
|
#include <simgear/props/props_io.hxx>
|
2010-10-20 16:54:16 +00:00
|
|
|
|
2003-05-12 21:34:29 +00:00
|
|
|
#include <simgear/scene/material/matlib.hxx>
|
2008-02-15 06:45:19 +00:00
|
|
|
#include <simgear/scene/model/particles.hxx>
|
2000-02-15 03:30:01 +00:00
|
|
|
|
2008-07-29 08:27:48 +00:00
|
|
|
#include <Aircraft/controls.hxx>
|
2005-11-01 13:41:49 +00:00
|
|
|
#include <Aircraft/replay.hxx>
|
2012-12-10 18:11:44 +00:00
|
|
|
#include <Aircraft/FlightHistory.hxx>
|
2000-08-16 00:09:03 +00:00
|
|
|
#include <Airports/runways.hxx>
|
2013-02-21 11:32:02 +00:00
|
|
|
#include <Airports/airport.hxx>
|
2008-08-14 18:13:39 +00:00
|
|
|
#include <Airports/dynamics.hxx>
|
|
|
|
|
Mathias Fröhlich:
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
|
|
|
#include <AIModel/AIManager.hxx>
|
2009-12-30 14:11:16 +00:00
|
|
|
|
2012-05-12 21:27:57 +00:00
|
|
|
#include <ATCDCL/ATISmgr.hxx>
|
2011-04-03 15:58:16 +00:00
|
|
|
#include <ATC/atc_mgr.hxx>
|
2009-12-30 14:11:16 +00:00
|
|
|
|
2004-01-31 19:47:45 +00:00
|
|
|
#include <Autopilot/route_mgr.hxx>
|
2010-06-24 15:09:33 +00:00
|
|
|
#include <Autopilot/autopilotgroup.hxx>
|
2009-09-21 13:57:39 +00:00
|
|
|
|
User-visible
- knobs now continue to rotate when you hold down the mouse
- the middle mouse button makes knobs rotate much faster
- there are NAV1, NAV2, and ADF radios that can be tuned using the mouse
- there are standby frequencies for NAV1 and NAV2, and buttons to swap
- there is a crude, rather silly-looking DME, hard-wired to NAV1
- there is a crude, rather silly-looking autopilot that can lock
the heading (to the bug on the gyro), can lock to NAV1, and can lock
the current altitude
- the knobs for changing the radials on NAV1 and NAV2 look much better
and are in the right place
- tuning into an ILS frequency doesn't change the displayed radial for
NAV1
Code
- I've created a new module, sp_panel.[ch]xx, that constructs the
default single-prop panel; this works entirely outside of FGPanel,
so it is possible to construct similar modules for other sorts of
panels; all code specific to the default panel has been removed from
panel.cxx
- current_panel is now a pointer
- radiostack.[ch]xx keeps track both of the actual radial and of the
selected radial (they will differ with ILS); the NAV gauges should
not spin around automatically to show the actual radial (we need to
do something similar with the autopilot)
- the panel is initialized fairly early
- make sure that standby frequencies also get initialized
- I've started combining and clipping small textures to save texture
memory; there's a lot more to do, but at least I've made a start
2000-05-02 18:26:00 +00:00
|
|
|
#include <Cockpit/panel.hxx>
|
2000-09-22 17:20:56 +00:00
|
|
|
#include <Cockpit/panel_io.hxx>
|
2009-12-30 14:11:16 +00:00
|
|
|
|
2012-04-21 13:31:20 +00:00
|
|
|
#include <Canvas/canvas_mgr.hxx>
|
2012-07-27 11:17:42 +00:00
|
|
|
#include <Canvas/gui_mgr.hxx>
|
2002-11-07 16:27:47 +00:00
|
|
|
#include <GUI/new_gui.hxx>
|
I'm attaching diffs to add a new FGInput module to FlightGear
(src/Input). So far, FGInput replaces most of src/Main/keyboard.cxx
(I've left a tiny stub); in the very near future, it will also take
over control of the joystick, mouse (Norm permitting), and panel
instrument interactions, so that there is a single mechanism for
configuring all input devices.
The new format should be (close to) self-explanatory by looking at the
new base-package file keyboard.xml, which is now included by
preferences.xml (I'll do the same thing for the joystick when I have a
chance). I have not managed to move all keybindings into this file
yet, but I've made a good start. I'm including Tony in the recipient
list so that he can see how bindings can use an external XML file.
This patch also adds support for multiple bindings for a single key,
special keys (i.e. keypad and function keys), and key modifiers
(shift/alt/ctrl); special keys use the PUI convention of adding 256 to
the Glut key code.
Unfortunately, everything comes with a price; in this case, I have not
yet found a general mechanism for the old (hard-coded) modal bindings,
which behaved differently depending on the autopilot state (i.e. left
rudder or move AP heading left); with my patches, this functionality
disappears, but you can still adjust the autopilot using the panel or
the GUI input dialogs.
2001-05-23 23:01:15 +00:00
|
|
|
#include <Input/input.hxx>
|
2002-09-24 14:51:37 +00:00
|
|
|
#include <Instrumentation/instrument_mgr.hxx>
|
2002-04-09 18:58:24 +00:00
|
|
|
#include <Model/acmodel.hxx>
|
2010-10-22 11:22:00 +00:00
|
|
|
#include <Model/modelmgr.hxx>
|
2004-10-22 09:58:24 +00:00
|
|
|
#include <AIModel/submodel.hxx>
|
2003-11-28 15:48:05 +00:00
|
|
|
#include <AIModel/AIManager.hxx>
|
2004-05-28 05:24:54 +00:00
|
|
|
#include <Navaids/navdb.hxx>
|
2000-04-24 23:51:26 +00:00
|
|
|
#include <Navaids/navlist.hxx>
|
1998-04-30 12:34:17 +00:00
|
|
|
#include <Scenery/scenery.hxx>
|
1998-04-22 13:25:39 +00:00
|
|
|
#include <Scenery/tilemgr.hxx>
|
2003-11-25 21:08:36 +00:00
|
|
|
#include <Scripting/NasalSys.hxx>
|
2006-02-11 12:02:40 +00:00
|
|
|
#include <Sound/voice.hxx>
|
2012-09-17 11:36:38 +00:00
|
|
|
#include <Sound/soundmanager.hxx>
|
2002-09-23 19:55:10 +00:00
|
|
|
#include <Systems/system_mgr.hxx>
|
1998-04-22 13:25:39 +00:00
|
|
|
#include <Time/light.hxx>
|
2004-06-03 17:59:14 +00:00
|
|
|
#include <Traffic/TrafficMgr.hxx>
|
2005-11-01 13:41:49 +00:00
|
|
|
#include <MultiPlayer/multiplaymgr.hxx>
|
2010-06-16 07:31:59 +00:00
|
|
|
#include <FDM/fdm_shell.hxx>
|
2011-11-05 13:18:36 +00:00
|
|
|
#include <Environment/ephemeris.hxx>
|
2004-03-16 20:19:07 +00:00
|
|
|
#include <Environment/environment_mgr.hxx>
|
2012-04-25 21:28:00 +00:00
|
|
|
#include <Viewer/renderer.hxx>
|
|
|
|
#include <Viewer/viewmgr.hxx>
|
2012-08-27 23:26:36 +00:00
|
|
|
#include <Navaids/NavDataCache.hxx>
|
2012-09-26 16:02:11 +00:00
|
|
|
#include <Instrumentation/HUD/HUD.hxx>
|
2012-09-26 19:30:24 +00:00
|
|
|
#include <Cockpit/cockpitDisplayManager.hxx>
|
2012-11-19 11:30:12 +00:00
|
|
|
#include <Network/HTTPClient.hxx>
|
1997-08-23 01:46:20 +00:00
|
|
|
|
1998-04-22 13:25:39 +00:00
|
|
|
#include "fg_init.hxx"
|
1999-11-19 02:10:24 +00:00
|
|
|
#include "fg_io.hxx"
|
2001-06-01 17:52:28 +00:00
|
|
|
#include "fg_commands.hxx"
|
2001-06-05 22:12:08 +00:00
|
|
|
#include "fg_props.hxx"
|
2013-03-16 15:43:55 +00:00
|
|
|
#include "FGInterpolator.hxx"
|
2001-01-13 22:06:39 +00:00
|
|
|
#include "options.hxx"
|
2000-07-08 06:29:19 +00:00
|
|
|
#include "globals.hxx"
|
2002-03-12 16:29:00 +00:00
|
|
|
#include "logger.hxx"
|
2005-12-21 13:36:04 +00:00
|
|
|
#include "main.hxx"
|
2012-09-18 19:50:28 +00:00
|
|
|
#include "positioninit.hxx"
|
2013-04-29 20:15:32 +00:00
|
|
|
#include "util.hxx"
|
1998-04-22 13:25:39 +00:00
|
|
|
|
2008-07-27 16:25:13 +00:00
|
|
|
using std::string;
|
2012-11-23 20:00:20 +00:00
|
|
|
using std::endl;
|
|
|
|
using std::cerr;
|
|
|
|
using std::cout;
|
2009-12-05 14:25:31 +00:00
|
|
|
using namespace boost::algorithm;
|
2003-05-09 18:44:33 +00:00
|
|
|
|
2002-11-16 20:17:11 +00:00
|
|
|
|
2001-07-16 19:17:58 +00:00
|
|
|
// Return the current base package version
|
|
|
|
string fgBasePackageVersion() {
|
|
|
|
SGPath base_path( globals->get_fg_root() );
|
|
|
|
base_path.append("version");
|
|
|
|
|
|
|
|
sg_gzifstream in( base_path.str() );
|
|
|
|
if ( !in.is_open() ) {
|
2002-10-04 13:20:53 +00:00
|
|
|
SGPath old_path( globals->get_fg_root() );
|
|
|
|
old_path.append( "Thanks" );
|
|
|
|
sg_gzifstream old( old_path.str() );
|
|
|
|
if ( !old.is_open() ) {
|
|
|
|
return "[none]";
|
|
|
|
} else {
|
|
|
|
return "[old version]";
|
|
|
|
}
|
2001-07-16 19:17:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
string version;
|
|
|
|
in >> version;
|
|
|
|
|
|
|
|
return version;
|
|
|
|
}
|
|
|
|
|
2002-10-10 15:02:50 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
template <class T>
|
2010-07-18 12:21:30 +00:00
|
|
|
bool fgFindAircraftInDir(const SGPath& dirPath, T* obj, bool (T::*pred)(const SGPath& p))
|
2007-04-05 19:59:44 +00:00
|
|
|
{
|
2010-07-06 20:06:50 +00:00
|
|
|
if (!dirPath.exists()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "fgFindAircraftInDir: no such path:" << dirPath.str());
|
2010-07-18 12:21:30 +00:00
|
|
|
return false;
|
2010-07-06 20:06:50 +00:00
|
|
|
}
|
2010-07-18 12:21:30 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
bool recurse = true;
|
|
|
|
simgear::Dir dir(dirPath);
|
|
|
|
simgear::PathList setFiles(dir.children(simgear::Dir::TYPE_FILE, "-set.xml"));
|
|
|
|
simgear::PathList::iterator p;
|
|
|
|
for (p = setFiles.begin(); p != setFiles.end(); ++p) {
|
|
|
|
// check file name ends with -set.xml
|
|
|
|
|
|
|
|
// if we found a -set.xml at this level, don't recurse any deeper
|
|
|
|
recurse = false;
|
|
|
|
|
|
|
|
bool done = (obj->*pred)(*p);
|
|
|
|
if (done) {
|
2010-07-18 12:21:30 +00:00
|
|
|
return true;
|
2003-09-19 20:06:27 +00:00
|
|
|
}
|
2010-07-06 20:06:50 +00:00
|
|
|
} // of -set.xml iteration
|
|
|
|
|
2010-07-18 12:21:30 +00:00
|
|
|
if (!recurse) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
simgear::PathList subdirs(dir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT));
|
|
|
|
for (p = subdirs.begin(); p != subdirs.end(); ++p) {
|
|
|
|
if (p->file() == "CVS") {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fgFindAircraftInDir(*p, obj, pred)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
} // of subdirs iteration
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
void fgFindAircraft(T* obj, bool (T::*pred)(const SGPath& p))
|
|
|
|
{
|
|
|
|
const string_list& paths(globals->get_aircraft_paths());
|
|
|
|
string_list::const_iterator it = paths.begin();
|
|
|
|
for (; it != paths.end(); ++it) {
|
|
|
|
bool done = fgFindAircraftInDir(SGPath(*it), obj, pred);
|
|
|
|
if (done) {
|
|
|
|
return;
|
2010-07-06 20:06:50 +00:00
|
|
|
}
|
2010-07-18 12:21:30 +00:00
|
|
|
} // of aircraft paths iteration
|
|
|
|
|
|
|
|
// if we reach this point, search the default location (always last)
|
|
|
|
SGPath rootAircraft(globals->get_fg_root());
|
|
|
|
rootAircraft.append("Aircraft");
|
|
|
|
fgFindAircraftInDir(rootAircraft, obj, pred);
|
2010-07-06 20:06:50 +00:00
|
|
|
}
|
2003-09-19 20:06:27 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
class FindAndCacheAircraft
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
FindAndCacheAircraft(SGPropertyNode* autoSave)
|
|
|
|
{
|
|
|
|
_cache = autoSave->getNode("sim/startup/path-cache", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool loadAircraft()
|
|
|
|
{
|
2010-11-29 21:48:37 +00:00
|
|
|
std::string aircraft = fgGetString( "/sim/aircraft", "");
|
2010-07-06 20:06:50 +00:00
|
|
|
if (aircraft.empty()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "no aircraft specified");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_searchAircraft = aircraft + "-set.xml";
|
2011-10-16 20:15:54 +00:00
|
|
|
std::string aircraftDir = fgGetString("/sim/aircraft-dir", "");
|
|
|
|
if (!aircraftDir.empty()) {
|
|
|
|
// aircraft-dir was set, skip any searching at all, if it's valid
|
|
|
|
simgear::Dir acPath(aircraftDir);
|
|
|
|
SGPath setFile = acPath.file(_searchAircraft);
|
|
|
|
if (setFile.exists()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "found aircraft in dir: " << aircraftDir );
|
|
|
|
|
|
|
|
try {
|
|
|
|
readProperties(setFile.str(), globals->get_props());
|
|
|
|
} catch ( const sg_exception &e ) {
|
|
|
|
SG_LOG(SG_INPUT, SG_ALERT, "Error reading aircraft: " << e.getFormattedMessage());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "aircraft '" << _searchAircraft <<
|
|
|
|
"' not found in specified dir:" << aircraftDir);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
if (!checkCache()) {
|
|
|
|
// prepare cache for re-scan
|
|
|
|
SGPropertyNode *n = _cache->getNode("fg-root", true);
|
|
|
|
n->setStringValue(globals->get_fg_root().c_str());
|
|
|
|
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
2010-11-29 21:48:37 +00:00
|
|
|
n = _cache->getNode("fg-aircraft", true);
|
|
|
|
n->setStringValue(getAircraftPaths().c_str());
|
|
|
|
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
2010-07-06 20:06:50 +00:00
|
|
|
_cache->removeChildren("aircraft");
|
2010-07-18 12:21:30 +00:00
|
|
|
|
|
|
|
fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft);
|
2010-07-06 20:06:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (_foundPath.str().empty()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "Cannot find specified aircraft: " << aircraft );
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Loading aircraft -set file from:" << _foundPath.str());
|
|
|
|
fgSetString( "/sim/aircraft-dir", _foundPath.dir().c_str());
|
|
|
|
if (!_foundPath.exists()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to find -set file:" << _foundPath.str());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
|
|
|
readProperties(_foundPath.str(), globals->get_props());
|
|
|
|
} catch ( const sg_exception &e ) {
|
|
|
|
SG_LOG(SG_INPUT, SG_ALERT, "Error reading aircraft: " << e.getFormattedMessage());
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2010-11-29 21:48:37 +00:00
|
|
|
SGPath getAircraftPaths() {
|
|
|
|
string_list pathList = globals->get_aircraft_paths();
|
|
|
|
SGPath aircraftPaths;
|
|
|
|
string_list::const_iterator it = pathList.begin();
|
|
|
|
if (it != pathList.end()) {
|
|
|
|
aircraftPaths.set(*it);
|
|
|
|
it++;
|
|
|
|
}
|
|
|
|
for (; it != pathList.end(); ++it) {
|
|
|
|
aircraftPaths.add(*it);
|
|
|
|
}
|
|
|
|
return aircraftPaths;
|
|
|
|
}
|
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
bool checkCache()
|
|
|
|
{
|
|
|
|
if (globals->get_fg_root() != _cache->getStringValue("fg-root", "")) {
|
|
|
|
return false; // cache mismatch
|
|
|
|
}
|
2010-11-29 21:48:37 +00:00
|
|
|
|
|
|
|
if (getAircraftPaths().str() != _cache->getStringValue("fg-aircraft", "")) {
|
|
|
|
return false; // cache mismatch
|
|
|
|
}
|
2010-07-06 20:06:50 +00:00
|
|
|
|
|
|
|
vector<SGPropertyNode_ptr> cache = _cache->getChildren("aircraft");
|
|
|
|
for (unsigned int i = 0; i < cache.size(); i++) {
|
|
|
|
const char *name = cache[i]->getStringValue("file", "");
|
|
|
|
if (!boost::equals(_searchAircraft, name, is_iequal())) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPath xml(cache[i]->getStringValue("path", ""));
|
|
|
|
xml.append(name);
|
|
|
|
if (xml.exists()) {
|
|
|
|
_foundPath = xml;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
} // of aircraft in cache iteration
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool checkAircraft(const SGPath& p)
|
|
|
|
{
|
|
|
|
// create cache node
|
|
|
|
int i = 0;
|
|
|
|
while (1) {
|
|
|
|
if (!_cache->getChild("aircraft", i++, false))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPropertyNode *n, *entry = _cache->getChild("aircraft", --i, true);
|
2007-04-02 23:19:36 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
std::string fileName(p.file());
|
|
|
|
n = entry->getNode("file", true);
|
|
|
|
n->setStringValue(fileName);
|
|
|
|
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
2007-04-02 23:19:36 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
n = entry->getNode("path", true);
|
|
|
|
n->setStringValue(p.dir());
|
|
|
|
n->setAttribute(SGPropertyNode::USERARCHIVE, true);
|
2007-04-02 23:19:36 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
if ( boost::equals(fileName, _searchAircraft.c_str(), is_iequal()) ) {
|
|
|
|
_foundPath = p;
|
|
|
|
return true;
|
2003-09-19 20:06:27 +00:00
|
|
|
}
|
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string _searchAircraft;
|
|
|
|
SGPath _foundPath;
|
|
|
|
SGPropertyNode* _cache;
|
|
|
|
};
|
2003-09-19 20:06:27 +00:00
|
|
|
|
2011-10-16 18:55:04 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
static SGPath platformDefaultDataPath()
|
|
|
|
{
|
|
|
|
char *envp = ::getenv( "APPDATA" );
|
|
|
|
SGPath config( envp );
|
|
|
|
config.append( "flightgear.org" );
|
2011-10-16 18:58:22 +00:00
|
|
|
return config;
|
2011-10-16 18:55:04 +00:00
|
|
|
}
|
2013-05-04 09:58:22 +00:00
|
|
|
|
2013-06-19 23:03:36 +00:00
|
|
|
#elif __APPLE__
|
2011-10-16 18:55:04 +00:00
|
|
|
#include <CoreServices/CoreServices.h>
|
|
|
|
|
|
|
|
static SGPath platformDefaultDataPath()
|
|
|
|
{
|
|
|
|
FSRef ref;
|
|
|
|
OSErr err = FSFindFolder(kUserDomain, kApplicationSupportFolderType, false, &ref);
|
|
|
|
if (err) {
|
|
|
|
return SGPath();
|
|
|
|
}
|
2013-06-10 19:42:53 +00:00
|
|
|
|
2011-10-16 18:55:04 +00:00
|
|
|
unsigned char path[1024];
|
|
|
|
if (FSRefMakePath(&ref, path, 1024) != noErr) {
|
|
|
|
return SGPath();
|
|
|
|
}
|
2013-06-10 19:42:53 +00:00
|
|
|
|
2011-10-16 18:55:04 +00:00
|
|
|
SGPath appData;
|
|
|
|
appData.set((const char*) path);
|
2012-01-05 22:10:19 +00:00
|
|
|
appData.append("FlightGear");
|
2011-10-16 18:55:04 +00:00
|
|
|
return appData;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static SGPath platformDefaultDataPath()
|
|
|
|
{
|
2013-06-10 19:42:53 +00:00
|
|
|
return SGPath::home() / ".fgfs";
|
2011-10-16 18:55:04 +00:00
|
|
|
}
|
2013-06-10 19:42:53 +00:00
|
|
|
#endif
|
2011-10-16 18:55:04 +00:00
|
|
|
|
2013-02-08 11:43:51 +00:00
|
|
|
void fgInitHome()
|
2011-10-21 15:49:15 +00:00
|
|
|
{
|
2013-06-10 19:42:53 +00:00
|
|
|
SGPath dataPath = SGPath::fromEnv("FG_HOME", platformDefaultDataPath());
|
|
|
|
globals->set_fg_home(dataPath.c_str());
|
2013-06-16 16:44:08 +00:00
|
|
|
|
|
|
|
simgear::Dir fgHome(dataPath);
|
|
|
|
if (!fgHome.exists()) {
|
|
|
|
fgHome.create(0755);
|
|
|
|
}
|
2013-02-08 11:43:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Read in configuration (file and command line)
|
|
|
|
bool fgInitConfig ( int argc, char **argv )
|
|
|
|
{
|
|
|
|
SGPath dataPath = globals->get_fg_home();
|
2013-06-16 16:44:08 +00:00
|
|
|
|
2011-10-16 18:55:04 +00:00
|
|
|
simgear::Dir exportDir(simgear::Dir(dataPath).file("Export"));
|
|
|
|
if (!exportDir.exists()) {
|
|
|
|
exportDir.create(0777);
|
|
|
|
}
|
2011-10-21 15:49:15 +00:00
|
|
|
|
2011-10-16 18:55:04 +00:00
|
|
|
// Set /sim/fg-home and don't allow malign code to override it until
|
|
|
|
// Nasal security is set up. Use FG_HOME if necessary.
|
|
|
|
SGPropertyNode *home = fgGetNode("/sim", true);
|
|
|
|
home->removeChild("fg-home", 0, false);
|
|
|
|
home = home->getChild("fg-home", 0, true);
|
|
|
|
home->setStringValue(dataPath.c_str());
|
|
|
|
home->setAttribute(SGPropertyNode::WRITE, false);
|
2011-10-21 15:49:15 +00:00
|
|
|
|
2012-09-29 18:02:03 +00:00
|
|
|
flightgear::Options* options = flightgear::Options::sharedInstance();
|
|
|
|
options->init(argc, argv, dataPath);
|
|
|
|
bool loadDefaults = flightgear::Options::sharedInstance()->shouldLoadDefaultConfig();
|
|
|
|
if (loadDefaults) {
|
|
|
|
// Read global preferences from $FG_ROOT/preferences.xml
|
|
|
|
SG_LOG(SG_INPUT, SG_INFO, "Reading global preferences");
|
|
|
|
fgLoadProps("preferences.xml", globals->get_props());
|
|
|
|
SG_LOG(SG_INPUT, SG_INFO, "Finished Reading global preferences");
|
|
|
|
|
|
|
|
// do not load user settings when reset to default is requested
|
|
|
|
if (flightgear::Options::sharedInstance()->isOptionSet("restore-defaults"))
|
|
|
|
{
|
|
|
|
SG_LOG(SG_ALL, SG_ALERT, "Ignoring user settings. Restoring defaults.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
globals->loadUserSettings(dataPath);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "not reading default configuration files");
|
|
|
|
}// of no-default-config selected
|
2011-10-21 15:49:15 +00:00
|
|
|
|
2011-12-29 23:39:08 +00:00
|
|
|
// Scan user config files and command line for a specified aircraft.
|
2012-09-29 18:02:03 +00:00
|
|
|
options->initAircraft();
|
2011-12-29 23:39:08 +00:00
|
|
|
|
2011-12-30 00:01:15 +00:00
|
|
|
FindAndCacheAircraft f(globals->get_props());
|
2010-07-06 20:06:50 +00:00
|
|
|
if (!f.loadAircraft()) {
|
|
|
|
return false;
|
2002-10-10 15:02:50 +00:00
|
|
|
}
|
|
|
|
|
2002-11-16 20:17:11 +00:00
|
|
|
// parse options after loading aircraft to ensure any user
|
|
|
|
// overrides of defaults are honored.
|
2012-09-29 18:02:03 +00:00
|
|
|
options->processOptions();
|
2011-10-16 17:35:40 +00:00
|
|
|
|
2002-10-10 15:02:50 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-08-27 23:26:36 +00:00
|
|
|
|
|
|
|
|
2003-02-21 02:45:47 +00:00
|
|
|
/**
|
2003-08-28 20:53:08 +00:00
|
|
|
* Initialize vor/ndb/ils/fix list management and query systems (as
|
|
|
|
* well as simple airport db list)
|
2012-09-25 16:24:12 +00:00
|
|
|
* This is called multiple times in the case of a cache rebuild,
|
|
|
|
* to allow length caching to take place in the background, without
|
|
|
|
* blocking the main/UI thread.
|
2003-02-21 02:45:47 +00:00
|
|
|
*/
|
|
|
|
bool
|
|
|
|
fgInitNav ()
|
|
|
|
{
|
2012-08-27 23:26:36 +00:00
|
|
|
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
2012-09-25 16:24:12 +00:00
|
|
|
static bool doingRebuild = false;
|
|
|
|
if (doingRebuild || cache->isRebuildRequired()) {
|
|
|
|
doingRebuild = true;
|
|
|
|
bool finished = cache->rebuild();
|
|
|
|
if (!finished) {
|
|
|
|
// sleep to give the rebuild thread more time
|
|
|
|
SGTimeStamp::sleepForMSec(50);
|
|
|
|
return false;
|
|
|
|
}
|
2012-08-27 23:26:36 +00:00
|
|
|
}
|
2012-09-18 19:50:28 +00:00
|
|
|
|
|
|
|
FGTACANList *channellist = new FGTACANList;
|
|
|
|
globals->set_channellist( channellist );
|
|
|
|
|
2012-08-27 23:26:36 +00:00
|
|
|
SGPath path(globals->get_fg_root());
|
|
|
|
path.append( "Navaids/TACAN_freq.dat" );
|
|
|
|
flightgear::loadTacan(path, channellist);
|
2012-09-18 19:50:28 +00:00
|
|
|
|
|
|
|
return true;
|
2002-11-16 21:34:51 +00:00
|
|
|
}
|
|
|
|
|
1998-04-25 15:11:10 +00:00
|
|
|
// General house keeping initializations
|
2002-11-16 21:34:51 +00:00
|
|
|
bool fgInitGeneral() {
|
1998-08-27 17:01:55 +00:00
|
|
|
string root;
|
1999-11-19 02:10:24 +00:00
|
|
|
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "General Initialization" );
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "======= ==============" );
|
1998-04-25 20:24:00 +00:00
|
|
|
|
2001-01-13 22:06:39 +00:00
|
|
|
root = globals->get_fg_root();
|
1998-09-08 21:40:08 +00:00
|
|
|
if ( ! root.length() ) {
|
2002-10-04 13:20:53 +00:00
|
|
|
// No root path set? Then bail ...
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
|
|
|
"Cannot continue without a path to the base package "
|
|
|
|
<< "being defined." );
|
|
|
|
exit(-1);
|
1998-04-25 15:11:10 +00:00
|
|
|
}
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "FG_ROOT = " << '"' << root << '"' << endl );
|
1998-04-25 15:11:10 +00:00
|
|
|
|
2012-08-18 12:11:31 +00:00
|
|
|
// Note: browser command is hard-coded for Mac/Windows, so this only affects other platforms
|
|
|
|
globals->set_browser(fgGetString("/sim/startup/browser-app", WEB_BROWSER));
|
|
|
|
fgSetString("/sim/startup/browser-app", globals->get_browser());
|
2008-07-09 19:35:53 +00:00
|
|
|
|
2012-05-31 07:57:22 +00:00
|
|
|
simgear::Dir cwd(simgear::Dir::current());
|
2008-06-22 11:29:32 +00:00
|
|
|
SGPropertyNode *curr = fgGetNode("/sim", true);
|
|
|
|
curr->removeChild("fg-current", 0, false);
|
|
|
|
curr = curr->getChild("fg-current", 0, true);
|
2012-05-31 07:57:22 +00:00
|
|
|
curr->setStringValue(cwd.path().str());
|
2008-06-22 11:29:32 +00:00
|
|
|
curr->setAttribute(SGPropertyNode::WRITE, false);
|
2008-10-01 15:03:53 +00:00
|
|
|
|
2010-08-18 16:50:07 +00:00
|
|
|
fgSetBool("/sim/startup/stdout-to-terminal", isatty(1) != 0 );
|
|
|
|
fgSetBool("/sim/startup/stderr-to-terminal", isatty(2) != 0 );
|
1999-06-18 03:42:54 +00:00
|
|
|
return true;
|
1998-04-25 15:11:10 +00:00
|
|
|
}
|
|
|
|
|
2013-02-08 13:15:20 +00:00
|
|
|
// Write various configuraton values out to the logs
|
|
|
|
void fgOutputSettings()
|
|
|
|
{
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Configuration State" );
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "======= ==============" );
|
|
|
|
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "aircraft-dir = " << '"' << fgGetString("/sim/aircraft-dir") << '"' );
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "fghome-dir = " << '"' << globals->get_fg_home() << '"');
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "aircraft-dir = " << '"' << fgGetString("/sim/aircraft-dir") << '"');
|
|
|
|
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "aircraft-search-paths = \n\t" << simgear::strutils::join(globals->get_aircraft_paths(), "\n\t") );
|
2013-02-11 12:51:54 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "scenery-search-paths = \n\t" << simgear::strutils::join(globals->get_fg_scenery(), "\n\t") );
|
2013-02-08 13:15:20 +00:00
|
|
|
}
|
|
|
|
|
1998-04-25 15:11:10 +00:00
|
|
|
// This is the top level init routine which calls all the other
|
|
|
|
// initialization routines. If you are adding a subsystem to flight
|
|
|
|
// gear, its initialization call should located in this routine.
|
|
|
|
// Returns non-zero if a problem encountered.
|
2012-09-18 19:29:36 +00:00
|
|
|
void fgCreateSubsystems() {
|
2009-10-24 09:22:20 +00:00
|
|
|
|
2012-09-18 19:29:36 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Creating Subsystems");
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "========== ==========");
|
1998-04-25 15:11:10 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the sound subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Sound manager uses an own subsystem group "SOUND" which is the last
|
|
|
|
// to be updated in every loop.
|
|
|
|
// Sound manager is updated last so it can use the CPU while the GPU
|
|
|
|
// is processing the scenery (doubled the frame-rate for me) -EMH-
|
2012-09-17 11:36:38 +00:00
|
|
|
globals->add_subsystem("sound", new FGSoundManager, SGSubsystemMgr::SOUND);
|
2011-11-20 15:20:05 +00:00
|
|
|
|
2003-09-24 17:20:55 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the event manager subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2004-11-18 05:00:44 +00:00
|
|
|
globals->get_event_mgr()->init();
|
2005-11-09 20:34:46 +00:00
|
|
|
globals->get_event_mgr()->setRealtimeProperty(fgGetNode("/sim/time/delta-realtime-sec", true));
|
2001-04-05 20:20:44 +00:00
|
|
|
|
2003-12-05 01:52:34 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2007-05-01 18:06:48 +00:00
|
|
|
// Initialize the property interpolator subsystem. Put into the INIT
|
|
|
|
// group because the "nasal" subsystem may need it at GENERAL take-down.
|
2003-12-05 01:52:34 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2013-03-17 22:48:42 +00:00
|
|
|
FGInterpolator* interp = new FGInterpolator;
|
|
|
|
interp->setRealtimeProperty(fgGetNode("/sim/time/delta-realtime-sec", true));
|
|
|
|
globals->add_subsystem("prop-interpolator", interp, SGSubsystemMgr::INIT);
|
|
|
|
SGPropertyNode::setInterpolationMgr(interp);
|
2004-02-20 17:35:33 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Add the FlightGear property utilities.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->add_subsystem("properties", new FGProperties);
|
2003-12-05 01:52:34 +00:00
|
|
|
|
2011-11-19 14:37:49 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Add the performance monitoring system.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->add_subsystem("performance-mon",
|
|
|
|
new SGPerformanceMonitor(globals->get_subsystem_mgr(),
|
2011-11-19 21:37:13 +00:00
|
|
|
fgGetNode("/sim/performance-monitor", true)));
|
2011-11-19 14:37:49 +00:00
|
|
|
|
2001-04-05 20:20:44 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the material property subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2001-03-25 14:20:12 +00:00
|
|
|
SGPath mpath( globals->get_fg_root() );
|
2011-09-02 18:26:55 +00:00
|
|
|
mpath.append( fgGetString("/sim/rendering/materials-file") );
|
2009-05-22 18:20:58 +00:00
|
|
|
if ( ! globals->get_matlib()->load(globals->get_fg_root(), mpath.str(),
|
2008-02-15 17:54:23 +00:00
|
|
|
globals->get_props()) ) {
|
2011-09-02 18:26:55 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
|
|
|
"Error loading materials file " << mpath.str() );
|
2002-10-04 13:20:53 +00:00
|
|
|
exit(-1);
|
2000-06-23 00:30:04 +00:00
|
|
|
}
|
|
|
|
|
2012-12-09 19:41:31 +00:00
|
|
|
globals->add_subsystem( "http", new FGHTTPClient );
|
|
|
|
|
2001-04-05 20:20:44 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the scenery management subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2008-02-15 06:45:38 +00:00
|
|
|
globals->get_scenery()->get_scene_graph()
|
|
|
|
->addChild(simgear::Particles::getCommonRoot());
|
2008-10-17 21:25:03 +00:00
|
|
|
simgear::GlobalParticleCallback::setSwitch(fgGetNode("/sim/rendering/particles", true));
|
2008-02-15 06:45:19 +00:00
|
|
|
|
2001-04-05 20:20:44 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the flight model subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2010-06-16 07:31:59 +00:00
|
|
|
globals->add_subsystem("flight", new FDMShell, SGSubsystemMgr::FDM);
|
2007-11-03 21:02:28 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the weather subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// Initialize the weather modeling subsystem
|
|
|
|
globals->add_subsystem("environment", new FGEnvironmentMgr);
|
2011-11-05 13:18:36 +00:00
|
|
|
globals->add_subsystem("ephemeris", new Ephemeris);
|
|
|
|
|
2006-06-24 03:42:30 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the aircraft systems and instrumentation (before the
|
|
|
|
// autopilot.)
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2010-06-16 07:31:59 +00:00
|
|
|
globals->add_subsystem("systems", new FGSystemMgr, SGSubsystemMgr::FDM);
|
2012-09-19 18:53:54 +00:00
|
|
|
globals->add_subsystem("instrumentation", new FGInstrumentMgr, SGSubsystemMgr::FDM);
|
2012-09-26 16:02:11 +00:00
|
|
|
globals->add_subsystem("hud", new HUD, SGSubsystemMgr::DISPLAY);
|
2012-09-26 19:30:24 +00:00
|
|
|
globals->add_subsystem("cockpit-displays", new flightgear::CockpitDisplayManager, SGSubsystemMgr::DISPLAY);
|
2012-09-26 16:02:11 +00:00
|
|
|
|
2004-01-31 19:47:45 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the XML Autopilot subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-04-05 18:40:07 +00:00
|
|
|
globals->add_subsystem( "xml-autopilot", FGXMLAutopilotGroup::createInstance("autopilot"), SGSubsystemMgr::FDM );
|
|
|
|
globals->add_subsystem( "xml-proprules", FGXMLAutopilotGroup::createInstance("property-rule"), SGSubsystemMgr::GENERAL );
|
2004-01-31 19:47:45 +00:00
|
|
|
globals->add_subsystem( "route-manager", new FGRouteMgr );
|
2002-04-13 13:11:34 +00:00
|
|
|
|
2009-09-07 07:27:38 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the Input-Output subsystem
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->add_subsystem( "io", new FGIO );
|
2012-11-19 11:30:12 +00:00
|
|
|
|
2002-03-12 16:29:00 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2002-11-07 16:27:47 +00:00
|
|
|
// Create and register the logger.
|
2002-03-12 16:29:00 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2003-01-16 16:01:26 +00:00
|
|
|
globals->add_subsystem("logger", new FGLogger);
|
2002-03-12 16:29:00 +00:00
|
|
|
|
2002-11-07 16:27:47 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Create and register the XML GUI.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2003-09-24 17:20:55 +00:00
|
|
|
globals->add_subsystem("gui", new NewGUI, SGSubsystemMgr::INIT);
|
2002-11-07 16:27:47 +00:00
|
|
|
|
2004-05-20 13:27:40 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the 2D cloud subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2004-10-20 08:18:29 +00:00
|
|
|
fgGetBool("/sim/rendering/bump-mapping", false);
|
2003-09-24 17:20:55 +00:00
|
|
|
|
2012-04-21 13:31:20 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the canvas 2d drawing subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2012-07-04 11:15:12 +00:00
|
|
|
globals->add_subsystem("Canvas", new CanvasMgr, SGSubsystemMgr::DISPLAY);
|
2012-07-27 11:17:42 +00:00
|
|
|
globals->add_subsystem("CanvasGUI", new GUIMgr, SGSubsystemMgr::DISPLAY);
|
2012-04-21 13:31:20 +00:00
|
|
|
|
2001-11-07 17:55:28 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2012-05-12 21:27:57 +00:00
|
|
|
// Initialise the ATIS Manager
|
|
|
|
// Note that this is old stuff, but is necessary for the
|
2011-04-03 15:58:16 +00:00
|
|
|
// current ATIS implementation. Therefore, leave it in here
|
|
|
|
// until the ATIS system is ported over to make use of the ATIS
|
|
|
|
// sub system infrastructure.
|
2002-03-01 17:39:52 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-05-12 21:27:57 +00:00
|
|
|
globals->add_subsystem("ATIS", new FGATISMgr, SGSubsystemMgr::INIT, 0.4);
|
2010-12-28 18:08:41 +00:00
|
|
|
|
2010-08-01 14:16:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2011-04-03 15:58:16 +00:00
|
|
|
// Initialize the ATC subsystem
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->add_subsystem("ATC", new FGATCManager, SGSubsystemMgr::POST_FDM);
|
2010-10-02 22:40:38 +00:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize multiplayer subsystem
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
globals->add_subsystem("mp", new FGMultiplayMgr, SGSubsystemMgr::POST_FDM);
|
|
|
|
|
2003-11-28 15:48:05 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialise the AI Model Manager
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, " AI Model Manager");
|
2011-11-19 14:37:49 +00:00
|
|
|
globals->add_subsystem("ai-model", new FGAIManager, SGSubsystemMgr::POST_FDM);
|
|
|
|
globals->add_subsystem("submodel-mgr", new FGSubmodelMgr, SGSubsystemMgr::POST_FDM);
|
2003-11-28 15:48:05 +00:00
|
|
|
|
|
|
|
|
2007-04-04 19:05:59 +00:00
|
|
|
// It's probably a good idea to initialize the top level traffic manager
|
|
|
|
// After the AI and ATC systems have been initialized properly.
|
|
|
|
// AI Traffic manager
|
2011-11-19 14:37:49 +00:00
|
|
|
globals->add_subsystem("traffic-manager", new FGTrafficManager, SGSubsystemMgr::POST_FDM);
|
2004-06-03 17:59:14 +00:00
|
|
|
|
2003-03-30 12:46:08 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Add a new 2D panel.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-05-16 10:43:09 +00:00
|
|
|
fgSetArchivable("/sim/panel/visibility");
|
|
|
|
fgSetArchivable("/sim/panel/x-offset");
|
|
|
|
fgSetArchivable("/sim/panel/y-offset");
|
|
|
|
fgSetArchivable("/sim/panel/jitter");
|
|
|
|
|
2001-04-05 20:20:44 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the controls subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2012-09-24 23:48:48 +00:00
|
|
|
|
2012-09-27 14:33:12 +00:00
|
|
|
globals->add_subsystem("controls", new FGControls, SGSubsystemMgr::GENERAL);
|
2001-04-05 20:20:44 +00:00
|
|
|
|
I'm attaching diffs to add a new FGInput module to FlightGear
(src/Input). So far, FGInput replaces most of src/Main/keyboard.cxx
(I've left a tiny stub); in the very near future, it will also take
over control of the joystick, mouse (Norm permitting), and panel
instrument interactions, so that there is a single mechanism for
configuring all input devices.
The new format should be (close to) self-explanatory by looking at the
new base-package file keyboard.xml, which is now included by
preferences.xml (I'll do the same thing for the joystick when I have a
chance). I have not managed to move all keybindings into this file
yet, but I've made a good start. I'm including Tony in the recipient
list so that he can see how bindings can use an external XML file.
This patch also adds support for multiple bindings for a single key,
special keys (i.e. keypad and function keys), and key modifiers
(shift/alt/ctrl); special keys use the PUI convention of adding 256 to
the Glut key code.
Unfortunately, everything comes with a price; in this case, I have not
yet found a general mechanism for the old (hard-coded) modal bindings,
which behaved differently depending on the autopilot state (i.e. left
rudder or move AP heading left); with my patches, this functionality
disappears, but you can still adjust the autopilot using the panel or
the GUI input dialogs.
2001-05-23 23:01:15 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the input subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-09-27 14:33:12 +00:00
|
|
|
globals->add_subsystem("input", new FGInput, SGSubsystemMgr::GENERAL);
|
I'm attaching diffs to add a new FGInput module to FlightGear
(src/Input). So far, FGInput replaces most of src/Main/keyboard.cxx
(I've left a tiny stub); in the very near future, it will also take
over control of the joystick, mouse (Norm permitting), and panel
instrument interactions, so that there is a single mechanism for
configuring all input devices.
The new format should be (close to) self-explanatory by looking at the
new base-package file keyboard.xml, which is now included by
preferences.xml (I'll do the same thing for the joystick when I have a
chance). I have not managed to move all keybindings into this file
yet, but I've made a good start. I'm including Tony in the recipient
list so that he can see how bindings can use an external XML file.
This patch also adds support for multiple bindings for a single key,
special keys (i.e. keypad and function keys), and key modifiers
(shift/alt/ctrl); special keys use the PUI convention of adding 256 to
the Glut key code.
Unfortunately, everything comes with a price; in this case, I have not
yet found a general mechanism for the old (hard-coded) modal bindings,
which behaved differently depending on the autopilot state (i.e. left
rudder or move AP heading left); with my patches, this functionality
disappears, but you can still adjust the autopilot using the panel or
the GUI input dialogs.
2001-05-23 23:01:15 +00:00
|
|
|
|
|
|
|
|
2003-07-17 18:24:17 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the replay subsystem
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->add_subsystem("replay", new FGReplay);
|
2012-12-10 18:11:44 +00:00
|
|
|
globals->add_subsystem("history", new FGFlightHistory);
|
|
|
|
|
2010-10-22 11:22:00 +00:00
|
|
|
#ifdef ENABLE_AUDIO_SUPPORT
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the sound-effects subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->add_subsystem("voice", new FGVoiceMgr, SGSubsystemMgr::DISPLAY);
|
|
|
|
#endif
|
2009-10-04 13:52:53 +00:00
|
|
|
|
2002-10-03 21:20:56 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2010-10-22 11:22:00 +00:00
|
|
|
// Initialize the lighting subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
globals->add_subsystem("lighting", new FGLight, SGSubsystemMgr::DISPLAY);
|
|
|
|
|
|
|
|
// ordering here is important : Nasal (via events), then models, then views
|
|
|
|
globals->add_subsystem("events", globals->get_event_mgr(), SGSubsystemMgr::DISPLAY);
|
|
|
|
|
2012-09-19 17:17:44 +00:00
|
|
|
globals->add_subsystem("aircraft-model", new FGAircraftModel, SGSubsystemMgr::DISPLAY);
|
|
|
|
globals->add_subsystem("model-manager", new FGModelMgr, SGSubsystemMgr::DISPLAY);
|
2010-10-22 11:22:00 +00:00
|
|
|
|
2012-11-20 13:33:20 +00:00
|
|
|
globals->add_subsystem("view-manager", new FGViewMgr, SGSubsystemMgr::DISPLAY);
|
2010-10-22 11:22:00 +00:00
|
|
|
|
|
|
|
globals->add_subsystem("tile-manager", globals->get_tile_mgr(),
|
|
|
|
SGSubsystemMgr::DISPLAY);
|
2012-09-18 19:29:36 +00:00
|
|
|
}
|
2002-10-03 21:20:56 +00:00
|
|
|
|
2012-09-18 19:29:36 +00:00
|
|
|
void fgPostInitSubsystems()
|
|
|
|
{
|
|
|
|
SGTimeStamp st;
|
|
|
|
st.stamp();
|
|
|
|
|
2003-11-25 21:08:36 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the Nasal interpreter.
|
|
|
|
// Do this last, so that the loaded scripts see initialized state
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
FGNasalSys* nasal = new FGNasalSys();
|
2006-06-10 22:24:05 +00:00
|
|
|
globals->add_subsystem("nasal", nasal, SGSubsystemMgr::INIT);
|
2003-11-25 21:08:36 +00:00
|
|
|
nasal->init();
|
2012-09-18 19:29:36 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Nasal init took:" << st.elapsedMSec());
|
2013-04-29 20:15:32 +00:00
|
|
|
|
|
|
|
// Ensure IOrules and path validation are working properly by trying to
|
|
|
|
// access a folder/file which should never be accessible.
|
|
|
|
const char* no_access_path =
|
|
|
|
#ifdef _WIN32
|
|
|
|
"Z:"
|
|
|
|
#endif
|
|
|
|
"/do-not-access";
|
|
|
|
|
|
|
|
if( fgValidatePath(no_access_path, true) )
|
|
|
|
SG_LOG
|
|
|
|
(
|
|
|
|
SG_GENERAL,
|
|
|
|
SG_ALERT,
|
|
|
|
"Check your IOrules! (write to '" << no_access_path << "' is allowed)"
|
|
|
|
);
|
|
|
|
if( fgValidatePath(no_access_path, false) )
|
|
|
|
SG_LOG
|
|
|
|
(
|
|
|
|
SG_GENERAL,
|
|
|
|
SG_ALERT,
|
|
|
|
"Check your IOrules! (read from '" << no_access_path << "' is allowed)"
|
|
|
|
);
|
2012-09-18 19:29:36 +00:00
|
|
|
|
2005-06-11 09:13:44 +00:00
|
|
|
// initialize methods that depend on other subsystems.
|
2012-09-18 19:29:36 +00:00
|
|
|
st.stamp();
|
2005-06-11 09:13:44 +00:00
|
|
|
globals->get_subsystem_mgr()->postinit();
|
2012-09-18 19:29:36 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Subsystems postinit took:" << st.elapsedMSec());
|
|
|
|
|
2001-04-05 20:20:44 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// End of subsystem initialization.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2012-01-29 09:34:11 +00:00
|
|
|
fgSetBool("/sim/crashed", false);
|
2010-11-02 23:19:09 +00:00
|
|
|
fgSetBool("/sim/initialized", true);
|
|
|
|
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, endl);
|
1998-04-24 00:49:17 +00:00
|
|
|
|
2002-10-04 13:20:53 +00:00
|
|
|
// Save the initial state for future
|
|
|
|
// reference.
|
2001-01-19 22:57:24 +00:00
|
|
|
globals->saveInitialState();
|
1997-08-23 01:46:20 +00:00
|
|
|
}
|
1999-04-27 15:52:32 +00:00
|
|
|
|
2011-03-22 20:02:57 +00:00
|
|
|
// Reset: this is what the 'reset' command (and hence, GUI) is attached to
|
2002-11-18 21:31:33 +00:00
|
|
|
void fgReInitSubsystems()
|
1999-04-27 15:52:32 +00:00
|
|
|
{
|
2012-11-18 15:35:54 +00:00
|
|
|
SGPropertyNode *master_freeze = fgGetNode("/sim/freeze/master");
|
2001-10-28 16:16:30 +00:00
|
|
|
|
2010-11-02 22:45:43 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "fgReInitSubsystems()");
|
2001-01-17 23:30:35 +00:00
|
|
|
|
2010-11-02 22:45:43 +00:00
|
|
|
// setup state to begin re-init
|
2002-01-20 03:52:36 +00:00
|
|
|
bool freeze = master_freeze->getBoolValue();
|
|
|
|
if ( !freeze ) {
|
2012-11-18 15:35:54 +00:00
|
|
|
master_freeze->setBoolValue(true);
|
2001-10-28 16:16:30 +00:00
|
|
|
}
|
2010-11-02 22:45:43 +00:00
|
|
|
|
|
|
|
fgSetBool("/sim/signals/reinit", true);
|
2003-12-29 10:10:35 +00:00
|
|
|
fgSetBool("/sim/crashed", false);
|
2000-07-23 21:32:59 +00:00
|
|
|
|
2010-11-02 22:45:43 +00:00
|
|
|
// do actual re-init steps
|
|
|
|
globals->get_subsystem("flight")->unbind();
|
|
|
|
|
|
|
|
// reset control state, before restoring initial state; -set or config files
|
|
|
|
// may specify values for flaps, trim tabs, magnetos, etc
|
|
|
|
globals->get_controls()->reset_all();
|
|
|
|
|
|
|
|
globals->restoreInitialState();
|
|
|
|
|
|
|
|
// update our position based on current presets
|
2012-12-15 15:25:45 +00:00
|
|
|
// this will mark position as needed finalized which we'll do in the
|
|
|
|
// main-loop
|
2012-09-18 19:50:28 +00:00
|
|
|
flightgear::initPosition();
|
2010-11-02 22:45:43 +00:00
|
|
|
|
2005-07-13 12:25:16 +00:00
|
|
|
// Force reupdating the positions of the ai 3d models. They are used for
|
|
|
|
// initializing ground level for the FDM.
|
2011-11-19 14:37:49 +00:00
|
|
|
globals->get_subsystem("ai-model")->reinit();
|
2005-07-13 12:25:16 +00:00
|
|
|
|
2002-11-18 21:31:33 +00:00
|
|
|
// Initialize the FDM
|
2010-06-16 07:31:59 +00:00
|
|
|
globals->get_subsystem("flight")->reinit();
|
2000-10-27 22:00:43 +00:00
|
|
|
|
2011-03-20 13:59:19 +00:00
|
|
|
// reset replay buffers
|
|
|
|
globals->get_subsystem("replay")->reinit();
|
|
|
|
|
2003-02-06 19:44:32 +00:00
|
|
|
// reload offsets from config defaults
|
|
|
|
globals->get_viewmgr()->reinit();
|
2002-04-21 03:27:34 +00:00
|
|
|
|
2012-12-16 15:05:21 +00:00
|
|
|
// ugly: finalizePosition waits for METAR to arrive for the new airport.
|
|
|
|
// we don't re-init the environment manager here, since historically we did
|
|
|
|
// not, and doing so seems to have other issues. All that's needed is to
|
|
|
|
// schedule METAR fetch immediately, so it's available for finalizePosition.
|
|
|
|
// So we manually extract the METAR-fetching component inside the environment
|
|
|
|
// manager, and re-init that.
|
|
|
|
SGSubsystemGroup* envMgr = static_cast<SGSubsystemGroup*>(globals->get_subsystem("environment"));
|
|
|
|
if (envMgr) {
|
|
|
|
envMgr->get_subsystem("realwx")->reinit();
|
|
|
|
}
|
|
|
|
|
2010-07-13 20:50:44 +00:00
|
|
|
globals->get_subsystem("time")->reinit();
|
2011-02-13 18:24:54 +00:00
|
|
|
|
2011-03-29 21:31:59 +00:00
|
|
|
// need to bind FDMshell again, since we manually unbound it above...
|
|
|
|
globals->get_subsystem("flight")->bind();
|
|
|
|
|
2012-09-19 18:57:52 +00:00
|
|
|
// need to reset aircraft (systems/instruments) so they can adapt to current environment
|
|
|
|
globals->get_subsystem("systems")->reinit();
|
|
|
|
globals->get_subsystem("instrumentation")->reinit();
|
|
|
|
|
2012-10-13 14:48:56 +00:00
|
|
|
globals->get_subsystem("ATIS")->reinit();
|
|
|
|
|
2010-11-02 22:45:43 +00:00
|
|
|
// setup state to end re-init
|
|
|
|
fgSetBool("/sim/signals/reinit", false);
|
2002-01-20 03:52:36 +00:00
|
|
|
if ( !freeze ) {
|
2012-11-18 15:35:54 +00:00
|
|
|
master_freeze->setBoolValue(false);
|
2002-01-20 03:52:36 +00:00
|
|
|
}
|
2004-07-22 16:42:14 +00:00
|
|
|
fgSetBool("/sim/sceneryloaded",false);
|
1999-04-27 15:52:32 +00:00
|
|
|
}
|
2002-04-13 13:11:34 +00:00
|
|
|
|
2008-07-09 12:22:33 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
// helper object to implement the --show-aircraft command.
|
|
|
|
// resides here so we can share the fgFindAircraftInDir template above,
|
|
|
|
// and hence ensure this command lists exectly the same aircraft as the normal
|
|
|
|
// loading path.
|
|
|
|
class ShowAircraft
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
ShowAircraft()
|
|
|
|
{
|
|
|
|
_minStatus = getNumMaturity(fgGetString("/sim/aircraft-min-status", "all"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void show(const SGPath& path)
|
|
|
|
{
|
|
|
|
fgFindAircraftInDir(path, this, &ShowAircraft::processAircraft);
|
|
|
|
|
|
|
|
std::sort(_aircraft.begin(), _aircraft.end(), ciLessLibC());
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool processAircraft(const SGPath& path)
|
|
|
|
{
|
|
|
|
SGPropertyNode root;
|
|
|
|
try {
|
|
|
|
readProperties(path.str(), &root);
|
2010-08-06 07:06:32 +00:00
|
|
|
} catch (sg_exception& ) {
|
2010-07-06 20:06:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
int maturity = 0;
|
|
|
|
string descStr(" ");
|
|
|
|
descStr += path.file();
|
2010-07-22 00:36:32 +00:00
|
|
|
// trim common suffix from file names
|
|
|
|
int nPos = descStr.rfind("-set.xml");
|
|
|
|
if (nPos == (int)(descStr.size() - 8)) {
|
|
|
|
descStr.resize(nPos);
|
|
|
|
}
|
2010-07-06 20:06:50 +00:00
|
|
|
|
|
|
|
SGPropertyNode *node = root.getNode("sim");
|
|
|
|
if (node) {
|
|
|
|
SGPropertyNode* desc = node->getNode("description");
|
|
|
|
// if a status tag is found, read it in
|
|
|
|
if (node->hasValue("status")) {
|
|
|
|
maturity = getNumMaturity(node->getStringValue("status"));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (desc) {
|
|
|
|
if (descStr.size() <= 27+3) {
|
|
|
|
descStr.append(29+3-descStr.size(), ' ');
|
|
|
|
} else {
|
|
|
|
descStr += '\n';
|
|
|
|
descStr.append( 32, ' ');
|
|
|
|
}
|
|
|
|
descStr += desc->getStringValue();
|
|
|
|
}
|
|
|
|
} // of have 'sim' node
|
|
|
|
|
|
|
|
if (maturity < _minStatus) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
_aircraft.push_back(descStr);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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[] = {"alpha","beta","early-production","production"};
|
|
|
|
|
|
|
|
if (!strcmp(str, "all")) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++)
|
|
|
|
if (strcmp(str,levels[i])==0)
|
|
|
|
return i;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// recommended in Meyers, Effective STL when internationalization and embedded
|
|
|
|
// NULLs aren't an issue. Much faster than the STL or Boost lex versions.
|
|
|
|
struct ciLessLibC : public std::binary_function<string, string, bool>
|
|
|
|
{
|
|
|
|
bool operator()(const std::string &lhs, const std::string &rhs) const
|
|
|
|
{
|
|
|
|
return strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ? 1 : 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
int _minStatus;
|
|
|
|
string_list _aircraft;
|
|
|
|
};
|
|
|
|
|
|
|
|
void fgShowAircraft(const SGPath &path)
|
|
|
|
{
|
|
|
|
ShowAircraft s;
|
|
|
|
s.show(path);
|
|
|
|
|
|
|
|
#ifdef _MSC_VER
|
|
|
|
cout << "Hit a key to continue..." << endl;
|
2012-11-24 12:33:36 +00:00
|
|
|
std::cin.get();
|
2010-07-06 20:06:50 +00:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
|