]> git.mxchange.org Git - flightgear.git/blob - src/Main/globals.cxx
Merge branch 'next' of git://gitorious.org/fg/flightgear into next
[flightgear.git] / src / Main / globals.cxx
1 // globals.cxx -- Global state that needs to be shared among the sim modules
2 //
3 // Written by Curtis Olson, started July 2000.
4 //
5 // Copyright (C) 2000  Curtis L. Olson - http://www.flightgear.org/~curt
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public License as
9 // published by the Free Software Foundation; either version 2 of the
10 // License, or (at your option) any later version.
11 //
12 // This program is distributed in the hope that it will be useful, but
13 // WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15 // General Public License for more details.
16 //
17 // You should have received a copy of the GNU General Public License
18 // along with this program; if not, write to the Free Software Foundation,
19 // Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20 //
21 // $Id$
22
23 #ifdef HAVE_CONFIG_H
24 #  include <config.h>
25 #endif
26
27 #include <simgear/structure/commands.hxx>
28 #include <simgear/misc/sg_path.hxx>
29 #include <simgear/misc/sg_dir.hxx>
30 #include <simgear/timing/sg_time.hxx>
31 #include <simgear/ephemeris/ephemeris.hxx>
32 #include <simgear/magvar/magvar.hxx>
33 #include <simgear/scene/material/matlib.hxx>
34 #include <simgear/structure/subsystem_mgr.hxx>
35 #include <simgear/structure/event_mgr.hxx>
36 #include <simgear/sound/soundmgr_openal.hxx>
37 #include <simgear/misc/ResourceManager.hxx>
38
39 #include <Aircraft/controls.hxx>
40 #include <Airports/runways.hxx>
41 #include <ATCDCL/ATCmgr.hxx>
42 #include <Autopilot/route_mgr.hxx>
43 #include <Cockpit/panel.hxx>
44 #include <GUI/new_gui.hxx>
45 #include <Model/acmodel.hxx>
46 #include <Model/modelmgr.hxx>
47 #include <MultiPlayer/multiplaymgr.hxx>
48 #include <Navaids/awynet.hxx>
49 #include <Scenery/scenery.hxx>
50 #include <Scenery/tilemgr.hxx>
51 #include <Navaids/navlist.hxx>
52
53 #include "globals.hxx"
54 #include "renderer.hxx"
55 #include "viewmgr.hxx"
56
57 #include "fg_props.hxx"
58 #include "fg_io.hxx"
59
60 \fclass AircraftResourceProvider : public simgear::ResourceProvider
61 {
62 public:
63   AircraftResourceProvider() :
64     simgear::ResourceProvider(simgear::ResourceManager::PRIORITY_HIGH)
65   {
66   }
67   
68   virtual SGPath resolve(const std::string& aResource, SGPath&) const
69   {
70     string_list pieces(sgPathBranchSplit(aResource));
71     if ((pieces.size() < 3) || (pieces.front() != "Aircraft")) {
72       return SGPath(); // not an Aircraft path
73     }
74     
75   // test against the aircraft-dir property
76     const char* aircraftDir = fgGetString("/sim/aircraft-dir");
77     string_list aircraftDirPieces(sgPathBranchSplit(aircraftDir));
78     if (aircraftDirPieces.empty() || (aircraftDirPieces.back() != pieces[1])) {
79       return SGPath(); // current aircraft-dir does not match resource aircraft
80     }
81     
82     SGPath r(aircraftDir);
83     for (unsigned int i=2; i<pieces.size(); ++i) {
84       r.append(pieces[i]);
85     }
86     
87     if (r.exists()) {
88       SG_LOG(SG_IO, SG_INFO, "found path:" << aResource << " via /sim/aircraft-dir: " << r.str());
89       return r;
90     }
91   
92   // try each aircaft dir in turn
93     std::string res(aResource, 9); // resource path with 'Aircraft/' removed
94     const string_list& dirs(globals->get_aircraft_paths());
95     string_list::const_iterator it = dirs.begin();
96     for (; it != dirs.end(); ++it) {
97       SGPath p(*it, res);
98       if (p.exists()) {
99         SG_LOG(SG_IO, SG_INFO, "found path:" << aResource << " in aircraft dir: " << r.str());
100         return p;
101       }
102     } // of aircraft path iteration
103     
104     return SGPath(); // not found
105   }
106 };
107
108 ////////////////////////////////////////////////////////////////////////
109 // Implementation of FGGlobals.
110 ////////////////////////////////////////////////////////////////////////
111
112 // global global :-)
113 FGGlobals *globals;
114
115
116 // Constructor
117 FGGlobals::FGGlobals() :
118     props( new SGPropertyNode ),
119     initial_state( NULL ),
120     locale( NULL ),
121     renderer( new FGRenderer ),
122     subsystem_mgr( new SGSubsystemMgr ),
123     event_mgr( new SGEventMgr ),
124     soundmgr( new SGSoundMgr ),
125     sim_time_sec( 0.0 ),
126     fg_root( "" ),
127     warp( 0 ),
128     warp_delta( 0 ),
129     time_params( NULL ),
130     ephem( NULL ),
131     mag( NULL ),
132     matlib( NULL ),
133     route_mgr( NULL ),
134     current_panel( NULL ),
135     ATC_mgr( NULL ),
136     controls( NULL ),
137     viewmgr( NULL ),
138     commands( SGCommandMgr::instance() ),
139     acmodel( NULL ),
140     model_mgr( NULL ),
141     channel_options_list( NULL ),
142     initial_waypoints( NULL ),
143     scenery( NULL ),
144     tile_mgr( NULL ),
145     fontcache ( new FGFontCache ),
146     navlist( NULL ),
147     loclist( NULL ),
148     gslist( NULL ),
149     dmelist( NULL ),
150     tacanlist( NULL ),
151     carrierlist( NULL ),
152     channellist( NULL ),
153     airwaynet( NULL )
154     
155 {
156   simgear::ResourceManager::instance()->addProvider(new AircraftResourceProvider());
157 }
158
159
160 // Destructor
161 FGGlobals::~FGGlobals() 
162 {
163     delete renderer;
164     renderer = NULL;
165     
166 // The AIModels manager performs a number of actions upon
167     // Shutdown that implicitly assume that other subsystems
168     // are still operational (Due to the dynamic allocation and
169     // deallocation of AIModel objects. To ensure we can safely
170     // shut down all subsystems, make sure we take down the 
171     // AIModels system first.
172     subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("ai_model");
173
174     subsystem_mgr->unbind();
175     delete subsystem_mgr;
176     delete event_mgr;
177     
178     delete time_params;
179     delete mag;
180     delete matlib;
181     delete route_mgr;
182     delete current_panel;
183
184     delete ATC_mgr;
185     delete controls;
186     delete viewmgr;
187
188 //     delete commands;
189     delete model_mgr;
190     delete channel_options_list;
191     delete initial_waypoints;
192     delete scenery;
193     delete fontcache;
194
195     delete navlist;
196     delete loclist;
197     delete gslist;
198     delete dmelist;
199     delete tacanlist;
200     delete carrierlist;
201     delete channellist;
202     delete airwaynet;
203
204     soundmgr->unbind();
205     delete soundmgr;
206 }
207
208
209 // set the fg_root path
210 void FGGlobals::set_fg_root (const string &root) {
211     fg_root = root;
212
213     // append /data to root if it exists
214     SGPath tmp( fg_root );
215     tmp.append( "data" );
216     tmp.append( "version" );
217     if ( ulFileExists( tmp.c_str() ) ) {
218         fgGetNode("BAD_FG_ROOT", true)->setStringValue(fg_root);
219         fg_root += "/data";
220         fgGetNode("GOOD_FG_ROOT", true)->setStringValue(fg_root);
221         SG_LOG(SG_GENERAL, SG_ALERT, "***\n***\n*** Warning: changing bad FG_ROOT/--fg-root to '"
222                 << fg_root << "'\n***\n***");
223     }
224
225     // remove /sim/fg-root before writing to prevent hijacking
226     SGPropertyNode *n = fgGetNode("/sim", true);
227     n->removeChild("fg-root", 0, false);
228     n = n->getChild("fg-root", 0, true);
229     n->setStringValue(fg_root.c_str());
230     n->setAttribute(SGPropertyNode::WRITE, false);
231     
232     simgear::ResourceManager::instance()->addBasePath(fg_root, 
233       simgear::ResourceManager::PRIORITY_DEFAULT);
234 }
235
236 void FGGlobals::set_fg_scenery (const string &scenery)
237 {
238     SGPath s;
239     if (scenery.empty()) {
240         s.set( fg_root );
241         s.append( "Scenery" );
242     } else
243         s.set( scenery );
244
245     string_list path_list = sgPathSplit( s.str() );
246     fg_scenery.clear();
247
248     for (unsigned i = 0; i < path_list.size(); i++) {
249         SGPath path(path_list[i]);
250         if (!path.exists()) {
251           SG_LOG(SG_GENERAL, SG_WARN, "scenery path not found:" << path.str());
252           continue;
253         }
254
255         simgear::Dir dir(path);
256         SGPath terrainDir(dir.file("Terrain"));
257         SGPath objectsDir(dir.file("Objects"));
258         
259       // this code used to add *either* the base dir, OR add the 
260       // Terrain and Objects subdirs, but the conditional logic was commented
261       // out, such that all three dirs are added. Unfortunately there's
262       // no information as to why the change was made.
263         fg_scenery.push_back(path.str());
264         
265         if (terrainDir.exists()) {
266           fg_scenery.push_back(terrainDir.str());
267         }
268         
269         if (objectsDir.exists()) {
270           fg_scenery.push_back(objectsDir.str());
271         }
272         
273         // insert a marker for FGTileEntry::load(), so that
274         // FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
275         // "B/Terrain", "B/Objects", ""]
276         fg_scenery.push_back("");
277     } // of path list iteration
278 }
279
280 void FGGlobals::append_aircraft_path(const std::string& path)
281 {
282   SGPath dirPath(path);
283   if (!dirPath.exists()) {
284     SG_LOG(SG_GENERAL, SG_WARN, "aircraft path not found:" << path);
285     return;
286   }
287   
288   unsigned int index = fg_aircraft_dirs.size();  
289   fg_aircraft_dirs.push_back(path);
290   
291 // make aircraft dirs available to Nasal
292   SGPropertyNode* sim = fgGetNode("/sim", true);
293   sim->removeChild("fg-aircraft", index, false);
294   SGPropertyNode* n = sim->getChild("fg-aircraft", index, true);
295   n->setStringValue(path);
296   n->setAttribute(SGPropertyNode::WRITE, false);
297 }
298
299 void FGGlobals::append_aircraft_paths(const std::string& path)
300 {
301   string_list paths = sgPathSplit(path);
302   for (unsigned int p = 0; p<paths.size(); ++p) {
303     append_aircraft_path(paths[p]);
304   }
305 }
306
307 SGPath FGGlobals::resolve_aircraft_path(const std::string& branch) const
308 {
309   return simgear::ResourceManager::instance()->findPath(branch);
310 }
311
312 SGPath FGGlobals::resolve_maybe_aircraft_path(const std::string& branch) const
313 {
314   return simgear::ResourceManager::instance()->findPath(branch);
315 }
316
317 FGRenderer *
318 FGGlobals::get_renderer () const
319 {
320    return renderer;
321 }
322
323 SGSubsystemMgr *
324 FGGlobals::get_subsystem_mgr () const
325 {
326     return subsystem_mgr;
327 }
328
329 SGSubsystem *
330 FGGlobals::get_subsystem (const char * name)
331 {
332     return subsystem_mgr->get_subsystem(name);
333 }
334
335 void
336 FGGlobals::add_subsystem (const char * name,
337                           SGSubsystem * subsystem,
338                           SGSubsystemMgr::GroupType type,
339                           double min_time_sec)
340 {
341     subsystem_mgr->add(name, subsystem, type, min_time_sec);
342 }
343
344 SGSoundMgr *
345 FGGlobals::get_soundmgr () const
346 {
347     return soundmgr;
348 }
349
350 SGEventMgr *
351 FGGlobals::get_event_mgr () const
352 {
353     return event_mgr;
354 }
355
356
357 // Save the current state as the initial state.
358 void
359 FGGlobals::saveInitialState ()
360 {
361   initial_state = new SGPropertyNode();
362
363   if (!copyProperties(props, initial_state))
364     SG_LOG(SG_GENERAL, SG_ALERT, "Error saving initial state");
365     
366   // delete various properties from the initial state, since we want to
367   // preserve their values even if doing a restore
368   
369   SGPropertyNode* sim = initial_state->getChild("sim");
370   sim->removeChild("presets");
371   SGPropertyNode* simStartup = sim->getChild("startup");
372   simStartup->removeChild("xsize");
373   simStartup->removeChild("ysize");
374   
375   SGPropertyNode* cameraGroupNode = sim->getNode("rendering/camera-group");
376   if (cameraGroupNode) {
377     cameraGroupNode->removeChild("camera");
378     cameraGroupNode->removeChild("gui");
379   }
380 }
381
382
383 // Restore the saved initial state, if any
384 void
385 FGGlobals::restoreInitialState ()
386 {
387     if ( initial_state == 0 ) {
388         SG_LOG(SG_GENERAL, SG_ALERT,
389                "No initial state available to restore!!!");
390         return;
391     }
392
393     if ( copyProperties(initial_state, props) ) {
394         SG_LOG( SG_GENERAL, SG_INFO, "Initial state restored successfully" );
395     } else {
396         SG_LOG( SG_GENERAL, SG_INFO,
397                 "Some errors restoring initial state (read-only props?)" );
398     }
399
400 }
401
402 FGViewer *
403 FGGlobals::get_current_view () const
404 {
405   return viewmgr->get_current_view();
406 }
407
408 // end of globals.cxx