X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FMain%2Fglobals.cxx;h=d41e00d5f2bff7e3bec088e73ca2cb2df72124d8;hb=16784d590a315e876a7b18076569620640ffbdf6;hp=a6381569ba53a8dac4351deef707c01767b2bd6c;hpb=52e5a9abe83882ca946429f7d8e71894d5852d8f;p=flightgear.git diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index a6381569b..d41e00d5f 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -27,6 +27,9 @@ #include #include +#include +#include + #include #include #include @@ -39,10 +42,11 @@ #include #include #include +#include +#include #include #include -#include #include #include #include @@ -52,6 +56,7 @@ #include #include #include +#include #include "globals.hxx" #include "locale.hxx" @@ -126,14 +131,11 @@ public: //////////////////////////////////////////////////////////////////////// // global global :-) -FGGlobals *globals; +FGGlobals *globals = NULL; // Constructor FGGlobals::FGGlobals() : - props( new SGPropertyNode ), - initial_state( NULL ), - locale( new FGLocale(props) ), renderer( new FGRenderer ), subsystem_mgr( new SGSubsystemMgr ), event_mgr( new SGEventMgr ), @@ -142,35 +144,42 @@ FGGlobals::FGGlobals() : fg_home( "" ), time_params( NULL ), ephem( NULL ), - matlib( NULL ), route_mgr( NULL ), - ATIS_mgr( NULL ), controls( NULL ), viewmgr( NULL ), commands( SGCommandMgr::instance() ), channel_options_list( NULL ), initial_waypoints( NULL ), - scenery( NULL ), - tile_mgr( NULL ), fontcache ( new FGFontCache ), channellist( NULL ), - haveUserSettings(false) + haveUserSettings(false), + _chatter_queue(NULL) { - simgear::ResourceManager::instance()->addProvider(new AircraftResourceProvider); - simgear::ResourceManager::instance()->addProvider(new CurrentAircraftDirProvider); - simgear::PropertyObjectBase::setDefaultRoot(props); - - positionLon = props->getNode("position/longitude-deg", true); - positionLat = props->getNode("position/latitude-deg", true); - positionAlt = props->getNode("position/altitude-ft", true); - - 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); - - orientPitch = props->getNode("orientation/pitch-deg", true); - orientHeading = props->getNode("orientation/heading-deg", true); - orientRoll = props->getNode("orientation/roll-deg", true); + SGPropertyNode* root = new SGPropertyNode; + props = SGPropertyNode_ptr(root); + locale = new FGLocale(props); + + simgear::ResourceManager::instance()->addProvider(new AircraftResourceProvider); + simgear::ResourceManager::instance()->addProvider(new CurrentAircraftDirProvider); + initProperties(); +} + +void FGGlobals::initProperties() +{ + simgear::PropertyObjectBase::setDefaultRoot(props); + + positionLon = props->getNode("position/longitude-deg", true); + positionLat = props->getNode("position/latitude-deg", true); + positionAlt = props->getNode("position/altitude-ft", true); + + 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); + + orientPitch = props->getNode("orientation/pitch-deg", true); + orientHeading = props->getNode("orientation/heading-deg", true); + orientRoll = props->getNode("orientation/roll-deg", true); + } // Destructor @@ -185,36 +194,67 @@ FGGlobals::~FGGlobals() // deallocation of AIModel objects. To ensure we can safely // shut down all subsystems, make sure we take down the // AIModels system first. - SGSubsystem* ai = subsystem_mgr->remove("ai-model"); + SGSubsystemRef ai = subsystem_mgr->get_subsystem("ai-model"); if (ai) { + subsystem_mgr->remove("ai-model"); ai->unbind(); - delete ai; + ai.clear(); // ensure AI is deleted now, not at end of this method } - SGSubsystem* sound = subsystem_mgr->remove("sound"); - + subsystem_mgr->shutdown(); - subsystem_mgr->unbind(); - delete subsystem_mgr; + subsystem_mgr->unbind(); + + subsystem_mgr->remove("aircraft-model"); + subsystem_mgr->remove("tile-manager"); + 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(); + } - delete renderer; - renderer = NULL; + // 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 + vw = 0; // don't delete the viewer until now + delete time_params; - delete matlib; + set_matlib(NULL); delete route_mgr; - - delete ATIS_mgr; - delete channel_options_list; delete initial_waypoints; - delete scenery; delete fontcache; - delete channellist; - delete sound; + simgear::PropertyObjectBase::setDefaultRoot(NULL); + simgear::SGModelLib::resetPropertyRoot(); + delete locale; locale = NULL; + + cleanupListeners(); + + props.clear(); + + delete commands; } // set the fg_root path @@ -233,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); @@ -300,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 @@ -350,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) @@ -403,6 +471,16 @@ FGGlobals::get_renderer () const return renderer; } +void FGGlobals::set_renderer(FGRenderer *render) +{ + if (render == renderer) { + return; + } + + delete renderer; + renderer = render; +} + SGSubsystemMgr * FGGlobals::get_subsystem_mgr () const { @@ -412,6 +490,10 @@ FGGlobals::get_subsystem_mgr () const SGSubsystem * FGGlobals::get_subsystem (const char * name) { + if (!subsystem_mgr) { + return NULL; + } + return subsystem_mgr->get_subsystem(name); } @@ -474,29 +556,68 @@ FGGlobals::get_view_position_cart() const return SGVec3d::fromGeod(get_view_position()); } -// Save the current state as the initial state. +static void treeDumpRefCounts(int depth, SGPropertyNode* nd) +{ + for (int i=0; inChildren(); ++i) { + SGPropertyNode* cp = nd->getChild(i); + if (SGReferenced::count(cp) > 1) { + SG_LOG(SG_GENERAL, SG_INFO, "\t" << cp->getPath() << " refcount:" << SGReferenced::count(cp)); + } + + treeDumpRefCounts(depth + 1, cp); + } +} + +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::saveInitialState () +FGGlobals::resetPropertyRoot() { - initial_state = new SGPropertyNode(); + 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); - // 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"); + //BaseStackSnapshot::dumpAll(std::cout); - // 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"); - } + 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); + n = n->getChild("fg-root", 0, true); + n->setStringValue(fg_root.c_str()); + n->setAttribute(SGPropertyNode::WRITE, false); } static std::string autosaveName() @@ -511,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) @@ -606,4 +705,63 @@ void FGGlobals::set_warp_delta( long int d ) fgSetInt("/sim/time/warp-delta", d); } +FGScenery* FGGlobals::get_scenery () const +{ + return _scenery.get(); +} + +void FGGlobals::set_scenery ( FGScenery *s ) +{ + _scenery = s; +} + +FGTileMgr* FGGlobals::get_tile_mgr () const +{ + return _tile_mgr.get(); +} + +void FGGlobals::set_tile_mgr ( FGTileMgr *t ) +{ + _tile_mgr = t; +} + +void FGGlobals::set_matlib( SGMaterialLib *m ) +{ + 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