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>
|
|
|
|
|
2001-12-22 23:16:43 +00:00
|
|
|
#if defined(__linux__) && defined(__i386__)
|
2001-12-22 19:10:37 +00:00
|
|
|
# include <fpu_control.h>
|
2002-01-04 20:56:28 +00:00
|
|
|
# include <signal.h>
|
2001-12-22 19:10:37 +00:00
|
|
|
#endif
|
|
|
|
|
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>
|
|
|
|
|
2005-03-09 21:56:00 +00:00
|
|
|
// Class references
|
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>
|
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>
|
|
|
|
#include <simgear/magvar/magvar.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/sound/soundmgr_openal.hxx>
|
|
|
|
#include <simgear/math/SGMath.hxx>
|
|
|
|
#include <simgear/math/sg_random.h>
|
2008-07-31 12:04:32 +00:00
|
|
|
|
2010-10-29 00:18:06 +00:00
|
|
|
#include <Aircraft/controls.hxx>
|
2003-08-17 09:54:41 +00:00
|
|
|
#include <Model/panelnode.hxx>
|
|
|
|
#include <Scenery/scenery.hxx>
|
|
|
|
#include <Scenery/tilemgr.hxx>
|
2009-10-04 13:52:53 +00:00
|
|
|
#include <Sound/fg_fx.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>
|
2012-04-25 21:28:00 +00:00
|
|
|
#include <Viewer/CameraGroup.hxx>
|
|
|
|
#include <Viewer/WindowSystemAdapter.hxx>
|
|
|
|
#include <Viewer/splash.hxx>
|
|
|
|
#include <Viewer/renderer.hxx>
|
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"
|
2003-08-29 16:46:21 +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
|
|
|
|
1998-07-06 02:42:02 +00:00
|
|
|
// Specify our current idle function state. This is used to run all
|
2004-03-31 21:10:32 +00:00
|
|
|
// our initializations out of the idle callback so that we can get a
|
1998-07-06 02:42:02 +00:00
|
|
|
// splash screen up and running right away.
|
2004-09-20 13:21:51 +00:00
|
|
|
int idle_state = 0;
|
2000-03-02 13:51:31 +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;
|
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
|
|
|
|
void fgInitSoundManager()
|
2011-11-05 13:18:36 +00:00
|
|
|
{
|
2011-11-20 15:20:05 +00:00
|
|
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
2001-10-28 16:16:30 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
smgr->bind();
|
|
|
|
smgr->init(fgGetString("/sim/sound/device-name", NULL));
|
2003-09-20 11:05:12 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
vector <const char*>devices = smgr->get_available_devices();
|
|
|
|
for (unsigned int i=0; i<devices.size(); i++) {
|
|
|
|
SGPropertyNode *p = fgGetNode("/sim/sound/devices/device", i, true);
|
|
|
|
p->setStringValue(devices[i]);
|
|
|
|
}
|
|
|
|
devices.clear();
|
|
|
|
}
|
2000-07-05 02:39:30 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
void fgSetNewSoundDevice(const char *device)
|
|
|
|
{
|
|
|
|
SGSoundMgr *smgr = globals->get_soundmgr();
|
|
|
|
smgr->suspend();
|
|
|
|
smgr->stop();
|
|
|
|
smgr->init(device);
|
|
|
|
smgr->resume();
|
|
|
|
}
|
2005-08-14 12:57:12 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
// Update sound manager state (init/suspend/resume) and propagate property values,
|
|
|
|
// since the sound manager doesn't read any properties itself.
|
|
|
|
// Actual sound update is triggered by the subsystem manager.
|
|
|
|
static void fgUpdateSound(double dt)
|
|
|
|
{
|
2008-09-05 19:46:21 +00:00
|
|
|
#ifdef ENABLE_AUDIO_SUPPORT
|
2010-01-10 11:00:52 +00:00
|
|
|
static bool smgr_init = true;
|
2010-04-10 09:37:22 +00:00
|
|
|
static SGPropertyNode *sound_working = fgGetNode("/sim/sound/working");
|
2010-01-10 11:00:52 +00:00
|
|
|
if (smgr_init == true) {
|
|
|
|
if (sound_working->getBoolValue() == true) {
|
|
|
|
fgInitSoundManager();
|
|
|
|
smgr_init = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
static SGPropertyNode *sound_enabled = fgGetNode("/sim/sound/enabled");
|
|
|
|
static SGSoundMgr *smgr = globals->get_soundmgr();
|
|
|
|
static bool smgr_enabled = true;
|
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
if (sound_working->getBoolValue() == false) { // request to reinit
|
2010-04-10 09:37:22 +00:00
|
|
|
smgr->reinit();
|
2010-04-10 09:46:27 +00:00
|
|
|
smgr->resume();
|
2010-04-10 09:37:22 +00:00
|
|
|
sound_working->setBoolValue(true);
|
|
|
|
}
|
|
|
|
|
2010-01-10 11:00:52 +00:00
|
|
|
if (smgr_enabled != sound_enabled->getBoolValue()) {
|
|
|
|
if (smgr_enabled == true) { // request to suspend
|
|
|
|
smgr->suspend();
|
|
|
|
smgr_enabled = false;
|
|
|
|
} else {
|
|
|
|
smgr->resume();
|
|
|
|
smgr_enabled = true;
|
|
|
|
}
|
2009-11-29 10:24:47 +00:00
|
|
|
}
|
|
|
|
|
2010-01-10 11:00:52 +00:00
|
|
|
if (smgr_enabled == true) {
|
|
|
|
static SGPropertyNode *volume = fgGetNode("/sim/sound/volume");
|
|
|
|
smgr->set_volume(volume->getFloatValue());
|
|
|
|
}
|
2009-11-29 10:24:47 +00:00
|
|
|
}
|
2008-09-05 19:46:21 +00:00
|
|
|
#endif
|
2011-11-20 15:20:05 +00:00
|
|
|
}
|
2008-09-05 19:46:21 +00:00
|
|
|
|
2011-11-20 15:20:05 +00:00
|
|
|
static void fgLoadInitialScenery()
|
|
|
|
{
|
|
|
|
static SGPropertyNode_ptr scenery_loaded
|
|
|
|
= fgGetNode("sim/sceneryloaded", true);
|
|
|
|
|
|
|
|
if (!scenery_loaded->getBoolValue())
|
2010-11-19 12:59:43 +00:00
|
|
|
{
|
|
|
|
if (globals->get_tile_mgr()->isSceneryLoaded()
|
|
|
|
&& fgGetBool("sim/fdm-initialized")) {
|
|
|
|
fgSetBool("sim/sceneryloaded",true);
|
2011-05-21 11:22:47 +00:00
|
|
|
fgSplashProgress("");
|
2010-11-19 12:59:43 +00:00
|
|
|
if (fgGetBool("/sim/sound/working")) {
|
|
|
|
globals->get_soundmgr()->activate();
|
|
|
|
}
|
|
|
|
globals->get_props()->tie("/sim/sound/devices/name",
|
|
|
|
SGRawValueFunctions<const char *>(0, fgSetNewSoundDevice), false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("loading scenery");
|
2010-11-19 12:59:43 +00:00
|
|
|
// be nice to loader threads while waiting for initial scenery, reduce to 2fps
|
2011-10-28 15:01:50 +00:00
|
|
|
SGTimeStamp::sleepForMSec(500);
|
2009-10-18 13:45:01 +00:00
|
|
|
}
|
2004-07-22 16:42:14 +00:00
|
|
|
}
|
1998-04-21 17:02:27 +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
|
|
|
{
|
2011-11-20 15:20:05 +00:00
|
|
|
static SGPropertyNode_ptr frame_signal
|
|
|
|
= fgGetNode("/sim/signals/frame", true);
|
2010-01-10 11:00:52 +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
|
|
|
SG_LOG( SG_GENERAL, SG_DEBUG, "Running Main Loop");
|
|
|
|
SG_LOG( SG_GENERAL, SG_DEBUG, "======= ==== ====");
|
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;
|
|
|
|
TimeManager* timeMgr = (TimeManager*) globals->get_subsystem("time");
|
|
|
|
timeMgr->computeTimeDeltas(sim_dt, real_dt);
|
|
|
|
|
|
|
|
// update magvar model
|
|
|
|
globals->get_mag()->update( globals->get_aircraft_position(),
|
|
|
|
globals->get_time_params()->getJD() );
|
|
|
|
|
|
|
|
// Propagate sound manager properties (note: actual update is triggered
|
|
|
|
// by the subsystem manager).
|
|
|
|
fgUpdateSound(sim_dt);
|
|
|
|
|
|
|
|
// update all subsystems
|
|
|
|
globals->get_subsystem_mgr()->update(sim_dt);
|
|
|
|
|
|
|
|
// END Tile Manager updates
|
|
|
|
fgLoadInitialScenery();
|
|
|
|
|
|
|
|
simgear::AtomicChangeListener::fireChangeListeners();
|
|
|
|
|
|
|
|
SG_LOG( SG_GENERAL, SG_DEBUG, "" );
|
2009-11-30 14:24:16 +00:00
|
|
|
}
|
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
// Operation for querying OpenGL parameters. This must be done in a
|
|
|
|
// valid OpenGL context, potentially in another thread.
|
|
|
|
namespace
|
|
|
|
{
|
|
|
|
struct GeneralInitOperation : public GraphicsContextOperation
|
|
|
|
{
|
|
|
|
GeneralInitOperation()
|
|
|
|
: GraphicsContextOperation(std::string("General init"))
|
|
|
|
{
|
|
|
|
}
|
|
|
|
void run(osg::GraphicsContext* gc)
|
|
|
|
{
|
2010-10-01 08:33:31 +00:00
|
|
|
SGPropertyNode* simRendering = fgGetNode("/sim/rendering");
|
|
|
|
|
|
|
|
simRendering->setStringValue("gl-vendor", (char*) glGetString(GL_VENDOR));
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_VENDOR));
|
|
|
|
|
|
|
|
simRendering->setStringValue("gl-renderer", (char*) glGetString(GL_RENDERER));
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_RENDERER));
|
|
|
|
|
|
|
|
simRendering->setStringValue("gl-version", (char*) glGetString(GL_VERSION));
|
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, glGetString(GL_VERSION));
|
2005-05-04 21:28:42 +00:00
|
|
|
|
|
|
|
GLint tmp;
|
|
|
|
glGetIntegerv( GL_MAX_TEXTURE_SIZE, &tmp );
|
2010-10-01 08:33:31 +00:00
|
|
|
simRendering->setIntValue("max-texture-size", tmp);
|
2005-05-04 21:28:42 +00:00
|
|
|
|
|
|
|
glGetIntegerv( GL_DEPTH_BITS, &tmp );
|
2010-10-01 08:33:31 +00:00
|
|
|
simRendering->setIntValue("depth-buffer-bits", tmp);
|
2008-08-01 15:57:29 +00:00
|
|
|
}
|
|
|
|
};
|
2010-07-29 00:07:32 +00:00
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
}
|
2005-05-04 21:28:42 +00:00
|
|
|
|
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
|
|
|
|
2008-08-01 15:57:29 +00:00
|
|
|
static void fgIdleFunction ( void ) {
|
|
|
|
static osg::ref_ptr<GeneralInitOperation> genOp;
|
|
|
|
if ( idle_state == 0 ) {
|
|
|
|
idle_state++;
|
|
|
|
// Pick some window on which to do queries.
|
|
|
|
// XXX Perhaps all this graphics initialization code should be
|
|
|
|
// moved to renderer.cxx?
|
|
|
|
genOp = new GeneralInitOperation;
|
|
|
|
osg::Camera* guiCamera = getGUICamera(CameraGroup::getDefault());
|
|
|
|
WindowSystemAdapter* wsa = WindowSystemAdapter::getWSA();
|
|
|
|
osg::GraphicsContext* gc = 0;
|
|
|
|
if (guiCamera)
|
|
|
|
gc = guiCamera->getGraphicsContext();
|
|
|
|
if (gc) {
|
|
|
|
gc->add(genOp.get());
|
|
|
|
} else {
|
|
|
|
wsa->windows[0]->gc->add(genOp.get());
|
|
|
|
}
|
|
|
|
guiStartInit(gc);
|
2007-04-29 09:58:37 +00:00
|
|
|
} else if ( idle_state == 1 ) {
|
2008-08-01 15:57:29 +00:00
|
|
|
if (genOp.valid()) {
|
|
|
|
if (!genOp->isFinished())
|
|
|
|
return;
|
|
|
|
genOp = 0;
|
|
|
|
}
|
2008-05-19 21:21:03 +00:00
|
|
|
if (!guiFinishInit())
|
|
|
|
return;
|
2007-04-29 09:58:37 +00:00
|
|
|
idle_state++;
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("loading aircraft list");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 2 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("loading navigation data");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 3 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
|
|
|
fgInitNav();
|
|
|
|
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("initializing scenery system");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 4 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
|
|
|
// based on the requested presets, calculate the true starting
|
|
|
|
// lon, lat
|
|
|
|
fgInitPosition();
|
2007-04-04 19:05:59 +00:00
|
|
|
fgInitTowerLocationListener();
|
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);
|
|
|
|
t->init(); // need to init now, not during initSubsystems
|
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
// Do some quick general initializations
|
|
|
|
if( !fgInitGeneral()) {
|
2006-08-07 15:16:46 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
|
|
|
"General initialization failed ..." );
|
2005-05-04 21:28:42 +00:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the property-based built-in commands
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
fgInitCommands();
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the material manager
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
globals->set_matlib( new SGMaterialLib );
|
2011-04-03 17:13:51 +00:00
|
|
|
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
|
2012-01-02 23:16:18 +00:00
|
|
|
simgear::SGModelLib::setPanelFunc(FGPanelNode::load);
|
2011-05-22 16:28:42 +00:00
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
// Initialize the TG scenery subsystem.
|
|
|
|
////////////////////////////////////////////////////////////////////
|
2011-06-11 22:44:07 +00:00
|
|
|
simgear::SGTerraSync* terra_sync = new simgear::SGTerraSync(globals->get_props());
|
|
|
|
globals->add_subsystem("terrasync", terra_sync);
|
2005-05-04 21:28:42 +00:00
|
|
|
globals->set_scenery( new FGScenery );
|
|
|
|
globals->get_scenery()->init();
|
|
|
|
globals->get_scenery()->bind();
|
|
|
|
globals->set_tile_mgr( new FGTileMgr );
|
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
fgSplashProgress("loading aircraft");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 5 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2009-10-05 09:12:50 +00:00
|
|
|
|
2011-05-22 16:28:42 +00:00
|
|
|
fgSplashProgress("initializing sky elements");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 6 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2011-11-05 13:18:36 +00:00
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
// Initialize MagVar model
|
|
|
|
SGMagVar *magvar = new SGMagVar();
|
|
|
|
globals->set_mag( magvar );
|
2011-11-05 13:18:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
// kludge to initialize mag compass
|
|
|
|
// (should only be done for in-flight
|
|
|
|
// startup)
|
2005-05-04 21:28:42 +00:00
|
|
|
// update magvar model
|
2011-11-04 12:02:43 +00:00
|
|
|
globals->get_mag()->update( fgGetDouble("/position/longitude-deg")
|
2011-11-05 13:18:36 +00:00
|
|
|
* SGD_DEGREES_TO_RADIANS,
|
|
|
|
fgGetDouble("/position/latitude-deg")
|
|
|
|
* SGD_DEGREES_TO_RADIANS,
|
|
|
|
fgGetDouble("/position/altitude-ft")
|
|
|
|
* SG_FEET_TO_METER,
|
|
|
|
globals->get_time_params()->getJD() );
|
2006-06-24 03:42:30 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
fgSplashProgress("initializing subsystems");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 7 ) {
|
2005-05-04 21:28:42 +00:00
|
|
|
idle_state++;
|
2003-04-15 14:10:47 +00:00
|
|
|
// Initialize audio support
|
2001-07-11 06:01:55 +00:00
|
|
|
#ifdef ENABLE_AUDIO_SUPPORT
|
|
|
|
|
2003-04-15 14:10:47 +00:00
|
|
|
// Start the intro music
|
|
|
|
if ( fgGetBool("/sim/startup/intro-music") ) {
|
|
|
|
SGPath mp3file( globals->get_fg_root() );
|
|
|
|
mp3file.append( "Sounds/intro.mp3" );
|
1999-04-27 19:27:45 +00:00
|
|
|
|
2006-08-07 15:16:46 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO,
|
2003-04-15 14:10:47 +00:00
|
|
|
"Starting intro music: " << mp3file.str() );
|
2001-07-11 06:01:55 +00:00
|
|
|
|
2009-10-04 13:52:53 +00:00
|
|
|
# if defined( __CYGWIN__ )
|
2003-04-15 14:10:47 +00:00
|
|
|
string command = "start /m `cygpath -w " + mp3file.str() + "`";
|
2010-01-23 22:26:30 +00:00
|
|
|
# elif defined( _WIN32 )
|
2003-04-15 14:10:47 +00:00
|
|
|
string command = "start /m " + mp3file.str();
|
2009-10-04 13:52:53 +00:00
|
|
|
# else
|
2003-04-15 14:10:47 +00:00
|
|
|
string command = "mpg123 " + mp3file.str() + "> /dev/null 2>&1";
|
2009-10-04 13:52:53 +00:00
|
|
|
# endif
|
2002-02-05 05:04:02 +00:00
|
|
|
|
2012-01-12 21:10:52 +00:00
|
|
|
if (0 != system ( command.c_str() ))
|
|
|
|
{
|
|
|
|
SG_LOG( SG_SOUND, SG_WARN,
|
|
|
|
"Failed to play mp3 file " << mp3file.str() << ". Maybe mp3 player is not installed." );
|
|
|
|
}
|
2003-04-15 14:10:47 +00:00
|
|
|
}
|
1998-07-06 02:42:02 +00:00
|
|
|
#endif
|
2003-04-15 14:10:47 +00:00
|
|
|
// This is the top level init routine which calls all the
|
|
|
|
// other subsystem initialization routines. If you are adding
|
2006-08-07 15:16:46 +00:00
|
|
|
// a subsystem to flightgear, its initialization call should be
|
2003-04-15 14:10:47 +00:00
|
|
|
// located in this routine.
|
|
|
|
if( !fgInitSubsystems()) {
|
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT,
|
2006-08-07 15:16:46 +00:00
|
|
|
"Subsystem initialization failed ..." );
|
2003-04-15 14:10:47 +00:00
|
|
|
exit(-1);
|
|
|
|
}
|
|
|
|
|
2010-11-10 21:19:25 +00:00
|
|
|
// Torsten Dreyer:
|
|
|
|
// ugly hack for automatic runway selection on startup based on
|
|
|
|
// metar data. Makes startup.nas obsolete and guarantees the same
|
|
|
|
// runway selection as for AI traffic. However, this code belongs to
|
|
|
|
// somewhere(?) else - if I only new where...
|
|
|
|
if( true == fgGetBool( "/environment/metar/valid" ) ) {
|
2011-09-17 17:26:23 +00:00
|
|
|
SG_LOG(SG_ENVIRONMENT, SG_INFO,
|
|
|
|
"Using METAR for runway selection: '" << fgGetString("/environment/metar/data") << "'" );
|
2010-11-10 21:19:25 +00:00
|
|
|
// the realwx_ctrl fetches metar in the foreground on init,
|
|
|
|
// If it was able to fetch a metar or one was given on the commandline,
|
|
|
|
// the valid flag is set here, otherwise it is false
|
|
|
|
double hdg = fgGetDouble( "/environment/metar/base-wind-dir-deg", 9999.0 );
|
|
|
|
string apt = fgGetString( "/sim/startup/options/airport" );
|
|
|
|
string rwy = fgGetString( "/sim/startup/options/runway" );
|
|
|
|
double strthdg = fgGetDouble( "/sim/startup/options/heading-deg", 9999.0 );
|
2010-11-10 22:28:07 +00:00
|
|
|
string parkpos = fgGetString( "/sim/presets/parkpos" );
|
2010-11-10 21:19:25 +00:00
|
|
|
bool onground = fgGetBool( "/sim/presets/onground", false );
|
|
|
|
// don't check for wind-speed < 1kt, this belongs to the runway-selection code
|
|
|
|
// the other logic is taken from former startup.nas
|
2010-11-10 22:28:07 +00:00
|
|
|
if( hdg < 360.0 && apt.length() > 0 && strthdg > 360.0 && rwy.length() == 0 && onground && parkpos.length() == 0 ) {
|
2010-11-10 21:19:25 +00:00
|
|
|
extern bool fgSetPosFromAirportIDandHdg( const string& id, double tgt_hdg );
|
|
|
|
fgSetPosFromAirportIDandHdg( apt, hdg );
|
|
|
|
}
|
2011-09-17 17:26:23 +00:00
|
|
|
} else {
|
|
|
|
SG_LOG(SG_ENVIRONMENT, SG_INFO,
|
|
|
|
"No METAR available to pick active runway" );
|
2010-11-10 21:19:25 +00:00
|
|
|
}
|
2011-05-22 16:28:42 +00:00
|
|
|
|
|
|
|
fgSplashProgress("initializing graphics engine");
|
2005-05-04 21:28:42 +00:00
|
|
|
|
2005-05-06 09:08:44 +00:00
|
|
|
} else if ( idle_state == 8 ) {
|
|
|
|
idle_state = 1000;
|
2010-07-13 20:50:44 +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") );
|
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 ) {
|
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);
|
2005-05-04 21:28:42 +00:00
|
|
|
fgRegisterIdleHandler( fgMainLoop );
|
1998-07-06 02:42:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
}
|
|
|
|
p->addChangeListener(new FGMakeUpperCase);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2002-11-16 20:17:11 +00:00
|
|
|
// Main top level initialization
|
2010-09-29 20:04:11 +00:00
|
|
|
int fgMainInit( int argc, char **argv ) {
|
2001-10-29 04:39:54 +00:00
|
|
|
|
1998-11-16 13:59:58 +00:00
|
|
|
// set default log levels
|
2003-11-24 17:46:38 +00:00
|
|
|
sglog().setLogLevels( SG_ALL, SG_ALERT );
|
1998-11-16 13:59:58 +00:00
|
|
|
|
2001-01-11 05:04:17 +00:00
|
|
|
string version;
|
|
|
|
#ifdef FLIGHTGEAR_VERSION
|
|
|
|
version = FLIGHTGEAR_VERSION;
|
|
|
|
#else
|
|
|
|
version = "unknown version";
|
|
|
|
#endif
|
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 );
|
2012-04-21 18:17:42 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_INFO, "Built with " << SG_COMPILER_STR << std::endl );
|
1998-11-20 01:02:35 +00:00
|
|
|
|
2000-10-19 23:09:33 +00:00
|
|
|
// Allocate global data structures. This needs to happen before
|
|
|
|
// we parse command line options
|
2001-01-12 15:37:40 +00:00
|
|
|
|
2000-10-19 21:24:43 +00:00
|
|
|
globals = new FGGlobals;
|
|
|
|
|
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-07-22 19:51:16 +00:00
|
|
|
FGControls *controls = new FGControls;
|
|
|
|
globals->set_controls( controls );
|
|
|
|
|
2001-01-26 00:21:36 +00:00
|
|
|
string_list *col = new string_list;
|
|
|
|
globals->set_channel_options_list( col );
|
|
|
|
|
2008-07-11 16:36:54 +00:00
|
|
|
fgValidatePath("", 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
|
|
|
|
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.)
|
1999-06-18 03:42:54 +00:00
|
|
|
if ( !fgInitConfig(argc, argv) ) {
|
2011-10-16 17:35:40 +00:00
|
|
|
SG_LOG( SG_GENERAL, SG_ALERT, "Config option parsing failed ..." );
|
|
|
|
exit(-1);
|
1998-04-24 00:49:17 +00:00
|
|
|
}
|
1999-06-18 03:42:54 +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 */);
|
2004-03-31 21:10:32 +00:00
|
|
|
|
2005-05-04 21:28:42 +00:00
|
|
|
// Initialize the splash screen right away
|
2005-05-08 14:32:56 +00:00
|
|
|
fntInit();
|
2007-05-03 18:12:29 +00:00
|
|
|
fgSplashInit();
|
2004-05-20 13:27:40 +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();
|
|
|
|
|
|
|
|
// clean up here; ensure we null globals to avoid
|
|
|
|
// confusing the atexit() handler
|
|
|
|
delete globals;
|
|
|
|
globals = NULL;
|
|
|
|
|
|
|
|
return result;
|
1998-04-21 17:02:27 +00:00
|
|
|
}
|