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