2000-07-07 17:27:53 +00:00
|
|
|
// globals.cxx -- Global state that needs to be shared among the sim modules
|
|
|
|
//
|
|
|
|
// Written by Curtis Olson, started July 2000.
|
|
|
|
//
|
2004-11-19 22:10:41 +00:00
|
|
|
// Copyright (C) 2000 Curtis L. Olson - http://www.flightgear.org/~curt
|
2000-07-07 17:27:53 +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
|
2009-10-24 08:31:37 +00:00
|
|
|
// along with this program; if not, write to the Free Software Foundation,
|
|
|
|
// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2000-07-07 17:27:53 +00:00
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
|
2005-10-22 11:22:05 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
2000-07-07 17:27:53 +00:00
|
|
|
|
2011-10-16 17:35:40 +00:00
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
#include <algorithm>
|
|
|
|
|
2013-12-30 15:23:01 +00:00
|
|
|
#include <osgViewer/Viewer>
|
|
|
|
#include <osgDB/Registry>
|
|
|
|
|
2003-09-24 17:20:55 +00:00
|
|
|
#include <simgear/structure/commands.hxx>
|
2003-04-24 02:18:12 +00:00
|
|
|
#include <simgear/misc/sg_path.hxx>
|
2010-07-05 07:31:09 +00:00
|
|
|
#include <simgear/misc/sg_dir.hxx>
|
2007-10-20 08:36:21 +00:00
|
|
|
#include <simgear/timing/sg_time.hxx>
|
|
|
|
#include <simgear/ephemeris/ephemeris.hxx>
|
|
|
|
#include <simgear/scene/material/matlib.hxx>
|
2008-07-31 12:04:32 +00:00
|
|
|
#include <simgear/structure/subsystem_mgr.hxx>
|
|
|
|
#include <simgear/structure/event_mgr.hxx>
|
2009-10-24 08:31:37 +00:00
|
|
|
#include <simgear/sound/soundmgr_openal.hxx>
|
2010-09-06 08:13:10 +00:00
|
|
|
#include <simgear/misc/ResourceManager.hxx>
|
2010-12-02 20:29:28 +00:00
|
|
|
#include <simgear/props/propertyObject.hxx>
|
2011-07-30 09:47:28 +00:00
|
|
|
#include <simgear/props/props_io.hxx>
|
2013-11-16 11:56:42 +00:00
|
|
|
#include <simgear/scene/model/modellib.hxx>
|
2014-05-31 17:04:56 +00:00
|
|
|
#include <simgear/package/Root.hxx>
|
2002-03-16 00:18:38 +00:00
|
|
|
|
2007-10-20 08:36:21 +00:00
|
|
|
#include <Aircraft/controls.hxx>
|
|
|
|
#include <Airports/runways.hxx>
|
|
|
|
#include <Autopilot/route_mgr.hxx>
|
2011-12-29 23:39:08 +00:00
|
|
|
#include <GUI/gui.h>
|
2007-10-20 08:36:21 +00:00
|
|
|
#include <Scenery/scenery.hxx>
|
|
|
|
#include <Scenery/tilemgr.hxx>
|
2008-12-09 14:34:30 +00:00
|
|
|
#include <Navaids/navlist.hxx>
|
2012-04-25 21:28:00 +00:00
|
|
|
#include <Viewer/renderer.hxx>
|
|
|
|
#include <Viewer/viewmgr.hxx>
|
2006-06-05 20:21:45 +00:00
|
|
|
|
2000-07-07 17:27:53 +00:00
|
|
|
#include "globals.hxx"
|
2012-04-21 18:17:42 +00:00
|
|
|
#include "locale.hxx"
|
2002-04-05 18:46:47 +00:00
|
|
|
|
2001-01-12 15:37:40 +00:00
|
|
|
#include "fg_props.hxx"
|
2002-08-25 20:56:16 +00:00
|
|
|
#include "fg_io.hxx"
|
2000-07-07 17:27:53 +00:00
|
|
|
|
2010-11-14 20:06:19 +00:00
|
|
|
class AircraftResourceProvider : public simgear::ResourceProvider
|
2010-09-06 08:13:10 +00:00
|
|
|
{
|
|
|
|
public:
|
|
|
|
AircraftResourceProvider() :
|
|
|
|
simgear::ResourceProvider(simgear::ResourceManager::PRIORITY_HIGH)
|
|
|
|
{
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2010-09-06 08:13:10 +00:00
|
|
|
virtual SGPath resolve(const std::string& aResource, SGPath&) const
|
|
|
|
{
|
|
|
|
string_list pieces(sgPathBranchSplit(aResource));
|
|
|
|
if ((pieces.size() < 3) || (pieces.front() != "Aircraft")) {
|
|
|
|
return SGPath(); // not an Aircraft path
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2010-09-08 10:01:26 +00:00
|
|
|
// test against the aircraft-dir property
|
2010-09-06 08:13:10 +00:00
|
|
|
const char* aircraftDir = fgGetString("/sim/aircraft-dir");
|
|
|
|
string_list aircraftDirPieces(sgPathBranchSplit(aircraftDir));
|
2010-11-14 20:06:19 +00:00
|
|
|
if (!aircraftDirPieces.empty() && (aircraftDirPieces.back() == pieces[1])) {
|
2015-09-28 20:12:46 +00:00
|
|
|
// disable this warning for release builds
|
|
|
|
#if defined(ENABLE_DEV_WARNINGS)
|
|
|
|
SGPath betterPath;
|
|
|
|
for (unsigned int i=2; i<pieces.size(); ++i) {
|
|
|
|
betterPath.append(pieces[i]);
|
|
|
|
}
|
|
|
|
SG_LOG(SG_AIRCRAFT, SG_WARN, "resolved path:" << aResource << " using /sim/aircraft-dir.\n"
|
|
|
|
"This is legacy behaviour, change to an aircraft relative path:" << betterPath);
|
|
|
|
#endif
|
|
|
|
|
2010-11-14 20:06:19 +00:00
|
|
|
// current aircraft-dir matches resource aircraft
|
|
|
|
SGPath r(aircraftDir);
|
|
|
|
for (unsigned int i=2; i<pieces.size(); ++i) {
|
|
|
|
r.append(pieces[i]);
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2010-11-14 20:06:19 +00:00
|
|
|
if (r.exists()) {
|
|
|
|
return r;
|
Don't load resources for the current aircraft from several aircraft dirs
* If one has the same aircraft in several aircraft directories,
FlightGear should not mix resources from the various aircraft
directories. For instance, if one starts FG with:
--fg-aircraft=/my/personal/dir:/path/to/fgaddon/Aircraft
and one has in /my/personal/dir/ec130 a clone of the upstream
developer repo, FlightGear should use either the upstream version from
/my/personal/dir/ec130 or the FGAddon version from
/path/to/fgaddon/Aircraft/ec130, but not some strange, untested hybrid
of both.
* This commit makes sure that when the looked-up resource starts with
Aircraft/<ac>, where <ac> is the current aircraft name [last component
of aircraftDir = fgGetString("/sim/aircraft-dir")], then
AircraftResourceProvider::resolve() doesn't search other aircraft
directories if the resource isn't found under 'aircraftDir'.
* To reproduce the bug before this commit, you may add the following
code (there is nothing specific about the SenecaII here, it's just the
aircraft I used for testing):
var file_path = resolvepath("Aircraft/SenecaII/flo-test");
if (file_path != "")
gui.popupTip("flo-test found", 2);
else
gui.popupTip("flo-test not found", 2);
in a keyboard binding for the SenecaII (for instance; you may use the
F11 binding that otherwise only prints a short message). You should
add this to the SenecaII/SenecaII-base.xml file *that will be loaded
by FlightGear*, let's say the one under /my/personal/dir in the
example above (beware of the <path-cache> in autosave_X_Y.xml). Then,
by creating or removing a file named "flo-test" in the SenecaII
subdirectory of other aircraft dirs (for instance,
/path/to/fgaddon/Aircraft in the example above), you can see that the
behavior of the loaded aircraft is influenced by the contents of
unrelated versions of the same aircraft that might be present in other
aircraft dirs (e.g., loaded /my/personal/dir/SenecaII influenced by
/path/to/fgaddon/Aircraft/SenecaII).
* Aircrafts loading resources using paths relative to the current
aircraft directory (e.g., with 'resolvepath("flo-test")') are not
affected by this kind of problem, because this scheme is handled by
CurrentAircraftDirProvider, which does not exhibit this bug.
2015-09-25 22:04:28 +00:00
|
|
|
} else {
|
|
|
|
// Stop here, otherwise we could end up returning a resource that
|
|
|
|
// belongs to an unrelated version of the same aircraft (from a
|
|
|
|
// different aircraft directory).
|
|
|
|
return SGPath();
|
2010-11-14 20:06:19 +00:00
|
|
|
}
|
2010-09-08 10:01:26 +00:00
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2010-11-14 20:06:19 +00:00
|
|
|
// try each aircraft dir in turn
|
2010-09-08 10:01:26 +00:00
|
|
|
std::string res(aResource, 9); // resource path with 'Aircraft/' removed
|
|
|
|
const string_list& dirs(globals->get_aircraft_paths());
|
|
|
|
string_list::const_iterator it = dirs.begin();
|
|
|
|
for (; it != dirs.end(); ++it) {
|
|
|
|
SGPath p(*it, res);
|
|
|
|
if (p.exists()) {
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
} // of aircraft path iteration
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2010-09-08 10:01:26 +00:00
|
|
|
return SGPath(); // not found
|
2010-09-06 08:13:10 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-12-13 09:10:39 +00:00
|
|
|
class CurrentAircraftDirProvider : public simgear::ResourceProvider
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
CurrentAircraftDirProvider() :
|
|
|
|
simgear::ResourceProvider(simgear::ResourceManager::PRIORITY_HIGH)
|
|
|
|
{
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2012-12-13 09:10:39 +00:00
|
|
|
virtual SGPath resolve(const std::string& aResource, SGPath&) const
|
|
|
|
{
|
|
|
|
const char* aircraftDir = fgGetString("/sim/aircraft-dir");
|
|
|
|
SGPath p(aircraftDir);
|
|
|
|
p.append(aResource);
|
|
|
|
return p.exists() ? p : SGPath();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2001-01-19 22:57:24 +00:00
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
// Implementation of FGGlobals.
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2000-07-07 17:27:53 +00:00
|
|
|
// global global :-)
|
2013-11-16 12:10:32 +00:00
|
|
|
FGGlobals *globals = NULL;
|
2000-07-07 17:27:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
// Constructor
|
|
|
|
FGGlobals::FGGlobals() :
|
2004-09-20 13:21:51 +00:00
|
|
|
renderer( new FGRenderer ),
|
2003-09-24 17:20:55 +00:00
|
|
|
subsystem_mgr( new SGSubsystemMgr ),
|
|
|
|
event_mgr( new SGEventMgr ),
|
2002-12-11 21:07:30 +00:00
|
|
|
sim_time_sec( 0.0 ),
|
|
|
|
fg_root( "" ),
|
2012-08-23 20:52:30 +00:00
|
|
|
fg_home( "" ),
|
2002-12-11 21:07:30 +00:00
|
|
|
time_params( NULL ),
|
2013-11-24 19:06:28 +00:00
|
|
|
commands( SGCommandMgr::instance() ),
|
2002-12-11 21:07:30 +00:00
|
|
|
channel_options_list( NULL ),
|
2004-06-14 18:47:21 +00:00
|
|
|
initial_waypoints( NULL ),
|
2011-12-29 23:39:08 +00:00
|
|
|
channellist( NULL ),
|
2016-01-01 20:53:02 +00:00
|
|
|
haveUserSettings(false)
|
2000-07-07 17:27:53 +00:00
|
|
|
{
|
2013-11-16 12:10:32 +00:00
|
|
|
SGPropertyNode* root = new SGPropertyNode;
|
|
|
|
props = SGPropertyNode_ptr(root);
|
|
|
|
locale = new FGLocale(props);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
simgear::ResourceManager::instance()->addProvider(new AircraftResourceProvider);
|
|
|
|
simgear::ResourceManager::instance()->addProvider(new CurrentAircraftDirProvider);
|
|
|
|
initProperties();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FGGlobals::initProperties()
|
|
|
|
{
|
|
|
|
simgear::PropertyObjectBase::setDefaultRoot(props);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
positionLon = props->getNode("position/longitude-deg", true);
|
|
|
|
positionLat = props->getNode("position/latitude-deg", true);
|
|
|
|
positionAlt = props->getNode("position/altitude-ft", true);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
viewLon = props->getNode("sim/current-view/viewer-lon-deg", true);
|
|
|
|
viewLat = props->getNode("sim/current-view/viewer-lat-deg", true);
|
|
|
|
viewAlt = props->getNode("sim/current-view/viewer-elev-ft", true);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
orientPitch = props->getNode("orientation/pitch-deg", true);
|
|
|
|
orientHeading = props->getNode("orientation/heading-deg", true);
|
|
|
|
orientRoll = props->getNode("orientation/roll-deg", true);
|
|
|
|
|
2000-07-07 17:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Destructor
|
2015-09-28 20:12:46 +00:00
|
|
|
FGGlobals::~FGGlobals()
|
2011-12-29 23:39:08 +00:00
|
|
|
{
|
|
|
|
// save user settings (unless already saved)
|
|
|
|
saveUserSettings();
|
|
|
|
|
2015-12-19 06:00:37 +00:00
|
|
|
// stop OSG threading first, to avoid thread races while we tear down
|
|
|
|
// scene-graph pieces
|
|
|
|
|
|
|
|
osg::ref_ptr<osgViewer::Viewer> vw(renderer->getViewer());
|
|
|
|
if (vw) {
|
|
|
|
// https://code.google.com/p/flightgear-bugs/issues/detail?id=1291
|
|
|
|
// explicitly stop trheading before we delete the renderer or
|
|
|
|
// viewMgr (which ultimately holds refs to the CameraGroup, and
|
|
|
|
// GraphicsContext)
|
|
|
|
vw->stopThreading();
|
|
|
|
}
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
subsystem_mgr->shutdown();
|
2015-09-28 20:12:46 +00:00
|
|
|
subsystem_mgr->unbind();
|
2013-11-16 14:25:12 +00:00
|
|
|
|
2015-12-10 22:48:02 +00:00
|
|
|
subsystem_mgr->remove(FGTileMgr::subsystemName());
|
2013-12-30 15:23:01 +00:00
|
|
|
// don't cancel the pager until after shutdown, since AIModels (and
|
|
|
|
// potentially others) can queue delete requests on the pager.
|
2014-01-04 16:10:42 +00:00
|
|
|
if (vw && vw->getDatabasePager()) {
|
|
|
|
vw->getDatabasePager()->cancel();
|
|
|
|
vw->getDatabasePager()->clear();
|
2013-12-30 17:16:53 +00:00
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-12-30 15:23:01 +00:00
|
|
|
osgDB::Registry::instance()->clearObjectCache();
|
2015-12-10 22:48:02 +00:00
|
|
|
subsystem_mgr->remove(FGScenery::subsystemName());
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
// renderer touches subsystems during its destruction
|
|
|
|
set_renderer(NULL);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2008-03-22 09:31:06 +00:00
|
|
|
delete subsystem_mgr;
|
2014-01-04 16:10:42 +00:00
|
|
|
subsystem_mgr = NULL; // important so ::get_subsystem returns NULL
|
|
|
|
vw = 0; // don't delete the viewer until now
|
2013-11-16 12:10:32 +00:00
|
|
|
|
2008-03-22 09:31:06 +00:00
|
|
|
delete time_params;
|
2013-11-21 17:38:22 +00:00
|
|
|
set_matlib(NULL);
|
2015-12-10 22:30:26 +00:00
|
|
|
|
2008-03-22 09:31:06 +00:00
|
|
|
delete channel_options_list;
|
|
|
|
delete initial_waypoints;
|
2007-10-20 08:36:21 +00:00
|
|
|
delete channellist;
|
2012-04-21 18:17:42 +00:00
|
|
|
|
2013-11-16 11:56:42 +00:00
|
|
|
simgear::PropertyObjectBase::setDefaultRoot(NULL);
|
|
|
|
simgear::SGModelLib::resetPropertyRoot();
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2012-04-21 18:17:42 +00:00
|
|
|
delete locale;
|
|
|
|
locale = NULL;
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-12-04 09:11:26 +00:00
|
|
|
cleanupListeners();
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
props.clear();
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-23 19:58:45 +00:00
|
|
|
delete commands;
|
2001-01-19 22:57:24 +00:00
|
|
|
}
|
|
|
|
|
2003-04-24 02:18:12 +00:00
|
|
|
// set the fg_root path
|
2013-06-27 08:37:06 +00:00
|
|
|
void FGGlobals::set_fg_root (const std::string &root) {
|
2012-01-12 21:06:40 +00:00
|
|
|
SGPath tmp(root);
|
|
|
|
fg_root = tmp.realpath();
|
2008-06-16 07:46:55 +00:00
|
|
|
|
2003-04-24 02:18:12 +00:00
|
|
|
// append /data to root if it exists
|
|
|
|
tmp.append( "data" );
|
|
|
|
tmp.append( "version" );
|
2011-11-19 20:25:51 +00:00
|
|
|
if ( tmp.exists() ) {
|
2009-01-30 17:55:14 +00:00
|
|
|
fgGetNode("BAD_FG_ROOT", true)->setStringValue(fg_root);
|
2003-04-24 02:18:12 +00:00
|
|
|
fg_root += "/data";
|
2009-01-30 17:55:14 +00:00
|
|
|
fgGetNode("GOOD_FG_ROOT", true)->setStringValue(fg_root);
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "***\n***\n*** Warning: changing bad FG_ROOT/--fg-root to '"
|
|
|
|
<< fg_root << "'\n***\n***");
|
2006-01-09 03:47:33 +00:00
|
|
|
}
|
|
|
|
|
2015-03-13 18:11:29 +00:00
|
|
|
// deliberately not a tied property, for fgValidatePath security
|
|
|
|
// write-protect to avoid accidents
|
2008-06-16 07:46:55 +00:00
|
|
|
SGPropertyNode *n = fgGetNode("/sim", true);
|
2014-03-05 23:41:41 +00:00
|
|
|
n->removeChild("fg-root", 0);
|
2008-06-16 07:46:55 +00:00
|
|
|
n = n->getChild("fg-root", 0, true);
|
|
|
|
n->setStringValue(fg_root.c_str());
|
|
|
|
n->setAttribute(SGPropertyNode::WRITE, false);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
|
|
|
simgear::ResourceManager::instance()->addBasePath(fg_root,
|
2010-09-06 08:13:10 +00:00
|
|
|
simgear::ResourceManager::PRIORITY_DEFAULT);
|
2003-04-24 02:18:12 +00:00
|
|
|
}
|
|
|
|
|
2012-08-23 20:52:30 +00:00
|
|
|
// set the fg_home path
|
2013-06-27 08:37:06 +00:00
|
|
|
void FGGlobals::set_fg_home (const std::string &home) {
|
2012-08-23 20:52:30 +00:00
|
|
|
SGPath tmp(home);
|
|
|
|
fg_home = tmp.realpath();
|
2013-06-27 08:37:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
PathList FGGlobals::get_data_paths() const
|
|
|
|
{
|
|
|
|
PathList r(additional_data_paths);
|
|
|
|
r.push_back(SGPath(fg_root));
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
PathList FGGlobals::get_data_paths(const std::string& suffix) const
|
|
|
|
{
|
|
|
|
PathList r;
|
|
|
|
BOOST_FOREACH(SGPath p, get_data_paths()) {
|
|
|
|
p.append(suffix);
|
|
|
|
if (p.exists()) {
|
|
|
|
r.push_back(p);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FGGlobals::append_data_path(const SGPath& path)
|
|
|
|
{
|
|
|
|
if (!path.exists()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "adding non-existant data path:" << path);
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-06-27 08:37:53 +00:00
|
|
|
additional_data_paths.push_back(path);
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const
|
|
|
|
{
|
|
|
|
BOOST_FOREACH(SGPath p, additional_data_paths) {
|
|
|
|
p.append(pathSuffix);
|
|
|
|
if (p.exists()) {
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-06-27 08:37:53 +00:00
|
|
|
SGPath rootPath(fg_root);
|
|
|
|
rootPath.append(pathSuffix);
|
|
|
|
if (rootPath.exists()) {
|
|
|
|
return rootPath;
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-06-27 08:37:53 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "dir not found in any data path:" << pathSuffix);
|
|
|
|
return SGPath();
|
2012-08-23 20:52:30 +00:00
|
|
|
}
|
|
|
|
|
2015-11-22 11:27:39 +00:00
|
|
|
void FGGlobals::append_fg_scenery (const std::string &paths, bool secure)
|
2010-07-05 07:31:09 +00:00
|
|
|
{
|
2011-05-24 23:03:51 +00:00
|
|
|
SGPropertyNode* sim = fgGetNode("/sim", true);
|
2011-10-16 17:35:40 +00:00
|
|
|
|
|
|
|
// find first unused fg-scenery property in /sim
|
|
|
|
int propIndex = 0;
|
|
|
|
while (sim->getChild("fg-scenery", propIndex) != NULL) {
|
2015-09-28 20:12:46 +00:00
|
|
|
++propIndex;
|
2011-10-16 17:35:40 +00:00
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2011-10-16 17:35:40 +00:00
|
|
|
BOOST_FOREACH(const SGPath& path, sgPathSplit( paths )) {
|
2012-01-12 21:06:40 +00:00
|
|
|
SGPath abspath(path.realpath());
|
|
|
|
if (!abspath.exists()) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "scenery path not found:" << abspath.str());
|
2010-07-05 07:31:09 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2011-10-16 17:35:40 +00:00
|
|
|
// check for duplicates
|
2012-01-12 21:06:40 +00:00
|
|
|
string_list::const_iterator ex = std::find(fg_scenery.begin(), fg_scenery.end(), abspath.str());
|
2011-10-16 17:35:40 +00:00
|
|
|
if (ex != fg_scenery.end()) {
|
2012-01-12 21:06:40 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "skipping duplicate add of scenery path:" << abspath.str());
|
2011-10-16 17:35:40 +00:00
|
|
|
continue;
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2016-03-19 20:05:28 +00:00
|
|
|
// tell the ResouceManager about the scenery path
|
|
|
|
// needed to load Models from this scenery path
|
|
|
|
simgear::ResourceManager::instance()->addBasePath(abspath.str(),
|
|
|
|
simgear::ResourceManager::PRIORITY_DEFAULT);
|
|
|
|
|
2012-01-12 21:06:40 +00:00
|
|
|
simgear::Dir dir(abspath);
|
2010-07-05 07:31:09 +00:00
|
|
|
SGPath terrainDir(dir.file("Terrain"));
|
|
|
|
SGPath objectsDir(dir.file("Objects"));
|
2015-09-28 20:12:46 +00:00
|
|
|
|
|
|
|
// this code used to add *either* the base dir, OR add the
|
2010-07-05 07:31:09 +00:00
|
|
|
// Terrain and Objects subdirs, but the conditional logic was commented
|
|
|
|
// out, such that all three dirs are added. Unfortunately there's
|
|
|
|
// no information as to why the change was made.
|
2012-01-12 21:06:40 +00:00
|
|
|
fg_scenery.push_back(abspath.str());
|
2015-11-22 11:27:39 +00:00
|
|
|
if (secure) {
|
|
|
|
secure_fg_scenery.push_back(abspath.str());
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2010-07-05 07:31:09 +00:00
|
|
|
if (terrainDir.exists()) {
|
|
|
|
fg_scenery.push_back(terrainDir.str());
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2010-07-05 07:31:09 +00:00
|
|
|
if (objectsDir.exists()) {
|
|
|
|
fg_scenery.push_back(objectsDir.str());
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2005-12-03 10:20:35 +00:00
|
|
|
// insert a marker for FGTileEntry::load(), so that
|
|
|
|
// FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
|
|
|
|
// "B/Terrain", "B/Objects", ""]
|
|
|
|
fg_scenery.push_back("");
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2011-05-24 23:03:51 +00:00
|
|
|
// make scenery dirs available to Nasal
|
2011-10-16 17:35:40 +00:00
|
|
|
SGPropertyNode* n = sim->getChild("fg-scenery", propIndex++, true);
|
2012-01-12 21:06:40 +00:00
|
|
|
n->setStringValue(abspath.str());
|
2011-05-24 23:03:51 +00:00
|
|
|
n->setAttribute(SGPropertyNode::WRITE, false);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2014-03-10 13:26:58 +00:00
|
|
|
// temporary fix so these values survive reset
|
|
|
|
n->setAttribute(SGPropertyNode::PRESERVE, true);
|
2010-07-05 07:31:09 +00:00
|
|
|
} // of path list iteration
|
2004-06-07 09:52:11 +00:00
|
|
|
}
|
|
|
|
|
2014-02-22 16:13:36 +00:00
|
|
|
void FGGlobals::clear_fg_scenery()
|
|
|
|
{
|
|
|
|
fg_scenery.clear();
|
2015-11-22 11:27:39 +00:00
|
|
|
secure_fg_scenery.clear();
|
2015-11-27 23:25:53 +00:00
|
|
|
fgGetNode("/sim", true)->removeChildren("fg-scenery");
|
|
|
|
|
2014-02-22 16:13:36 +00:00
|
|
|
}
|
|
|
|
|
2014-06-11 17:19:41 +00:00
|
|
|
void FGGlobals::set_catalog_aircraft_path(const SGPath& path)
|
|
|
|
{
|
|
|
|
catalog_aircraft_dir = path;
|
|
|
|
}
|
|
|
|
|
|
|
|
string_list FGGlobals::get_aircraft_paths() const
|
|
|
|
{
|
|
|
|
string_list r;
|
|
|
|
if (!catalog_aircraft_dir.isNull()) {
|
|
|
|
r.push_back(catalog_aircraft_dir.str());
|
|
|
|
}
|
|
|
|
|
|
|
|
r.insert(r.end(), fg_aircraft_dirs.begin(), fg_aircraft_dirs.end());
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
2010-07-18 12:21:30 +00:00
|
|
|
void FGGlobals::append_aircraft_path(const std::string& path)
|
|
|
|
{
|
|
|
|
SGPath dirPath(path);
|
|
|
|
if (!dirPath.exists()) {
|
2014-01-15 17:10:12 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "aircraft path not found:" << path);
|
2010-07-18 12:21:30 +00:00
|
|
|
return;
|
|
|
|
}
|
2014-06-22 13:36:25 +00:00
|
|
|
|
2014-01-15 17:10:12 +00:00
|
|
|
SGPath acSubdir(dirPath);
|
|
|
|
acSubdir.append("Aircraft");
|
2014-01-22 10:56:04 +00:00
|
|
|
if (acSubdir.exists()) {
|
2014-06-22 13:36:25 +00:00
|
|
|
SG_LOG(
|
|
|
|
SG_GENERAL,
|
|
|
|
SG_WARN,
|
|
|
|
"Specified an aircraft-dir with an 'Aircraft' subdirectory:" << dirPath
|
|
|
|
<< ", will instead use child directory:" << acSubdir
|
|
|
|
);
|
2014-01-22 10:56:04 +00:00
|
|
|
dirPath = acSubdir;
|
2014-01-15 17:10:12 +00:00
|
|
|
}
|
2014-06-22 13:36:25 +00:00
|
|
|
|
2012-01-12 21:06:40 +00:00
|
|
|
std::string abspath = dirPath.realpath();
|
|
|
|
fg_aircraft_dirs.push_back(abspath);
|
2010-07-18 12:21:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FGGlobals::append_aircraft_paths(const std::string& path)
|
|
|
|
{
|
|
|
|
string_list paths = sgPathSplit(path);
|
|
|
|
for (unsigned int p = 0; p<paths.size(); ++p) {
|
|
|
|
append_aircraft_path(paths[p]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SGPath FGGlobals::resolve_aircraft_path(const std::string& branch) const
|
|
|
|
{
|
2010-09-06 08:13:10 +00:00
|
|
|
return simgear::ResourceManager::instance()->findPath(branch);
|
2010-07-18 12:21:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
SGPath FGGlobals::resolve_maybe_aircraft_path(const std::string& branch) const
|
|
|
|
{
|
2010-09-06 08:13:10 +00:00
|
|
|
return simgear::ResourceManager::instance()->findPath(branch);
|
2010-07-18 12:21:30 +00:00
|
|
|
}
|
2003-04-24 02:18:12 +00:00
|
|
|
|
2012-09-25 09:07:11 +00:00
|
|
|
SGPath FGGlobals::resolve_resource_path(const std::string& branch) const
|
2012-04-21 13:31:20 +00:00
|
|
|
{
|
|
|
|
return simgear::ResourceManager::instance()
|
|
|
|
->findPath(branch, SGPath(fgGetString("/sim/aircraft-dir")));
|
|
|
|
}
|
|
|
|
|
2004-09-20 13:21:51 +00:00
|
|
|
FGRenderer *
|
|
|
|
FGGlobals::get_renderer () const
|
|
|
|
{
|
|
|
|
return renderer;
|
|
|
|
}
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
void FGGlobals::set_renderer(FGRenderer *render)
|
|
|
|
{
|
|
|
|
if (render == renderer) {
|
|
|
|
return;
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
delete renderer;
|
|
|
|
renderer = render;
|
|
|
|
}
|
|
|
|
|
2003-09-24 17:20:55 +00:00
|
|
|
SGSubsystemMgr *
|
2003-01-16 16:01:26 +00:00
|
|
|
FGGlobals::get_subsystem_mgr () const
|
|
|
|
{
|
|
|
|
return subsystem_mgr;
|
|
|
|
}
|
|
|
|
|
2003-09-24 17:20:55 +00:00
|
|
|
SGSubsystem *
|
2015-12-10 21:05:54 +00:00
|
|
|
FGGlobals::get_subsystem (const char * name) const
|
2003-01-16 16:01:26 +00:00
|
|
|
{
|
2013-11-16 14:25:12 +00:00
|
|
|
if (!subsystem_mgr) {
|
|
|
|
return NULL;
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2003-01-16 16:01:26 +00:00
|
|
|
return subsystem_mgr->get_subsystem(name);
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
FGGlobals::add_subsystem (const char * name,
|
2003-09-24 17:20:55 +00:00
|
|
|
SGSubsystem * subsystem,
|
|
|
|
SGSubsystemMgr::GroupType type,
|
2003-01-16 16:01:26 +00:00
|
|
|
double min_time_sec)
|
|
|
|
{
|
|
|
|
subsystem_mgr->add(name, subsystem, type, min_time_sec);
|
|
|
|
}
|
|
|
|
|
2003-09-24 17:20:55 +00:00
|
|
|
SGEventMgr *
|
|
|
|
FGGlobals::get_event_mgr () const
|
|
|
|
{
|
|
|
|
return event_mgr;
|
|
|
|
}
|
|
|
|
|
2012-09-17 23:58:27 +00:00
|
|
|
SGGeod
|
2011-08-20 06:54:47 +00:00
|
|
|
FGGlobals::get_aircraft_position() const
|
|
|
|
{
|
2012-09-19 17:17:44 +00:00
|
|
|
return SGGeod::fromDegFt(positionLon->getDoubleValue(),
|
|
|
|
positionLat->getDoubleValue(),
|
|
|
|
positionAlt->getDoubleValue());
|
2011-08-20 06:54:47 +00:00
|
|
|
}
|
|
|
|
|
2011-10-30 09:31:41 +00:00
|
|
|
SGVec3d
|
2012-09-25 09:06:30 +00:00
|
|
|
FGGlobals::get_aircraft_position_cart() const
|
2011-10-26 16:26:11 +00:00
|
|
|
{
|
|
|
|
return SGVec3d::fromGeod(get_aircraft_position());
|
|
|
|
}
|
2011-08-20 06:54:47 +00:00
|
|
|
|
2012-09-19 17:17:44 +00:00
|
|
|
void FGGlobals::get_aircraft_orientation(double& heading, double& pitch, double& roll)
|
|
|
|
{
|
|
|
|
heading = orientHeading->getDoubleValue();
|
|
|
|
pitch = orientPitch->getDoubleValue();
|
|
|
|
roll = orientRoll->getDoubleValue();
|
|
|
|
}
|
|
|
|
|
2012-09-25 09:06:30 +00:00
|
|
|
SGGeod
|
|
|
|
FGGlobals::get_view_position() const
|
|
|
|
{
|
|
|
|
return SGGeod::fromDegFt(viewLon->getDoubleValue(),
|
|
|
|
viewLat->getDoubleValue(),
|
|
|
|
viewAlt->getDoubleValue());
|
|
|
|
}
|
|
|
|
|
|
|
|
SGVec3d
|
|
|
|
FGGlobals::get_view_position_cart() const
|
|
|
|
{
|
|
|
|
return SGVec3d::fromGeod(get_view_position());
|
|
|
|
}
|
2003-09-24 17:20:55 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
static void treeDumpRefCounts(int depth, SGPropertyNode* nd)
|
|
|
|
{
|
|
|
|
for (int i=0; i<nd->nChildren(); ++i) {
|
|
|
|
SGPropertyNode* cp = nd->getChild(i);
|
|
|
|
if (SGReferenced::count(cp) > 1) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "\t" << cp->getPath() << " refcount:" << SGReferenced::count(cp));
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
treeDumpRefCounts(depth + 1, cp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-13 16:41:31 +00:00
|
|
|
static void treeClearAliases(SGPropertyNode* nd)
|
|
|
|
{
|
|
|
|
if (nd->isAlias()) {
|
|
|
|
nd->unalias();
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2014-01-13 16:41:31 +00:00
|
|
|
for (int i=0; i<nd->nChildren(); ++i) {
|
|
|
|
SGPropertyNode* cp = nd->getChild(i);
|
|
|
|
treeClearAliases(cp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
void
|
|
|
|
FGGlobals::resetPropertyRoot()
|
|
|
|
{
|
|
|
|
delete locale;
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-12-04 09:11:26 +00:00
|
|
|
cleanupListeners();
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-12-04 09:11:26 +00:00
|
|
|
// we don't strictly need to clear these (they will be reset when we
|
|
|
|
// initProperties again), but trying to reduce false-positives when dumping
|
|
|
|
// ref-counts.
|
|
|
|
positionLon.clear();
|
|
|
|
positionLat.clear();
|
|
|
|
positionAlt.clear();
|
|
|
|
viewLon.clear();
|
|
|
|
viewLat.clear();
|
|
|
|
viewAlt.clear();
|
|
|
|
orientPitch.clear();
|
|
|
|
orientHeading.clear();
|
|
|
|
orientRoll.clear();
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2014-01-13 16:41:31 +00:00
|
|
|
// clear aliases so ref-counts are accurate when dumped
|
|
|
|
treeClearAliases(props);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "root props refcount:" << props.getNumRefs());
|
|
|
|
treeDumpRefCounts(0, props);
|
2013-11-22 22:42:04 +00:00
|
|
|
|
2013-12-04 09:11:26 +00:00
|
|
|
//BaseStackSnapshot::dumpAll(std::cout);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
props = new SGPropertyNode;
|
|
|
|
initProperties();
|
|
|
|
locale = new FGLocale(props);
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
// remove /sim/fg-root before writing to prevent hijacking
|
|
|
|
SGPropertyNode *n = props->getNode("/sim", true);
|
2014-03-05 23:41:41 +00:00
|
|
|
n->removeChild("fg-root", 0);
|
2013-11-16 12:10:32 +00:00
|
|
|
n = n->getChild("fg-root", 0, true);
|
|
|
|
n->setStringValue(fg_root.c_str());
|
|
|
|
n->setAttribute(SGPropertyNode::WRITE, false);
|
|
|
|
}
|
|
|
|
|
2013-02-03 16:57:31 +00:00
|
|
|
static std::string autosaveName()
|
|
|
|
{
|
|
|
|
std::ostringstream os;
|
|
|
|
string_list versionParts = simgear::strutils::split(VERSION, ".");
|
|
|
|
if (versionParts.size() < 2) {
|
|
|
|
return "autosave.xml";
|
|
|
|
}
|
2015-09-28 20:12:46 +00:00
|
|
|
|
2013-02-03 16:57:31 +00:00
|
|
|
os << "autosave_" << versionParts[0] << "_" << versionParts[1] << ".xml";
|
|
|
|
return os.str();
|
|
|
|
}
|
2001-01-19 22:57:24 +00:00
|
|
|
|
2011-12-29 23:39:08 +00:00
|
|
|
// Load user settings from autosave.xml
|
|
|
|
void
|
2011-12-30 00:01:15 +00:00
|
|
|
FGGlobals::loadUserSettings(const SGPath& dataPath)
|
2011-12-29 23:39:08 +00:00
|
|
|
{
|
2011-12-30 00:01:15 +00:00
|
|
|
// remember that we have (tried) to load any existing autsave.xml
|
2011-12-29 23:39:08 +00:00
|
|
|
haveUserSettings = true;
|
2011-12-30 00:01:15 +00:00
|
|
|
|
2013-02-03 16:57:31 +00:00
|
|
|
SGPath autosaveFile = simgear::Dir(dataPath).file(autosaveName());
|
2011-12-30 00:01:15 +00:00
|
|
|
SGPropertyNode autosave;
|
|
|
|
if (autosaveFile.exists()) {
|
|
|
|
SG_LOG(SG_INPUT, SG_INFO, "Reading user settings from " << autosaveFile.str());
|
|
|
|
try {
|
|
|
|
readProperties(autosaveFile.str(), &autosave, SGPropertyNode::USERARCHIVE);
|
|
|
|
} catch (sg_exception& e) {
|
|
|
|
SG_LOG(SG_INPUT, SG_WARN, "failed to read user settings:" << e.getMessage()
|
|
|
|
<< "(from " << e.getOrigin() << ")");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
copyProperties(&autosave, globals->get_props());
|
2011-12-29 23:39:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Save user settings in autosave.xml
|
|
|
|
void
|
|
|
|
FGGlobals::saveUserSettings()
|
|
|
|
{
|
|
|
|
// only save settings when we have (tried) to load the previous
|
|
|
|
// settings (otherwise user data was lost)
|
|
|
|
if (!haveUserSettings)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (fgGetBool("/sim/startup/save-on-exit")) {
|
|
|
|
// don't save settings more than once on shutdown
|
|
|
|
haveUserSettings = false;
|
|
|
|
|
2012-08-23 20:52:30 +00:00
|
|
|
SGPath autosaveFile(globals->get_fg_home());
|
2013-02-03 16:57:31 +00:00
|
|
|
autosaveFile.append(autosaveName());
|
2011-12-29 23:39:08 +00:00
|
|
|
autosaveFile.create_dir( 0700 );
|
|
|
|
SG_LOG(SG_IO, SG_INFO, "Saving user settings to " << autosaveFile.str());
|
|
|
|
try {
|
|
|
|
writeProperties(autosaveFile.str(), globals->get_props(), false, SGPropertyNode::USERARCHIVE);
|
|
|
|
} catch (const sg_exception &e) {
|
2013-02-03 16:57:31 +00:00
|
|
|
guiErrorMessage("Error writing autosave:", e);
|
2011-12-29 23:39:08 +00:00
|
|
|
}
|
|
|
|
SG_LOG(SG_INPUT, SG_DEBUG, "Finished Saving user settings");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-21 23:43:41 +00:00
|
|
|
long int FGGlobals::get_warp() const
|
|
|
|
{
|
|
|
|
return fgGetInt("/sim/time/warp");
|
|
|
|
}
|
|
|
|
|
|
|
|
void FGGlobals::set_warp( long int w )
|
|
|
|
{
|
|
|
|
fgSetInt("/sim/time/warp", w);
|
|
|
|
}
|
|
|
|
|
|
|
|
long int FGGlobals::get_warp_delta() const
|
|
|
|
{
|
|
|
|
return fgGetInt("/sim/time/warp-delta");
|
|
|
|
}
|
|
|
|
|
|
|
|
void FGGlobals::set_warp_delta( long int d )
|
|
|
|
{
|
|
|
|
fgSetInt("/sim/time/warp-delta", d);
|
|
|
|
}
|
2012-01-02 23:16:18 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
FGScenery* FGGlobals::get_scenery () const
|
|
|
|
{
|
2015-12-10 22:48:02 +00:00
|
|
|
return get_subsystem<FGScenery>();
|
2013-11-16 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
2015-12-10 22:48:02 +00:00
|
|
|
FGTileMgr* FGGlobals::get_tile_mgr () const
|
2013-11-16 12:10:32 +00:00
|
|
|
{
|
2015-12-10 22:48:02 +00:00
|
|
|
return get_subsystem<FGTileMgr>();
|
2013-11-16 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
2015-12-10 22:48:02 +00:00
|
|
|
FGViewMgr *FGGlobals::get_viewmgr() const
|
2013-11-16 12:10:32 +00:00
|
|
|
{
|
2015-12-10 22:48:02 +00:00
|
|
|
return get_subsystem<FGViewMgr>();
|
2013-11-16 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
2016-01-17 21:06:45 +00:00
|
|
|
flightgear::View* FGGlobals::get_current_view () const
|
2013-11-16 12:10:32 +00:00
|
|
|
{
|
2015-12-10 22:48:02 +00:00
|
|
|
FGViewMgr* vm = get_viewmgr();
|
|
|
|
return vm ? vm->get_current_view() : 0;
|
2013-11-16 12:10:32 +00:00
|
|
|
}
|
|
|
|
|
2013-11-21 17:38:22 +00:00
|
|
|
void FGGlobals::set_matlib( SGMaterialLib *m )
|
|
|
|
{
|
|
|
|
matlib = m;
|
|
|
|
}
|
|
|
|
|
2015-12-10 21:05:54 +00:00
|
|
|
FGControls *FGGlobals::get_controls() const
|
|
|
|
{
|
|
|
|
return get_subsystem<FGControls>();
|
|
|
|
}
|
|
|
|
|
2013-12-04 09:11:26 +00:00
|
|
|
void FGGlobals::addListenerToCleanup(SGPropertyChangeListener* l)
|
|
|
|
{
|
|
|
|
_listeners_to_cleanup.push_back(l);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FGGlobals::cleanupListeners()
|
|
|
|
{
|
|
|
|
SGPropertyChangeListenerVec::iterator i = _listeners_to_cleanup.begin();
|
|
|
|
for (; i != _listeners_to_cleanup.end(); ++i) {
|
|
|
|
delete *i;
|
|
|
|
}
|
|
|
|
_listeners_to_cleanup.clear();
|
|
|
|
}
|
|
|
|
|
2014-05-31 17:04:56 +00:00
|
|
|
simgear::pkg::Root* FGGlobals::packageRoot()
|
|
|
|
{
|
|
|
|
return _packageRoot.get();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FGGlobals::setPackageRoot(const SGSharedPtr<simgear::pkg::Root>& p)
|
|
|
|
{
|
|
|
|
_packageRoot = p;
|
|
|
|
}
|
|
|
|
|
2001-01-19 22:57:24 +00:00
|
|
|
// end of globals.cxx
|