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
|
|
|
|
|
|
|
|
2018-09-18 16:34:12 +00:00
|
|
|
#include <config.h>
|
1998-04-22 13:25:39 +00:00
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
#include <simgear/compiler.h>
|
|
|
|
|
2018-09-18 16:34:12 +00:00
|
|
|
#include <cstdio>
|
|
|
|
#include <cstdlib>
|
|
|
|
#include <cstring> // strcmp()
|
1998-07-22 21:40:43 +00:00
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
#if defined(SG_WINDOWS)
|
2008-10-01 15:03:53 +00:00
|
|
|
# include <io.h> // isatty()
|
2013-11-14 16:48:14 +00:00
|
|
|
# include <process.h> // _getpid()
|
|
|
|
# include <Windows.h>
|
2008-10-01 15:03:53 +00:00
|
|
|
# define isatty _isatty
|
2013-11-16 09:31:18 +00:00
|
|
|
#else
|
|
|
|
// for open() and options
|
|
|
|
# include <sys/types.h>
|
|
|
|
# include <sys/stat.h>
|
|
|
|
# include <fcntl.h>
|
2007-06-16 21:35:16 +00:00
|
|
|
#endif
|
2001-03-22 04:02:11 +00:00
|
|
|
|
2008-07-25 18:38:29 +00:00
|
|
|
#include <string>
|
2013-11-16 12:10:32 +00:00
|
|
|
|
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
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
#include <osgViewer/Viewer>
|
|
|
|
|
2013-12-09 22:13:45 +00:00
|
|
|
#include <simgear/canvas/Canvas.hxx>
|
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>
|
2017-02-09 18:48:33 +00:00
|
|
|
#include <simgear/io/iostreams/sgstream.hxx>
|
2011-07-18 09:09:43 +00:00
|
|
|
#include <simgear/misc/strutils.hxx>
|
Integrate the EmbeddedResourceManager into FlightGear
${CMAKE_SOURCE_DIR}/src/EmbeddedResources/FlightGear-resources.xml
(currently empty) is automatically "compiled" into
${CMAKE_BINARY_DIR}/src/EmbeddedResources/FlightGear-resources.[ch]xx by
fgrcc inside the build directory. These files are incorporated into the
FlightGear build (FlightGear-resources.cxx is linked into FlightGear).
When the XML embedded resource declaration file added here,
FlightGear-resources.xml, is compiled, fgrcc is passed the
--root=${CMAKE_SOURCE_DIR} option, so that files referred to in
FlightGear-resources.xml are looked up relatively to the root directory
of the FlightGear repository. One could use a second XML embedded
resource declaration file compiled with a different --root option to
grab files from FGData, for instance. I would name such a file
FGData-resources.xml to be consistent with the current naming scheme.
Note: this --root option applies to the paths of real files. Don't
confuse it with the 'prefix' attribute of <qresource> elements
inside XML resource declaration files (such as
FlightGear-resources.xml), which applies to the virtual path of
each resource defined beneath.
The commands in src/Main/CMakeLists.txt ensure that
FlightGear-resources.xml is recompiled with fgrcc whenever it is
changed, and obviously also when FlightGear-resources.cxx or
FlightGear-resources.hxx is missing. However, CMake doesn't know how to
parse fgrcc XML resource declaration files, therefore when a resource is
modified but the XML file it is declared in is not (here,
FlightGear-resources.xml), you have to trigger yourself a recompilation
of the XML resource declaration file to see the new resource contents
inside FlightGear. The easiest ways to do so are:
- either update the timestamp of the XML resource declaration file;
- or remove one or both of the generated files
(FlightGear-resources.cxx and FlightGear-resources.hxx here).
The EmbeddedResourceManager is created in fgMainInit() just after
Options::processOptions() set the language that was either requested by
the user or obtained from the system (locales). Resources from
FlightGear-resources.cxx are added to it, after which
EmbeddedResourceManager::selectLocale() is called with the user's
preferred locale (obtained with FGLocale::getPreferredLanguage()).
Upon reset (fgStartNewReset()), EmbeddedResourceManager::selectLocale()
is called in a similar way after Options::processOptions(), however in
this case the EmbeddedResourceManager instance doesn't have to be
recreated.
2017-04-27 22:09:14 +00:00
|
|
|
#include <simgear/embedded_resources/EmbeddedResourceManager.hxx>
|
2011-07-30 09:47:28 +00:00
|
|
|
#include <simgear/props/props_io.hxx>
|
2013-11-16 12:10:32 +00:00
|
|
|
#include <simgear/scene/tsync/terrasync.hxx>
|
2010-10-20 16:54:16 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
#include <simgear/scene/model/modellib.hxx>
|
2003-05-12 21:34:29 +00:00
|
|
|
#include <simgear/scene/material/matlib.hxx>
|
2013-12-04 09:09:47 +00:00
|
|
|
#include <simgear/scene/material/Effect.hxx>
|
2008-02-15 06:45:19 +00:00
|
|
|
#include <simgear/scene/model/particles.hxx>
|
2013-09-28 13:07:45 +00:00
|
|
|
#include <simgear/scene/tsync/terrasync.hxx>
|
2016-03-28 22:50:47 +00:00
|
|
|
#include <simgear/scene/tgdb/userdata.hxx>
|
2000-02-15 03:30:01 +00:00
|
|
|
|
2014-05-31 17:04:56 +00:00
|
|
|
#include <simgear/package/Root.hxx>
|
2014-06-11 17:19:41 +00:00
|
|
|
#include <simgear/package/Package.hxx>
|
|
|
|
#include <simgear/package/Install.hxx>
|
|
|
|
#include <simgear/package/Catalog.hxx>
|
2014-05-31 17:04:56 +00:00
|
|
|
|
Improved infrastructure for add-ons: C++ classes, metadata file, Nasal interface
This commit adds C++ classes for add-on management, most notably
AddonManager, Addon and AddonVersion. The AddonManager is used to
register add-ons. It relies on an std::map<std::string, AddonRef> to
hold the metadata of each registered add-on (keys of the std::map are
add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>).
Accessor methods are available for:
- retrieving the list of registered or loaded add-ons (terminology
explained in $FG_ROOT/Docs/README.add-ons);
- checking if a particular add-on has already been registered or
loaded;
- for each add-on, obtaining an Addon instance which can be queried
for its name, id, version, base path, the minimum and maximum
FlightGear versions it requires, its base node in the Property Tree,
its order in the load sequence, short and long description strings,
home page, etc.
The most important metadata is made accessible in the Property Tree
under /addons/by-id/<addon-id> and the property
/addons/by-id/<addon-id>/loaded can be checked or listened to, in
order to determine when a particular add-on is loaded. There is also a
Nasal interface to access add-on metadata in a convenient way.
In order to provide this metadata, each add-on must from now on have in
its base directory a file called 'addon-metadata.xml'.
All this is documented in much more detail in
$FG_ROOT/Docs/README.add-ons.
Mailing-list discussion:
https://sourceforge.net/p/flightgear/mailman/message/36146017/
2017-11-06 12:58:14 +00:00
|
|
|
#include <Add-ons/AddonManager.hxx>
|
|
|
|
|
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>
|
2016-06-17 16:53:35 +00:00
|
|
|
#include <Aircraft/initialstate.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>
|
2015-12-05 00:25:29 +00:00
|
|
|
#include <Airports/airportdynamicsmanager.hxx>
|
2008-08-14 18:13:39 +00:00
|
|
|
|
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>
|
2013-12-09 22:13:45 +00:00
|
|
|
#include <Canvas/FGCanvasSystemAdapter.hxx>
|
2002-11-07 16:27:47 +00:00
|
|
|
#include <GUI/new_gui.hxx>
|
2013-11-06 23:49:58 +00:00
|
|
|
#include <GUI/MessageBox.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>
|
2015-12-19 08:29:00 +00:00
|
|
|
#include <AIModel/performancedb.hxx>
|
Integrate the EmbeddedResourceManager into FlightGear
${CMAKE_SOURCE_DIR}/src/EmbeddedResources/FlightGear-resources.xml
(currently empty) is automatically "compiled" into
${CMAKE_BINARY_DIR}/src/EmbeddedResources/FlightGear-resources.[ch]xx by
fgrcc inside the build directory. These files are incorporated into the
FlightGear build (FlightGear-resources.cxx is linked into FlightGear).
When the XML embedded resource declaration file added here,
FlightGear-resources.xml, is compiled, fgrcc is passed the
--root=${CMAKE_SOURCE_DIR} option, so that files referred to in
FlightGear-resources.xml are looked up relatively to the root directory
of the FlightGear repository. One could use a second XML embedded
resource declaration file compiled with a different --root option to
grab files from FGData, for instance. I would name such a file
FGData-resources.xml to be consistent with the current naming scheme.
Note: this --root option applies to the paths of real files. Don't
confuse it with the 'prefix' attribute of <qresource> elements
inside XML resource declaration files (such as
FlightGear-resources.xml), which applies to the virtual path of
each resource defined beneath.
The commands in src/Main/CMakeLists.txt ensure that
FlightGear-resources.xml is recompiled with fgrcc whenever it is
changed, and obviously also when FlightGear-resources.cxx or
FlightGear-resources.hxx is missing. However, CMake doesn't know how to
parse fgrcc XML resource declaration files, therefore when a resource is
modified but the XML file it is declared in is not (here,
FlightGear-resources.xml), you have to trigger yourself a recompilation
of the XML resource declaration file to see the new resource contents
inside FlightGear. The easiest ways to do so are:
- either update the timestamp of the XML resource declaration file;
- or remove one or both of the generated files
(FlightGear-resources.cxx and FlightGear-resources.hxx here).
The EmbeddedResourceManager is created in fgMainInit() just after
Options::processOptions() set the language that was either requested by
the user or obtained from the system (locales). Resources from
FlightGear-resources.cxx are added to it, after which
EmbeddedResourceManager::selectLocale() is called with the user's
preferred locale (obtained with FGLocale::getPreferredLanguage()).
Upon reset (fgStartNewReset()), EmbeddedResourceManager::selectLocale()
is called in a similar way after Options::processOptions(), however in
this case the EmbeddedResourceManager instance doesn't have to be
recreated.
2017-04-27 22:09:14 +00:00
|
|
|
#include <Main/locale.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>
|
2014-03-13 18:18:23 +00:00
|
|
|
#include <Scenery/SceneryPager.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>
|
2013-11-16 12:10:32 +00:00
|
|
|
#include <Time/TimeManager.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>
|
2013-11-16 12:10:32 +00:00
|
|
|
#include <Viewer/FGEventHandler.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>
|
2016-11-08 09:41:49 +00:00
|
|
|
#include <Network/DNSClient.hxx>
|
2013-05-19 14:29:49 +00:00
|
|
|
#include <Network/fgcom.hxx>
|
2014-03-03 20:59:16 +00:00
|
|
|
#include <Network/http/httpd.hxx>
|
2014-05-31 17:04:56 +00:00
|
|
|
#include <Include/version.h>
|
2015-03-19 17:01:38 +00:00
|
|
|
#include <Viewer/splash.hxx>
|
2013-11-16 12:10:32 +00:00
|
|
|
#include <Viewer/CameraGroup.hxx>
|
|
|
|
|
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"
|
2013-11-16 14:22:34 +00:00
|
|
|
#include "AircraftDirVisitorBase.hxx"
|
1998-04-22 13:25:39 +00:00
|
|
|
|
2013-11-16 10:05:09 +00:00
|
|
|
#if defined(SG_MAC)
|
|
|
|
#include <GUI/CocoaHelpers.h> // for Mac impl of platformDefaultDataPath()
|
|
|
|
#endif
|
|
|
|
|
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;
|
2014-05-31 17:04:56 +00:00
|
|
|
|
2009-12-05 14:25:31 +00:00
|
|
|
using namespace boost::algorithm;
|
2014-05-31 17:04:56 +00:00
|
|
|
using namespace simgear::pkg;
|
2003-05-09 18:44:33 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
extern osg::ref_ptr<osgViewer::Viewer> viewer;
|
2002-11-16 20:17:11 +00:00
|
|
|
|
2001-07-16 19:17:58 +00:00
|
|
|
// Return the current base package version
|
2015-03-06 18:52:06 +00:00
|
|
|
string fgBasePackageVersion(const SGPath& base_path) {
|
|
|
|
SGPath p(base_path);
|
|
|
|
p.append("version");
|
|
|
|
if (!p.exists()) {
|
2013-11-06 23:49:58 +00:00
|
|
|
return string();
|
|
|
|
}
|
|
|
|
|
2016-06-21 11:29:04 +00:00
|
|
|
sg_gzifstream in( p );
|
2013-11-06 23:49:58 +00:00
|
|
|
if (!in.is_open()) {
|
|
|
|
return string();
|
2001-07-16 19:17:58 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
string version;
|
|
|
|
in >> version;
|
|
|
|
|
|
|
|
return version;
|
|
|
|
}
|
|
|
|
|
2013-11-16 14:22:34 +00:00
|
|
|
class FindAndCacheAircraft : public AircraftDirVistorBase
|
2010-07-06 20:06:50 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
FindAndCacheAircraft(SGPropertyNode* autoSave)
|
|
|
|
{
|
|
|
|
_cache = autoSave->getNode("sim/startup/path-cache", true);
|
|
|
|
}
|
|
|
|
|
2018-08-30 14:23:45 +00:00
|
|
|
/**
|
|
|
|
* @brief haveExplicitAircraft - check if the combination of /sim/aircraft
|
|
|
|
* and /sim/aircraft-dir defines an explicit -set.xml. We need to detect
|
|
|
|
* this case to short-circuit package detection
|
|
|
|
* @return
|
|
|
|
*/
|
|
|
|
bool haveExplicitAircraft() const
|
|
|
|
{
|
|
|
|
const std::string aircraftDir = fgGetString("/sim/aircraft-dir", "");
|
|
|
|
if (aircraftDir.empty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::string aircraft = fgGetString( "/sim/aircraft", "");
|
|
|
|
SGPath setFile = SGPath::fromUtf8(aircraftDir) / (aircraft + "-set.xml");
|
|
|
|
return setFile.exists();
|
|
|
|
}
|
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
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()) {
|
2017-04-09 16:38:38 +00:00
|
|
|
flightgear::fatalMessageBoxWithoutExit("No aircraft",
|
|
|
|
"No aircraft was specified");
|
2010-07-06 20:06:50 +00:00
|
|
|
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 {
|
2016-06-23 13:26:34 +00:00
|
|
|
readProperties(setFile, globals->get_props());
|
2011-10-16 20:15:54 +00:00
|
|
|
} catch ( const sg_exception &e ) {
|
2017-04-09 16:38:38 +00:00
|
|
|
SG_LOG(SG_INPUT, SG_ALERT,
|
|
|
|
"Error reading aircraft: " << e.getFormattedMessage());
|
|
|
|
flightgear::fatalMessageBoxWithoutExit(
|
|
|
|
"Error reading aircraft",
|
|
|
|
"An error occured reading the requested aircraft (" + aircraft + ")",
|
|
|
|
e.getFormattedMessage());
|
2011-10-16 20:15:54 +00:00
|
|
|
return false;
|
|
|
|
}
|
2017-06-21 23:22:18 +00:00
|
|
|
|
|
|
|
checkAircraftMinVersion();
|
|
|
|
|
2016-06-17 16:53:35 +00:00
|
|
|
// apply state after the -set.xml, but before any options are are set
|
|
|
|
flightgear::applyInitialState();
|
2011-10-16 20:15:54 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "aircraft '" << _searchAircraft <<
|
|
|
|
"' not found in specified dir:" << aircraftDir);
|
2017-04-09 16:38:38 +00:00
|
|
|
flightgear::fatalMessageBoxWithoutExit(
|
|
|
|
"Aircraft not found",
|
|
|
|
"The requested aircraft (" + aircraft + ") could not be found "
|
|
|
|
"in the specified location.",
|
|
|
|
aircraftDir);
|
2011-10-16 20:15:54 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
if (!checkCache()) {
|
|
|
|
// prepare cache for re-scan
|
|
|
|
SGPropertyNode *n = _cache->getNode("fg-root", true);
|
2016-06-23 13:26:34 +00:00
|
|
|
n->setStringValue(globals->get_fg_root().utf8Str());
|
2010-07-06 20:06:50 +00:00
|
|
|
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
|
|
|
|
2013-11-16 14:22:34 +00:00
|
|
|
visitAircraftPaths();
|
2010-07-06 20:06:50 +00:00
|
|
|
}
|
|
|
|
|
2016-06-23 13:26:34 +00:00
|
|
|
if (_foundPath.isNull()) {
|
2017-04-09 16:38:38 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT,
|
|
|
|
"Cannot find the specified aircraft: '" << aircraft << "'");
|
|
|
|
flightgear::fatalMessageBoxWithoutExit(
|
|
|
|
"Aircraft not found",
|
|
|
|
"The requested aircraft (" + aircraft + ") could not be found "
|
|
|
|
"in any of the search paths.");
|
2010-07-06 20:06:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-06-23 13:26:34 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Loading aircraft -set file from:" << _foundPath);
|
2010-07-06 20:06:50 +00:00
|
|
|
fgSetString( "/sim/aircraft-dir", _foundPath.dir().c_str());
|
|
|
|
if (!_foundPath.exists()) {
|
2016-06-23 13:26:34 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "Unable to find -set file:" << _foundPath);
|
2010-07-06 20:06:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2016-06-23 13:26:34 +00:00
|
|
|
readProperties(_foundPath, globals->get_props());
|
2010-07-06 20:06:50 +00:00
|
|
|
} catch ( const sg_exception &e ) {
|
2017-04-09 16:38:38 +00:00
|
|
|
SG_LOG(SG_INPUT, SG_ALERT,
|
|
|
|
"Error reading aircraft: " << e.getFormattedMessage());
|
|
|
|
flightgear::fatalMessageBoxWithoutExit(
|
|
|
|
"Error reading aircraft",
|
|
|
|
"An error occured reading the requested aircraft (" + aircraft + ")",
|
|
|
|
e.getFormattedMessage());
|
2010-07-06 20:06:50 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-06-17 16:53:35 +00:00
|
|
|
|
|
|
|
// apply state after the -set.xml, but before any options are are set
|
|
|
|
flightgear::applyInitialState();
|
|
|
|
|
2017-06-21 23:22:18 +00:00
|
|
|
checkAircraftMinVersion();
|
2016-06-17 16:53:35 +00:00
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2016-06-21 11:29:04 +00:00
|
|
|
std::string getAircraftPaths()
|
|
|
|
{
|
|
|
|
return SGPath::join(globals->get_aircraft_paths(), ";");
|
2010-11-29 21:48:37 +00:00
|
|
|
}
|
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
bool checkCache()
|
|
|
|
{
|
2016-06-21 11:29:04 +00:00
|
|
|
if (globals->get_fg_root().utf8Str() != _cache->getStringValue("fg-root", "")) {
|
2010-07-06 20:06:50 +00:00
|
|
|
return false; // cache mismatch
|
|
|
|
}
|
2010-11-29 21:48:37 +00:00
|
|
|
|
2016-06-21 11:29:04 +00:00
|
|
|
if (getAircraftPaths() != _cache->getStringValue("fg-aircraft", "")) {
|
2010-11-29 21:48:37 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2013-11-16 14:22:34 +00:00
|
|
|
virtual VisitResult visit(const SGPath& p)
|
2010-07-06 20:06:50 +00:00
|
|
|
{
|
|
|
|
// 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;
|
2013-11-16 14:22:34 +00:00
|
|
|
return VISIT_DONE;
|
2003-09-19 20:06:27 +00:00
|
|
|
}
|
|
|
|
|
2013-11-16 14:22:34 +00:00
|
|
|
return VISIT_CONTINUE;
|
2010-07-06 20:06:50 +00:00
|
|
|
}
|
2017-06-21 23:22:18 +00:00
|
|
|
|
|
|
|
bool checkAircraftMinVersion()
|
|
|
|
{
|
|
|
|
SGPropertyNode* minVersionNode = globals->get_props()->getNode("/sim/minimum-fg-version");
|
|
|
|
if (minVersionNode) {
|
|
|
|
std::string minVersion = minVersionNode->getStringValue();
|
|
|
|
const int c = simgear::strutils::compare_versions(FLIGHTGEAR_VERSION, minVersion, 2);
|
|
|
|
if (c < 0) {
|
|
|
|
SG_LOG(SG_AIRCRAFT, SG_DEV_ALERT, "Aircraft minimum version (" << minVersion <<
|
|
|
|
") is higher than FG version:" << FLIGHTGEAR_VERSION);
|
|
|
|
flightgear::modalMessageBox("Aircraft requires newer version of FlightGear",
|
|
|
|
"The selected aircraft requires FlightGear version " + minVersion
|
|
|
|
+ " to work correctly. Some features may not work as expected, or the aircraft may not load at all.");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_AIRCRAFT, SG_DEV_ALERT, "Aircraft does not specify a minimum FG version: please add one at /sim/minimum-fg-version");
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
2010-07-06 20:06:50 +00:00
|
|
|
|
|
|
|
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()
|
|
|
|
{
|
2016-12-28 15:57:26 +00:00
|
|
|
SGPath appDataPath = SGPath::fromEnv("APPDATA");
|
|
|
|
|
|
|
|
if (appDataPath.isNull()) {
|
2017-04-09 16:38:38 +00:00
|
|
|
flightgear::fatalMessageBoxThenExit(
|
2016-12-28 15:57:26 +00:00
|
|
|
"FlightGear", "Unable to get the value of APPDATA.",
|
|
|
|
"FlightGear is unable to retrieve the value of the APPDATA environment "
|
|
|
|
"variable. This is quite unexpected on Windows platforms, and FlightGear "
|
|
|
|
"can't continue its execution without this value, sorry.");
|
|
|
|
}
|
|
|
|
|
|
|
|
return appDataPath / "flightgear.org";
|
2011-10-16 18:55:04 +00:00
|
|
|
}
|
2013-05-04 09:58:22 +00:00
|
|
|
|
2013-11-16 10:05:09 +00:00
|
|
|
#elif defined(SG_MAC)
|
2013-06-10 19:42:53 +00:00
|
|
|
|
2013-11-16 10:05:09 +00:00
|
|
|
// platformDefaultDataPath defined in GUI/CocoaHelpers.h
|
2013-06-10 19:42:53 +00:00
|
|
|
|
2011-10-16 18:55:04 +00:00
|
|
|
#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
|
|
|
|
2018-07-02 22:13:36 +00:00
|
|
|
#if defined(SG_WINDOWS)
|
|
|
|
static HANDLE static_fgHomeWriteMutex = nullptr;
|
|
|
|
#endif
|
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
bool fgInitHome()
|
2011-10-21 15:49:15 +00:00
|
|
|
{
|
2013-06-10 19:42:53 +00:00
|
|
|
SGPath dataPath = SGPath::fromEnv("FG_HOME", platformDefaultDataPath());
|
2016-06-21 11:29:04 +00:00
|
|
|
globals->set_fg_home(dataPath);
|
2013-06-16 16:44:08 +00:00
|
|
|
|
|
|
|
simgear::Dir fgHome(dataPath);
|
|
|
|
if (!fgHome.exists()) {
|
|
|
|
fgHome.create(0755);
|
|
|
|
}
|
2013-11-14 16:48:14 +00:00
|
|
|
|
|
|
|
if (!fgHome.exists()) {
|
2017-04-09 16:38:38 +00:00
|
|
|
flightgear::fatalMessageBoxWithoutExit(
|
|
|
|
"Problem setting up user data",
|
|
|
|
"Unable to create the user-data storage folder at '" +
|
|
|
|
dataPath.utf8Str() + "'.");
|
2013-11-14 16:48:14 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fgGetBool("/sim/fghome-readonly", false)) {
|
|
|
|
// user / config forced us into readonly mode, fine
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Running with FG_HOME readonly");
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-02-27 15:45:28 +00:00
|
|
|
bool result = false;
|
|
|
|
#if defined(SG_WINDOWS)
|
|
|
|
// don't use a PID file on Windows, because deleting on close is
|
|
|
|
// unreliable and causes false-positives. Instead, use a named
|
|
|
|
// mutex.
|
|
|
|
|
2018-07-02 22:13:36 +00:00
|
|
|
static_fgHomeWriteMutex = CreateMutexA(nullptr, FALSE, "org.flightgear.fgfs.primary");
|
|
|
|
if (static_fgHomeWriteMutex == nullptr) {
|
2017-02-27 15:45:28 +00:00
|
|
|
printf("CreateMutex error: %d\n", GetLastError());
|
|
|
|
SG_LOG(SG_GENERAL, SG_POPUP, "Failed to create mutex for multi-app protection");
|
|
|
|
return false;
|
|
|
|
} else if (GetLastError() == ERROR_ALREADY_EXISTS) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "flightgear instance already running, switching to FG_HOME read-only.");
|
|
|
|
fgSetBool("/sim/fghome-readonly", true);
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Created multi-app mutex, we are in writeable mode");
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
#else
|
2013-11-14 16:48:14 +00:00
|
|
|
// write our PID, and check writeability
|
|
|
|
SGPath pidPath(dataPath, "fgfs.pid");
|
|
|
|
if (pidPath.exists()) {
|
2016-03-08 17:37:32 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "flightgear instance already running, switching to FG_HOME read-only.");
|
2013-11-14 16:48:14 +00:00
|
|
|
// set a marker property so terrasync/navcache don't try to write
|
|
|
|
// from secondary instances
|
|
|
|
fgSetBool("/sim/fghome-readonly", true);
|
|
|
|
return true;
|
|
|
|
}
|
2017-04-09 16:38:38 +00:00
|
|
|
|
|
|
|
char buf[16];
|
|
|
|
std::string ps = pidPath.local8BitStr();
|
2017-02-27 15:45:28 +00:00
|
|
|
|
|
|
|
// do open+unlink trick to the file is deleted on exit, even if we
|
2013-11-14 16:48:14 +00:00
|
|
|
// crash or exit(-1)
|
2013-12-09 22:15:35 +00:00
|
|
|
ssize_t len = snprintf(buf, 16, "%d", getpid());
|
2016-06-23 13:26:34 +00:00
|
|
|
int fd = ::open(ps.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, 0644);
|
2013-11-14 16:48:14 +00:00
|
|
|
if (fd >= 0) {
|
2013-12-09 22:15:35 +00:00
|
|
|
result = ::write(fd, buf, len) == len;
|
2016-06-23 13:26:34 +00:00
|
|
|
if( ::unlink(ps.c_str()) != 0 ) // delete file when app quits
|
2013-12-09 22:15:35 +00:00
|
|
|
result = false;
|
2013-11-14 16:48:14 +00:00
|
|
|
}
|
2013-12-09 22:16:25 +00:00
|
|
|
|
2017-04-09 16:38:38 +00:00
|
|
|
if (!result) {
|
|
|
|
flightgear::fatalMessageBoxWithoutExit(
|
|
|
|
"File permissions problem",
|
|
|
|
"Can't write to user-data storage folder, check file permissions "
|
|
|
|
"and FG_HOME.",
|
|
|
|
"User-data at '" + dataPath.utf8Str() + "'.");
|
|
|
|
return false;
|
|
|
|
}
|
2017-02-27 15:45:28 +00:00
|
|
|
#endif
|
2013-12-09 22:16:25 +00:00
|
|
|
fgSetBool("/sim/fghome-readonly", false);
|
2017-04-09 16:38:38 +00:00
|
|
|
return result;
|
2013-02-08 11:43:51 +00:00
|
|
|
}
|
|
|
|
|
2018-07-02 22:13:36 +00:00
|
|
|
void fgShutdownHome()
|
|
|
|
{
|
|
|
|
#if defined(SG_WINDOWS)
|
|
|
|
if (static_fgHomeWriteMutex) {
|
|
|
|
CloseHandle(static_fgHomeWriteMutex);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-03-11 07:25:38 +00:00
|
|
|
static void createBaseStorageDirForAddons(const SGPath& exportDir)
|
|
|
|
{
|
|
|
|
SGPath addonStorageBasePath = exportDir / "Addons";
|
|
|
|
if (addonStorageBasePath.exists()) {
|
|
|
|
if (!addonStorageBasePath.isDir()) {
|
|
|
|
throw sg_error(
|
|
|
|
"Unable to create add-on storage base directory, because the entry "
|
|
|
|
"already exists but is not a directory: '" +
|
|
|
|
addonStorageBasePath.utf8Str() + "'");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
simgear::Dir(addonStorageBasePath).create(0777); // respect user's umask
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-08 11:43:51 +00:00
|
|
|
// Read in configuration (file and command line)
|
2013-11-16 12:10:32 +00:00
|
|
|
int fgInitConfig ( int argc, char **argv, bool reinit )
|
2013-02-08 11:43:51 +00:00
|
|
|
{
|
|
|
|
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()) {
|
2013-12-19 14:53:32 +00:00
|
|
|
exportDir.create(0755);
|
2011-10-16 18:55:04 +00:00
|
|
|
}
|
2018-03-11 07:25:38 +00:00
|
|
|
|
|
|
|
// Reserve a directory where add-ons can write. There will be a subdir for
|
|
|
|
// each add-on, see Addon::createStorageDir() and Addon::getStoragePath().
|
|
|
|
createBaseStorageDirForAddons(exportDir.path());
|
|
|
|
|
2015-03-13 18:11:29 +00:00
|
|
|
// Set /sim/fg-home. Use FG_HOME if necessary.
|
|
|
|
// deliberately not a tied property, for fgValidatePath security
|
|
|
|
// write-protect to avoid accidents
|
2011-10-16 18:55:04 +00:00
|
|
|
SGPropertyNode *home = fgGetNode("/sim", true);
|
2014-03-05 23:41:41 +00:00
|
|
|
home->removeChild("fg-home", 0);
|
2011-10-16 18:55:04 +00:00
|
|
|
home = home->getChild("fg-home", 0, true);
|
2016-06-23 13:26:34 +00:00
|
|
|
home->setStringValue(dataPath.utf8Str());
|
2011-10-16 18:55:04 +00:00
|
|
|
home->setAttribute(SGPropertyNode::WRITE, false);
|
2011-10-21 15:49:15 +00:00
|
|
|
|
2013-11-16 12:00:00 +00:00
|
|
|
fgSetDefaults();
|
2012-09-29 18:02:03 +00:00
|
|
|
flightgear::Options* options = flightgear::Options::sharedInstance();
|
2013-11-16 12:10:32 +00:00
|
|
|
if (!reinit) {
|
|
|
|
options->init(argc, argv, dataPath);
|
|
|
|
}
|
2016-09-05 14:45:37 +00:00
|
|
|
|
2017-02-27 23:15:07 +00:00
|
|
|
// establish default for developer-mode based upon compiled build types
|
|
|
|
bool developerMode = true;
|
|
|
|
if (!strcmp(FG_BUILD_TYPE, "Release")) {
|
|
|
|
developerMode = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// allow command line to override
|
|
|
|
if (options->isOptionSet("developer")) {
|
|
|
|
string s = options->valueForOption("developer", "yes");
|
|
|
|
developerMode = simgear::strutils::to_bool(s);
|
|
|
|
}
|
|
|
|
|
|
|
|
fgSetBool("/sim/developer-mode", developerMode);
|
|
|
|
sglog().setDeveloperMode(developerMode);
|
|
|
|
|
2017-01-11 17:58:22 +00:00
|
|
|
// Read global defaults from $FG_ROOT/defaults
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Reading global defaults");
|
|
|
|
SGPath defaultsXML = globals->get_fg_root() / "defaults.xml";
|
|
|
|
if (!defaultsXML.exists()) {
|
2017-04-09 16:38:38 +00:00
|
|
|
flightgear::fatalMessageBoxThenExit(
|
|
|
|
"Missing file",
|
|
|
|
"Couldn't load an essential simulator data file.",
|
|
|
|
defaultsXML.utf8Str());
|
2017-01-11 17:58:22 +00:00
|
|
|
}
|
2017-04-09 16:38:38 +00:00
|
|
|
|
2017-01-11 17:58:22 +00:00
|
|
|
fgLoadProps("defaults.xml", globals->get_props());
|
2018-11-06 17:07:09 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_DEBUG, "Finished Reading global defaults");
|
2016-09-05 14:45:37 +00:00
|
|
|
|
|
|
|
// do not load user settings when reset to default is requested, or if
|
|
|
|
// told to explicitly ignore
|
|
|
|
if (options->isOptionSet("restore-defaults") || options->isOptionSet("ignore-autosave"))
|
|
|
|
{
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "Ignoring user settings. Restoring defaults.");
|
2012-09-29 18:02:03 +00:00
|
|
|
} else {
|
2016-09-05 14:45:37 +00:00
|
|
|
globals->loadUserSettings(dataPath);
|
|
|
|
}
|
|
|
|
|
2013-11-23 19:58:45 +00:00
|
|
|
return flightgear::FG_OPTIONS_OK;
|
|
|
|
}
|
2011-12-29 23:39:08 +00:00
|
|
|
|
2014-06-11 17:19:41 +00:00
|
|
|
static void initAircraftDirsNasalSecurity()
|
|
|
|
{
|
2015-03-13 18:11:29 +00:00
|
|
|
// deliberately not a tied property, for fgValidatePath security
|
|
|
|
// write-protect to avoid accidents
|
2014-06-11 17:19:41 +00:00
|
|
|
SGPropertyNode* sim = fgGetNode("/sim", true);
|
|
|
|
sim->removeChildren("fg-aircraft");
|
2014-06-12 14:38:21 +00:00
|
|
|
|
2014-06-11 17:19:41 +00:00
|
|
|
int index = 0;
|
2016-06-21 11:29:04 +00:00
|
|
|
const PathList& aircraft_paths = globals->get_aircraft_paths();
|
|
|
|
for (PathList::const_iterator it = aircraft_paths.begin();
|
|
|
|
it != aircraft_paths.end(); ++it, ++index )
|
2014-06-11 17:19:41 +00:00
|
|
|
{
|
|
|
|
SGPropertyNode* n = sim->getChild("fg-aircraft", index, true);
|
2016-06-21 11:29:04 +00:00
|
|
|
n->setStringValue(it->utf8Str());
|
2014-06-11 17:19:41 +00:00
|
|
|
n->setAttribute(SGPropertyNode::WRITE, false);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-26 12:20:51 +00:00
|
|
|
void fgInitAircraftPaths(bool reinit)
|
2013-11-23 19:58:45 +00:00
|
|
|
{
|
2015-03-10 08:30:55 +00:00
|
|
|
if (!globals->packageRoot()) {
|
|
|
|
fgInitPackageRoot();
|
2014-12-26 12:20:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SGSharedPtr<Root> pkgRoot(globals->packageRoot());
|
|
|
|
SGPropertyNode* aircraftProp = fgGetNode("/sim/aircraft", true);
|
|
|
|
aircraftProp->setAttribute(SGPropertyNode::PRESERVE, true);
|
|
|
|
|
|
|
|
if (!reinit) {
|
|
|
|
flightgear::Options::sharedInstance()->initPaths();
|
|
|
|
}
|
|
|
|
}
|
2014-06-11 17:19:41 +00:00
|
|
|
|
2014-12-26 12:20:51 +00:00
|
|
|
int fgInitAircraft(bool reinit)
|
|
|
|
{
|
2014-06-11 17:19:41 +00:00
|
|
|
if (!reinit) {
|
2013-11-23 19:58:45 +00:00
|
|
|
flightgear::Options::sharedInstance()->initAircraft();
|
|
|
|
}
|
2014-12-26 12:20:51 +00:00
|
|
|
|
2018-08-30 14:23:45 +00:00
|
|
|
FindAndCacheAircraft f(globals->get_props());
|
|
|
|
const bool haveExplicit = f.haveExplicitAircraft();
|
|
|
|
|
2014-12-26 12:20:51 +00:00
|
|
|
SGSharedPtr<Root> pkgRoot(globals->packageRoot());
|
|
|
|
SGPropertyNode* aircraftProp = fgGetNode("/sim/aircraft", true);
|
2014-06-15 18:10:24 +00:00
|
|
|
string aircraftId(aircraftProp->getStringValue());
|
2018-08-30 14:23:45 +00:00
|
|
|
|
|
|
|
PackageRef acftPackage;
|
|
|
|
if (!haveExplicit) {
|
|
|
|
acftPackage = pkgRoot->getPackageById(aircraftId);
|
|
|
|
}
|
|
|
|
|
2014-06-11 17:19:41 +00:00
|
|
|
if (acftPackage) {
|
2014-06-12 12:06:01 +00:00
|
|
|
if (acftPackage->isInstalled()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Loading aircraft from package:" << acftPackage->qualifiedId());
|
|
|
|
|
|
|
|
// set catalog path so intra-package dependencies within the catalog
|
|
|
|
// are resolved correctly.
|
|
|
|
globals->set_catalog_aircraft_path(acftPackage->catalog()->installRoot());
|
|
|
|
|
|
|
|
// set aircraft-dir to short circuit the search process
|
|
|
|
InstallRef acftInstall = acftPackage->install();
|
2016-06-23 13:26:34 +00:00
|
|
|
fgSetString("/sim/aircraft-dir", acftInstall->path().utf8Str());
|
2014-06-12 12:06:01 +00:00
|
|
|
|
|
|
|
// overwrite the fully qualified ID with the aircraft one, so the
|
|
|
|
// code in FindAndCacheAircraft works as normal
|
2014-06-15 18:10:24 +00:00
|
|
|
// note since we may be using a variant, we can't use the package ID
|
|
|
|
size_t lastDot = aircraftId.rfind('.');
|
2015-11-19 21:37:03 +00:00
|
|
|
if (lastDot != std::string::npos) {
|
2015-10-16 01:05:35 +00:00
|
|
|
aircraftId = aircraftId.substr(lastDot + 1);
|
|
|
|
}
|
2015-08-03 20:53:56 +00:00
|
|
|
aircraftProp->setStringValue(aircraftId);
|
2015-10-16 01:05:35 +00:00
|
|
|
|
2014-06-12 12:06:01 +00:00
|
|
|
// run the traditional-code path below
|
|
|
|
} else {
|
|
|
|
#if 0
|
2014-06-11 17:19:41 +00:00
|
|
|
// naturally the better option would be to on-demand install it!
|
2017-04-09 16:38:38 +00:00
|
|
|
flightgear::fatalMessageBoxWithoutExit(
|
|
|
|
"Aircraft not installed",
|
|
|
|
"Requested aircraft is not currently installed.",
|
|
|
|
aircraftId);
|
2014-06-11 17:19:41 +00:00
|
|
|
|
|
|
|
return flightgear::FG_OPTIONS_ERROR;
|
2014-06-12 12:06:01 +00:00
|
|
|
#endif
|
2015-10-16 01:05:35 +00:00
|
|
|
// fall back the default aircraft instead
|
2014-06-11 17:19:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
initAircraftDirsNasalSecurity();
|
|
|
|
|
2010-07-06 20:06:50 +00:00
|
|
|
if (!f.loadAircraft()) {
|
2013-11-23 19:58:45 +00:00
|
|
|
return flightgear::FG_OPTIONS_ERROR;
|
2002-10-10 15:02:50 +00:00
|
|
|
}
|
2013-11-23 19:58:45 +00:00
|
|
|
|
|
|
|
return flightgear::FG_OPTIONS_OK;
|
2002-10-10 15:02:50 +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,
|
2013-10-20 19:46:40 +00:00
|
|
|
* to allow lengthy caching to take place in the background, without
|
2012-09-25 16:24:12 +00:00
|
|
|
* blocking the main/UI thread.
|
2003-02-21 02:45:47 +00:00
|
|
|
*/
|
|
|
|
bool
|
|
|
|
fgInitNav ()
|
|
|
|
{
|
2015-03-08 00:40:22 +00:00
|
|
|
flightgear::NavDataCache* cache = flightgear::NavDataCache::instance();
|
|
|
|
static bool doingRebuild = false;
|
|
|
|
|
|
|
|
if (!cache) {
|
|
|
|
cache = flightgear::NavDataCache::createInstance();
|
|
|
|
doingRebuild = cache->isRebuildRequired();
|
|
|
|
}
|
|
|
|
|
2015-03-19 17:01:38 +00:00
|
|
|
static const char* splashIdentsByRebuildPhase[] = {
|
|
|
|
"loading-nav-dat",
|
2016-10-19 11:01:35 +00:00
|
|
|
"navdata-reading-apt-dat-files",
|
|
|
|
"navdata-loading-airports",
|
2015-03-19 17:01:38 +00:00
|
|
|
"navdata-navaids",
|
|
|
|
"navdata-fixes",
|
|
|
|
"navdata-pois"
|
|
|
|
};
|
|
|
|
|
2015-03-08 00:40:22 +00:00
|
|
|
if (doingRebuild) {
|
2015-03-19 17:01:38 +00:00
|
|
|
flightgear::NavDataCache::RebuildPhase phase;
|
|
|
|
phase = cache->rebuild();
|
|
|
|
if (phase != flightgear::NavDataCache::REBUILD_DONE) {
|
|
|
|
// update the splash text based on percentage, phase
|
|
|
|
|
|
|
|
fgSplashProgress(splashIdentsByRebuildPhase[phase],
|
|
|
|
cache->rebuildPhaseCompletionPercentage());
|
|
|
|
|
2015-03-08 00:40:22 +00:00
|
|
|
// sleep to give the rebuild thread more time
|
|
|
|
SGTimeStamp::sleepForMSec(50);
|
|
|
|
return false;
|
|
|
|
}
|
2012-09-25 16:24:12 +00:00
|
|
|
}
|
2014-12-26 12:20:51 +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" );
|
2017-02-25 16:38:00 +00:00
|
|
|
flightgear::NavLoader().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() {
|
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
|
|
|
|
2016-06-21 11:29:04 +00:00
|
|
|
if ( globals->get_fg_root().isNull() ) {
|
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." );
|
2013-10-15 21:16:50 +00:00
|
|
|
return false;
|
1998-04-25 15:11:10 +00:00
|
|
|
}
|
2016-06-21 11:29:04 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "FG_ROOT = " << '"' << globals->get_fg_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);
|
2014-03-05 23:41:41 +00:00
|
|
|
curr->removeChild("fg-current", 0);
|
2008-06-22 11:29:32 +00:00
|
|
|
curr = curr->getChild("fg-current", 0, true);
|
2016-06-23 13:26:34 +00:00
|
|
|
curr->setStringValue(cwd.path().utf8Str());
|
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 );
|
2016-03-28 22:50:47 +00:00
|
|
|
|
|
|
|
sgUserDataInit( globals->get_props() );
|
|
|
|
|
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" );
|
2018-05-23 10:16:22 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "============= =====" );
|
2013-02-08 13:15:20 +00:00
|
|
|
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "aircraft-dir = " << '"' << fgGetString("/sim/aircraft-dir") << '"' );
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "fghome-dir = " << '"' << globals->get_fg_home() << '"');
|
2015-03-17 22:10:49 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "download-dir = " << '"' << fgGetString("/sim/paths/download-dir") << '"' );
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "terrasync-dir = " << '"' << fgGetString("/sim/terrasync/scenery-dir") << '"' );
|
|
|
|
|
2016-06-21 11:29:04 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "aircraft-search-paths = \n\t" << SGPath::join(globals->get_aircraft_paths(), "\n\t") );
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "scenery-search-paths = \n\t" << SGPath::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.
|
2013-11-16 12:10:32 +00:00
|
|
|
void fgCreateSubsystems(bool duringReset) {
|
2009-10-24 09:22:20 +00:00
|
|
|
|
2012-09-18 19:29:36 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Creating Subsystems");
|
2018-05-23 10:16:22 +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-
|
2015-12-10 22:48:02 +00:00
|
|
|
globals->add_new_subsystem<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
|
|
|
////////////////////////////////////////////////////////////////////
|
2014-07-11 23:17:35 +00:00
|
|
|
globals->add_subsystem("prop-interpolator", new FGInterpolator, SGSubsystemMgr::INIT);
|
|
|
|
|
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
|
|
|
|
2015-12-05 00:25:29 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Add the FlightGear property utilities.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2015-12-10 22:48:02 +00:00
|
|
|
globals->add_new_subsystem<flightgear::AirportDynamicsManager>();
|
2015-12-05 00:25:29 +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.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2013-11-21 17:38:22 +00:00
|
|
|
SGPath mpath( globals->get_fg_root() );
|
|
|
|
mpath.append( fgGetString("/sim/rendering/materials-file") );
|
2016-06-23 13:26:34 +00:00
|
|
|
if ( ! globals->get_matlib()->load(globals->get_fg_root().local8BitStr(), mpath.local8BitStr(),
|
2013-11-21 17:38:22 +00:00
|
|
|
globals->get_props()) ) {
|
|
|
|
throw sg_io_exception("Error loading materials file", mpath);
|
2000-06-23 00:30:04 +00:00
|
|
|
}
|
2015-03-10 08:30:55 +00:00
|
|
|
|
|
|
|
// may exist already due to GUI startup
|
2016-03-24 15:08:38 +00:00
|
|
|
if (!globals->get_subsystem<FGHTTPClient>()) {
|
|
|
|
globals->add_new_subsystem<FGHTTPClient>();
|
2015-03-10 08:30:55 +00:00
|
|
|
}
|
2016-11-08 09:41:49 +00:00
|
|
|
globals->add_new_subsystem<FGDNSClient>();
|
2015-03-10 08:30:55 +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);
|
2015-12-31 05:11:06 +00:00
|
|
|
globals->add_new_subsystem<Ephemeris>();
|
2011-11-05 13:18:36 +00:00
|
|
|
|
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 );
|
2015-12-10 22:30:26 +00:00
|
|
|
globals->add_new_subsystem<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.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2013-12-09 22:13:45 +00:00
|
|
|
simgear::canvas::Canvas::setSystemAdapter(
|
|
|
|
simgear::canvas::SystemAdapterPtr(new canvas::FGCanvasSystemAdapter)
|
|
|
|
);
|
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
|
|
|
|
2010-08-01 14:16:33 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2011-04-03 15:58:16 +00:00
|
|
|
// Initialize the ATC subsystem
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2015-12-19 08:29:00 +00:00
|
|
|
|
|
|
|
globals->add_new_subsystem<PerformanceDB>(SGSubsystemMgr::POST_FDM);
|
2011-04-03 15:58:16 +00:00
|
|
|
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
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2015-12-19 08:29:00 +00:00
|
|
|
|
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
|
|
|
|
2015-12-10 21:05:54 +00:00
|
|
|
globals->add_new_subsystem<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.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
2018-01-14 13:16:56 +00:00
|
|
|
globals->add_new_subsystem<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
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2018-09-09 12:42:51 +00:00
|
|
|
globals->add_new_subsystem<FGReplay>(SGSubsystemMgr::GENERAL);
|
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
|
|
|
|
2013-05-19 14:29:49 +00:00
|
|
|
#ifdef ENABLE_IAX
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the FGCom subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->add_subsystem("fgcom", new FGCom);
|
|
|
|
#endif
|
|
|
|
|
2014-03-03 20:59:16 +00:00
|
|
|
{
|
|
|
|
SGSubsystem * httpd = flightgear::http::FGHttpd::createInstance( fgGetNode(flightgear::http::PROPERTY_ROOT) );
|
|
|
|
if( NULL != httpd )
|
|
|
|
globals->add_subsystem("httpd", httpd );
|
|
|
|
}
|
|
|
|
|
2002-10-03 21:20:56 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
2010-10-22 11:22:00 +00:00
|
|
|
// Initialize the lighting subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
// ordering here is important : Nasal (via events), then models, then views
|
2013-11-16 12:10:32 +00:00
|
|
|
if (!duringReset) {
|
|
|
|
globals->add_subsystem("lighting", new FGLight, SGSubsystemMgr::DISPLAY);
|
|
|
|
globals->add_subsystem("events", globals->get_event_mgr(), SGSubsystemMgr::DISPLAY);
|
|
|
|
}
|
2010-10-22 11:22:00 +00:00
|
|
|
|
2015-12-19 04:13:23 +00:00
|
|
|
globals->add_new_subsystem<FGAircraftModel>(SGSubsystemMgr::DISPLAY);
|
2015-12-19 03:56:56 +00:00
|
|
|
globals->add_new_subsystem<FGModelMgr>(SGSubsystemMgr::DISPLAY);
|
2010-10-22 11:22:00 +00:00
|
|
|
|
2015-12-10 22:48:02 +00:00
|
|
|
globals->add_new_subsystem<FGViewMgr>(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
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
2018-08-19 11:34:27 +00:00
|
|
|
globals->add_new_subsystem<FGNasalSys>(SGSubsystemMgr::INIT);
|
2013-04-29 20:15:32 +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);
|
1997-08-23 01:46:20 +00:00
|
|
|
}
|
1999-04-27 15:52:32 +00:00
|
|
|
|
2014-02-24 06:10:29 +00:00
|
|
|
// re-position is a simplified version of the traditional (legacy)
|
|
|
|
// reset procedure. We only need to poke systems which will be upset by
|
|
|
|
// a sudden change in aircraft position. Since this potentially includes
|
|
|
|
// Nasal, we trigger the 'reinit' signal.
|
|
|
|
void fgStartReposition()
|
|
|
|
{
|
|
|
|
SGPropertyNode *master_freeze = fgGetNode("/sim/freeze/master");
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "fgStartReposition()");
|
|
|
|
|
|
|
|
// ensure we are frozen
|
|
|
|
bool freeze = master_freeze->getBoolValue();
|
|
|
|
if ( !freeze ) {
|
|
|
|
master_freeze->setBoolValue(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
// set this signal so Nasal scripts can take action.
|
|
|
|
fgSetBool("/sim/signals/reinit", true);
|
|
|
|
fgSetBool("/sim/crashed", false);
|
|
|
|
|
2018-09-09 12:42:51 +00:00
|
|
|
FDMShell* fdm = globals->get_subsystem<FDMShell>();
|
2014-03-10 12:00:51 +00:00
|
|
|
fdm->unbind();
|
2014-02-24 06:10:29 +00:00
|
|
|
|
|
|
|
// update our position based on current presets
|
|
|
|
// this will mark position as needed finalized which we'll do in the
|
|
|
|
// main-loop
|
|
|
|
flightgear::initPosition();
|
|
|
|
|
|
|
|
simgear::SGTerraSync* terraSync =
|
|
|
|
static_cast<simgear::SGTerraSync*>(globals->get_subsystem("terrasync"));
|
|
|
|
if (terraSync) {
|
|
|
|
terraSync->reposition();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Initialize the FDM
|
2018-09-09 12:42:51 +00:00
|
|
|
globals->get_subsystem<FDMShell>()->reinit();
|
2014-02-24 06:10:29 +00:00
|
|
|
|
|
|
|
// reset replay buffers
|
2018-09-09 12:42:51 +00:00
|
|
|
globals->get_subsystem<FGReplay>()->reinit();
|
2014-02-24 06:10:29 +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();
|
|
|
|
}
|
|
|
|
|
2018-09-09 12:42:51 +00:00
|
|
|
// need to bind FDMshell again
|
2014-03-10 12:02:10 +00:00
|
|
|
fdm->bind();
|
2018-09-09 12:42:51 +00:00
|
|
|
|
2014-03-10 12:02:10 +00:00
|
|
|
// need to reset aircraft (systems/instruments/autopilot)
|
|
|
|
// so they can adapt to current environment
|
2014-02-24 06:10:29 +00:00
|
|
|
globals->get_subsystem("systems")->reinit();
|
|
|
|
globals->get_subsystem("instrumentation")->reinit();
|
2014-03-10 12:02:10 +00:00
|
|
|
globals->get_subsystem("xml-autopilot")->reinit();
|
2014-03-05 15:16:07 +00:00
|
|
|
|
2014-02-24 06:10:29 +00:00
|
|
|
// setup state to end re-init
|
|
|
|
fgSetBool("/sim/signals/reinit", false);
|
|
|
|
if ( !freeze ) {
|
|
|
|
master_freeze->setBoolValue(false);
|
|
|
|
}
|
|
|
|
fgSetBool("/sim/sceneryloaded",false);
|
|
|
|
}
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
void fgStartNewReset()
|
|
|
|
{
|
2018-09-01 18:21:47 +00:00
|
|
|
// save user settings now, so that USERARCIVE-d values changes since the
|
|
|
|
// last init are recorded and hence re-loaded when we fgInitConfig down
|
|
|
|
// later in this function. Otherwise all such settings are lost.
|
|
|
|
globals->saveUserSettings();
|
|
|
|
|
2013-12-09 23:27:25 +00:00
|
|
|
SGPropertyNode_ptr preserved(new SGPropertyNode);
|
2014-02-24 06:10:29 +00:00
|
|
|
|
2013-12-15 20:45:08 +00:00
|
|
|
if (!copyPropertiesWithAttribute(globals->get_props(), preserved, SGPropertyNode::PRESERVE))
|
2013-12-09 23:27:25 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "Error saving preserved state");
|
2013-11-16 12:10:32 +00:00
|
|
|
|
|
|
|
fgSetBool("/sim/signals/reinit", true);
|
|
|
|
fgSetBool("/sim/freeze/master", true);
|
|
|
|
|
|
|
|
SGSubsystemMgr* subsystemManger = globals->get_subsystem_mgr();
|
2018-08-19 11:34:27 +00:00
|
|
|
// Nasal is added in fgPostInit, ensure it's already shutdown
|
2015-12-19 08:32:25 +00:00
|
|
|
// before other subsystems, so Nasal listeners don't fire during shutdown
|
2014-01-13 16:41:31 +00:00
|
|
|
subsystemManger->remove("nasal");
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
subsystemManger->shutdown();
|
|
|
|
subsystemManger->unbind();
|
|
|
|
|
2013-12-15 20:45:08 +00:00
|
|
|
// remove most subsystems, with a few exceptions.
|
2013-11-16 12:10:32 +00:00
|
|
|
for (int g=0; g<SGSubsystemMgr::MAX_GROUPS; ++g) {
|
|
|
|
SGSubsystemGroup* grp = subsystemManger->get_group(static_cast<SGSubsystemMgr::GroupType>(g));
|
2017-12-04 21:41:05 +00:00
|
|
|
for (auto nm : grp->member_names()) {
|
|
|
|
if ((nm == "time") || (nm == "terrasync") || (nm == "events")
|
|
|
|
|| (nm == "lighting") || (nm == FGScenery::subsystemName()))
|
2013-11-16 12:10:32 +00:00
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
try {
|
2017-12-04 21:41:05 +00:00
|
|
|
subsystemManger->remove(nm.c_str());
|
2013-11-16 12:10:32 +00:00
|
|
|
} catch (std::exception& e) {
|
2017-12-04 21:41:05 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "caught std::exception shutting down:" << nm);
|
2013-11-16 12:10:32 +00:00
|
|
|
} catch (...) {
|
2017-12-04 21:41:05 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "caught generic exception shutting down:" << nm);
|
2013-11-16 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// don't delete here, dropping the ref should be sufficient
|
|
|
|
}
|
|
|
|
} // of top-level groups iteration
|
|
|
|
|
2014-03-11 16:45:31 +00:00
|
|
|
FGRenderer* render = globals->get_renderer();
|
|
|
|
// needed or we crash in multi-threaded OSG mode
|
|
|
|
render->getViewer()->stopThreading();
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
// order is important here since tile-manager shutdown needs to
|
|
|
|
// access the scenery object
|
2015-12-10 22:48:02 +00:00
|
|
|
subsystemManger->remove(FGScenery::subsystemName());
|
|
|
|
|
2014-03-13 18:18:23 +00:00
|
|
|
FGScenery::getPagerSingleton()->clearRequests();
|
2013-11-16 12:10:32 +00:00
|
|
|
flightgear::CameraGroup::setDefault(NULL);
|
|
|
|
|
|
|
|
// don't cancel the pager until after shutdown, since AIModels (and
|
|
|
|
// potentially others) can queue delete requests on the pager.
|
|
|
|
render->getViewer()->getDatabasePager()->cancel();
|
2013-12-09 23:27:25 +00:00
|
|
|
render->getViewer()->getDatabasePager()->clear();
|
2013-11-16 12:10:32 +00:00
|
|
|
|
2013-12-06 17:33:13 +00:00
|
|
|
osgDB::Registry::instance()->clearObjectCache();
|
2016-03-28 22:50:47 +00:00
|
|
|
// Pager requests depend on this, so don't clear it until now
|
|
|
|
sgUserDataInit( NULL );
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
// preserve the event handler; re-creating it would entail fixing the
|
|
|
|
// idle handler
|
|
|
|
osg::ref_ptr<flightgear::FGEventHandler> eventHandler = render->getEventHandler();
|
|
|
|
|
|
|
|
globals->set_renderer(NULL);
|
2013-11-21 17:38:22 +00:00
|
|
|
globals->set_matlib(NULL);
|
2013-11-16 12:10:32 +00:00
|
|
|
|
2013-12-04 09:09:47 +00:00
|
|
|
simgear::clearEffectCache();
|
2013-11-25 23:53:58 +00:00
|
|
|
simgear::SGModelLib::resetPropertyRoot();
|
2013-12-15 20:45:08 +00:00
|
|
|
simgear::GlobalParticleCallback::setSwitch(NULL);
|
2018-09-13 21:52:52 +00:00
|
|
|
simgear::UniformFactory::instance()->reset();
|
2013-11-16 12:10:32 +00:00
|
|
|
|
2013-12-15 20:45:08 +00:00
|
|
|
globals->resetPropertyRoot();
|
2014-03-26 19:23:34 +00:00
|
|
|
// otherwise channels are duplicated
|
|
|
|
globals->get_channel_options_list()->clear();
|
Improved infrastructure for add-ons: C++ classes, metadata file, Nasal interface
This commit adds C++ classes for add-on management, most notably
AddonManager, Addon and AddonVersion. The AddonManager is used to
register add-ons. It relies on an std::map<std::string, AddonRef> to
hold the metadata of each registered add-on (keys of the std::map are
add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>).
Accessor methods are available for:
- retrieving the list of registered or loaded add-ons (terminology
explained in $FG_ROOT/Docs/README.add-ons);
- checking if a particular add-on has already been registered or
loaded;
- for each add-on, obtaining an Addon instance which can be queried
for its name, id, version, base path, the minimum and maximum
FlightGear versions it requires, its base node in the Property Tree,
its order in the load sequence, short and long description strings,
home page, etc.
The most important metadata is made accessible in the Property Tree
under /addons/by-id/<addon-id> and the property
/addons/by-id/<addon-id>/loaded can be checked or listened to, in
order to determine when a particular add-on is loaded. There is also a
Nasal interface to access add-on metadata in a convenient way.
In order to provide this metadata, each add-on must from now on have in
its base directory a file called 'addon-metadata.xml'.
All this is documented in much more detail in
$FG_ROOT/Docs/README.add-ons.
Mailing-list discussion:
https://sourceforge.net/p/flightgear/mailman/message/36146017/
2017-11-06 12:58:14 +00:00
|
|
|
|
2017-12-15 22:53:46 +00:00
|
|
|
flightgear::addons::AddonManager::reset();
|
|
|
|
flightgear::addons::AddonManager::createInstance();
|
Improved infrastructure for add-ons: C++ classes, metadata file, Nasal interface
This commit adds C++ classes for add-on management, most notably
AddonManager, Addon and AddonVersion. The AddonManager is used to
register add-ons. It relies on an std::map<std::string, AddonRef> to
hold the metadata of each registered add-on (keys of the std::map are
add-on identifiers, and AddonRef is currently SGSharedPtr<Addon>).
Accessor methods are available for:
- retrieving the list of registered or loaded add-ons (terminology
explained in $FG_ROOT/Docs/README.add-ons);
- checking if a particular add-on has already been registered or
loaded;
- for each add-on, obtaining an Addon instance which can be queried
for its name, id, version, base path, the minimum and maximum
FlightGear versions it requires, its base node in the Property Tree,
its order in the load sequence, short and long description strings,
home page, etc.
The most important metadata is made accessible in the Property Tree
under /addons/by-id/<addon-id> and the property
/addons/by-id/<addon-id>/loaded can be checked or listened to, in
order to determine when a particular add-on is loaded. There is also a
Nasal interface to access add-on metadata in a convenient way.
In order to provide this metadata, each add-on must from now on have in
its base directory a file called 'addon-metadata.xml'.
All this is documented in much more detail in
$FG_ROOT/Docs/README.add-ons.
Mailing-list discussion:
https://sourceforge.net/p/flightgear/mailman/message/36146017/
2017-11-06 12:58:14 +00:00
|
|
|
|
2013-11-22 22:42:04 +00:00
|
|
|
fgInitConfig(0, NULL, true);
|
|
|
|
fgInitGeneral(); // all of this?
|
|
|
|
|
2014-03-11 22:43:25 +00:00
|
|
|
flightgear::Options::sharedInstance()->processOptions();
|
Integrate the EmbeddedResourceManager into FlightGear
${CMAKE_SOURCE_DIR}/src/EmbeddedResources/FlightGear-resources.xml
(currently empty) is automatically "compiled" into
${CMAKE_BINARY_DIR}/src/EmbeddedResources/FlightGear-resources.[ch]xx by
fgrcc inside the build directory. These files are incorporated into the
FlightGear build (FlightGear-resources.cxx is linked into FlightGear).
When the XML embedded resource declaration file added here,
FlightGear-resources.xml, is compiled, fgrcc is passed the
--root=${CMAKE_SOURCE_DIR} option, so that files referred to in
FlightGear-resources.xml are looked up relatively to the root directory
of the FlightGear repository. One could use a second XML embedded
resource declaration file compiled with a different --root option to
grab files from FGData, for instance. I would name such a file
FGData-resources.xml to be consistent with the current naming scheme.
Note: this --root option applies to the paths of real files. Don't
confuse it with the 'prefix' attribute of <qresource> elements
inside XML resource declaration files (such as
FlightGear-resources.xml), which applies to the virtual path of
each resource defined beneath.
The commands in src/Main/CMakeLists.txt ensure that
FlightGear-resources.xml is recompiled with fgrcc whenever it is
changed, and obviously also when FlightGear-resources.cxx or
FlightGear-resources.hxx is missing. However, CMake doesn't know how to
parse fgrcc XML resource declaration files, therefore when a resource is
modified but the XML file it is declared in is not (here,
FlightGear-resources.xml), you have to trigger yourself a recompilation
of the XML resource declaration file to see the new resource contents
inside FlightGear. The easiest ways to do so are:
- either update the timestamp of the XML resource declaration file;
- or remove one or both of the generated files
(FlightGear-resources.cxx and FlightGear-resources.hxx here).
The EmbeddedResourceManager is created in fgMainInit() just after
Options::processOptions() set the language that was either requested by
the user or obtained from the system (locales). Resources from
FlightGear-resources.cxx are added to it, after which
EmbeddedResourceManager::selectLocale() is called with the user's
preferred locale (obtained with FGLocale::getPreferredLanguage()).
Upon reset (fgStartNewReset()), EmbeddedResourceManager::selectLocale()
is called in a similar way after Options::processOptions(), however in
this case the EmbeddedResourceManager instance doesn't have to be
recreated.
2017-04-27 22:09:14 +00:00
|
|
|
|
2017-08-26 15:49:30 +00:00
|
|
|
// Rebuild the lists of allowed paths for cases where a path comes from an
|
|
|
|
// untrusted source, such as the global property tree (this uses $FG_HOME
|
|
|
|
// and other paths set by Options::processOptions()).
|
|
|
|
fgInitAllowedPaths();
|
|
|
|
|
Integrate the EmbeddedResourceManager into FlightGear
${CMAKE_SOURCE_DIR}/src/EmbeddedResources/FlightGear-resources.xml
(currently empty) is automatically "compiled" into
${CMAKE_BINARY_DIR}/src/EmbeddedResources/FlightGear-resources.[ch]xx by
fgrcc inside the build directory. These files are incorporated into the
FlightGear build (FlightGear-resources.cxx is linked into FlightGear).
When the XML embedded resource declaration file added here,
FlightGear-resources.xml, is compiled, fgrcc is passed the
--root=${CMAKE_SOURCE_DIR} option, so that files referred to in
FlightGear-resources.xml are looked up relatively to the root directory
of the FlightGear repository. One could use a second XML embedded
resource declaration file compiled with a different --root option to
grab files from FGData, for instance. I would name such a file
FGData-resources.xml to be consistent with the current naming scheme.
Note: this --root option applies to the paths of real files. Don't
confuse it with the 'prefix' attribute of <qresource> elements
inside XML resource declaration files (such as
FlightGear-resources.xml), which applies to the virtual path of
each resource defined beneath.
The commands in src/Main/CMakeLists.txt ensure that
FlightGear-resources.xml is recompiled with fgrcc whenever it is
changed, and obviously also when FlightGear-resources.cxx or
FlightGear-resources.hxx is missing. However, CMake doesn't know how to
parse fgrcc XML resource declaration files, therefore when a resource is
modified but the XML file it is declared in is not (here,
FlightGear-resources.xml), you have to trigger yourself a recompilation
of the XML resource declaration file to see the new resource contents
inside FlightGear. The easiest ways to do so are:
- either update the timestamp of the XML resource declaration file;
- or remove one or both of the generated files
(FlightGear-resources.cxx and FlightGear-resources.hxx here).
The EmbeddedResourceManager is created in fgMainInit() just after
Options::processOptions() set the language that was either requested by
the user or obtained from the system (locales). Resources from
FlightGear-resources.cxx are added to it, after which
EmbeddedResourceManager::selectLocale() is called with the user's
preferred locale (obtained with FGLocale::getPreferredLanguage()).
Upon reset (fgStartNewReset()), EmbeddedResourceManager::selectLocale()
is called in a similar way after Options::processOptions(), however in
this case the EmbeddedResourceManager instance doesn't have to be
recreated.
2017-04-27 22:09:14 +00:00
|
|
|
const auto& resMgr = simgear::EmbeddedResourceManager::instance();
|
|
|
|
// The language was (re)set in processOptions()
|
|
|
|
const string locale = globals->get_locale()->getPreferredLanguage();
|
|
|
|
resMgr->selectLocale(locale);
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO,
|
|
|
|
"EmbeddedResourceManager: selected locale '" << locale << "'");
|
|
|
|
|
2014-03-11 22:43:25 +00:00
|
|
|
// PRESERVED properties over-write state from options, intentionally
|
2013-12-15 20:45:08 +00:00
|
|
|
if ( copyProperties(preserved, globals->get_props()) ) {
|
2013-12-09 23:27:25 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Preserved state restored successfully" );
|
|
|
|
} else {
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO,
|
|
|
|
"Some errors restoring preserved state (read-only props?)" );
|
|
|
|
}
|
|
|
|
|
|
|
|
fgGetNode("/sim")->removeChild("aircraft-dir");
|
2014-12-26 12:20:51 +00:00
|
|
|
fgInitAircraftPaths(true);
|
2013-11-23 19:58:45 +00:00
|
|
|
fgInitAircraft(true);
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
render = new FGRenderer;
|
|
|
|
render->setEventHandler(eventHandler);
|
2014-03-11 16:45:47 +00:00
|
|
|
eventHandler->reset();
|
2013-11-16 12:10:32 +00:00
|
|
|
globals->set_renderer(render);
|
|
|
|
render->init();
|
|
|
|
render->setViewer(viewer.get());
|
2014-01-13 14:46:38 +00:00
|
|
|
|
2016-03-28 22:50:47 +00:00
|
|
|
sgUserDataInit( globals->get_props() );
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
viewer->getDatabasePager()->setUpThreads(1, 1);
|
|
|
|
|
2016-11-18 16:53:23 +00:00
|
|
|
// must do this before preinit for Rembrandt
|
2013-11-16 12:10:32 +00:00
|
|
|
flightgear::CameraGroup::buildDefaultGroup(viewer.get());
|
2016-11-18 16:53:23 +00:00
|
|
|
render->preinit();
|
2014-03-11 16:45:31 +00:00
|
|
|
viewer->startThreading();
|
2014-01-13 14:46:38 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
fgOSResetProperties();
|
2013-11-23 19:58:45 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
// init some things manually
|
|
|
|
// which do not follow the regular init pattern
|
|
|
|
|
|
|
|
globals->get_event_mgr()->init();
|
|
|
|
globals->get_event_mgr()->setRealtimeProperty(fgGetNode("/sim/time/delta-realtime-sec", true));
|
|
|
|
|
2013-11-21 17:38:22 +00:00
|
|
|
globals->set_matlib( new SGMaterialLib );
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
// terra-sync needs the property tree root, pass it back in
|
2017-12-04 21:41:05 +00:00
|
|
|
auto terra_sync = static_cast<simgear::SGTerraSync*>(subsystemManger->get_subsystem("terrasync"));
|
|
|
|
if (terra_sync) {
|
|
|
|
terra_sync->setRoot(globals->get_props());
|
|
|
|
}
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
fgSetBool("/sim/signals/reinit", false);
|
|
|
|
fgSetBool("/sim/freeze/master", false);
|
|
|
|
fgSetBool("/sim/sceneryloaded",false);
|
|
|
|
}
|
2008-07-09 12:22:33 +00:00
|
|
|
|
2015-03-10 08:30:55 +00:00
|
|
|
void fgInitPackageRoot()
|
|
|
|
{
|
|
|
|
if (globals->packageRoot()) {
|
|
|
|
return;
|
|
|
|
}
|
2016-03-24 15:10:06 +00:00
|
|
|
|
|
|
|
SGPath packageAircraftDir = flightgear::Options::sharedInstance()->valueForOption("download-dir");
|
|
|
|
if (packageAircraftDir.isNull()) {
|
|
|
|
packageAircraftDir = flightgear::defaultDownloadDir();
|
|
|
|
}
|
|
|
|
|
2015-03-10 08:30:55 +00:00
|
|
|
packageAircraftDir.append("Aircraft");
|
|
|
|
|
2016-06-23 13:26:34 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "init package root at:" << packageAircraftDir);
|
2016-03-24 15:10:06 +00:00
|
|
|
|
|
|
|
|
2015-03-10 08:30:55 +00:00
|
|
|
SGSharedPtr<Root> pkgRoot(new Root(packageAircraftDir, FLIGHTGEAR_VERSION));
|
|
|
|
// set the http client later (too early in startup right now)
|
|
|
|
globals->setPackageRoot(pkgRoot);
|
|
|
|
|
|
|
|
}
|
2017-06-14 17:26:38 +00:00
|
|
|
|
|
|
|
int fgUninstall()
|
|
|
|
{
|
|
|
|
SGPath dataPath = SGPath::fromEnv("FG_HOME", platformDefaultDataPath());
|
|
|
|
simgear::Dir fgHome(dataPath);
|
|
|
|
if (fgHome.exists()) {
|
|
|
|
if (!fgHome.remove(true /* recursive */)) {
|
|
|
|
fprintf(stderr, "Errors occurred trying to remove FG_HOME");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fgHome.exists()) {
|
|
|
|
fprintf(stderr, "unable to remove FG_HOME");
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
|
|
|
|
|
|
|
#if defined(SG_WINDOWS)
|
|
|
|
SGPath p = flightgear::defaultDownloadDir();
|
|
|
|
// we don't want to remove the whole dir, let's nuke specific
|
|
|
|
// subdirs which are (hopefully) safe
|
|
|
|
|
|
|
|
SGPath terrasyncPath = p / "TerraSync";
|
|
|
|
if (terrasyncPath.exists()) {
|
|
|
|
simgear::Dir dir(terrasyncPath);
|
|
|
|
if (!dir.remove(true /*recursive*/)) {
|
|
|
|
fprintf(stderr, "Errors occurred trying to remove Documents/FlightGear/TerraSync");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPath packagesPath = p / "Aircraft";
|
|
|
|
if (packagesPath.exists()) {
|
|
|
|
simgear::Dir dir(packagesPath);
|
|
|
|
if (!dir.remove(true /*recursive*/)) {
|
|
|
|
fprintf(stderr, "Errors occurred trying to remove Documents/FlightGear/Aircraft");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|