]> git.mxchange.org Git - flightgear.git/blob - src/Main/globals.cxx
Juggle fgfs link order to keep GNU ld happy.
[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 mag;
135     delete matlib;
136     delete route_mgr;
137     delete current_panel;
138
139     delete ATC_mgr;
140     delete AI_mgr;
141     delete controls;
142     delete viewmgr;
143
144 //     delete commands;
145     delete acmodel;
146     delete model_mgr;
147     delete channel_options_list;
148     delete initial_waypoints;
149     delete tile_mgr;
150     delete scenery;
151     delete fontcache;
152
153     delete navlist;
154     delete loclist;
155     delete gslist;
156     delete dmelist;
157     delete tacanlist;
158     delete carrierlist;
159     delete channellist;
160     delete airwaynet;
161     delete multiplayer_mgr;
162
163     soundmgr->unbind();
164     delete soundmgr;
165 }
166
167
168 // set the fg_root path
169 void FGGlobals::set_fg_root (const string &root) {
170     fg_root = root;
171
172     // append /data to root if it exists
173     SGPath tmp( fg_root );
174     tmp.append( "data" );
175     tmp.append( "version" );
176     if ( ulFileExists( tmp.c_str() ) ) {
177         fgGetNode("BAD_FG_ROOT", true)->setStringValue(fg_root);
178         fg_root += "/data";
179         fgGetNode("GOOD_FG_ROOT", true)->setStringValue(fg_root);
180         SG_LOG(SG_GENERAL, SG_ALERT, "***\n***\n*** Warning: changing bad FG_ROOT/--fg-root to '"
181                 << fg_root << "'\n***\n***");
182     }
183
184     // remove /sim/fg-root before writing to prevent hijacking
185     SGPropertyNode *n = fgGetNode("/sim", true);
186     n->removeChild("fg-root", 0, false);
187     n = n->getChild("fg-root", 0, true);
188     n->setStringValue(fg_root.c_str());
189     n->setAttribute(SGPropertyNode::WRITE, false);
190 }
191
192 void FGGlobals::set_fg_scenery (const string &scenery) {
193     SGPath s;
194     if (scenery.empty()) {
195         s.set( fg_root );
196         s.append( "Scenery" );
197     } else
198         s.set( scenery );
199
200     string_list path_list = sgPathSplit( s.str() );
201     fg_scenery.clear();
202
203     for (unsigned i = 0; i < path_list.size(); i++) {
204
205         ulDir *d = ulOpenDir( path_list[i].c_str() );
206         if (d == NULL)
207             continue;
208         ulCloseDir( d );
209
210         SGPath pt( path_list[i] ), po( path_list[i] );
211         pt.append("Terrain");
212         po.append("Objects");
213
214         ulDir *td = ulOpenDir( pt.c_str() );
215         ulDir *od = ulOpenDir( po.c_str() );
216
217         // "Terrain" and "Airports" directory don't exist. add directory as is
218         // otherwise, automatically append either Terrain, Objects, or both
219         //if (td == NULL && od == NULL)
220             fg_scenery.push_back( path_list[i] );
221         //else {
222             if (td != NULL) {
223                 fg_scenery.push_back( pt.str() );
224                 ulCloseDir( td );
225             }
226             if (od != NULL) {
227                 fg_scenery.push_back( po.str() );
228                 ulCloseDir( od );
229             }
230         //}
231         // insert a marker for FGTileEntry::load(), so that
232         // FG_SCENERY=A:B becomes list ["A/Terrain", "A/Objects", "",
233         // "B/Terrain", "B/Objects", ""]
234         fg_scenery.push_back("");
235     }
236 }
237
238
239 FGRenderer *
240 FGGlobals::get_renderer () const
241 {
242    return renderer;
243 }
244
245 SGSubsystemMgr *
246 FGGlobals::get_subsystem_mgr () const
247 {
248     return subsystem_mgr;
249 }
250
251 SGSubsystem *
252 FGGlobals::get_subsystem (const char * name)
253 {
254     return subsystem_mgr->get_subsystem(name);
255 }
256
257 void
258 FGGlobals::add_subsystem (const char * name,
259                           SGSubsystem * subsystem,
260                           SGSubsystemMgr::GroupType type,
261                           double min_time_sec)
262 {
263     subsystem_mgr->add(name, subsystem, type, min_time_sec);
264 }
265
266 SGSoundMgr *
267 FGGlobals::get_soundmgr () const
268 {
269     return soundmgr;
270 }
271
272 SGEventMgr *
273 FGGlobals::get_event_mgr () const
274 {
275     return event_mgr;
276 }
277
278
279 // Save the current state as the initial state.
280 void
281 FGGlobals::saveInitialState ()
282 {
283   initial_state = new SGPropertyNode();
284
285   if (!copyProperties(props, initial_state))
286     SG_LOG(SG_GENERAL, SG_ALERT, "Error saving initial state");
287 }
288
289
290 // Restore the saved initial state, if any
291 void
292 FGGlobals::restoreInitialState ()
293 {
294     if ( initial_state == 0 ) {
295         SG_LOG(SG_GENERAL, SG_ALERT,
296                "No initial state available to restore!!!");
297         return;
298     }
299
300     SGPropertyNode *currentPresets = new SGPropertyNode;
301     SGPropertyNode *targetNode = fgGetNode( "/sim/presets" );
302
303     // stash the /sim/presets tree
304     if ( !copyProperties(targetNode, currentPresets) ) {
305         SG_LOG( SG_GENERAL, SG_ALERT, "Failed to save /sim/presets subtree" );
306     }
307     
308     if ( copyProperties(initial_state, props) ) {
309         SG_LOG( SG_GENERAL, SG_INFO, "Initial state restored successfully" );
310     } else {
311         SG_LOG( SG_GENERAL, SG_INFO,
312                 "Some errors restoring initial state (read-only props?)" );
313     }
314
315     // recover the /sim/presets tree
316     if ( !copyProperties(currentPresets, targetNode) ) {
317         SG_LOG( SG_GENERAL, SG_ALERT,
318                 "Failed to restore /sim/presets subtree" );
319     }
320
321    delete currentPresets;
322 }
323
324 FGViewer *
325 FGGlobals::get_current_view () const
326 {
327   return viewmgr->get_current_view();
328 }
329
330 // end of globals.cxx