1
0
Fork 0
This commit is contained in:
Torsten Dreyer 2011-04-03 20:42:20 +02:00
commit 4a63946e94
27 changed files with 637 additions and 417 deletions

View file

@ -20,7 +20,7 @@
; C:\> subst X: /d
;
#define FGVER "v20110228"
#define FGVER "v20110324"
[Setup]
AppId=FlightGear {#FGVER}
@ -52,7 +52,7 @@ Name: "insoal"; Description: "Install OpenAL (the sound engine)"
; NOTE: run subst X: F:\ (or whatever path the expanded tree resides at)
Source: "X:\*.txt"; DestDir: "{app}"; Flags: ignoreversion
Source: "X:\bin\Win32\*.*"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion recursesubdirs
Source: "X:\bin\vcredist_x86.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
;;; Source: "X:\bin\vcredist_x86.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "X:\bin\oalinst.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
Source: "X:\data\*.*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
@ -88,7 +88,7 @@ Name: "{group}\Tools\Explore Documentation Folder"; Filename: "{app}\data\Docs"
; Name: "{userdesktop}\FlightGear {#FGVER}"; Filename: "{app}\bin\Win32\fgfs.exe"; Parameters: "--fg-root=."; WorkingDir: "{app}"; Tasks: desktopicon
[Run]
Filename: "{app}\bin\vcredist_x86.exe"; WorkingDir: "{app}"; Parameters: "/qb!"; Description: "Installing Flightgear prerequisites"
;;; Filename: "{app}\bin\vcredist_x86.exe"; WorkingDir: "{app}"; Parameters: "/qb!"; Description: "Installing Flightgear prerequisites"
; Put installation directory into the fgrun.prefs
filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "--silent ""--fg-exe={app}\bin\Win32\fgfs.exe"" ""--ts-exe={app}\bin\Win32\terrasync.exe"" ""--fg-root={app}\data"" ""--fg-scenery={app}\data\Scenery;{app}\scenery;{code:TerrasyncDir}"" --ts-dir=3"

View file

@ -24,13 +24,16 @@
# include "config.h"
#endif
#include <float.h>
#include <simgear/constants.h>
#include <simgear/structure/exception.hxx>
#include <Main/fg_props.hxx>
#include <Network/native_ctrls.hxx>
#include <Network/native_fdm.hxx>
#include <Network/net_ctrls.hxx>
#include <Network/net_fdm.hxx>
#include <FDM/fdm_shell.hxx>
#include "replay.hxx"
@ -46,7 +49,9 @@ const double FGReplay::lt_dt = 5.0; // long term sample rate (sec)
* Constructor
*/
FGReplay::FGReplay() {
FGReplay::FGReplay() :
last_replay_state(0)
{
}
@ -54,73 +59,82 @@ FGReplay::FGReplay() {
* Destructor
*/
FGReplay::~FGReplay() {
while ( !short_term.empty() ) {
//cerr << "Deleting Short term" <<endl;
FGReplay::~FGReplay()
{
clear();
}
/**
* Clear all internal buffers.
*/
void FGReplay::clear()
{
while ( !short_term.empty() )
{
delete short_term.front();
short_term.pop_front();
}
while ( !medium_term.empty() ) {
//cerr << "Deleting Medium term" <<endl;
delete medium_term.front();
while ( !medium_term.empty() )
{
delete medium_term.front();
medium_term.pop_front();
}
while ( !long_term.empty() ) {
//cerr << "Deleting Long term" <<endl;
delete long_term.front();
while ( !long_term.empty() )
{
delete long_term.front();
long_term.pop_front();
}
while ( !recycler.empty() ) {
//cerr << "Deleting Recycler" <<endl;
delete recycler.front();
while ( !recycler.empty() )
{
delete recycler.front();
recycler.pop_front();
}
}
/**
* Initialize the data structures
*/
void FGReplay::init() {
void FGReplay::init()
{
disable_replay = fgGetNode( "/sim/replay/disable", true );
replay_master = fgGetNode( "/sim/freeze/replay-state", true );
replay_time = fgGetNode( "/sim/replay/time", true);
reinit();
}
/**
* Reset replay queues.
*/
void FGReplay::reinit()
{
sim_time = 0.0;
last_mt_time = 0.0;
last_lt_time = 0.0;
// Make sure all queues are flushed
while ( !short_term.empty() ) {
delete short_term.front();
short_term.pop_front();
}
while ( !medium_term.empty() ) {
delete medium_term.front();
medium_term.pop_front();
}
while ( !long_term.empty() ) {
delete long_term.front();
long_term.pop_front();
}
while ( !recycler.empty() ) {
delete recycler.front();
recycler.pop_front();
}
clear();
// Create an estimated nr of required ReplayData objects
// 120 is an estimated maximum frame rate.
int estNrObjects = (int) ((st_list_time*120) + (mt_list_time*mt_dt) +
(lt_list_time*lt_dt));
for (int i = 0; i < estNrObjects; i++) {
for (int i = 0; i < estNrObjects; i++)
{
recycler.push_back(new FGReplayData);
}
replay_master->setIntValue(0);
disable_replay->setBoolValue(0);
replay_time->setDoubleValue(0);
}
/**
* Bind to the property tree
*/
void FGReplay::bind() {
disable_replay = fgGetNode( "/sim/replay/disable", true );
void FGReplay::bind()
{
}
@ -128,7 +142,8 @@ void FGReplay::bind() {
* Unbind from the property tree
*/
void FGReplay::unbind() {
void FGReplay::unbind()
{
// nothing to unbind
}
@ -137,24 +152,62 @@ void FGReplay::unbind() {
* Update the saved data
*/
void FGReplay::update( double dt ) {
void FGReplay::update( double dt )
{
timingInfo.clear();
stamp("begin");
static SGPropertyNode *replay_master
= fgGetNode( "/sim/freeze/replay-state", true );
if( disable_replay->getBoolValue() ) {
if ( sim_time != 0.0 ) {
// we were recording data
init();
}
return;
if ( disable_replay->getBoolValue() )
{
replay_master->setIntValue(0);
replay_time->setDoubleValue(0);
disable_replay->setBoolValue(0);
}
//stamp("point_01");
if ( replay_master->getIntValue() > 0 ) {
// don't record the replay session
return;
int replay_state = replay_master->getIntValue();
if ((replay_state > 0)&&
(last_replay_state == 0))
{
// replay is starting, suspend FDM
/* FIXME we need to suspend/resume the FDM - not the entire FDM shell.
* FDM isn't available via the global subsystem manager yet, so need a
* method at the FDMshell for now */
((FDMShell*) globals->get_subsystem("flight"))->getFDM()->suspend();
}
else
if ((replay_state == 0)&&
(last_replay_state > 0))
{
// replay was active, restore most recent frame
replay(DBL_MAX);
// replay is finished, resume FDM
((FDMShell*) globals->get_subsystem("flight"))->getFDM()->resume();
}
// remember recent state
last_replay_state = replay_state;
switch(replay_state)
{
case 0:
// replay inactive, keep recording
break;
case 1:
// replay active
replay( replay_time->getDoubleValue() );
replay_time->setDoubleValue( replay_time->getDoubleValue()
+ ( dt * fgGetInt("/sim/speed-up") ) );
return; // don't record the replay session
case 2:
// replay paused, no-op
return; // don't record the replay session
default:
throw sg_range_exception("unknown FGReplay state");
}
// flight recording
//cerr << "Recording replay" << endl;
sim_time += dt;
@ -175,12 +228,13 @@ void FGReplay::update( double dt ) {
if (!recycler.size()) {
stamp("Replay_01");
r = new FGReplayData;
stamp("Replay_02");
stamp("Replay_02");
} else {
r = recycler.front();
recycler.pop_front();
//stamp("point_04be");
r = recycler.front();
recycler.pop_front();
//stamp("point_04be");
}
r->sim_time = sim_time;
//r->ctrls = c;
//stamp("point_04e");

View file

@ -69,6 +69,7 @@ public:
virtual ~FGReplay();
virtual void init();
virtual void reinit();
virtual void bind();
virtual void unbind();
virtual void update( double dt );
@ -78,6 +79,7 @@ public:
double get_end_time();
private:
void clear();
static const double st_list_time; // 60 secs of high res data
static const double mt_list_time; // 10 mins of 1 fps data
@ -90,12 +92,15 @@ private:
double sim_time;
double last_mt_time;
double last_lt_time;
int last_replay_state;
replay_list_type short_term;
replay_list_type medium_term;
replay_list_type long_term;
replay_list_type recycler;
SGPropertyNode_ptr disable_replay;
SGPropertyNode_ptr replay_master;
SGPropertyNode_ptr replay_time;
};

View file

@ -76,12 +76,8 @@ FGEnvironmentMgr::~FGEnvironmentMgr ()
remove_subsystem("precipitation");
delete subsys;
subsys = get_subsystem("metarfetcher");
remove_subsystem("metarfetcher");
delete subsys;
subsys = get_subsystem("metarcontroller");
remove_subsystem("metarcontroller");
subsys = get_subsystem("realwx");
remove_subsystem("realwx");
delete subsys;
subsys = get_subsystem("controller");
@ -346,9 +342,6 @@ FGEnvironmentMgr::set_cloud_layer_maxalpha (int index, double maxalpha)
thesky->get_cloud_layer(index)->setMaxAlpha(maxalpha);
}
void
FGEnvironmentMgr::set_cloud_layer_coverage_type (int index, int type )
{

View file

@ -40,6 +40,7 @@
#include <simgear/threads/SGQueue.hxx>
#endif
using simgear::PropertyList;
namespace Environment {

View file

@ -570,6 +570,22 @@ void FGJSBsim::update( double dt )
/******************************************************************************/
void FGJSBsim::suspend()
{
fdmex->Hold();
SGSubsystem::suspend();
}
/******************************************************************************/
void FGJSBsim::resume()
{
fdmex->Resume();
SGSubsystem::resume();
}
/******************************************************************************/
// Convert from the FGInterface struct to the JSBsim generic_ struct
bool FGJSBsim::copy_to_JSBsim()
@ -1011,7 +1027,9 @@ void FGJSBsim::set_Latitude(double lat)
_set_Sea_level_radius( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetSeaLevelRadiusFtIC( sea_level_radius_meters * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc );
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
@ -1024,7 +1042,9 @@ void FGJSBsim::set_Longitude(double lon)
update_ic();
fgic->SetLongitudeRadIC( lon );
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
// Sets the altitude above sea level.
@ -1049,7 +1069,9 @@ void FGJSBsim::set_Altitude(double alt)
"Terrain elevation: " << FGInterface::get_Runway_altitude() * SG_METER_TO_FEET );
fgic->SetLatitudeRadIC( lat_geoc );
fgic->SetAltitudeASLFtIC(alt);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
void FGJSBsim::set_V_calibrated_kts(double vc)
@ -1061,7 +1083,9 @@ void FGJSBsim::set_V_calibrated_kts(double vc)
update_ic();
fgic->SetVcalibratedKtsIC(vc);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
void FGJSBsim::set_Mach_number(double mach)
@ -1073,7 +1097,9 @@ void FGJSBsim::set_Mach_number(double mach)
update_ic();
fgic->SetMachIC(mach);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
void FGJSBsim::set_Velocities_Local( double north, double east, double down )
@ -1088,7 +1114,9 @@ void FGJSBsim::set_Velocities_Local( double north, double east, double down )
fgic->SetVNorthFpsIC(north);
fgic->SetVEastFpsIC(east);
fgic->SetVDownFpsIC(down);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
void FGJSBsim::set_Velocities_Wind_Body( double u, double v, double w)
@ -1103,7 +1131,9 @@ void FGJSBsim::set_Velocities_Wind_Body( double u, double v, double w)
fgic->SetUBodyFpsIC(u);
fgic->SetVBodyFpsIC(v);
fgic->SetWBodyFpsIC(w);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
//Euler angles
@ -1119,7 +1149,9 @@ void FGJSBsim::set_Euler_Angles( double phi, double theta, double psi )
fgic->SetThetaRadIC(theta);
fgic->SetPhiRadIC(phi);
fgic->SetPsiRadIC(psi);
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
//Flight Path
@ -1137,7 +1169,9 @@ void FGJSBsim::set_Climb_Rate( double roc)
if( !(fabs(roc) > 1 && fabs(fgic->GetFlightPathAngleRadIC()) < 0.01) ) {
fgic->SetClimbRateFpsIC(roc);
}
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
void FGJSBsim::set_Gamma_vert_rad( double gamma)
@ -1148,7 +1182,9 @@ void FGJSBsim::set_Gamma_vert_rad( double gamma)
if( !(fabs(gamma) < 0.01 && fabs(fgic->GetClimbRateFpsIC()) > 1) ) {
fgic->SetFlightPathAngleRadIC(gamma);
}
needTrim=true;
if (!fdmex->Holding())
needTrim=true;
}
void FGJSBsim::init_gear(void )

View file

@ -113,6 +113,12 @@ public:
/// Unbind properties
void unbind();
/// Suspend integration
void suspend();
/// Resume integration
void resume();
/// @name Position Parameter Set
//@{
/** Set geocentric latitude

View file

@ -236,12 +236,6 @@ TankPropertiesList::TankPropertiesList( SGPropertyNode_ptr rootNode )
}
_tiedProperties.setRoot( rootNode );
_tiedProperties.Tie("total-fuel-kg", this, &TankPropertiesList::getTotalContent_kg );
_tiedProperties.Tie("total-fuel-lbs", this, &TankPropertiesList::getTotalContent_lbs );
_tiedProperties.Tie("total-fuel-gal_us", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gals", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gal_imp", this, &TankPropertiesList::getTotalContent_gal_imp );
_tiedProperties.Tie("total-fuel-norm", this, &TankPropertiesList::getTotalContent_norm );
}
double TankPropertiesList::getTotalContent_lbs() const
@ -297,6 +291,12 @@ double TankPropertiesList::getTotalContent_norm() const
void TankPropertiesList::bind()
{
_tiedProperties.Tie("total-fuel-kg", this, &TankPropertiesList::getTotalContent_kg );
_tiedProperties.Tie("total-fuel-lbs", this, &TankPropertiesList::getTotalContent_lbs );
_tiedProperties.Tie("total-fuel-gal_us", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gals", this, &TankPropertiesList::getTotalContent_gal_us );
_tiedProperties.Tie("total-fuel-gal_imp", this, &TankPropertiesList::getTotalContent_gal_imp );
_tiedProperties.Tie("total-fuel-norm", this, &TankPropertiesList::getTotalContent_norm );
for( const_iterator it = begin(); it != end(); ++it ) {
(*it)->bind();
}

View file

@ -90,11 +90,11 @@ void FDMShell::reinit()
void FDMShell::bind()
{
_tankProperties.bind();
if (_impl && _impl->get_inited()) {
if (_impl->get_bound()) {
throw sg_exception("FDMShell::bind of bound FGInterface impl");
}
_tankProperties.bind();
_impl->bind();
}
}
@ -139,8 +139,8 @@ void FDMShell::update(double dt)
// pull environmental data in, since the FDMs are lazy
_impl->set_Velocities_Local_Airmass(
_props->getDoubleValue("environment/wind-from-north-fps", 0.0),
_props->getDoubleValue("environment/wind-from-east-fps", 0.0),
_props->getDoubleValue("environment/wind-from-down-fps", 0.0));
_props->getDoubleValue("environment/wind-from-east-fps", 0.0),
_props->getDoubleValue("environment/wind-from-down-fps", 0.0));
if (_props->getBoolValue("environment/params/control-fdm-atmosphere")) {
// convert from Rankine to Celsius
@ -160,24 +160,8 @@ void FDMShell::update(double dt)
_impl->ToggleDataLogging(doLog);
}
// FIXME - replay manager should handle most of this
int replayState = fgGetInt("/sim/freeze/replay-state", 0);
if (replayState == 0) {
_impl->update(dt); // normal code path
} else if (replayState == 1) {
// should be inside FGReplay!
SGPropertyNode* replay_time = fgGetNode("/sim/replay/time", true);
FGReplay *r = (FGReplay *)(globals->get_subsystem( "replay" ));
r->replay( replay_time->getDoubleValue() );
replay_time->setDoubleValue( replay_time->getDoubleValue()
+ ( dt
* fgGetInt("/sim/speed-up") ) );
} else if (replayState == 2) {
// paused replay, no-op
} else {
throw sg_range_exception("unknown FGReplay state");
}
if (!_impl->is_suspended())
_impl->update(dt);
}
void FDMShell::createImplementation()
@ -268,3 +252,13 @@ void FDMShell::createImplementation()
}
/*
* Return FDM subsystem.
*/
SGSubsystem* FDMShell::getFDM()
{
/* FIXME we could drop/replace this method, when _impl was a added
* to the global subsystem manager - like other proper subsystems... */
return _impl;
}

View file

@ -50,7 +50,8 @@ public:
virtual void unbind();
virtual void update(double dt);
SGSubsystem* getFDM();
private:
void createImplementation();

File diff suppressed because it is too large Load diff

View file

@ -221,7 +221,7 @@ do_exit (const SGPropertyNode * arg)
static bool
do_reset (const SGPropertyNode * arg)
{
doSimulatorReset();
fgReInitSubsystems();
return true;
}
@ -1243,8 +1243,10 @@ do_log_level (const SGPropertyNode * arg)
static bool
do_replay (const SGPropertyNode * arg)
{
// freeze the master fdm
// freeze the fdm, resume from sim pause
fgSetInt( "/sim/freeze/replay-state", 1 );
fgSetBool("/sim/freeze/master", 0 );
fgSetBool("/sim/freeze/clock", 0 );
FGReplay *r = (FGReplay *)(globals->get_subsystem( "replay" ));

View file

@ -1517,7 +1517,7 @@ bool fgInitSubsystems() {
return true;
}
// Reset: this is what the 'reset' command (and hence, GUI) is attached to
void fgReInitSubsystems()
{
static const SGPropertyNode *master_freeze
@ -1553,11 +1553,17 @@ void fgReInitSubsystems()
// Initialize the FDM
globals->get_subsystem("flight")->reinit();
// reset replay buffers
globals->get_subsystem("replay")->reinit();
// reload offsets from config defaults
globals->get_viewmgr()->reinit();
globals->get_subsystem("time")->reinit();
// need to bind FDMshell again, since we manually unbound it above...
globals->get_subsystem("flight")->bind();
// setup state to end re-init
fgSetBool("/sim/signals/reinit", false);
if ( !freeze ) {
@ -1567,13 +1573,6 @@ void fgReInitSubsystems()
}
void doSimulatorReset(void) // from gui_local.cxx -- TODO merge with fgReInitSubsystems()
{
fgReInitSubsystems();
}
///////////////////////////////////////////////////////////////////////////////
// helper object to implement the --show-aircraft command.
// resides here so we can share the fgFindAircraftInDir template above,

View file

@ -62,16 +62,10 @@ bool fgInitGeneral ();
// gear, its initialization call should located in this routine.
bool fgInitSubsystems();
// Reset
// Reset: this is what the 'reset' command (and hence, GUI) is attached to
void fgReInitSubsystems();
/**
* this is what the 'reset' command (and hence, GUI) is attached too
* it overlaps with fgReInitSubsystems quite substantially
*/
void doSimulatorReset(void);
// Set the initial position based on presets (or defaults)
bool fgInitPosition();

View file

@ -204,7 +204,7 @@ fgviewerMain(int argc, char** argv)
}
globals->set_matlib( new SGMaterialLib );
simgear::SGModelLib::init(globals->get_fg_root());
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
// Initialize the material property subsystem.

View file

@ -121,6 +121,15 @@ static void fgMainLoop( void ) {
static SGPropertyNode_ptr frame_signal
= fgGetNode("/sim/signals/frame", true);
static SGPropertyNode_ptr _statisticsFlag
= fgGetNode("/sim/timing-statistics/enabled", true);
static SGPropertyNode_ptr _statisticsInterval
= fgGetNode("/sim/timing-statistics/interval-s", true);
static SGPropertyNode_ptr _statiticsMinJitter
= fgGetNode("/sim/timing-statistics/min-jitter-ms", true);
static SGPropertyNode_ptr _statiticsMinTime
= fgGetNode("/sim/timing-statistics/min-time-ms", true);
frame_signal->fireValueChanged();
SGCloudLayer::enable_bump_mapping = fgGetBool("/sim/rendering/bump-mapping");
@ -206,6 +215,28 @@ static void fgMainLoop( void ) {
simgear::sleepForMSec(500);
}
}
// print timing statistics
static bool _lastStatisticsFlag = false;
if (_lastStatisticsFlag != _statisticsFlag->getBoolValue())
{
// flag has changed, update subsystem manager
_lastStatisticsFlag = _statisticsFlag->getBoolValue();
globals->get_subsystem_mgr()->collectDebugTiming(_lastStatisticsFlag);
}
if (_lastStatisticsFlag)
{
static double elapsed = 0;
elapsed += real_dt;
if (elapsed >= _statisticsInterval->getDoubleValue())
{
// print and reset timing statistics
globals->get_subsystem_mgr()->printTimingStatistics(_statiticsMinTime->getDoubleValue(),
_statiticsMinJitter->getDoubleValue());
elapsed = 0;
}
}
simgear::AtomicChangeListener::fireChangeListeners();
SG_LOG( SG_ALL, SG_DEBUG, "" );
@ -359,8 +390,7 @@ static void fgIdleFunction ( void ) {
// Initialize the material manager
////////////////////////////////////////////////////////////////////
globals->set_matlib( new SGMaterialLib );
simgear::SGModelLib::init(globals->get_fg_root());
simgear::SGModelLib::setPropRoot(globals->get_props());
simgear::SGModelLib::init(globals->get_fg_root(), globals->get_props());
simgear::SGModelLib::setPanelFunc(load_panel);
////////////////////////////////////////////////////////////////////

View file

@ -1,4 +1,4 @@
// model.cxx - manage a 3D aircraft model.
// acmodel.cxx - manage a 3D aircraft model.
// Written by David Megginson, started 2002.
//
// This file is in the Public Domain, and comes with no warranty.
@ -84,6 +84,7 @@ void
FGAircraftModel::reinit()
{
deinit();
_fx->reinit();
init();
}

View file

@ -1,4 +1,4 @@
// model.hxx - manage a 3D aircraft model.
// acmodel.hxx - manage a 3D aircraft model.
// Written by David Megginson, started 2002.
//
// This file is in the Public Domain, and comes with no warranty.

View file

@ -541,9 +541,9 @@ FGGeneric::reinit()
SGPropertyNode root;
try {
readProperties(path.str(), &root);
} catch (const sg_exception &) {
} catch (const sg_exception & ex) {
SG_LOG(SG_GENERAL, SG_ALERT,
"Unable to load the protocol configuration file");
"Unable to load the protocol configuration file: " << ex.getFormattedMessage() );
return;
}

View file

@ -38,6 +38,31 @@
static FGNasalSys* nasalSys = 0;
// Listener class for loading Nasal modules on demand
class FGNasalModuleListener : public SGPropertyChangeListener
{
public:
FGNasalModuleListener(SGPropertyNode* node);
virtual void valueChanged(SGPropertyNode* node);
private:
SGPropertyNode_ptr _node;
};
FGNasalModuleListener::FGNasalModuleListener(SGPropertyNode* node) : _node(node)
{
}
void FGNasalModuleListener::valueChanged(SGPropertyNode*)
{
if (_node->getBoolValue("enabled",false)&&
!_node->getBoolValue("loaded",true))
{
nasalSys->loadPropertyScripts(_node);
}
}
// Read and return file contents in a single buffer. Note use of
// stat() to get the file size. This is a win32 function, believe it
@ -737,12 +762,15 @@ void FGNasalSys::init()
// Now load the various source files in the Nasal directory
simgear::Dir nasalDir(SGPath(globals->get_fg_root(), "Nasal"));
simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas");
for (unsigned int i=0; i<scripts.size(); ++i) {
SGPath fullpath(scripts[i]);
SGPath file = fullpath.file();
loadModule(fullpath, file.base().c_str());
loadScriptDirectory(nasalDir);
// Add modules in Nasal subdirectories to property tree
simgear::PathList directories = nasalDir.children(simgear::Dir::TYPE_DIR+
simgear::Dir::NO_DOT_OR_DOTDOT, "");
for (unsigned int i=0; i<directories.size(); ++i) {
simgear::Dir dir(directories[i]);
simgear::PathList scripts = dir.children(simgear::Dir::TYPE_FILE, ".nas");
addModule(directories[i].file(), scripts);
}
// set signal and remove node to avoid restoring at reinit
@ -777,29 +805,75 @@ void FGNasalSys::update(double)
_context = naNewContext();
}
// Loads all scripts in given directory
void FGNasalSys::loadScriptDirectory(simgear::Dir nasalDir)
{
simgear::PathList scripts = nasalDir.children(simgear::Dir::TYPE_FILE, ".nas");
for (unsigned int i=0; i<scripts.size(); ++i) {
SGPath fullpath(scripts[i]);
SGPath file = fullpath.file();
loadModule(fullpath, file.base().c_str());
}
}
// Create module with list of scripts
void FGNasalSys::addModule(string moduleName, simgear::PathList scripts)
{
if (scripts.size()>0)
{
SGPropertyNode* nasal = globals->get_props()->getNode("nasal");
SGPropertyNode* module_node = nasal->getChild(moduleName,0,true);
for (unsigned int i=0; i<scripts.size(); ++i) {
SGPropertyNode* pFileNode = module_node->getChild("file",i,true);
pFileNode->setStringValue(scripts[i].c_str());
}
if (!module_node->hasChild("enabled",0))
{
SGPropertyNode* node = module_node->getChild("enabled",0,true);
node->setBoolValue(true);
node->setAttribute(SGPropertyNode::USERARCHIVE,true);
}
}
}
// Loads the scripts found under /nasal in the global tree
void FGNasalSys::loadPropertyScripts()
{
SGPropertyNode* nasal = globals->get_props()->getNode("nasal");
if(!nasal) return;
for(int i=0; i<nasal->nChildren(); i++) {
for(int i=0; i<nasal->nChildren(); i++)
{
SGPropertyNode* n = nasal->getChild(i);
loadPropertyScripts(n);
}
}
const char* module = n->getName();
if(n->hasChild("module"))
module = n->getStringValue("module");
// Loads the scripts found under /nasal in the global tree
void FGNasalSys::loadPropertyScripts(SGPropertyNode* n)
{
bool is_loaded = false;
const char* module = n->getName();
if(n->hasChild("module"))
module = n->getStringValue("module");
if (n->getBoolValue("enabled",true))
{
// allow multiple files to be specified within a single
// Nasal module tag
int j = 0;
SGPropertyNode *fn;
bool file_specified = false;
bool ok=true;
while((fn = n->getChild("file", j)) != NULL) {
file_specified = true;
const char* file = fn->getStringValue();
SGPath p = globals->resolve_maybe_aircraft_path(file);
loadModule(p, module);
SGPath p(file);
if (!p.isAbsolute() || !p.exists())
{
p = globals->resolve_maybe_aircraft_path(file);
}
ok &= loadModule(p, module);
j++;
}
@ -809,10 +883,30 @@ void FGNasalSys::loadPropertyScripts()
createModule(module, n->getPath().c_str(), src, strlen(src));
if(!file_specified && !src)
{
// module no longer exists - clear the archived "enable" flag
n->setAttribute(SGPropertyNode::USERARCHIVE,false);
SGPropertyNode* node = n->getChild("enabled",0,false);
if (node)
node->setAttribute(SGPropertyNode::USERARCHIVE,false);
SG_LOG(SG_NASAL, SG_ALERT, "Nasal error: " <<
"no <file> or <script> defined in " <<
"/nasal/" << module);
"no <file> or <script> defined in " <<
"/nasal/" << module);
}
else
is_loaded = ok;
}
else
{
SGPropertyNode* enable = n->getChild("enabled");
if (enable)
{
FGNasalModuleListener* listener = new FGNasalModuleListener(n);
enable->addChangeListener(listener, false);
}
}
n->setBoolValue("loaded",is_loaded);
}
// Logs a runtime error, with stack trace, to the FlightGear log stream
@ -832,7 +926,7 @@ void FGNasalSys::logError(naContext context)
// Reads a script file, executes it, and places the resulting
// namespace into the global namespace under the specified module
// name.
void FGNasalSys::loadModule(SGPath file, const char* module)
bool FGNasalSys::loadModule(SGPath file, const char* module)
{
int len = 0;
char* buf = readfile(file.c_str(), &len);
@ -840,25 +934,26 @@ void FGNasalSys::loadModule(SGPath file, const char* module)
SG_LOG(SG_NASAL, SG_ALERT,
"Nasal error: could not read script file " << file.c_str()
<< " into module " << module);
return;
return false;
}
createModule(module, file.c_str(), buf, len);
bool ok = createModule(module, file.c_str(), buf, len);
delete[] buf;
return ok;
}
// Parse and run. Save the local variables namespace, as it will
// become a sub-object of globals. The optional "arg" argument can be
// used to pass an associated property node to the module, which can then
// be accessed via cmdarg(). (This is, for example, used by XML dialogs.)
void FGNasalSys::createModule(const char* moduleName, const char* fileName,
bool FGNasalSys::createModule(const char* moduleName, const char* fileName,
const char* src, int len,
const SGPropertyNode* cmdarg,
int argc, naRef* args)
{
naRef code = parse(fileName, src, len);
if(naIsNil(code))
return;
return false;
// See if we already have a module hash to use. This allows the
// user to, for example, add functions to the built-in math
@ -873,6 +968,7 @@ void FGNasalSys::createModule(const char* moduleName, const char* fileName,
call(code, argc, args, locals);
hashset(_globals, moduleName, locals);
return true;
}
void FGNasalSys::deleteModule(const char* moduleName)

View file

@ -3,6 +3,7 @@
#include <simgear/misc/sg_path.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/misc/sg_dir.hxx>
#include <simgear/nasal/nasal.h>
#include <simgear/scene/model/modellib.hxx>
#include <simgear/xml/easyxml.hxx>
@ -24,7 +25,7 @@ public:
// Loads a nasal script from an external file and inserts it as a
// global module of the specified name.
void loadModule(SGPath file, const char* moduleName);
bool loadModule(SGPath file, const char* moduleName);
// Simple hook to run arbitrary source code. Returns a bool to
// indicate successful execution. Does *not* return any Nasal
@ -53,7 +54,7 @@ public:
// Callbacks for command and timer bindings
virtual bool handleCommand(const SGPropertyNode* arg);
void createModule(const char* moduleName, const char* fileName,
bool createModule(const char* moduleName, const char* fileName,
const char* src, int len, const SGPropertyNode* cmdarg=0,
int argc=0, naRef*args=0);
@ -65,6 +66,7 @@ public:
private:
friend class FGNasalScript;
friend class FGNasalListener;
friend class FGNasalModuleListener;
//
// FGTimer subclass for handling Nasal timer callbacks.
@ -85,6 +87,9 @@ private:
static int _listenerId;
void loadPropertyScripts();
void loadPropertyScripts(SGPropertyNode* n);
void loadScriptDirectory(simgear::Dir nasalDir);
void addModule(string moduleName, simgear::PathList scripts);
void hashset(naRef hash, const char* key, naRef val);
void logError(naContext);
naRef parse(const char* filename, const char* buf, int len);

View file

@ -8,4 +8,4 @@ libSound_a_SOURCES = \
sample_queue.cxx sample_queue.hxx \
voiceplayer.cxx voiceplayer.hxx
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_builddir) -I$(top_builddir)/src

View file

@ -109,6 +109,9 @@ FGFX::init()
void
FGFX::reinit()
{
for ( unsigned int i = 0; i < _sound.size(); i++ ) {
delete _sound[i];
}
_sound.clear();
init();
};

View file

@ -42,12 +42,6 @@
using std::string;
#if defined( HAVE_VERSION_H ) && HAVE_VERSION_H
# include <Include/version.h>
#else
# include <Include/no_version.h>
#endif
#include "voiceplayer.hxx"
///////////////////////////////////////////////////////////////////////////////

View file

@ -135,6 +135,7 @@ public:
public:
bool silence;
virtual ~Element() {}
virtual inline void play (float volume) {}
virtual inline void stop () {}
virtual bool is_playing () = 0;
@ -186,7 +187,7 @@ public:
inline Voice (FGVoicePlayer *_player)
: element(NULL), player(_player), volume(1.0) {}
~Voice ();
virtual ~Voice ();
inline void append (Element *_element) { elements.push_back(_element); }
@ -229,7 +230,7 @@ public:
dev_name(_dev_name), dir_prefix(""),
speaker(this,properties_handler) {}
~FGVoicePlayer ();
virtual ~FGVoicePlayer ();
void init ();
void pause();

View file

@ -88,9 +88,11 @@ void TimeManager::init()
_warp->getIntValue());
globals->set_time_params(_impl);
// frame/update-rate counters
// frame-rate / worst-case latency / update-rate counters
_frameRate = fgGetNode("/sim/frame-rate", true);
_frameLatency = fgGetNode("/sim/frame-latency-max-ms", true);
_lastFrameTime = 0;
_frameLatencyMax = 0.0;
_frameCount = 0;
}
@ -160,7 +162,9 @@ void TimeManager::computeTimeDeltas(double& simDt, double& realDt)
SGTimeStamp currentStamp;
currentStamp.stamp();
double dt = (currentStamp - _lastStamp).toSecs();
if (dt > _frameLatencyMax)
_frameLatencyMax = dt;
// Limit the time we need to spend in simulation loops
// That means, if the /sim/max-simtime-per-frame value is strictly positive
// you can limit the maximum amount of time you will do simulations for
@ -251,7 +255,9 @@ void TimeManager::computeFrameRate()
// Calculate frame rate average
if ((_impl->get_cur_time() != _lastFrameTime)) {
_frameRate->setIntValue(_frameCount);
_frameLatency->setDoubleValue(_frameLatencyMax*1000);
_frameCount = 0;
_frameLatencyMax = 0.0;
}
_lastFrameTime = _impl->get_cur_time();

View file

@ -78,9 +78,11 @@ private:
SGPropertyNode_ptr _longitudeDeg;
SGPropertyNode_ptr _latitudeDeg;
// frame-rate / update-rate counters
// frame-rate / worst-case latency / update-rate counters
SGPropertyNode_ptr _frameRate;
SGPropertyNode_ptr _frameLatency;
time_t _lastFrameTime;
double _frameLatencyMax;
int _frameCount;
};