27
27
#include <boost/foreach.hpp>
28
28
#include <algorithm>
30
#include <osgViewer/Viewer>
31
#include <osgDB/Registry>
30
33
#include <simgear/structure/commands.hxx>
31
34
#include <simgear/misc/sg_path.hxx>
32
35
#include <simgear/misc/sg_dir.hxx>
39
42
#include <simgear/misc/ResourceManager.hxx>
40
43
#include <simgear/props/propertyObject.hxx>
41
44
#include <simgear/props/props_io.hxx>
45
#include <simgear/scene/model/modellib.hxx>
43
47
#include <Aircraft/controls.hxx>
44
48
#include <Airports/runways.hxx>
128
131
////////////////////////////////////////////////////////////////////////
130
133
// global global :-)
134
FGGlobals *globals = NULL;
135
138
FGGlobals::FGGlobals() :
136
props( new SGPropertyNode ),
137
139
initial_state( NULL ),
138
locale( new FGLocale(props) ),
139
140
renderer( new FGRenderer ),
140
141
subsystem_mgr( new SGSubsystemMgr ),
141
142
event_mgr( new SGEventMgr ),
152
152
commands( SGCommandMgr::instance() ),
153
153
channel_options_list( NULL ),
154
154
initial_waypoints( NULL ),
157
155
fontcache ( new FGFontCache ),
158
156
channellist( NULL ),
159
haveUserSettings(false)
161
simgear::ResourceManager::instance()->addProvider(new AircraftResourceProvider);
162
simgear::ResourceManager::instance()->addProvider(new CurrentAircraftDirProvider);
163
simgear::PropertyObjectBase::setDefaultRoot(props);
165
positionLon = props->getNode("position/longitude-deg", true);
166
positionLat = props->getNode("position/latitude-deg", true);
167
positionAlt = props->getNode("position/altitude-ft", true);
169
viewLon = props->getNode("sim/current-view/viewer-lon-deg", true);
170
viewLat = props->getNode("sim/current-view/viewer-lat-deg", true);
171
viewAlt = props->getNode("sim/current-view/viewer-elev-ft", true);
173
orientPitch = props->getNode("orientation/pitch-deg", true);
174
orientHeading = props->getNode("orientation/heading-deg", true);
175
orientRoll = props->getNode("orientation/roll-deg", true);
157
haveUserSettings(false),
160
SGPropertyNode* root = new SGPropertyNode;
161
props = SGPropertyNode_ptr(root);
162
locale = new FGLocale(props);
164
simgear::ResourceManager::instance()->addProvider(new AircraftResourceProvider);
165
simgear::ResourceManager::instance()->addProvider(new CurrentAircraftDirProvider);
169
void FGGlobals::initProperties()
171
simgear::PropertyObjectBase::setDefaultRoot(props);
173
positionLon = props->getNode("position/longitude-deg", true);
174
positionLat = props->getNode("position/latitude-deg", true);
175
positionAlt = props->getNode("position/altitude-ft", true);
177
viewLon = props->getNode("sim/current-view/viewer-lon-deg", true);
178
viewLat = props->getNode("sim/current-view/viewer-lat-deg", true);
179
viewAlt = props->getNode("sim/current-view/viewer-elev-ft", true);
181
orientPitch = props->getNode("orientation/pitch-deg", true);
182
orientHeading = props->getNode("orientation/heading-deg", true);
183
orientRoll = props->getNode("orientation/roll-deg", true);
187
196
// deallocation of AIModel objects. To ensure we can safely
188
197
// shut down all subsystems, make sure we take down the
189
198
// AIModels system first.
190
SGSubsystem* ai = subsystem_mgr->remove("ai-model");
199
SGSubsystemRef ai = subsystem_mgr->get_subsystem("ai-model");
201
subsystem_mgr->remove("ai-model");
203
ai.clear(); // ensure AI is deleted now, not at end of this method
195
SGSubsystem* sound = subsystem_mgr->remove("sound");
197
206
subsystem_mgr->shutdown();
198
subsystem_mgr->unbind();
207
subsystem_mgr->unbind();
209
subsystem_mgr->remove("aircraft-model");
210
subsystem_mgr->remove("tile-manager");
211
subsystem_mgr->remove("model-manager");
214
osg::ref_ptr<osgViewer::Viewer> vw(renderer->getViewer());
216
// https://code.google.com/p/flightgear-bugs/issues/detail?id=1291
217
// explicitly stop trheading before we delete the renderer or
218
// viewMgr (which ultimately holds refs to the CameraGroup, and
223
// don't cancel the pager until after shutdown, since AIModels (and
224
// potentially others) can queue delete requests on the pager.
225
if (vw && vw->getDatabasePager()) {
226
vw->getDatabasePager()->cancel();
227
vw->getDatabasePager()->clear();
230
osgDB::Registry::instance()->clearObjectCache();
232
// renderer touches subsystems during its destruction
235
_chatter_queue.clear();
199
237
delete subsystem_mgr;
238
subsystem_mgr = NULL; // important so ::get_subsystem returns NULL
239
vw = 0; // don't delete the viewer until now
204
241
delete time_params;
206
243
delete route_mgr;
210
245
delete channel_options_list;
211
246
delete initial_waypoints;
213
247
delete fontcache;
215
248
delete channellist;
250
simgear::PropertyObjectBase::setDefaultRoot(NULL);
251
simgear::SGModelLib::resetPropertyRoot();
222
263
// set the fg_root path
223
void FGGlobals::set_fg_root (const string &root) {
264
void FGGlobals::set_fg_root (const std::string &root) {
224
265
SGPath tmp(root);
225
266
fg_root = tmp.realpath();
249
290
// set the fg_home path
250
void FGGlobals::set_fg_home (const string &home) {
291
void FGGlobals::set_fg_home (const std::string &home) {
251
292
SGPath tmp(home);
252
293
fg_home = tmp.realpath();
255
void FGGlobals::append_fg_scenery (const string &paths)
296
PathList FGGlobals::get_data_paths() const
298
PathList r(additional_data_paths);
299
r.push_back(SGPath(fg_root));
303
PathList FGGlobals::get_data_paths(const std::string& suffix) const
306
BOOST_FOREACH(SGPath p, get_data_paths()) {
316
void FGGlobals::append_data_path(const SGPath& path)
318
if (!path.exists()) {
319
SG_LOG(SG_GENERAL, SG_WARN, "adding non-existant data path:" << path);
322
additional_data_paths.push_back(path);
325
SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const
327
BOOST_FOREACH(SGPath p, additional_data_paths) {
328
p.append(pathSuffix);
334
SGPath rootPath(fg_root);
335
rootPath.append(pathSuffix);
336
if (rootPath.exists()) {
340
SG_LOG(SG_GENERAL, SG_WARN, "dir not found in any data path:" << pathSuffix);
344
void FGGlobals::append_fg_scenery (const std::string &paths)
257
346
// fg_scenery.clear();
258
347
SGPropertyNode* sim = fgGetNode("/sim", true);
312
401
SGPath dirPath(path);
313
402
if (!dirPath.exists()) {
314
SG_LOG(SG_GENERAL, SG_WARN, "aircraft path not found:" << path);
403
SG_LOG(SG_GENERAL, SG_ALERT, "aircraft path not found:" << path);
407
SGPath acSubdir(dirPath);
408
acSubdir.append("Aircraft");
409
if (acSubdir.exists()) {
410
SG_LOG(SG_GENERAL, SG_WARN, "Specified an aircraft-dir with an 'Aircraft' subdirectory:" << dirPath
411
<< ", will instead use child directory:" << acSubdir);
317
415
std::string abspath = dirPath.realpath();
319
416
unsigned int index = fg_aircraft_dirs.size();
320
417
fg_aircraft_dirs.push_back(abspath);
428
539
return SGVec3d::fromGeod(get_view_position());
542
static void treeDumpRefCounts(int depth, SGPropertyNode* nd)
544
for (int i=0; i<nd->nChildren(); ++i) {
545
SGPropertyNode* cp = nd->getChild(i);
546
if (SGReferenced::count(cp) > 1) {
547
SG_LOG(SG_GENERAL, SG_INFO, "\t" << cp->getPath() << " refcount:" << SGReferenced::count(cp));
550
treeDumpRefCounts(depth + 1, cp);
554
static void treeClearAliases(SGPropertyNode* nd)
560
for (int i=0; i<nd->nChildren(); ++i) {
561
SGPropertyNode* cp = nd->getChild(i);
562
treeClearAliases(cp);
567
FGGlobals::resetPropertyRoot()
573
// we don't strictly need to clear these (they will be reset when we
574
// initProperties again), but trying to reduce false-positives when dumping
583
orientHeading.clear();
586
// clear aliases so ref-counts are accurate when dumped
587
treeClearAliases(props);
589
SG_LOG(SG_GENERAL, SG_INFO, "root props refcount:" << props.getNumRefs());
590
treeDumpRefCounts(0, props);
592
//BaseStackSnapshot::dumpAll(std::cout);
594
props = new SGPropertyNode;
596
locale = new FGLocale(props);
598
// remove /sim/fg-root before writing to prevent hijacking
599
SGPropertyNode *n = props->getNode("/sim", true);
600
n->removeChild("fg-root", 0, false);
601
n = n->getChild("fg-root", 0, true);
602
n->setStringValue(fg_root.c_str());
603
n->setAttribute(SGPropertyNode::WRITE, false);
431
606
// Save the current state as the initial state.
433
608
FGGlobals::saveInitialState ()
631
static std::string autosaveName()
633
std::ostringstream os;
634
string_list versionParts = simgear::strutils::split(VERSION, ".");
635
if (versionParts.size() < 2) {
636
return "autosave.xml";
639
os << "autosave_" << versionParts[0] << "_" << versionParts[1] << ".xml";
457
643
// Restore the saved initial state, if any
483
669
// remember that we have (tried) to load any existing autsave.xml
484
670
haveUserSettings = true;
486
SGPath autosaveFile = simgear::Dir(dataPath).file("autosave.xml");
672
SGPath autosaveFile = simgear::Dir(dataPath).file(autosaveName());
487
673
SGPropertyNode autosave;
488
674
if (autosaveFile.exists()) {
489
675
SG_LOG(SG_INPUT, SG_INFO, "Reading user settings from " << autosaveFile.str());
511
697
haveUserSettings = false;
513
699
SGPath autosaveFile(globals->get_fg_home());
514
autosaveFile.append( "autosave.xml" );
700
autosaveFile.append(autosaveName());
515
701
autosaveFile.create_dir( 0700 );
516
702
SG_LOG(SG_IO, SG_INFO, "Saving user settings to " << autosaveFile.str());
518
704
writeProperties(autosaveFile.str(), globals->get_props(), false, SGPropertyNode::USERARCHIVE);
519
705
} catch (const sg_exception &e) {
520
guiErrorMessage("Error writing autosave.xml: ", e);
706
guiErrorMessage("Error writing autosave:", e);
522
708
SG_LOG(SG_INPUT, SG_DEBUG, "Finished Saving user settings");
549
735
fgSetInt("/sim/time/warp-delta", d);
738
FGScenery* FGGlobals::get_scenery () const
740
return _scenery.get();
743
void FGGlobals::set_scenery ( FGScenery *s )
748
FGTileMgr* FGGlobals::get_tile_mgr () const
750
return _tile_mgr.get();
753
void FGGlobals::set_tile_mgr ( FGTileMgr *t )
758
void FGGlobals::set_matlib( SGMaterialLib *m )
763
FGSampleQueue* FGGlobals::get_chatter_queue() const
765
return _chatter_queue;
768
void FGGlobals::set_chatter_queue(FGSampleQueue* queue)
770
_chatter_queue = queue;
773
void FGGlobals::addListenerToCleanup(SGPropertyChangeListener* l)
775
_listeners_to_cleanup.push_back(l);
778
void FGGlobals::cleanupListeners()
780
SGPropertyChangeListenerVec::iterator i = _listeners_to_cleanup.begin();
781
for (; i != _listeners_to_cleanup.end(); ++i) {
784
_listeners_to_cleanup.clear();
552
787
// end of globals.cxx