]> git.mxchange.org Git - flightgear.git/blob - src/Main/globals.cxx
Make FGIO a proper subsystem and add a reinit method for the generic protocol. This...
[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
19 // Foundation, 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/sound/soundmgr_openal.hxx>
28 #include <simgear/structure/commands.hxx>
29 #include <simgear/misc/sg_path.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
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     sim_time_sec( 0.0 ),
77     fg_root( "" ),
78     warp( 0 ),
79     warp_delta( 0 ),
80     time_params( NULL ),
81     ephem( NULL ),
82     mag( NULL ),
83     matlib( NULL ),
84     route_mgr( NULL ),
85     current_panel( NULL ),
86     soundmgr( 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     delete subsystem_mgr;
131     delete event_mgr;
132     delete time_params;
133     delete ephem;
134     delete mag;
135     delete matlib;
136     delete route_mgr;
137     delete current_panel;
138     delete soundmgr;
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
165
166 // set the fg_root path
167 void FGGlobals::set_fg_root (const string &root) {
168     fg_root = root;
169
170     // append /data to root if it exists
171     SGPath tmp( fg_root );
172     tmp.append( "data" );
173     tmp.append( "version" );
174     if ( ulFileExists( tmp.c_str() ) ) {
175         fgGetNode("BAD_FG_ROOT", true)->setStringValue(fg_root);
176         fg_root += "/data";
177         fgGetNode("GOOD_FG_ROOT", true)->setStringValue(fg_root);
178         SG_LOG(SG_GENERAL, SG_ALERT, "***\n***\n*** Warning: changing bad FG_ROOT/--fg-root to '"
179                 << fg_root << "'\n***\n***");
180     }
181
182     // remove /sim/fg-root before writing to prevent hijacking
183     SGPropertyNode *n = fgGetNode("/sim", true);
184     n->removeChild("fg-root", 0, false);
185     n = n->getChild("fg-root", 0, true);
186     n->setStringValue(fg_root.c_str());
187     n->setAttribute(SGPropertyNode::WRITE, false);
188 }
189
190 void FGGlobals::set_fg_scenery (const string &scenery) {
191     SGPath s;
192     if (scenery.empty()) {
193         s.set( fg_root );
194         s.append( "Scenery" );
195     } else
196         s.set( scenery );
197
198     string_list path_list = sgPathSplit( s.str() );
199     fg_scenery.clear();
200
201     for (unsigned i = 0; i < path_list.size(); i++) {
202
203         ulDir *d = ulOpenDir( path_list[i].c_str() );
204         if (d == NULL)
205             continue;
206         ulCloseDir( d );
207
208         SGPath pt( path_list[i] ), po( path_list[i] );
209         pt.append("Terrain");
210         po.append("Objects");
211
212         ulDir *td = ulOpenDir( pt.c_str() );
213         ulDir *od = ulOpenDir( po.c_str() );
214
215         // "Terrain" and "Airports" directory don't exist. add directory as is
216         // otherwise, automatically append either Terrain, Objects, or both
217         //if (td == NULL && od == NULL)
218             fg_scenery.push_back( path_list[i] );
219         //else {
220             if (td != NULL) {
221                 fg_scenery.push_back( pt.str() );
222                 ulCloseDir( td );
223             }
224             if (od != NULL) {
225                 fg_scenery.push_back( po.str() );
226                 ulCloseDir( od );
227             }
228         //}
229         // insert a marker for FGTileEntry::load(), so that
230         // FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
231         // "B/Terrain", "B/Objects", ""]
232         fg_scenery.push_back("");
233     }
234 }
235
236
237 FGRenderer *
238 FGGlobals::get_renderer () const
239 {
240    return renderer;
241 }
242
243 SGSubsystemMgr *
244 FGGlobals::get_subsystem_mgr () const
245 {
246     return subsystem_mgr;
247 }
248
249 SGSubsystem *
250 FGGlobals::get_subsystem (const char * name)
251 {
252     return subsystem_mgr->get_subsystem(name);
253 }
254
255 void
256 FGGlobals::add_subsystem (const char * name,
257                           SGSubsystem * subsystem,
258                           SGSubsystemMgr::GroupType type,
259                           double min_time_sec)
260 {
261     subsystem_mgr->add(name, subsystem, type, min_time_sec);
262 }
263
264
265 SGEventMgr *
266 FGGlobals::get_event_mgr () const
267 {
268     return event_mgr;
269 }
270
271
272 // Save the current state as the initial state.
273 void
274 FGGlobals::saveInitialState ()
275 {
276   initial_state = new SGPropertyNode();
277
278   if (!copyProperties(props, initial_state))
279     SG_LOG(SG_GENERAL, SG_ALERT, "Error saving initial state");
280 }
281
282
283 // Restore the saved initial state, if any
284 void
285 FGGlobals::restoreInitialState ()
286 {
287     if ( initial_state == 0 ) {
288         SG_LOG(SG_GENERAL, SG_ALERT,
289                "No initial state available to restore!!!");
290         return;
291     }
292
293     SGPropertyNode *currentPresets = new SGPropertyNode;
294     SGPropertyNode *targetNode = fgGetNode( "/sim/presets" );
295
296     // stash the /sim/presets tree
297     if ( !copyProperties(targetNode, currentPresets) ) {
298         SG_LOG( SG_GENERAL, SG_ALERT, "Failed to save /sim/presets subtree" );
299     }
300     
301     if ( copyProperties(initial_state, props) ) {
302         SG_LOG( SG_GENERAL, SG_INFO, "Initial state restored successfully" );
303     } else {
304         SG_LOG( SG_GENERAL, SG_INFO,
305                 "Some errors restoring initial state (read-only props?)" );
306     }
307
308     // recover the /sim/presets tree
309     if ( !copyProperties(currentPresets, targetNode) ) {
310         SG_LOG( SG_GENERAL, SG_ALERT,
311                 "Failed to restore /sim/presets subtree" );
312     }
313
314    delete currentPresets;
315 }
316
317 FGViewer *
318 FGGlobals::get_current_view () const
319 {
320   return viewmgr->get_current_view();
321 }
322
323 // end of globals.cxx