1999-06-18 03:42:54 +00:00
|
|
|
// main.cxx -- top level sim routines
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
2002-04-05 00:38:55 +00:00
|
|
|
// Written by Curtis Olson, started May 1997.
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
2004-11-19 22:10:41 +00:00
|
|
|
// Copyright (C) 1997 - 2002 Curtis L. Olson - http://www.flightgear.org/~curt
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
|
|
|
// This program is free software; you can redistribute it and/or
|
|
|
|
// modify it under the terms of the GNU General Public License as
|
|
|
|
// published by the Free Software Foundation; either version 2 of the
|
|
|
|
// License, or (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful, but
|
|
|
|
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
// General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
|
// along with this program; if not, write to the Free Software
|
2006-02-21 01:16:04 +00:00
|
|
|
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
1998-04-21 17:02:27 +00:00
|
|
|
//
|
|
|
|
// $Id$
|
|
|
|
|
1999-06-18 03:42:54 +00:00
|
|
|
|
1998-04-24 00:49:17 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
1998-04-21 17:02:27 +00:00
|
|
|
|
2003-08-17 09:54:41 +00:00
|
|
|
#include <simgear/compiler.h>
|
2016-03-19 12:10:36 +00:00
|
|
|
#include <simgear/props/props_io.hxx>
|
2003-08-17 09:54:41 +00:00
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
#include <osg/Camera>
|
|
|
|
#include <osg/GraphicsContext>
|
2008-03-22 09:31:06 +00:00
|
|
|
#include <osgDB/Registry>
|
|
|
|
|
2014-01-18 14:50:31 +00:00
|
|
|
#if defined(HAVE_CRASHRPT)
|
|
|
|
#include <CrashRpt.h>
|
2014-01-22 22:33:30 +00:00
|
|
|
|
|
|
|
// defined in bootstrap.cxx
|
|
|
|
extern bool global_crashRptEnabled;
|
|
|
|
|
2014-01-18 14:50:31 +00:00
|
|
|
#endif
|
|
|
|
|
2005-03-09 21:56:00 +00:00
|
|
|
// Class references
|
2012-10-31 00:40:43 +00:00
|
|
|
#include <simgear/canvas/VGInitOperation.hxx>
|
2003-05-15 21:35:51 +00:00
|
|
|
#include <simgear/scene/model/modellib.hxx>
|
2004-09-20 13:21:51 +00:00
|
|
|
#include <simgear/scene/material/matlib.hxx>
|
2013-12-09 23:25:04 +00:00
|
|
|
#include <simgear/scene/material/Effect.hxx>
|
2009-11-03 11:41:00 +00:00
|
|
|
#include <simgear/props/AtomicChangeListener.hxx>
|
2008-07-31 12:04:32 +00:00
|
|
|
#include <simgear/props/props.hxx>
|
2010-12-26 23:19:57 +00:00
|
|
|
#include <simgear/timing/sg_time.hxx>
|
2010-10-23 19:37:26 +00:00
|
|
|
#include <simgear/io/raw_socket.hxx>
|
2011-06-11 22:44:07 +00:00
|
|
|
#include <simgear/scene/tsync/terrasync.hxx>
|
2012-05-12 21:27:57 +00:00
|
|
|
#include <simgear/math/SGMath.hxx>
|
|
|
|
#include <simgear/math/sg_random.h>
|
2014-01-27 17:27:12 +00:00
|
|
|
#include <simgear/misc/strutils.hxx>
|
2008-07-31 12:04:32 +00:00
|
|
|
|
2003-08-17 09:54:41 +00:00
|
|
|
#include <Model/panelnode.hxx>
|
|
|
|
#include <Scenery/scenery.hxx>
|
2012-09-17 11:36:38 +00:00
|
|
|
#include <Sound/soundmanager.hxx>
|
2010-07-13 20:50:44 +00:00
|
|
|
#include <Time/TimeManager.hxx>
|
2010-12-26 23:19:57 +00:00
|
|
|
#include <GUI/gui.h>
|
2014-01-27 17:27:12 +00:00
|
|
|
#include <GUI/MessageBox.hxx>
|
2012-04-25 21:28:00 +00:00
|
|
|
#include <Viewer/splash.hxx>
|
|
|
|
#include <Viewer/renderer.hxx>
|
2012-10-31 00:40:43 +00:00
|
|
|
#include <Viewer/WindowSystemAdapter.hxx>
|
2012-08-27 23:26:36 +00:00
|
|
|
#include <Navaids/NavDataCache.hxx>
|
2014-01-20 21:54:06 +00:00
|
|
|
#include <Include/version.h>
|
2004-09-20 13:21:51 +00:00
|
|
|
|
Andy Ross:
The biggest and coolest patch adds mouse sensitivity to the 3D
cockpits, so we can finally work the radios. This ended up requiring
significant modifications outside of the 3D cockpit code. Stuff folks
will want to look at:
+ The list of all "3D" cockpits is stored statically in the
panelnode.cxx file. This is clumsy, and won't migrate well to a
multiple-aircraft feature. Really, there should be a per-model list
of 3D panels, but I couldn't find a clean place to put this. The
only handle you get back after parsing a model is a generic ssg
node, to which I obviously can't add panel-specific methods.
+ The aircraft model is parsed *very* early in the initialization
order. Earlier, in fact, than the static list of allowable command
bindings is built in fgInitCommands(). This is bad, as it means
that mouse bindings on the instruments can't work yet. I moved the
call to fgInitCommands, but someone should look carefully to see
that I picked the right place. There's a lot of initialization
code, and I got a little lost in there... :)
+ I added yet another "update" hook to the fgRenderFrame routine to
hook the updates for the 3D panels. This is only required for
"mouse press delay", and it's a fairly clumsy mechanism based on
frame rate instead of real time. There appears to be delay handling
already in place in the Input stuff, and there's a discussion going
on about different mouse behavior right now. Maybe this is a good
time to unify these two (now three) approaches?
2002-10-29 19:44:03 +00:00
|
|
|
#include "fg_commands.hxx"
|
2003-08-17 09:54:41 +00:00
|
|
|
#include "fg_io.hxx"
|
2003-08-29 16:46:21 +00:00
|
|
|
#include "main.hxx"
|
2008-07-11 16:36:54 +00:00
|
|
|
#include "util.hxx"
|
2008-07-29 08:27:48 +00:00
|
|
|
#include "fg_init.hxx"
|
2009-08-05 14:29:32 +00:00
|
|
|
#include "fg_os.hxx"
|
2012-04-25 21:28:00 +00:00
|
|
|
#include "fg_props.hxx"
|
2012-09-18 19:50:28 +00:00
|
|
|
#include "positioninit.hxx"
|
2013-12-09 00:13:44 +00:00
|
|
|
#include "screensaver_control.hxx"
|
2012-09-30 15:34:51 +00:00
|
|
|
#include "subsystemFactory.hxx"
|
2013-10-15 21:16:50 +00:00
|
|
|
#include "options.hxx"
|
2003-08-29 16:46:21 +00:00
|
|
|
|
2014-12-26 12:20:51 +00:00
|
|
|
#if defined(HAVE_QT)
|
|
|
|
#include <GUI/QtLauncher.hxx>
|
|
|
|
#endif
|
2013-12-09 00:13:44 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
using namespace flightgear;
|
|
|
|
|
2008-08-14 18:13:39 +00:00
|
|
|
using std::cerr;
|
2012-05-12 21:27:57 +00:00
|
|
|
using std::vector;
|
2008-08-14 18:13:39 +00:00
|
|
|
|
2006-08-07 15:16:46 +00:00
|
|
|
// The atexit() function handler should know when the graphical subsystem
|
2004-08-24 08:40:41 +00:00
|
|
|
// is initialized.
|
|
|
|
extern int _bootstrap_OSInit;
|
|
|
|
|
2012-11-18 15:35:54 +00:00
|
|
|
static SGPropertyNode_ptr frame_signal;
|
2012-11-18 16:20:11 +00:00
|
|
|
static TimeManager* timeMgr;
|
2012-11-18 15:35:54 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
// What should we do when we have nothing else to do? Let's get ready
|
|
|
|
// for the next move and update the display?
|
|
|
|
static void fgMainLoop( void )
|
2010-01-10 11:00:52 +00:00
|
|
|
{
|
2016-07-20 13:03:15 +00:00
|
|
|
|
|
|
|
if (sglog().has_popup()) {
|
|
|
|
std::string s = sglog().get_popup();
|
2016-07-21 06:56:05 +00:00
|
|
|
flightgear::modalMessageBox("Alert", s, "");
|
2016-07-20 13:03:15 +00:00
|
|
|
}
|
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
frame_signal->fireValueChanged();
|
2010-01-10 11:00:52 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
// compute simulated time (allowing for pause, warp, etc) and
|
|
|
|
// real elapsed time
|
|
|
|
double sim_dt, real_dt;
|
|
|
|
timeMgr->computeTimeDeltas(sim_dt, real_dt);
|
|
|
|
|
|
|
|
// update all subsystems
|
|
|
|
globals->get_subsystem_mgr()->update(sim_dt);
|
|
|
|
|
|
|
|
simgear::AtomicChangeListener::fireChangeListeners();
|
2009-11-30 14:24:16 +00:00
|
|
|
}
|
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
static void initTerrasync()
|
|
|
|
{
|
2014-01-15 22:01:02 +00:00
|
|
|
// add the terrasync root as a data path so data can be retrieved from it
|
|
|
|
// (even if we are in read-only mode)
|
2016-10-18 21:10:09 +00:00
|
|
|
SGPath terraSyncDir(globals->get_terrasync_dir());
|
2014-01-15 22:01:02 +00:00
|
|
|
globals->append_data_path(terraSyncDir);
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
if (fgGetBool("/sim/fghome-readonly", false)) {
|
|
|
|
return;
|
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
// start TerraSync up now, so it can be synchronizing shared models
|
|
|
|
// and airports data in parallel with a nav-cache rebuild.
|
2015-03-17 22:10:49 +00:00
|
|
|
SGPath tsyncCache(terraSyncDir);
|
2013-11-14 16:48:14 +00:00
|
|
|
tsyncCache.append("terrasync-cache.xml");
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
// wipe the cache file if requested
|
|
|
|
if (flightgear::Options::sharedInstance()->isOptionSet("restore-defaults")) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "restore-defaults requested, wiping terrasync update cache at " <<
|
|
|
|
tsyncCache);
|
|
|
|
if (tsyncCache.exists()) {
|
|
|
|
tsyncCache.remove();
|
|
|
|
}
|
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2016-06-23 13:26:34 +00:00
|
|
|
fgSetString("/sim/terrasync/cache-path", tsyncCache.utf8Str());
|
2016-08-18 15:23:39 +00:00
|
|
|
|
|
|
|
// make fg-root dir available so existing Scenery data can be copied, and
|
|
|
|
// hence not downloaded again.
|
|
|
|
fgSetString("/sim/terrasync/installation-dir", (globals->get_fg_root() / "Scenery").utf8Str());
|
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
simgear::SGTerraSync* terra_sync = new simgear::SGTerraSync();
|
|
|
|
terra_sync->setRoot(globals->get_props());
|
|
|
|
globals->add_subsystem("terrasync", terra_sync);
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
terra_sync->bind();
|
|
|
|
terra_sync->init();
|
|
|
|
}
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2016-03-19 12:10:36 +00:00
|
|
|
static void fgSetVideoOptions()
|
|
|
|
{
|
|
|
|
std::string vendor = fgGetString("/sim/rendering/gl-vendor");
|
|
|
|
SGPath path(globals->get_fg_root());
|
|
|
|
path.append("Video");
|
|
|
|
path.append(vendor);
|
|
|
|
if (path.exists())
|
|
|
|
{
|
|
|
|
std::string renderer = fgGetString("/sim/rendering/gl-renderer");
|
2016-03-21 10:50:11 +00:00
|
|
|
size_t pos = renderer.find("x86/");
|
|
|
|
if (pos == std::string::npos) {
|
|
|
|
pos = renderer.find('/');
|
|
|
|
}
|
2016-03-19 12:10:36 +00:00
|
|
|
if (pos == std::string::npos) {
|
|
|
|
pos = renderer.find(" (");
|
|
|
|
}
|
|
|
|
if (pos != std::string::npos) {
|
|
|
|
renderer = renderer.substr(0, pos);
|
|
|
|
}
|
|
|
|
path.append(renderer+".xml");
|
|
|
|
if (path.exists()) {
|
2016-06-23 13:26:34 +00:00
|
|
|
SG_LOG(SG_INPUT, SG_INFO, "Reading video settings from " << path);
|
2016-03-19 12:10:36 +00:00
|
|
|
try {
|
|
|
|
SGPropertyNode *r_prop = fgGetNode("/sim/rendering");
|
2016-06-23 13:26:34 +00:00
|
|
|
readProperties(path, r_prop);
|
2016-03-19 12:10:36 +00:00
|
|
|
} catch (sg_exception& e) {
|
|
|
|
SG_LOG(SG_INPUT, SG_WARN, "failed to read video settings:" << e.getMessage()
|
|
|
|
<< "(from " << e.getOrigin() << ")");
|
|
|
|
}
|
2016-03-21 10:50:11 +00:00
|
|
|
|
|
|
|
flightgear::Options* options = flightgear::Options::sharedInstance();
|
2016-11-01 13:04:36 +00:00
|
|
|
if (!options->isOptionSet("ignore-autosave")) {
|
|
|
|
globals->loadUserSettings();
|
2016-03-21 10:50:11 +00:00
|
|
|
}
|
2016-03-19 12:10:36 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-01-27 17:27:12 +00:00
|
|
|
static void checkOpenGLVersion()
|
|
|
|
{
|
|
|
|
#if defined(SG_MAC)
|
|
|
|
// Mac users can't upgrade their drivers, so complaining about
|
|
|
|
// versions doesn't help them much
|
|
|
|
return;
|
|
|
|
#endif
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2014-01-27 17:27:12 +00:00
|
|
|
// format of these strings is not standardised, so be careful about
|
|
|
|
// parsing them.
|
|
|
|
std::string versionString(fgGetString("/sim/rendering/gl-version"));
|
|
|
|
string_list parts = simgear::strutils::split(versionString);
|
|
|
|
if (parts.size() == 3) {
|
|
|
|
if (parts[1].find("NVIDIA") != std::string::npos) {
|
|
|
|
// driver version number, dot-seperared
|
|
|
|
string_list driverVersion = simgear::strutils::split(parts[2], ".");
|
|
|
|
if (!driverVersion.empty()) {
|
|
|
|
int majorDriverVersion = simgear::strutils::to_int(driverVersion[0]);
|
|
|
|
if (majorDriverVersion < 300) {
|
|
|
|
std::ostringstream ss;
|
|
|
|
ss << "Please upgrade to at least version 300 of the nVidia drivers (installed version is " << parts[2] << ")";
|
|
|
|
|
|
|
|
flightgear::modalMessageBox("Outdated graphics drivers",
|
|
|
|
"FlightGear has detected outdated drivers for your graphics card.",
|
|
|
|
ss.str());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} // of NVIDIA-style version string
|
|
|
|
} // of three parts
|
|
|
|
}
|
|
|
|
|
2012-11-18 16:20:11 +00:00
|
|
|
static void registerMainLoop()
|
|
|
|
{
|
|
|
|
// stash current frame signal property
|
|
|
|
frame_signal = fgGetNode("/sim/signals/frame", true);
|
|
|
|
timeMgr = (TimeManager*) globals->get_subsystem("time");
|
|
|
|
fgRegisterIdleHandler( fgMainLoop );
|
|
|
|
}
|
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
// This is the top level master main function that is registered as
|
2011-05-22 16:28:42 +00:00
|
|
|
// our idle function
|
2007-04-29 09:58:37 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
// The first few passes take care of initialization things (a couple
|
|
|
|
// per pass) and once everything has been initialized fgMainLoop from
|
|
|
|
// then on.
|
2007-04-29 09:58:37 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
static int idle_state = 0;
|
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
static void fgIdleFunction ( void ) {
|
2012-09-17 11:41:42 +00:00
|
|
|
// Specify our current idle function state. This is used to run all
|
|
|
|
// our initializations out of the idle callback so that we can get a
|
|
|
|
// splash screen up and running right away.
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
if ( idle_state == 0 ) {
|
2012-09-25 20:39:13 +00:00
|
|
|
if (guiInit())
|
|
|
|
{
|
2014-01-27 17:27:12 +00:00
|
|
|
checkOpenGLVersion();
|
2016-03-19 12:10:36 +00:00
|
|
|
fgSetVideoOptions();
|
2012-09-25 20:39:13 +00:00
|
|
|
idle_state+=2;
|
|
|
|
fgSplashProgress("loading-aircraft-list");
|
2016-07-21 11:55:31 +00:00
|
|
|
fgSetBool("/sim/rendering/initialized", true);
|
2008-08-01 15:57:29 +00:00
|
|
|
}
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 2 ) {
|
2013-11-14 16:48:14 +00:00
|
|
|
initTerrasync();
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2012-09-26 12:38:26 +00:00
|
|
|
fgSplashProgress("loading-nav-dat");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 3 ) {
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2012-09-25 16:24:12 +00:00
|
|
|
bool done = fgInitNav();
|
|
|
|
if (done) {
|
|
|
|
++idle_state;
|
|
|
|
fgSplashProgress("init-scenery");
|
|
|
|
}
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 4 ) {
|
2013-11-16 12:10:32 +00:00
|
|
|
idle_state++;
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2010-07-13 20:50:44 +00:00
|
|
|
TimeManager* t = new TimeManager;
|
|
|
|
globals->add_subsystem("time", t, SGSubsystemMgr::INIT);
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
// Do some quick general initializations
|
|
|
|
if( !fgInitGeneral()) {
|
2013-10-15 21:16:50 +00:00
|
|
|
throw sg_exception("General initialization failed");
|
2005-05-04 21:28:42 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the property-based built-in commands
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
fgInitCommands();
|
2017-03-21 20:59:35 +00:00
|
|
|
fgInitSceneCommands();
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2012-09-30 15:34:51 +00:00
|
|
|
flightgear::registerSubsystemCommands(globals->get_commands());
|
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the material manager
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->set_matlib( new SGMaterialLib );
|
2012-01-02 23:16:18 +00:00
|
|
|
simgear::SGModelLib::setPanelFunc(FGPanelNode::load);
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
} else if (( idle_state == 5 ) || (idle_state == 2005)) {
|
|
|
|
idle_state+=2;
|
|
|
|
flightgear::initPosition();
|
|
|
|
flightgear::initTowerLocationListener();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2016-06-21 11:29:04 +00:00
|
|
|
simgear::SGModelLib::init(globals->get_fg_root().local8BitStr(), globals->get_props());
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
TimeManager* timeManager = (TimeManager*) globals->get_subsystem("time");
|
|
|
|
timeManager->init();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the TG scenery subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2015-12-10 22:48:02 +00:00
|
|
|
globals->add_new_subsystem<FGScenery>(SGSubsystemMgr::DISPLAY);
|
2005-05-04 21:28:42 +00:00
|
|
|
globals->get_scenery()->init();
|
|
|
|
globals->get_scenery()->bind();
|
2016-07-30 12:26:45 +00:00
|
|
|
|
2012-09-21 17:36:25 +00:00
|
|
|
fgSplashProgress("creating-subsystems");
|
2013-11-16 12:10:32 +00:00
|
|
|
} else if (( idle_state == 7 ) || (idle_state == 2007)) {
|
|
|
|
bool isReset = (idle_state == 2007);
|
|
|
|
idle_state = 8; // from the next state on, reset & startup are identical
|
2012-09-18 19:29:36 +00:00
|
|
|
SGTimeStamp st;
|
|
|
|
st.stamp();
|
2013-11-16 12:10:32 +00:00
|
|
|
fgCreateSubsystems(isReset);
|
2012-09-18 19:29:36 +00:00
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Creating subsystems took:" << st.elapsedMSec());
|
2012-09-21 17:36:25 +00:00
|
|
|
fgSplashProgress("binding-subsystems");
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2012-09-18 19:29:36 +00:00
|
|
|
} else if ( idle_state == 8 ) {
|
|
|
|
idle_state++;
|
|
|
|
SGTimeStamp st;
|
|
|
|
st.stamp();
|
|
|
|
globals->get_subsystem_mgr()->bind();
|
|
|
|
SG_LOG(SG_GENERAL, SG_INFO, "Binding subsystems took:" << st.elapsedMSec());
|
|
|
|
|
2012-09-21 17:36:25 +00:00
|
|
|
fgSplashProgress("init-subsystems");
|
2012-09-18 19:29:36 +00:00
|
|
|
} else if ( idle_state == 9 ) {
|
|
|
|
SGSubsystem::InitStatus status = globals->get_subsystem_mgr()->incrementalInit();
|
|
|
|
if ( status == SGSubsystem::INIT_DONE) {
|
|
|
|
++idle_state;
|
2012-09-21 17:36:25 +00:00
|
|
|
fgSplashProgress("finishing-subsystems");
|
2012-09-18 19:29:36 +00:00
|
|
|
} else {
|
2012-09-21 17:36:25 +00:00
|
|
|
fgSplashProgress("init-subsystems");
|
2003-04-15 14:10:47 +00:00
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2012-09-18 19:29:36 +00:00
|
|
|
} else if ( idle_state == 10 ) {
|
2012-12-15 15:25:45 +00:00
|
|
|
idle_state = 900;
|
2012-09-18 19:29:36 +00:00
|
|
|
fgPostInitSubsystems();
|
2012-12-15 15:25:45 +00:00
|
|
|
fgSplashProgress("finalize-position");
|
2012-09-18 19:29:36 +00:00
|
|
|
} else if ( idle_state == 900 ) {
|
2005-05-06 09:08:44 +00:00
|
|
|
idle_state = 1000;
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2003-04-15 14:10:47 +00:00
|
|
|
// setup OpenGL view parameters
|
2011-05-22 16:28:42 +00:00
|
|
|
globals->get_renderer()->setupView();
|
1998-07-06 02:42:02 +00:00
|
|
|
|
2004-09-20 13:21:51 +00:00
|
|
|
globals->get_renderer()->resize( fgGetInt("/sim/startup/xsize"),
|
|
|
|
fgGetInt("/sim/startup/ysize") );
|
2012-10-31 00:40:43 +00:00
|
|
|
WindowSystemAdapter::getWSA()->windows[0]->gc->add(
|
|
|
|
new simgear::canvas::VGInitOperation()
|
|
|
|
);
|
2003-09-17 10:02:36 +00:00
|
|
|
|
2009-10-24 09:22:20 +00:00
|
|
|
int session = fgGetInt("/sim/session",0);
|
|
|
|
session++;
|
|
|
|
fgSetInt("/sim/session",session);
|
2005-05-04 21:28:42 +00:00
|
|
|
}
|
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
if ( idle_state == 1000 ) {
|
2017-01-29 15:18:10 +00:00
|
|
|
sglog().setStartupLoggingEnabled(false);
|
|
|
|
|
2003-04-15 14:10:47 +00:00
|
|
|
// We've finished all our initialization steps, from now on we
|
|
|
|
// run the main loop.
|
2005-05-06 09:08:44 +00:00
|
|
|
fgSetBool("sim/sceneryloaded", false);
|
2012-11-18 16:20:11 +00:00
|
|
|
registerMainLoop();
|
1998-07-06 02:42:02 +00:00
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
if ( idle_state == 2000 ) {
|
|
|
|
fgStartNewReset();
|
|
|
|
idle_state = 2005;
|
|
|
|
}
|
1998-07-06 02:42:02 +00:00
|
|
|
}
|
|
|
|
|
2013-11-16 12:10:32 +00:00
|
|
|
void fgResetIdleState()
|
|
|
|
{
|
|
|
|
idle_state = 2000;
|
|
|
|
fgRegisterIdleHandler( &fgIdleFunction );
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2006-03-10 11:46:03 +00:00
|
|
|
static void upper_case_property(const char *name)
|
|
|
|
{
|
2009-07-17 12:54:12 +00:00
|
|
|
using namespace simgear;
|
2006-03-10 11:46:03 +00:00
|
|
|
SGPropertyNode *p = fgGetNode(name, false);
|
|
|
|
if (!p) {
|
|
|
|
p = fgGetNode(name, true);
|
|
|
|
p->setStringValue("");
|
|
|
|
} else {
|
2009-07-17 12:54:12 +00:00
|
|
|
props::Type t = p->getType();
|
|
|
|
if (t == props::NONE || t == props::UNSPECIFIED)
|
2006-03-10 11:46:03 +00:00
|
|
|
p->setStringValue("");
|
|
|
|
else
|
2009-07-17 12:54:12 +00:00
|
|
|
assert(t == props::STRING);
|
2006-03-10 11:46:03 +00:00
|
|
|
}
|
2013-12-04 09:11:26 +00:00
|
|
|
SGPropertyChangeListener* muc = new FGMakeUpperCase;
|
|
|
|
globals->addListenerToCleanup(muc);
|
|
|
|
p->addChangeListener(muc);
|
2006-03-10 11:46:03 +00:00
|
|
|
}
|
|
|
|
|
2017-04-12 10:13:14 +00:00
|
|
|
// this hack is needed to avoid weird viewport sizing within OSG on Windows.
|
|
|
|
// still required as of March 2017, sad times.
|
|
|
|
// see for example https://sourceforge.net/p/flightgear/codetickets/1958/
|
|
|
|
static void ATIScreenSizeHack()
|
|
|
|
{
|
|
|
|
osg::ref_ptr<osg::Camera> hackCam = new osg::Camera;
|
|
|
|
hackCam->setRenderOrder(osg::Camera::PRE_RENDER);
|
|
|
|
int prettyMuchAnyInt = 1;
|
|
|
|
hackCam->setViewport(0, 0, prettyMuchAnyInt, prettyMuchAnyInt);
|
|
|
|
globals->get_renderer()->addCamera(hackCam, false);
|
|
|
|
}
|
|
|
|
|
2016-09-27 22:16:46 +00:00
|
|
|
// Propose NVIDIA Optimus / AMD Xpress to use high-end GPU
|
2013-07-15 19:47:14 +00:00
|
|
|
#if defined(SG_WINDOWS)
|
|
|
|
extern "C" {
|
|
|
|
_declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
2016-09-27 22:16:46 +00:00
|
|
|
_declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
|
2013-07-15 19:47:14 +00:00
|
|
|
}
|
|
|
|
#endif
|
2013-02-08 11:43:51 +00:00
|
|
|
|
2017-01-29 15:18:10 +00:00
|
|
|
static void logToHome()
|
2013-02-08 11:43:51 +00:00
|
|
|
{
|
|
|
|
SGPath logPath = globals->get_fg_home();
|
|
|
|
logPath.append("fgfs.log");
|
|
|
|
if (logPath.exists()) {
|
|
|
|
SGPath prevLogPath = globals->get_fg_home();
|
|
|
|
prevLogPath.append("fgfs_0.log");
|
|
|
|
logPath.rename(prevLogPath);
|
|
|
|
// bit strange, we need to restore the correct value of logPath now
|
|
|
|
logPath = globals->get_fg_home();
|
|
|
|
logPath.append("fgfs.log");
|
|
|
|
}
|
|
|
|
sglog().logToFile(logPath, SG_ALL, SG_INFO);
|
2014-01-18 14:50:31 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_CRASHRPT)
|
2014-01-22 22:33:30 +00:00
|
|
|
if (global_crashRptEnabled) {
|
|
|
|
crAddFile2(logPath.c_str(), NULL, "FlightGear Log File", CR_AF_MAKE_FILE_COPY);
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "CrashRpt enabled");
|
|
|
|
} else {
|
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "CrashRpt enabled at compile time but failed to install");
|
|
|
|
}
|
2014-01-18 14:50:31 +00:00
|
|
|
#endif
|
2013-02-08 11:43:51 +00:00
|
|
|
}
|
|
|
|
|
2002-11-16 20:17:11 +00:00
|
|
|
// Main top level initialization
|
2014-12-26 12:20:51 +00:00
|
|
|
int fgMainInit( int argc, char **argv )
|
|
|
|
{
|
2017-01-29 15:18:10 +00:00
|
|
|
// set default log level to 'info' for startup, we will revert to a lower
|
|
|
|
// level once startup is done.
|
|
|
|
sglog().setLogLevels( SG_ALL, SG_INFO );
|
|
|
|
sglog().setStartupLoggingEnabled(true);
|
1998-11-16 13:59:58 +00:00
|
|
|
|
2013-02-08 11:43:51 +00:00
|
|
|
globals = new FGGlobals;
|
2013-11-14 16:48:14 +00:00
|
|
|
if (!fgInitHome()) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-14 16:48:14 +00:00
|
|
|
if (!fgGetBool("/sim/fghome-readonly")) {
|
|
|
|
// now home is initialised, we can log to a file inside it
|
2017-01-29 15:18:10 +00:00
|
|
|
logToHome();
|
2013-11-14 16:48:14 +00:00
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2015-06-07 19:08:03 +00:00
|
|
|
std::string version(FLIGHTGEAR_VERSION);
|
2001-03-24 06:03:11 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "FlightGear: Version "
|
2003-04-15 14:10:47 +00:00
|
|
|
<< version );
|
2017-02-27 23:15:07 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "FlightGear: Build Type " << FG_BUILD_TYPE );
|
2014-01-20 21:54:06 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Built with " << SG_COMPILER_STR);
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Jenkins number/ID " << HUDSON_BUILD_NUMBER << ":"
|
|
|
|
<< HUDSON_BUILD_ID);
|
1998-11-20 01:02:35 +00:00
|
|
|
|
2006-08-07 15:16:46 +00:00
|
|
|
// seed the random number generator
|
2001-01-13 22:06:39 +00:00
|
|
|
sg_srandom_time();
|
|
|
|
|
2001-01-26 00:21:36 +00:00
|
|
|
string_list *col = new string_list;
|
|
|
|
globals->set_channel_options_list( col );
|
|
|
|
|
2015-07-13 22:15:36 +00:00
|
|
|
fgValidatePath(globals->get_fg_home(), false); // initialize static variables
|
2006-03-10 11:46:03 +00:00
|
|
|
upper_case_property("/sim/presets/airport-id");
|
|
|
|
upper_case_property("/sim/presets/runway");
|
|
|
|
upper_case_property("/sim/tower/airport-id");
|
2008-06-06 07:49:41 +00:00
|
|
|
upper_case_property("/autopilot/route-manager/input");
|
2006-03-10 11:46:03 +00:00
|
|
|
|
2016-09-08 10:41:40 +00:00
|
|
|
// check if the launcher is reuested, since it affects config file parsing
|
|
|
|
bool showLauncher = flightgear::Options::checkForArg(argc, argv, "launcher");
|
|
|
|
// an Info.plist bundle can't define command line arguments, but it can set
|
|
|
|
// environment variables. This avoids needed a wrapper shell-script on OS-X.
|
|
|
|
showLauncher |= (::getenv("FG_LAUNCHER") != 0);
|
|
|
|
if (showLauncher) {
|
|
|
|
// to minimise strange interactions when launcher and config files
|
|
|
|
// set overlaping options, we disable the default files. Users can
|
|
|
|
// still explicitly request config files via --config options if they choose.
|
|
|
|
flightgear::Options::sharedInstance()->setShouldLoadDefaultConfig(false);
|
|
|
|
}
|
|
|
|
|
2002-11-16 20:17:11 +00:00
|
|
|
// Load the configuration parameters. (Command line options
|
2006-08-07 15:16:46 +00:00
|
|
|
// override config file options. Config file options override
|
2002-11-16 20:17:11 +00:00
|
|
|
// defaults.)
|
2013-11-16 12:10:32 +00:00
|
|
|
int configResult = fgInitConfig(argc, argv, false);
|
2013-10-15 21:16:50 +00:00
|
|
|
if (configResult == flightgear::FG_OPTIONS_ERROR) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (configResult == flightgear::FG_OPTIONS_EXIT) {
|
|
|
|
return EXIT_SUCCESS;
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
2014-12-26 12:20:51 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_QT)
|
2015-03-06 18:52:06 +00:00
|
|
|
if (showLauncher) {
|
2015-11-30 23:10:32 +00:00
|
|
|
flightgear::initApp(argc, argv);
|
Split flightgear::initApp() to make it usable even without FGGlobals initialized
- Add an optional argument to flightgear::initApp(): doInitQSettings.
This argument defaults to true, preserving initApp()'s behavior in
this respect. If this argument is set to false, FGGlobals doesn't have
to be initialized.
- New function flightgear::initQSettings(), called by
flightgear::initApp() when its 'doInitQSettings' argument is true.
This allows initializing the QSettings exactly when it is needed.
- New function flightgear::checkKeyboardModifiersForSettingFGRoot().
The code it contains used to be run from initApp(), which is
undesirable because:
1) initApp() is not only called at FG initialization (fgMainInit()),
but also from QtMessageBox(), from QtFileDialog::exec() and twice
from Options::setupRoot(). However, checking the Alt and Shift
modifiers to set 'fg-root' in QSettings to the special value
"!ask" only makes sense in fgMainInit(), not in these other
places.
2) This code relies on the QSettings to be set up, and therefore on
FGGlobals. Thus, freeing initApp() of its dependency on FGGlobals
requires splitting this keyboard modifiers checking code out of
initApp().
2016-12-26 20:45:44 +00:00
|
|
|
flightgear::checkKeyboardModifiersForSettingFGRoot();
|
|
|
|
|
2015-10-16 01:05:17 +00:00
|
|
|
if (!flightgear::runLauncherDialog()) {
|
2014-12-26 12:20:51 +00:00
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
|
|
|
}
|
2017-03-01 15:27:33 +00:00
|
|
|
#else
|
|
|
|
if (showLauncher) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_ALERT, "\n!Launcher requested, but FlightGear was compiled without Qt support!");
|
|
|
|
}
|
2014-12-26 12:20:51 +00:00
|
|
|
#endif
|
2016-03-24 15:10:06 +00:00
|
|
|
fgInitAircraftPaths(false);
|
2014-12-26 12:20:51 +00:00
|
|
|
|
2013-11-23 19:58:45 +00:00
|
|
|
configResult = fgInitAircraft(false);
|
|
|
|
if (configResult == flightgear::FG_OPTIONS_ERROR) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (configResult == flightgear::FG_OPTIONS_EXIT) {
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-11-23 19:58:45 +00:00
|
|
|
configResult = flightgear::Options::sharedInstance()->processOptions();
|
|
|
|
if (configResult == flightgear::FG_OPTIONS_ERROR) {
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
} else if (configResult == flightgear::FG_OPTIONS_EXIT) {
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|
2017-03-21 20:59:35 +00:00
|
|
|
|
1998-08-20 15:10:33 +00:00
|
|
|
// Initialize the Window/Graphics environment.
|
2004-03-31 21:10:32 +00:00
|
|
|
fgOSInit(&argc, argv);
|
2004-08-24 08:40:41 +00:00
|
|
|
_bootstrap_OSInit++;
|
1998-08-20 15:10:33 +00:00
|
|
|
|
2004-12-20 08:36:56 +00:00
|
|
|
fgRegisterIdleHandler( &fgIdleFunction );
|
2004-03-31 21:10:32 +00:00
|
|
|
|
2010-10-23 19:37:26 +00:00
|
|
|
// Initialize sockets (WinSock needs this)
|
|
|
|
simgear::Socket::initSockets();
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2004-03-31 21:10:32 +00:00
|
|
|
// Clouds3D requires an alpha channel
|
2010-07-01 18:51:05 +00:00
|
|
|
fgOSOpenWindow(true /* request stencil buffer */);
|
2013-11-16 12:10:21 +00:00
|
|
|
fgOSResetProperties();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2005-05-08 14:32:56 +00:00
|
|
|
fntInit();
|
2016-11-18 16:53:23 +00:00
|
|
|
globals->get_renderer()->preinit();
|
2004-05-20 13:27:40 +00:00
|
|
|
|
2017-04-12 10:13:14 +00:00
|
|
|
if (fgGetBool("/sim/ati-viewport-hack", true)) {
|
|
|
|
SG_LOG(SG_GENERAL, SG_WARN, "Enabling ATI/AMD viewport hack");
|
|
|
|
ATIScreenSizeHack();
|
|
|
|
}
|
|
|
|
|
2013-02-08 13:15:20 +00:00
|
|
|
fgOutputSettings();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-12-09 00:13:44 +00:00
|
|
|
//try to disable the screensaver
|
|
|
|
fgOSDisableScreensaver();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2004-10-17 17:29:34 +00:00
|
|
|
// pass control off to the master event handler
|
2010-09-29 20:04:11 +00:00
|
|
|
int result = fgOSMainLoop();
|
2013-11-14 16:37:36 +00:00
|
|
|
frame_signal.clear();
|
2013-11-12 22:26:37 +00:00
|
|
|
fgOSCloseWindow();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2013-12-09 23:25:04 +00:00
|
|
|
simgear::clearEffectCache();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2010-09-29 20:04:11 +00:00
|
|
|
// clean up here; ensure we null globals to avoid
|
|
|
|
// confusing the atexit() handler
|
|
|
|
delete globals;
|
|
|
|
globals = NULL;
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2012-08-27 23:26:36 +00:00
|
|
|
// delete the NavCache here. This will cause the destruction of many cached
|
|
|
|
// objects (eg, airports, navaids, runways).
|
|
|
|
delete flightgear::NavDataCache::instance();
|
2017-03-21 20:59:35 +00:00
|
|
|
|
2010-09-29 20:04:11 +00:00
|
|
|
return result;
|
1998-04-21 17:02:27 +00:00
|
|
|
}
|