]> git.mxchange.org Git - flightgear.git/blob - src/Main/globals.cxx
ad38089194f6af50d08de6be8c83532d445c3048
[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
38 #include <Aircraft/controls.hxx>
39 #include <Airports/runways.hxx>
40 #include <ATCDCL/AIMgr.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 \f
61 ////////////////////////////////////////////////////////////////////////
62 // Implementation of FGGlobals.
63 ////////////////////////////////////////////////////////////////////////
64
65 // global global :-)
66 FGGlobals *globals;
67
68
69 // Constructor
70 FGGlobals::FGGlobals() :
71     props( new SGPropertyNode ),
72     initial_state( NULL ),
73     locale( NULL ),
74     renderer( new FGRenderer ),
75     subsystem_mgr( new SGSubsystemMgr ),
76     event_mgr( new SGEventMgr ),
77     soundmgr( new SGSoundMgr ),
78     sim_time_sec( 0.0 ),
79     fg_root( "" ),
80     warp( 0 ),
81     warp_delta( 0 ),
82     time_params( NULL ),
83     ephem( NULL ),
84     mag( NULL ),
85     matlib( NULL ),
86     route_mgr( NULL ),
87     current_panel( NULL ),
88     ATC_mgr( NULL ),
89     AI_mgr( NULL ),
90     controls( NULL ),
91     viewmgr( NULL ),
92     commands( SGCommandMgr::instance() ),
93     acmodel( NULL ),
94     model_mgr( NULL ),
95     channel_options_list( NULL ),
96     initial_waypoints( NULL ),
97     scenery( NULL ),
98     tile_mgr( NULL ),
99     fontcache ( new FGFontCache ),
100     navlist( NULL ),
101     loclist( NULL ),
102     gslist( NULL ),
103     dmelist( NULL ),
104     tacanlist( NULL ),
105     carrierlist( NULL ),
106     channellist( NULL ),
107     airwaynet( NULL ),
108     multiplayer_mgr( NULL )
109 {
110 }
111
112
113 // Destructor
114 FGGlobals::~FGGlobals() 
115 {
116     delete renderer;
117 // The AIModels manager performs a number of actions upon
118     // Shutdown that implicitly assume that other subsystems
119     // are still operational (Due to the dynamic allocation and
120     // deallocation of AIModel objects. To ensure we can safely
121     // shut down all subsystems, make sure we take down the 
122     // AIModels system first.
123     subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("ai_model");
124     // FGInput (FGInputEvent) and FGDialog calls get_subsystem() in their destructors, 
125     // which is not safe since some subsystem are already deleted but can be referred.
126     // So these subsystems must be deleted prior to deleting subsystem_mgr unless
127     // ~SGSubsystemGroup and SGSubsystemMgr::get_subsystem are changed not to refer to
128     // deleted subsystems.
129     subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("input");
130     subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("gui");
131     subsystem_mgr->unbind();
132     delete subsystem_mgr;
133     delete event_mgr;
134     delete time_params;
135     delete mag;
136     delete matlib;
137     delete route_mgr;
138     delete current_panel;
139
140     delete ATC_mgr;
141     delete AI_mgr;
142     delete controls;
143     delete viewmgr;
144
145 //     delete commands;
146     delete acmodel;
147     delete model_mgr;
148     delete channel_options_list;
149     delete initial_waypoints;
150     delete tile_mgr;
151     delete scenery;
152     delete fontcache;
153
154     delete navlist;
155     delete loclist;
156     delete gslist;
157     delete dmelist;
158     delete tacanlist;
159     delete carrierlist;
160     delete channellist;
161     delete airwaynet;
162     delete multiplayer_mgr;
163
164     soundmgr->unbind();
165     delete soundmgr;
166 }
167
168
169 // set the fg_root path
170 void FGGlobals::set_fg_root (const string &root) {
171     fg_root = root;
172
173     // append /data to root if it exists
174     SGPath tmp( fg_root );
175     tmp.append( "data" );
176     tmp.append( "version" );
177     if ( ulFileExists( tmp.c_str() ) ) {
178         fgGetNode("BAD_FG_ROOT", true)->setStringValue(fg_root);
179         fg_root += "/data";
180         fgGetNode("GOOD_FG_ROOT", true)->setStringValue(fg_root);
181         SG_LOG(SG_GENERAL, SG_ALERT, "***\n***\n*** Warning: changing bad FG_ROOT/--fg-root to '"
182                 << fg_root << "'\n***\n***");
183     }
184
185     // remove /sim/fg-root before writing to prevent hijacking
186     SGPropertyNode *n = fgGetNode("/sim", true);
187     n->removeChild("fg-root", 0, false);
188     n = n->getChild("fg-root", 0, true);
189     n->setStringValue(fg_root.c_str());
190     n->setAttribute(SGPropertyNode::WRITE, false);
191 }
192
193 void FGGlobals::set_fg_scenery (const string &scenery)
194 {
195     SGPath s;
196     if (scenery.empty()) {
197         s.set( fg_root );
198         s.append( "Scenery" );
199     } else
200         s.set( scenery );
201
202     string_list path_list = sgPathSplit( s.str() );
203     fg_scenery.clear();
204
205     for (unsigned i = 0; i < path_list.size(); i++) {
206         SGPath path(path_list[i]);
207         if (!path.exists()) {
208           SG_LOG(SG_GENERAL, SG_WARN, "scenery path not found:" << path.str());
209           continue;
210         }
211
212         simgear::Dir dir(path);
213         SGPath terrainDir(dir.file("Terrain"));
214         SGPath objectsDir(dir.file("Objects"));
215         
216       // this code used to add *either* the base dir, OR add the 
217       // Terrain and Objects subdirs, but the conditional logic was commented
218       // out, such that all three dirs are added. Unfortunately there's
219       // no information as to why the change was made.
220         fg_scenery.push_back(path.str());
221         
222         if (terrainDir.exists()) {
223           fg_scenery.push_back(terrainDir.str());
224         }
225         
226         if (objectsDir.exists()) {
227           fg_scenery.push_back(objectsDir.str());
228         }
229         
230         // insert a marker for FGTileEntry::load(), so that
231         // FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
232         // "B/Terrain", "B/Objects", ""]
233         fg_scenery.push_back("");
234     } // of path list iteration
235 }
236
237
238 FGRenderer *
239 FGGlobals::get_renderer () const
240 {
241    return renderer;
242 }
243
244 SGSubsystemMgr *
245 FGGlobals::get_subsystem_mgr () const
246 {
247     return subsystem_mgr;
248 }
249
250 SGSubsystem *
251 FGGlobals::get_subsystem (const char * name)
252 {
253     return subsystem_mgr->get_subsystem(name);
254 }
255
256 void
257 FGGlobals::add_subsystem (const char * name,
258                           SGSubsystem * subsystem,
259                           SGSubsystemMgr::GroupType type,
260                           double min_time_sec)
261 {
262     subsystem_mgr->add(name, subsystem, type, min_time_sec);
263 }
264
265 SGSoundMgr *
266 FGGlobals::get_soundmgr () const
267 {
268     return soundmgr;
269 }
270
271 SGEventMgr *
272 FGGlobals::get_event_mgr () const
273 {
274     return event_mgr;
275 }
276
277
278 // Save the current state as the initial state.
279 void
280 FGGlobals::saveInitialState ()
281 {
282   initial_state = new SGPropertyNode();
283
284   if (!copyProperties(props, initial_state))
285     SG_LOG(SG_GENERAL, SG_ALERT, "Error saving initial state");
286 }
287
288
289 // Restore the saved initial state, if any
290 void
291 FGGlobals::restoreInitialState ()
292 {
293     if ( initial_state == 0 ) {
294         SG_LOG(SG_GENERAL, SG_ALERT,
295                "No initial state available to restore!!!");
296         return;
297     }
298
299     SGPropertyNode *currentPresets = new SGPropertyNode;
300     SGPropertyNode *targetNode = fgGetNode( "/sim/presets" );
301
302     // stash the /sim/presets tree
303     if ( !copyProperties(targetNode, currentPresets) ) {
304         SG_LOG( SG_GENERAL, SG_ALERT, "Failed to save /sim/presets subtree" );
305     }
306     
307     if ( copyProperties(initial_state, props) ) {
308         SG_LOG( SG_GENERAL, SG_INFO, "Initial state restored successfully" );
309     } else {
310         SG_LOG( SG_GENERAL, SG_INFO,
311                 "Some errors restoring initial state (read-only props?)" );
312     }
313
314     // recover the /sim/presets tree
315     if ( !copyProperties(currentPresets, targetNode) ) {
316         SG_LOG( SG_GENERAL, SG_ALERT,
317                 "Failed to restore /sim/presets subtree" );
318     }
319
320    delete currentPresets;
321 }
322
323 FGViewer *
324 FGGlobals::get_current_view () const
325 {
326   return viewmgr->get_current_view();
327 }
328
329 // end of globals.cxx