]> git.mxchange.org Git - flightgear.git/blob - src/Main/globals.cxx
Merge branch 'ehofman/particle' 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/timing/sg_time.hxx>
30 #include <simgear/ephemeris/ephemeris.hxx>
31 #include <simgear/magvar/magvar.hxx>
32 #include <simgear/scene/material/matlib.hxx>
33 #include <simgear/structure/subsystem_mgr.hxx>
34 #include <simgear/structure/event_mgr.hxx>
35 #include <simgear/sound/soundmgr_openal.hxx>
36
37 #include <Aircraft/controls.hxx>
38 #include <Airports/runways.hxx>
39 #include <ATCDCL/AIMgr.hxx>
40 #include <ATCDCL/ATCmgr.hxx>
41 #include <Autopilot/route_mgr.hxx>
42 #include <Cockpit/panel.hxx>
43 #include <GUI/new_gui.hxx>
44 #include <Model/acmodel.hxx>
45 #include <Model/modelmgr.hxx>
46 #include <MultiPlayer/multiplaymgr.hxx>
47 #include <Navaids/awynet.hxx>
48 #include <Scenery/scenery.hxx>
49 #include <Scenery/tilemgr.hxx>
50 #include <Navaids/navlist.hxx>
51
52 #include "globals.hxx"
53 #include "renderer.hxx"
54 #include "viewmgr.hxx"
55
56 #include "fg_props.hxx"
57 #include "fg_io.hxx"
58
59 \f
60 ////////////////////////////////////////////////////////////////////////
61 // Implementation of FGGlobals.
62 ////////////////////////////////////////////////////////////////////////
63
64 // global global :-)
65 FGGlobals *globals;
66
67
68 // Constructor
69 FGGlobals::FGGlobals() :
70     props( new SGPropertyNode ),
71     initial_state( NULL ),
72     locale( NULL ),
73     renderer( new FGRenderer ),
74     subsystem_mgr( new SGSubsystemMgr ),
75     event_mgr( new SGEventMgr ),
76     soundmgr( new SGSoundMgr ),
77     sim_time_sec( 0.0 ),
78     fg_root( "" ),
79     warp( 0 ),
80     warp_delta( 0 ),
81     time_params( NULL ),
82     ephem( NULL ),
83     mag( NULL ),
84     matlib( NULL ),
85     route_mgr( NULL ),
86     current_panel( NULL ),
87     ATC_mgr( NULL ),
88     AI_mgr( NULL ),
89     controls( NULL ),
90     viewmgr( NULL ),
91     commands( SGCommandMgr::instance() ),
92     acmodel( NULL ),
93     model_mgr( NULL ),
94     channel_options_list( NULL ),
95     initial_waypoints( NULL ),
96     scenery( NULL ),
97     tile_mgr( NULL ),
98     fontcache ( new FGFontCache ),
99     navlist( NULL ),
100     loclist( NULL ),
101     gslist( NULL ),
102     dmelist( NULL ),
103     tacanlist( NULL ),
104     carrierlist( NULL ),
105     channellist( NULL ),
106     airwaynet( NULL ),
107     multiplayer_mgr( NULL )
108 {
109 }
110
111
112 // Destructor
113 FGGlobals::~FGGlobals() 
114 {
115     delete renderer;
116 // The AIModels manager performs a number of actions upon
117     // Shutdown that implicitly assume that other subsystems
118     // are still operational (Due to the dynamic allocation and
119     // deallocation of AIModel objects. To ensure we can safely
120     // shut down all subsystems, make sure we take down the 
121     // AIModels system first.
122     subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("ai_model");
123     // FGInput (FGInputEvent) and FGDialog calls get_subsystem() in their destructors, 
124     // which is not safe since some subsystem are already deleted but can be referred.
125     // So these subsystems must be deleted prior to deleting subsystem_mgr unless
126     // ~SGSubsystemGroup and SGSubsystemMgr::get_subsystem are changed not to refer to
127     // deleted subsystems.
128     subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("input");
129     subsystem_mgr->get_group(SGSubsystemMgr::GENERAL)->remove_subsystem("gui");
130     subsystem_mgr->unbind();
131     delete subsystem_mgr;
132     delete event_mgr;
133     delete time_params;
134     delete ephem;
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     SGPath s;
195     if (scenery.empty()) {
196         s.set( fg_root );
197         s.append( "Scenery" );
198     } else
199         s.set( scenery );
200
201     string_list path_list = sgPathSplit( s.str() );
202     fg_scenery.clear();
203
204     for (unsigned i = 0; i < path_list.size(); i++) {
205
206         ulDir *d = ulOpenDir( path_list[i].c_str() );
207         if (d == NULL)
208             continue;
209         ulCloseDir( d );
210
211         SGPath pt( path_list[i] ), po( path_list[i] );
212         pt.append("Terrain");
213         po.append("Objects");
214
215         ulDir *td = ulOpenDir( pt.c_str() );
216         ulDir *od = ulOpenDir( po.c_str() );
217
218         // "Terrain" and "Airports" directory don't exist. add directory as is
219         // otherwise, automatically append either Terrain, Objects, or both
220         //if (td == NULL && od == NULL)
221             fg_scenery.push_back( path_list[i] );
222         //else {
223             if (td != NULL) {
224                 fg_scenery.push_back( pt.str() );
225                 ulCloseDir( td );
226             }
227             if (od != NULL) {
228                 fg_scenery.push_back( po.str() );
229                 ulCloseDir( od );
230             }
231         //}
232         // insert a marker for FGTileEntry::load(), so that
233         // FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
234         // "B/Terrain", "B/Objects", ""]
235         fg_scenery.push_back("");
236     }
237 }
238
239
240 FGRenderer *
241 FGGlobals::get_renderer () const
242 {
243    return renderer;
244 }
245
246 SGSubsystemMgr *
247 FGGlobals::get_subsystem_mgr () const
248 {
249     return subsystem_mgr;
250 }
251
252 SGSubsystem *
253 FGGlobals::get_subsystem (const char * name)
254 {
255     return subsystem_mgr->get_subsystem(name);
256 }
257
258 void
259 FGGlobals::add_subsystem (const char * name,
260                           SGSubsystem * subsystem,
261                           SGSubsystemMgr::GroupType type,
262                           double min_time_sec)
263 {
264     subsystem_mgr->add(name, subsystem, type, min_time_sec);
265 }
266
267 SGSoundMgr *
268 FGGlobals::get_soundmgr () const
269 {
270     return soundmgr;
271 }
272
273 SGEventMgr *
274 FGGlobals::get_event_mgr () const
275 {
276     return event_mgr;
277 }
278
279
280 // Save the current state as the initial state.
281 void
282 FGGlobals::saveInitialState ()
283 {
284   initial_state = new SGPropertyNode();
285
286   if (!copyProperties(props, initial_state))
287     SG_LOG(SG_GENERAL, SG_ALERT, "Error saving initial state");
288 }
289
290
291 // Restore the saved initial state, if any
292 void
293 FGGlobals::restoreInitialState ()
294 {
295     if ( initial_state == 0 ) {
296         SG_LOG(SG_GENERAL, SG_ALERT,
297                "No initial state available to restore!!!");
298         return;
299     }
300
301     SGPropertyNode *currentPresets = new SGPropertyNode;
302     SGPropertyNode *targetNode = fgGetNode( "/sim/presets" );
303
304     // stash the /sim/presets tree
305     if ( !copyProperties(targetNode, currentPresets) ) {
306         SG_LOG( SG_GENERAL, SG_ALERT, "Failed to save /sim/presets subtree" );
307     }
308     
309     if ( copyProperties(initial_state, props) ) {
310         SG_LOG( SG_GENERAL, SG_INFO, "Initial state restored successfully" );
311     } else {
312         SG_LOG( SG_GENERAL, SG_INFO,
313                 "Some errors restoring initial state (read-only props?)" );
314     }
315
316     // recover the /sim/presets tree
317     if ( !copyProperties(currentPresets, targetNode) ) {
318         SG_LOG( SG_GENERAL, SG_ALERT,
319                 "Failed to restore /sim/presets subtree" );
320     }
321
322    delete currentPresets;
323 }
324
325 FGViewer *
326 FGGlobals::get_current_view () const
327 {
328   return viewmgr->get_current_view();
329 }
330
331 // end of globals.cxx