X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Fglobals.cxx;h=d41e00d5f2bff7e3bec088e73ca2cb2df72124d8;hb=16784d590a315e876a7b18076569620640ffbdf6;hp=2fda3045bada940993b8c0d3146202eb393aaf49;hpb=af6095c5d13c3379f96b563e857eb2897aea1f8c;p=flightgear.git diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index 2fda3045b..d41e00d5f 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include #include @@ -40,10 +43,10 @@ #include #include #include +#include #include #include -#include #include #include #include @@ -53,6 +56,7 @@ #include #include #include +#include #include "globals.hxx" #include "locale.hxx" @@ -132,7 +136,6 @@ FGGlobals *globals = NULL; // Constructor FGGlobals::FGGlobals() : - initial_state( NULL ), renderer( new FGRenderer ), subsystem_mgr( new SGSubsystemMgr ), event_mgr( new SGEventMgr ), @@ -141,9 +144,7 @@ FGGlobals::FGGlobals() : fg_home( "" ), time_params( NULL ), ephem( NULL ), - matlib( NULL ), route_mgr( NULL ), - ATIS_mgr( NULL ), controls( NULL ), viewmgr( NULL ), commands( SGCommandMgr::instance() ), @@ -151,7 +152,8 @@ FGGlobals::FGGlobals() : initial_waypoints( NULL ), fontcache ( new FGFontCache ), channellist( NULL ), - haveUserSettings(false) + haveUserSettings(false), + _chatter_queue(NULL) { SGPropertyNode* root = new SGPropertyNode; props = SGPropertyNode_ptr(root); @@ -207,17 +209,36 @@ FGGlobals::~FGGlobals() subsystem_mgr->remove("model-manager"); _tile_mgr.clear(); + osg::ref_ptr 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(); + } + + // don't cancel the pager until after shutdown, since AIModels (and + // potentially others) can queue delete requests on the pager. + if (vw && vw->getDatabasePager()) { + vw->getDatabasePager()->cancel(); + vw->getDatabasePager()->clear(); + } + + osgDB::Registry::instance()->clearObjectCache(); + // renderer touches subsystems during its destruction set_renderer(NULL); _scenery.clear(); - + _chatter_queue.clear(); + delete subsystem_mgr; - subsystem_mgr = NULL; // important so ::get_subsystem returns NULL + subsystem_mgr = NULL; // important so ::get_subsystem returns NULL + vw = 0; // don't delete the viewer until now delete time_params; set_matlib(NULL); delete route_mgr; - delete ATIS_mgr; delete channel_options_list; delete initial_waypoints; delete fontcache; @@ -229,7 +250,11 @@ FGGlobals::~FGGlobals() delete locale; locale = NULL; + cleanupListeners(); + props.clear(); + + delete commands; } // set the fg_root path @@ -248,9 +273,10 @@ void FGGlobals::set_fg_root (const std::string &root) { << fg_root << "'\n***\n***"); } - // remove /sim/fg-root before writing to prevent hijacking + // deliberately not a tied property, for fgValidatePath security + // write-protect to avoid accidents SGPropertyNode *n = fgGetNode("/sim", true); - n->removeChild("fg-root", 0, false); + n->removeChild("fg-root", 0); n = n->getChild("fg-root", 0, true); n->setStringValue(fg_root.c_str()); n->setAttribute(SGPropertyNode::WRITE, false); @@ -315,7 +341,6 @@ SGPath FGGlobals::find_data_dir(const std::string& pathSuffix) const void FGGlobals::append_fg_scenery (const std::string &paths) { -// fg_scenery.clear(); SGPropertyNode* sim = fgGetNode("/sim", true); // find first unused fg-scenery property in /sim @@ -365,27 +390,55 @@ void FGGlobals::append_fg_scenery (const std::string &paths) SGPropertyNode* n = sim->getChild("fg-scenery", propIndex++, true); n->setStringValue(abspath.str()); n->setAttribute(SGPropertyNode::WRITE, false); + + // temporary fix so these values survive reset + n->setAttribute(SGPropertyNode::PRESERVE, true); } // of path list iteration } +void FGGlobals::clear_fg_scenery() +{ + fg_scenery.clear(); +} + +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; +} + void FGGlobals::append_aircraft_path(const std::string& path) { SGPath dirPath(path); if (!dirPath.exists()) { - SG_LOG(SG_GENERAL, SG_WARN, "aircraft path not found:" << path); + SG_LOG(SG_GENERAL, SG_ALERT, "aircraft path not found:" << path); return; } + + SGPath acSubdir(dirPath); + acSubdir.append("Aircraft"); + if (acSubdir.exists()) { + SG_LOG( + SG_GENERAL, + SG_WARN, + "Specified an aircraft-dir with an 'Aircraft' subdirectory:" << dirPath + << ", will instead use child directory:" << acSubdir + ); + dirPath = acSubdir; + } + std::string abspath = dirPath.realpath(); - - unsigned int index = fg_aircraft_dirs.size(); fg_aircraft_dirs.push_back(abspath); - -// make aircraft dirs available to Nasal - SGPropertyNode* sim = fgGetNode("/sim", true); - sim->removeChild("fg-aircraft", index, false); - SGPropertyNode* n = sim->getChild("fg-aircraft", index, true); - n->setStringValue(abspath); - n->setAttribute(SGPropertyNode::WRITE, false); } void FGGlobals::append_aircraft_paths(const std::string& path) @@ -515,51 +568,58 @@ static void treeDumpRefCounts(int depth, SGPropertyNode* nd) } } +static void treeClearAliases(SGPropertyNode* nd) +{ + if (nd->isAlias()) { + nd->unalias(); + } + + for (int i=0; inChildren(); ++i) { + SGPropertyNode* cp = nd->getChild(i); + treeClearAliases(cp); + } +} + void FGGlobals::resetPropertyRoot() { delete locale; + cleanupListeners(); + + // 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(); + + // clear aliases so ref-counts are accurate when dumped + treeClearAliases(props); + SG_LOG(SG_GENERAL, SG_INFO, "root props refcount:" << props.getNumRefs()); treeDumpRefCounts(0, props); + //BaseStackSnapshot::dumpAll(std::cout); + props = new SGPropertyNode; initProperties(); locale = new FGLocale(props); // remove /sim/fg-root before writing to prevent hijacking SGPropertyNode *n = props->getNode("/sim", true); - n->removeChild("fg-root", 0, false); + n->removeChild("fg-root", 0); n = n->getChild("fg-root", 0, true); n->setStringValue(fg_root.c_str()); n->setAttribute(SGPropertyNode::WRITE, false); } -// Save the current state as the initial state. -void -FGGlobals::saveInitialState () -{ - initial_state = new SGPropertyNode(); - - // copy properties which are READ/WRITEable - but not USERARCHIVEd or PRESERVEd - int checked = SGPropertyNode::READ+SGPropertyNode::WRITE+ - SGPropertyNode::USERARCHIVE+SGPropertyNode::PRESERVE; - int expected = SGPropertyNode::READ+SGPropertyNode::WRITE; - if (!copyProperties(props, initial_state, expected, checked)) - SG_LOG(SG_GENERAL, SG_ALERT, "Error saving initial state"); - - // delete various properties from the initial state, since we want to - // preserve their values even if doing a restore - // => Properties should now use the PRESERVE flag to protect their values - // on sim-reset. Remove some specific properties for backward compatibility. - SGPropertyNode* sim = initial_state->getChild("sim"); - SGPropertyNode* cameraGroupNode = sim->getNode("rendering/camera-group"); - if (cameraGroupNode) { - cameraGroupNode->removeChild("camera"); - cameraGroupNode->removeChild("gui"); - } -} - static std::string autosaveName() { std::ostringstream os; @@ -572,28 +632,6 @@ static std::string autosaveName() return os.str(); } -// Restore the saved initial state, if any -void -FGGlobals::restoreInitialState () -{ - if ( initial_state == 0 ) { - SG_LOG(SG_GENERAL, SG_ALERT, - "No initial state available to restore!!!"); - return; - } - // copy properties which are READ/WRITEable - but not USERARCHIVEd or PRESERVEd - int checked = SGPropertyNode::READ+SGPropertyNode::WRITE+ - SGPropertyNode::USERARCHIVE+SGPropertyNode::PRESERVE; - int expected = SGPropertyNode::READ+SGPropertyNode::WRITE; - if ( copyProperties(initial_state, props, expected, checked)) { - SG_LOG( SG_GENERAL, SG_INFO, "Initial state restored successfully" ); - } else { - SG_LOG( SG_GENERAL, SG_INFO, - "Some errors restoring initial state (read-only props?)" ); - } - -} - // Load user settings from autosave.xml void FGGlobals::loadUserSettings(const SGPath& dataPath) @@ -689,9 +727,41 @@ void FGGlobals::set_tile_mgr ( FGTileMgr *t ) void FGGlobals::set_matlib( SGMaterialLib *m ) { - if (matlib) - delete matlib; matlib = m; } +FGSampleQueue* FGGlobals::get_chatter_queue() const +{ + return _chatter_queue; +} + +void FGGlobals::set_chatter_queue(FGSampleQueue* queue) +{ + _chatter_queue = queue; +} + +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(); +} + +simgear::pkg::Root* FGGlobals::packageRoot() +{ + return _packageRoot.get(); +} + +void FGGlobals::setPackageRoot(const SGSharedPtr& p) +{ + _packageRoot = p; +} + // end of globals.cxx