]> git.mxchange.org Git - flightgear.git/blobdiff - src/Main/fg_init.cxx
Various mods to allow querying for nearest airport (with optional ability to
[flightgear.git] / src / Main / fg_init.cxx
index 15fcf922e44d6c3c2405ccff4a792c57543b744c..8691347359c55581c42e880878f72e44f48217ef 100644 (file)
 #  include <math.h>
 #endif
 
-#ifdef HAVE_WINDOWS_H
-#  include <windows.h>
-#endif
-
-#include GLUT_H
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>             // strcmp()
 #endif
 
 #include <simgear/compiler.h>
-#include <simgear/misc/exception.hxx>
 
 #include STL_STRING
 
 #include <simgear/constants.h>
 #include <simgear/debug/logstream.hxx>
+#include <simgear/structure/exception.hxx>
+#include <simgear/structure/event_mgr.hxx>
 #include <simgear/math/point3d.hxx>
 #include <simgear/math/polar3d.hxx>
 #include <simgear/math/sg_geodesy.hxx>
 #include <simgear/misc/sg_path.hxx>
+#include <simgear/misc/interpolator.hxx>
+#include <simgear/scene/material/matlib.hxx>
 #ifdef FG_USE_CLOUDS_3D
-#  include <simgear/sky/clouds3d/SkySceneLoader.hpp>
-#  include <simgear/sky/clouds3d/SkyUtil.hpp>
+#  include <simgear/scene/sky/clouds3d/SkySceneLoader.hpp>
+#  include <simgear/scene/sky/clouds3d/SkyUtil.hpp>
+#  include <simgear/screen/texture.hxx>
 #endif
 #include <simgear/timing/sg_time.hxx>
 #include <simgear/timing/lowleveltime.h>
@@ -78,7 +76,8 @@
 #include <ATC/ATCmgr.hxx>
 #include <ATC/AIMgr.hxx>
 #include <Autopilot/auto_gui.hxx>
-#include <Autopilot/newauto.hxx>
+#include <Autopilot/route_mgr.hxx>
+#include <Autopilot/xmlauto.hxx>
 #include <Cockpit/cockpit.hxx>
 #include <Cockpit/radiostack.hxx>
 #include <Cockpit/panel.hxx>
@@ -88,7 +87,7 @@
 #include <FDM/ExternalNet/ExternalNet.hxx>
 #include <FDM/ExternalPipe/ExternalPipe.hxx>
 #include <FDM/JSBSim/JSBSim.hxx>
-#include <FDM/LaRCsim.hxx>
+#include <FDM/LaRCsim/LaRCsim.hxx>
 #include <FDM/MagicCarpet.hxx>
 #include <FDM/UFO.hxx>
 #include <FDM/NullFDM.hxx>
 #include <Include/general.hxx>
 #include <Input/input.hxx>
 #include <Instrumentation/instrument_mgr.hxx>
-// #include <Joystick/joystick.hxx>
-#include <Objects/matlib.hxx>
 #include <Model/acmodel.hxx>
+#include <AIModel/AIManager.hxx>
 #include <Navaids/fixlist.hxx>
 #include <Navaids/ilslist.hxx>
 #include <Navaids/mkrbeacons.hxx>
 #include <Navaids/navlist.hxx>
+#include <Replay/replay.hxx>
 #include <Scenery/scenery.hxx>
 #include <Scenery/tilemgr.hxx>
-#if defined(HAVE_PLIB_PSL)
-#include <Scripting/scriptmgr.hxx>
-#endif
+#include <Scripting/NasalSys.hxx>
 #include <Sound/fg_fx.hxx>
-#include <Sound/soundmgr.hxx>
 #include <Systems/system_mgr.hxx>
-#include <Time/FGEventMgr.hxx>
 #include <Time/light.hxx>
-#include <Time/sunpos.hxx>
 #include <Time/moonpos.hxx>
+#include <Time/sunpos.hxx>
+#include <Time/sunsolver.hxx>
 #include <Time/tmp.hxx>
 
 #ifdef FG_MPLAYER_AS
 
 SG_USING_STD(string);
 
+
+class Sound;
+
 extern const char *default_root;
 
 #ifdef FG_USE_CLOUDS_3D
@@ -270,8 +269,27 @@ bool fgInitFGRoot ( int argc, char **argv ) {
         root = "/FlightGear";
 #elif defined( WIN32 )
         root = "\\FlightGear";
-#elif defined( macintosh )
-        root = "";
+#elif defined(OSX_BUNDLE) 
+        /* the following code looks for the base package directly inside
+            the application bundle. This can be changed fairly easily by
+            fiddling with the code below. And yes, I know it's ugly and verbose.
+        */
+        CFBundleRef appBundle = CFBundleGetMainBundle();
+        CFURLRef appUrl = CFBundleCopyBundleURL(appBundle);
+        CFRelease(appBundle);
+
+        // look for a 'data' subdir directly inside the bundle : is there
+        // a better place? maybe in Resources? I don't know ...
+        CFURLRef dataDir = CFURLCreateCopyAppendingPathComponent(NULL, appUrl, CFSTR("data"), true);
+
+        // now convert down to a path, and the a c-string
+        CFStringRef path = CFURLCopyFileSystemPath(dataDir, kCFURLPOSIXPathStyle);
+        root = CFStringGetCStringPtr(path, CFStringGetSystemEncoding());
+
+        // tidy up.
+        CFRelease(appBundle);
+        CFRelease(dataDir);
+        CFRelease(path);
 #else
         root = PKGLIBDIR;
 #endif
@@ -458,8 +476,8 @@ bool fgDetectLanguage() {
 
     SGPropertyNode *locale = fgInitLocale(language);
     if (!locale) {
-       cerr << "No internationalization settings specified in preferences.xml"
-            << endl;
+       SG_LOG(SG_GENERAL, SG_ALERT,
+              "No internationalization settings specified in preferences.xml" );
 
        return false;
     }
@@ -510,6 +528,38 @@ do_options (int argc, char ** argv)
 }
 
 
+static string fgFindAircraftPath( const SGPath &path, const string &aircraft ) {
+    ulDirEnt* dire;
+    ulDir *dirp = ulOpenDir(path.str().c_str());
+    if (dirp == NULL) {
+        cerr << "Unable to open aircraft directory." << endl;
+        exit(-1);
+    }
+
+    while ((dire = ulReadDir(dirp)) != NULL) {
+        if (dire->d_isdir) {
+            if ( strcmp("CVS", dire->d_name) && strcmp(".", dire->d_name)
+                 && strcmp("..", dire->d_name) )
+            {
+                SGPath next = path;
+                next.append(dire->d_name);
+
+                string result = fgFindAircraftPath( next, aircraft );
+                if ( ! result.empty() ) {
+                    return result;
+                }
+            }
+        } else if ( !strcmp(dire->d_name, aircraft.c_str()) ) {
+            return path.str();
+        }
+    }
+
+    ulCloseDir(dirp);
+
+    return "";
+}
+
+
 // Read in configuration (file and command line)
 bool fgInitConfig ( int argc, char **argv ) {
 
@@ -529,24 +579,37 @@ bool fgInitConfig ( int argc, char **argv ) {
     // Scan user config files and command line for a specified aircraft.
     fgInitFGAircraft(argc, argv);
 
-    string aircraft = fgGetString("/sim/aircraft", "");
+    string aircraft = fgGetString( "/sim/aircraft", "" );
     if ( aircraft.size() > 0 ) {
-        SGPath aircraft_path(globals->get_fg_root());
-        aircraft_path.append("Aircraft");
-        aircraft_path.append(aircraft);
-        aircraft_path.concat("-set.xml");
-        SG_LOG(SG_INPUT, SG_INFO, "Reading default aircraft: " << aircraft
-               << " from " << aircraft_path.str());
-        try {
-            readProperties(aircraft_path.str(), globals->get_props());
-        } catch (const sg_exception &e) {
-            string message = "Error reading default aircraft: ";
-            message += e.getFormattedMessage();
-            SG_LOG(SG_INPUT, SG_ALERT, message);
-            exit(2);
+        SGPath aircraft_search( globals->get_fg_root() );
+        aircraft_search.append( "Aircraft" );
+
+        string aircraft_set = aircraft + "-set.xml";
+
+        string result = fgFindAircraftPath( aircraft_search, aircraft_set );
+        if ( !result.empty() ) {
+            fgSetString( "/sim/aircraft-dir", result.c_str() );
+            SGPath full_name( result );
+            full_name.append( aircraft_set );
+
+            SG_LOG(SG_INPUT, SG_INFO, "Reading default aircraft: " << aircraft
+                   << " from " << full_name.str());
+            try {
+                readProperties( full_name.str(), globals->get_props() );
+            } catch ( const sg_exception &e ) {
+                string message = "Error reading default aircraft: ";
+                message += e.getFormattedMessage();
+                SG_LOG(SG_INPUT, SG_ALERT, message);
+                exit(2);
+            }
+        } else {
+            SG_LOG( SG_INPUT, SG_ALERT, "Cannot find specified aircraft: "
+                    << aircraft );
+            return false;
         }
+
     } else {
-        SG_LOG(SG_INPUT, SG_ALERT, "No default aircraft specified");
+        SG_LOG( SG_INPUT, SG_ALERT, "No default aircraft specified" );
     }
 
     // parse options after loading aircraft to ensure any user
@@ -559,23 +622,23 @@ bool fgInitConfig ( int argc, char **argv ) {
 
 // find basic airport location info from airport database
 bool fgFindAirportID( const string& id, FGAirport *a ) {
+    FGAirport result;
     if ( id.length() ) {
-        SGPath path( globals->get_fg_root() );
-        path.append( "Airports" );
-        path.append( "simple.mk4" );
-        FGAirports airports( path.c_str() );
-
         SG_LOG( SG_GENERAL, SG_INFO, "Searching for airport code = " << id );
 
-        if ( ! airports.search( id, a ) ) {
+        result = globals->get_airports()->search( id );
+
+        if ( result.id.empty() ) {
             SG_LOG( SG_GENERAL, SG_ALERT,
-                    "Failed to find " << id << " in " << path.str() );
+                    "Failed to find " << id << " in basic.dat.gz" );
             return false;
         }
     } else {
         return false;
     }
 
+    *a = result;
+
     SG_LOG( SG_GENERAL, SG_INFO,
             "Position for " << id << " is ("
             << a->longitude << ", "
@@ -659,16 +722,11 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
     if ( id.length() ) {
         // set initial position from runway and heading
 
-        SGPath path( globals->get_fg_root() );
-        path.append( "Airports" );
-        path.append( "runways.mk4" );
-        FGRunways runways( path.c_str() );
-
         SG_LOG( SG_GENERAL, SG_INFO,
                 "Attempting to set starting position from airport code "
                 << id << " heading " << tgt_hdg );
                
-        if ( ! runways.search( id, (int)tgt_hdg, &r ) ) {
+        if ( ! globals->get_runways()->search( id, (int)tgt_hdg, &r ) ) {
             SG_LOG( SG_GENERAL, SG_ALERT,
                     "Failed to find a good runway for " << id << '\n' );
             return false;
@@ -698,6 +756,7 @@ static bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg ) {
         double oaz = azimuth;
         if ( fabs(fgGetDouble("/sim/presets/offset-azimuth")) > SG_EPSILON ) {
             oaz = fgGetDouble("/sim/presets/offset-azimuth") + 180;
+            heading = tgt_hdg;
         }
         while ( oaz >= 360.0 ) { oaz -= 360.0; }
         geo_direct_wgs_84 ( 0, lat2, lon2, oaz, odist, &olat, &olon, &az2 );
@@ -732,16 +791,11 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
     if ( id.length() ) {
         // set initial position from airport and runway number
 
-        SGPath path( globals->get_fg_root() );
-        path.append( "Airports" );
-        path.append( "runways.mk4" );
-        FGRunways runways( path.c_str() );
-
         SG_LOG( SG_GENERAL, SG_INFO,
                 "Attempting to set starting position for "
-                << id << ":" << runway );
+                << id << ":" << rwy );
 
-        if ( ! runways.search( id, rwy, &r ) ) {
+        if ( ! globals->get_runways()->search( id, rwy, &r ) ) {
             SG_LOG( SG_GENERAL, SG_ALERT,
                     "Failed to find runway " << rwy << 
                     " at airport " << id );
@@ -775,6 +829,7 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
        if ( fabs(fgGetDouble("/sim/presets/offset-azimuth")) > SG_EPSILON )
        {
            oaz = fgGetDouble("/sim/presets/offset-azimuth") + 180;
+            heading = fgGetDouble("/sim/presets/heading-deg");
        }
        while ( oaz >= 360.0 ) { oaz -= 360.0; }
        geo_direct_wgs_84 ( 0, lat2, lon2, oaz, odist, &olat, &olon, &az2 );
@@ -803,6 +858,7 @@ static bool fgSetPosFromAirportIDandRwy( const string& id, const string& rwy ) {
 
 
 static void fgSetDistOrAltFromGlideSlope() {
+    // cout << "fgSetDistOrAltFromGlideSlope()" << endl;
     string apt_id = fgGetString("/sim/presets/airport-id");
     double gs = fgGetDouble("/sim/presets/glideslope-deg")
         * SG_DEGREES_TO_RADIANS ;
@@ -944,11 +1000,24 @@ static bool fgSetPosFromFix( const string& id ) {
 
 
 /**
- * Initialize vor/ndb/ils/fix list management and query systems
+ * Initialize vor/ndb/ils/fix list management and query systems (as
+ * well as simple airport db list)
  */
 bool
 fgInitNav ()
 {
+    SG_LOG(SG_GENERAL, SG_INFO, "Loading Simple Airport List");
+    SGPath p_simple( globals->get_fg_root() );
+    p_simple.append( "Airports/basic.dat" );
+    FGAirportList *airports = new FGAirportList( p_simple.str() );
+    globals->set_airports( airports );
+
+    SG_LOG(SG_GENERAL, SG_INFO, "Loading Runway List");
+    SGPath p_runway( globals->get_fg_root() );
+    p_runway.append( "Airports/runways.dat" );
+    FGRunwayList *runways = new FGRunwayList( p_runway.str() );
+    globals->set_runways( runways );
+
     SG_LOG(SG_GENERAL, SG_INFO, "Loading Navaids");
 
     SG_LOG(SG_GENERAL, SG_INFO, "  VOR/NDB");
@@ -977,12 +1046,21 @@ fgInitNav ()
 
 // Set the initial position based on presets (or defaults)
 bool fgInitPosition() {
+    // cout << "fgInitPosition()" << endl;
+    double gs = fgGetDouble("/sim/presets/glideslope-deg")
+        * SG_DEGREES_TO_RADIANS ;
+    double od = fgGetDouble("/sim/presets/offset-distance");
+    double alt = fgGetDouble("/sim/presets/altitude-ft");
+
     bool set_pos = false;
 
     // If glideslope is specified, then calculate offset-distance or
     // altitude relative to glide slope if either of those was not
     // specified.
-    fgSetDistOrAltFromGlideSlope();
+    if ( fabs( gs ) > 0.01 ) {
+        fgSetDistOrAltFromGlideSlope();
+    }
+
 
     // If we have an explicit, in-range lon/lat, don't change it, just use it.
     // If not, check for an airport-id and use that.
@@ -1006,63 +1084,44 @@ bool fgInitPosition() {
     string ndb = fgGetString("/sim/presets/ndb-id");
     double ndb_freq = fgGetDouble("/sim/presets/ndb-freq");
     string fix = fgGetString("/sim/presets/fix");
+
     if ( !set_pos && !apt.empty() && !rwy_no.empty() ) {
         // An airport + runway is requested
         if ( fgSetPosFromAirportIDandRwy( apt, rwy_no ) ) {
-            // set position (a little off the heading for single
+            // set tower position (a little off the heading for single
             // runway airports)
             fgSetTowerPosFromAirportID( apt, hdg );
-
             set_pos = true;
         }
     }
+
     if ( !set_pos && !apt.empty() ) {
         // An airport is requested (find runway closest to hdg)
-        bool ok = false;
-        if (fgGetDouble("/sim/presets/altitude-ft") <= 0 &&
-            fgGetDouble("/sim/presets/offset-distance") == 0)
-            ok = fgSetPosFromAirportIDandHdg( apt, hdg );
-        else
-            ok = fgSetPosFromAirportID( apt );
-            
-        if (ok) {
-                // set position (a little off the heading for single
-                // runway airports)
-                fgSetTowerPosFromAirportID( apt, hdg );
-
+        if ( fgSetPosFromAirportIDandHdg( apt, hdg ) ) {
+            // set tower position (a little off the heading for single
+            // runway airports)
+            fgSetTowerPosFromAirportID( apt, hdg );
             set_pos = true;
         }
     }
+
     if ( !set_pos && !vor.empty() ) {
         // a VOR is requested
         if ( fgSetPosFromNAV( vor, vor_freq ) ) {
-            if ( fgGetDouble("/sim/presets/altitude-ft") > -9990.0 ) {
-                fgSetBool("/sim/presets/onground", false);
-            } else {
-                fgSetBool("/sim/presets/onground", true);
-            }
             set_pos = true;
         }
     }
+
     if ( !set_pos && !ndb.empty() ) {
         // an NDB is requested
         if ( fgSetPosFromNAV( ndb, ndb_freq ) ) {
-            if ( fgGetDouble("/sim/presets/altitude-ft") > -9990.0 ) {
-                fgSetBool("/sim/presets/onground", false);
-            } else {
-                fgSetBool("/sim/presets/onground", true);
-            }
             set_pos = true;
         }
     }
+
     if ( !set_pos && !fix.empty() ) {
         // a Fix is requested
         if ( fgSetPosFromFix( fix ) ) {
-            if ( fgGetDouble("/sim/presets/altitude-ft") > -9990.0 ) {
-                fgSetBool("/sim/presets/onground", false);
-            } else {
-                fgSetBool("/sim/presets/onground", true);
-            }
             set_pos = true;
         }
     }
@@ -1081,6 +1140,13 @@ bool fgInitPosition() {
     fgSetDouble( "/orientation/heading-deg",
                  fgGetDouble("/sim/presets/heading-deg") );
 
+    // determine if this should be an on-ground or in-air start
+    if ( fabs(gs) > 0.01 || fabs(od) > 0.1 || alt > 0.1 ) {
+        fgSetBool("/sim/presets/onground", false);
+    } else {
+        fgSetBool("/sim/presets/onground", true);
+    }                              
+
     return true;
 }
 
@@ -1212,11 +1278,11 @@ void fgInitFDM() {
 static void printMat(const sgVec4 *mat, char *name="")
 {
     int i;
-    cout << name << endl;
+    SG_LOG(SG_GENERAL, SG_BULK, name );
     for(i=0; i<4; i++) {
-        cout <<"  "<<mat[i][0]<<" "<<mat[i][1]<<" "<<mat[i][2]<<" "<<mat[i][3]<<endl;
+        SG_LOG(SG_GENERAL, SG_BULK, "  " << mat[i][0] << " " << mat[i][1]
+                                    << " " << mat[i][2] << " " << mat[i][3] );
     }
-    cout << endl;
 }
 
 // Initialize view parameters
@@ -1251,65 +1317,151 @@ SGTime *fgInitTime() {
                             zone.str(),
                             cur_time_override->getLongValue() );
 
+    globals->set_warp_delta( 0 );
+
+    t->update( 0.0, 0.0,
+               cur_time_override->getLongValue(),
+               globals->get_warp() );
+
+    return t;
+}
+
+
+// set up a time offset (aka warp) if one is specified
+void fgInitTimeOffset() {
+    static const SGPropertyNode *longitude
+        = fgGetNode("/position/longitude-deg");
+    static const SGPropertyNode *latitude
+        = fgGetNode("/position/latitude-deg");
+    static const SGPropertyNode *cur_time_override
+        = fgGetNode("/sim/time/cur-time-override", true);
+
     // Handle potential user specified time offsets
+    int orig_warp = globals->get_warp();
+    SGTime *t = globals->get_time_params();
     time_t cur_time = t->get_cur_time();
     time_t currGMT = sgTimeGetGMT( gmtime(&cur_time) );
     time_t systemLocalTime = sgTimeGetGMT( localtime(&cur_time) );
     time_t aircraftLocalTime = 
         sgTimeGetGMT( fgLocaltime(&cur_time, t->get_zonename() ) );
 
-    // Okay, we now have six possible scenarios
+    // Okay, we now have several possible scenarios
     int offset = fgGetInt("/sim/startup/time-offset");
     const string &offset_type = fgGetString("/sim/startup/time-offset-type");
-    if (offset_type == "system-offset") {
-        globals->set_warp( offset );
-    } else if (offset_type == "gmt-offset") {
-        globals->set_warp( offset - (currGMT - systemLocalTime) );
-    } else if (offset_type == "latitude-offset") {
-        globals->set_warp( offset - (aircraftLocalTime - systemLocalTime) );
-    } else if (offset_type == "system") {
-        globals->set_warp( offset - cur_time );
-    } else if (offset_type == "gmt") {
-        globals->set_warp( offset - currGMT );
-    } else if (offset_type == "latitude") {
-        globals->set_warp( offset - (aircraftLocalTime - systemLocalTime) - 
-                           cur_time ); 
+
+    int warp = 0;
+    if ( offset_type == "real" ) {
+        warp = 0;
+    } else if ( offset_type == "dawn" ) {
+        warp = fgTimeSecondsUntilSunAngle( cur_time,
+                                           longitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           latitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           90.0, true ); 
+    } else if ( offset_type == "morning" ) {
+        warp = fgTimeSecondsUntilSunAngle( cur_time,
+                                           longitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           latitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           75.0, true ); 
+    } else if ( offset_type == "noon" ) {
+        warp = fgTimeSecondsUntilSunAngle( cur_time,
+                                           longitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           latitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           0.0, true ); 
+    } else if ( offset_type == "afternoon" ) {
+        warp = fgTimeSecondsUntilSunAngle( cur_time,
+                                           longitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           latitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           60.0, false ); 
+     } else if ( offset_type == "dusk" ) {
+        warp = fgTimeSecondsUntilSunAngle( cur_time,
+                                           longitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           latitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           90.0, false ); 
+     } else if ( offset_type == "evening" ) {
+        warp = fgTimeSecondsUntilSunAngle( cur_time,
+                                           longitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           latitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           100.0, false ); 
+    } else if ( offset_type == "midnight" ) {
+        warp = fgTimeSecondsUntilSunAngle( cur_time,
+                                           longitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           latitude->getDoubleValue()
+                                             * SGD_DEGREES_TO_RADIANS,
+                                           180.0, false ); 
+    } else if ( offset_type == "system-offset" ) {
+        warp = offset;
+    } else if ( offset_type == "gmt-offset" ) {
+        warp = offset - (currGMT - systemLocalTime);
+    } else if ( offset_type == "latitude-offset" ) {
+        warp = offset - (aircraftLocalTime - systemLocalTime);
+    } else if ( offset_type == "system" ) {
+        warp = offset - cur_time;
+    } else if ( offset_type == "gmt" ) {
+        warp = offset - currGMT;
+    } else if ( offset_type == "latitude" ) {
+        warp = offset - (aircraftLocalTime - systemLocalTime) - cur_time; 
     } else {
         SG_LOG( SG_GENERAL, SG_ALERT,
                 "FG_TIME::Unsupported offset type " << offset_type );
         exit( -1 );
     }
-
-    SG_LOG( SG_GENERAL, SG_INFO, "After time init, warp = " 
-            << globals->get_warp() );
-
-    globals->set_warp_delta( 0 );
-
-    t->update( 0.0, 0.0,
+    globals->set_warp( orig_warp + warp );
+    t->update( longitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
+               latitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS,
                cur_time_override->getLongValue(),
                globals->get_warp() );
 
-    return t;
+    SG_LOG( SG_GENERAL, SG_INFO, "After fgInitTimeOffset(): warp = " 
+            << globals->get_warp() );
 }
 
-
 // This is the top level init routine which calls all the other
 // initialization routines.  If you are adding a subsystem to flight
 // gear, its initialization call should located in this routine.
 // Returns non-zero if a problem encountered.
 bool fgInitSubsystems() {
-    static const SGPropertyNode *longitude
-        = fgGetNode("/sim/presets/longitude-deg");
-    static const SGPropertyNode *latitude
-        = fgGetNode("/sim/presets/latitude-deg");
-    static const SGPropertyNode *altitude
-        = fgGetNode("/sim/presets/altitude-ft");
+    // static const SGPropertyNode *longitude
+    //     = fgGetNode("/sim/presets/longitude-deg");
+    // static const SGPropertyNode *latitude
+    //     = fgGetNode("/sim/presets/latitude-deg");
+    // static const SGPropertyNode *altitude
+    //     = fgGetNode("/sim/presets/altitude-ft");
 
-    fgLIGHT *l = &cur_light_params;
+    FGLight *l = (FGLight *)(globals->get_subsystem("lighting"));
 
     SG_LOG( SG_GENERAL, SG_INFO, "Initialize Subsystems");
     SG_LOG( SG_GENERAL, SG_INFO, "========== ==========");
 
+    ////////////////////////////////////////////////////////////////////
+    // Initialize the event manager subsystem.
+    ////////////////////////////////////////////////////////////////////
+
+     globals->get_event_mgr()->init();
+     globals->get_event_mgr()->setFreezeProperty(fgGetNode("/sim/freeze/clock"));
+
+    ////////////////////////////////////////////////////////////////////
+    // Initialize the property interpolator subsystem
+    ////////////////////////////////////////////////////////////////////
+    globals->add_subsystem("interpolator", new SGInterpolator);
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Add the FlightGear property utilities.
+    ////////////////////////////////////////////////////////////////////
+    globals->add_subsystem("properties", new FGProperties);
 
     ////////////////////////////////////////////////////////////////////
     // Initialize the material property subsystem.
@@ -1317,22 +1469,11 @@ bool fgInitSubsystems() {
 
     SGPath mpath( globals->get_fg_root() );
     mpath.append( "materials.xml" );
-    if ( ! material_lib.load( mpath.str() ) ) {
+    if ( ! globals->get_matlib()->load(globals->get_fg_root(), mpath.str()) ) {
         SG_LOG( SG_GENERAL, SG_ALERT, "Error loading material lib!" );
         exit(-1);
     }
 
-    ////////////////////////////////////////////////////////////////////
-    // Initialize the event manager subsystem.
-    ////////////////////////////////////////////////////////////////////
-
-    global_events.init();
-
-    // Output event stats every 60 seconds
-    global_events.Register( "FGEventMgr::print_stats()",
-                            &global_events, &FGEventMgr::print_stats,
-                            60000 );
-
 
     ////////////////////////////////////////////////////////////////////
     // Initialize the scenery management subsystem.
@@ -1349,10 +1490,10 @@ bool fgInitSubsystems() {
     }
 
     // cause refresh of viewer scenery timestamps every 15 seconds...
-    global_events.Register( "FGTileMgr::refresh_view_timestamps()",
-                            globals->get_tile_mgr(),
-                            &FGTileMgr::refresh_view_timestamps,
-                            15000 );
+    globals->get_event_mgr()->addTask( "FGTileMgr::refresh_view_timestamps()",
+                                       globals->get_tile_mgr(),
+                                       &FGTileMgr::refresh_view_timestamps,
+                                       15 );
 
     SG_LOG( SG_GENERAL, SG_DEBUG,
             "Current terrain elevation after tile mgr init " <<
@@ -1371,36 +1512,17 @@ bool fgInitSubsystems() {
 
 
     ////////////////////////////////////////////////////////////////////
-    // Initialize the view manager subsystem.
+    // Initialize the XML Autopilot subsystem.
     ////////////////////////////////////////////////////////////////////
 
-    fgInitView();
-
+    globals->add_subsystem( "xml-autopilot", new FGXMLAutopilot );
+    globals->add_subsystem( "route-manager", new FGRouteMgr );
 
     ////////////////////////////////////////////////////////////////////
-    // Initialize the lighting subsystem.
+    // Initialize the view manager subsystem.
     ////////////////////////////////////////////////////////////////////
 
-    // fgUpdateSunPos() needs a few position and view parameters set
-    // so it can calculate local relative sun angle and a few other
-    // things for correctly orienting the sky.
-    fgUpdateSunPos();
-    fgUpdateMoonPos();
-    global_events.Register( "fgUpdateSunPos()", &fgUpdateSunPos,
-                            60000);
-    global_events.Register( "fgUpdateMoonPos()", &fgUpdateMoonPos,
-                            60000);
-
-    // Initialize Lighting interpolation tables
-    l->Init();
-
-    // force one lighting update to make it right to start with...
-    l->Update();
-    // update the lighting parameters (based on sun angle)
-    global_events.Register( "fgLight::Update()",
-                            &cur_light_params, &fgLIGHT::Update,
-                            30000 );
-
+    fgInitView();
 
     ////////////////////////////////////////////////////////////////////
     // Create and register the logger.
@@ -1408,21 +1530,11 @@ bool fgInitSubsystems() {
     
     globals->add_subsystem("logger", new FGLogger);
 
-
-#if defined(HAVE_PLIB_PSL)
-    ////////////////////////////////////////////////////////////////////
-    // Create and register the script manager.
-    ////////////////////////////////////////////////////////////////////
-
-    globals->add_subsystem("scripting", new FGScriptMgr);
-#endif // HAVE_PLIB_PSL
-
-
     ////////////////////////////////////////////////////////////////////
     // Create and register the XML GUI.
     ////////////////////////////////////////////////////////////////////
 
-    globals->add_subsystem("gui", new NewGUI, FGSubsystemMgr::INIT);
+    globals->add_subsystem("gui", new NewGUI, SGSubsystemMgr::INIT);
 
 
     ////////////////////////////////////////////////////////////////////
@@ -1430,8 +1542,8 @@ bool fgInitSubsystems() {
     ////////////////////////////////////////////////////////////////////
 
     // update the current timezone each 30 minutes
-    global_events.Register( "fgUpdateLocalTime()", &fgUpdateLocalTime,
-                            30*60*1000 );
+    globals->get_event_mgr()->addTask( "fgUpdateLocalTime()",
+                                       &fgUpdateLocalTime, 30*60 );
 
 
     ////////////////////////////////////////////////////////////////////
@@ -1477,22 +1589,44 @@ bool fgInitSubsystems() {
     WeatherDatabase = FGLocalWeatherDatabase::theFGLocalWeatherDatabase;
 
     // register the periodic update of the weather
-    global_events.Register( "weather update", &fgUpdateWeatherDatabase,
-                            30000);
+    globals->get_event_mgr()->add( "weather update",
+                                   &fgUpdateWeatherDatabase, 30000);
 #else
-    globals->get_environment_mgr()->init();
-    globals->get_environment_mgr()->bind();
+    globals->add_subsystem("environment", new FGEnvironmentMgr);
 #endif
 
+
+    ////////////////////////////////////////////////////////////////////
+    // Initialize the lighting subsystem.
+    ////////////////////////////////////////////////////////////////////
+
+    globals->add_subsystem("lighting", new FGLight);
+
+
 #ifdef FG_USE_CLOUDS_3D
     ////////////////////////////////////////////////////////////////////
     // Initialize the 3D cloud subsystem.
     ////////////////////////////////////////////////////////////////////
     if ( fgGetBool("/sim/rendering/clouds3d") ) {
+        static const SGPropertyNode *longitude
+           = fgGetNode("/sim/presets/longitude-deg");
+        static const SGPropertyNode *latitude
+           = fgGetNode("/sim/presets/latitude-deg");
+        static const SGPropertyNode *altitude
+           = fgGetNode("/sim/presets/altitude-ft");
+
         SGPath cloud_path(globals->get_fg_root());
-        cloud_path.append("large.sky");
+#if 0
+        cloud_path.append("Textures/Sky/scattered.rgba");
         SG_LOG(SG_GENERAL, SG_INFO, "Loading CLOUDS3d from: " << cloud_path.c_str());
+
+        SGTexture tx;
+        tx.read_rgba_texture(cloud_path.c_str());
+        if ( !sgCloud3d->Load( tx.texture(), tx.width(),
+#else
+        cloud_path.append("large.sky");
         if ( !sgCloud3d->Load( cloud_path.str(),
+#endif
                                latitude->getDoubleValue(),
                                longitude->getDoubleValue()) )
         {
@@ -1523,18 +1657,25 @@ bool fgInitSubsystems() {
     // Initialise the AI Manager 
     ////////////////////////////////////////////////////////////////////
 
-    if (fgGetBool("/sim/ai-traffic/enabled")) {
-        SG_LOG(SG_GENERAL, SG_INFO, "  AI Manager");
-        globals->set_AI_mgr(new FGAIMgr);
-        globals->get_AI_mgr()->init();
-    }
+    SG_LOG(SG_GENERAL, SG_INFO, "  AI Manager");
+    globals->set_AI_mgr(new FGAIMgr);
+    globals->get_AI_mgr()->init();
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Initialise the AI Model Manager
+    ////////////////////////////////////////////////////////////////////
+
+    SG_LOG(SG_GENERAL, SG_INFO, "  AI Model Manager");
+    globals->add_subsystem("ai_model", new FGAIManager);
+
 
 #ifdef ENABLE_AUDIO_SUPPORT
     ////////////////////////////////////////////////////////////////////
     // Initialize the sound subsystem.
     ////////////////////////////////////////////////////////////////////
 
-    globals->set_soundmgr(new FGSoundMgr);
+    globals->set_soundmgr(new SGSoundMgr);
     globals->get_soundmgr()->init();
     globals->get_soundmgr()->bind();
 
@@ -1575,13 +1716,9 @@ bool fgInitSubsystems() {
     // Initialize the autopilot subsystem.
     ////////////////////////////////////////////////////////////////////
 
-    globals->set_autopilot(new FGAutopilot);
-    globals->get_autopilot()->init();
-    globals->get_autopilot()->bind();
-
                                 // FIXME: these should go in the
                                 // GUI initialization code, not here.
-    fgAPAdjustInit();
+    // fgAPAdjustInit();
     NewTgtAirportInit();
     NewHeadingInit();
     NewAltitudeInit();
@@ -1593,27 +1730,25 @@ bool fgInitSubsystems() {
     globals->get_io()->init();
     globals->get_io()->bind();
 
-    // Initialize the 2D panel.
+
+    ////////////////////////////////////////////////////////////////////
+    // Add a new 2D panel.
+    ////////////////////////////////////////////////////////////////////
+
     string panel_path = fgGetString("/sim/panel/path",
                                     "Panels/Default/default.xml");
-    current_panel = fgReadPanel(panel_path);
-    if (current_panel == 0) {
+
+    globals->set_current_panel( fgReadPanel(panel_path) );
+    if (globals->get_current_panel() == 0) {
         SG_LOG( SG_INPUT, SG_ALERT, 
                 "Error reading new panel from " << panel_path );
     } else {
         SG_LOG( SG_INPUT, SG_INFO, "Loaded new panel from " << panel_path );
-        current_panel->init();
-        current_panel->bind();
+        globals->get_current_panel()->init();
+        globals->get_current_panel()->bind();
     }
 
     
-    ////////////////////////////////////////////////////////////////////
-    // Initialize the default (kludged) properties.
-    ////////////////////////////////////////////////////////////////////
-
-    fgInitProps();
-
-
     ////////////////////////////////////////////////////////////////////
     // Initialize the controls subsystem.
     ////////////////////////////////////////////////////////////////////
@@ -1629,6 +1764,11 @@ bool fgInitSubsystems() {
     globals->add_subsystem("input", new FGInput);
 
 
+    ////////////////////////////////////////////////////////////////////
+    // Initialize the replay subsystem
+    ////////////////////////////////////////////////////////////////////
+    globals->add_subsystem("replay", new FGReplay);
+
     ////////////////////////////////////////////////////////////////////
     // Bind and initialize subsystems.
     ////////////////////////////////////////////////////////////////////
@@ -1636,7 +1776,6 @@ bool fgInitSubsystems() {
     globals->get_subsystem_mgr()->bind();
     globals->get_subsystem_mgr()->init();
 
-
 #ifdef FG_MPLAYER_AS
     ////////////////////////////////////////////////////////////////////
     // Initialize multiplayer subsystem
@@ -1649,6 +1788,14 @@ bool fgInitSubsystems() {
     globals->get_multiplayer_rx_mgr()->init();
 #endif
 
+    ////////////////////////////////////////////////////////////////////////
+    // Initialize the Nasal interpreter.
+    // Do this last, so that the loaded scripts see initialized state
+    ////////////////////////////////////////////////////////////////////////
+    FGNasalSys* nasal = new FGNasalSys();
+    globals->add_subsystem("nasal", nasal);
+    nasal->init();
+
     ////////////////////////////////////////////////////////////////////////
     // End of subsystem initialization.
     ////////////////////////////////////////////////////////////////////
@@ -1665,10 +1812,10 @@ bool fgInitSubsystems() {
 
 void fgReInitSubsystems()
 {
-    static const SGPropertyNode *longitude
-        = fgGetNode("/sim/presets/longitude-deg");
-    static const SGPropertyNode *latitude
-        = fgGetNode("/sim/presets/latitude-deg");
+    // static const SGPropertyNode *longitude
+    //     = fgGetNode("/sim/presets/longitude-deg");
+    // static const SGPropertyNode *latitude
+    //     = fgGetNode("/sim/presets/latitude-deg");
     static const SGPropertyNode *altitude
         = fgGetNode("/sim/presets/altitude-ft");
     static const SGPropertyNode *master_freeze
@@ -1682,6 +1829,7 @@ void fgReInitSubsystems()
     if ( !freeze ) {
         fgSetBool("/sim/freeze/master", true);
     }
+    fgSetBool("/sim/crashed", false);
 
     // Initialize the FDM
     fgInitFDM();
@@ -1696,13 +1844,12 @@ void fgReInitSubsystems()
     fgInitView();
 
     globals->get_controls()->reset_all();
-    globals->get_autopilot()->reset();
 
-    fgUpdateSunPos();
-    fgUpdateMoonPos();
-    cur_light_params.Update();
     fgUpdateLocalTime();
 
+    // re-init to proper time of day setting
+    fgInitTimeOffset();
+
     if ( !freeze ) {
         fgSetBool("/sim/freeze/master", false);
     }