diff --git a/src/Environment/environment_mgr.cxx b/src/Environment/environment_mgr.cxx index 3182f1159..40ca18f20 100644 --- a/src/Environment/environment_mgr.cxx +++ b/src/Environment/environment_mgr.cxx @@ -42,6 +42,7 @@ #include "precipitation_mgr.hxx" #include "ridge_lift.hxx" #include "terrainsampler.hxx" +#include "Airports/simple.hxx" class SGSky; extern SGSky *thesky; @@ -49,8 +50,11 @@ extern SGSky *thesky; FGEnvironmentMgr::FGEnvironmentMgr () : _environment(new FGEnvironment()), fgClouds(new FGClouds()), + _cloudLayersDirty(true), _altitudeNode(fgGetNode("/position/altitude-ft", true)), - _cloudLayersDirty(true) + _longitude_n(fgGetNode( "/position/longitude-deg", true )), + _latitude_n( fgGetNode( "/position/latitude-deg", true )), + _positionTimeToLive(0.0) { set_subsystem("controller", Environment::LayerInterpolateController::createInstance( fgGetNode("/environment/config", true ) )); set_subsystem("realwx", Environment::RealWxController::createInstance( fgGetNode("/environment/realwx", true ) ), 1.0 ); @@ -111,73 +115,73 @@ FGEnvironmentMgr::bind () _tiedProperties.setRoot( fgGetNode( "/environment", true ) ); _tiedProperties.Tie( "effective-visibility-m", thesky, - &SGSky::get_visibility ); + &SGSky::get_visibility ); _tiedProperties.Tie("rebuild-layers", fgClouds, - &FGClouds::get_update_event, - &FGClouds::set_update_event); + &FGClouds::get_update_event, + &FGClouds::set_update_event); _tiedProperties.Tie("turbulence/use-cloud-turbulence", &sgEnviro, - &SGEnviro::get_turbulence_enable_state, - &SGEnviro::set_turbulence_enable_state); + &SGEnviro::get_turbulence_enable_state, + &SGEnviro::set_turbulence_enable_state); for (int i = 0; i < MAX_CLOUD_LAYERS; i++) { - SGPropertyNode_ptr layerNode = fgGetNode("/environment/clouds",true)->getChild("layer", i, true ); + SGPropertyNode_ptr layerNode = fgGetNode("/environment/clouds",true)->getChild("layer", i, true ); - _tiedProperties.Tie( layerNode->getNode("span-m",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_span_m, - &FGEnvironmentMgr::set_cloud_layer_span_m); + _tiedProperties.Tie( layerNode->getNode("span-m",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_span_m, + &FGEnvironmentMgr::set_cloud_layer_span_m); - _tiedProperties.Tie( layerNode->getNode("elevation-ft",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_elevation_ft, - &FGEnvironmentMgr::set_cloud_layer_elevation_ft); + _tiedProperties.Tie( layerNode->getNode("elevation-ft",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_elevation_ft, + &FGEnvironmentMgr::set_cloud_layer_elevation_ft); - _tiedProperties.Tie( layerNode->getNode("thickness-ft",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_thickness_ft, - &FGEnvironmentMgr::set_cloud_layer_thickness_ft); + _tiedProperties.Tie( layerNode->getNode("thickness-ft",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_thickness_ft, + &FGEnvironmentMgr::set_cloud_layer_thickness_ft); - _tiedProperties.Tie( layerNode->getNode("transition-ft",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_transition_ft, - &FGEnvironmentMgr::set_cloud_layer_transition_ft); + _tiedProperties.Tie( layerNode->getNode("transition-ft",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_transition_ft, + &FGEnvironmentMgr::set_cloud_layer_transition_ft); - _tiedProperties.Tie( layerNode->getNode("coverage",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_coverage, - &FGEnvironmentMgr::set_cloud_layer_coverage); + _tiedProperties.Tie( layerNode->getNode("coverage",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_coverage, + &FGEnvironmentMgr::set_cloud_layer_coverage); - _tiedProperties.Tie( layerNode->getNode("coverage-type",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_coverage_type, - &FGEnvironmentMgr::set_cloud_layer_coverage_type); + _tiedProperties.Tie( layerNode->getNode("coverage-type",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_coverage_type, + &FGEnvironmentMgr::set_cloud_layer_coverage_type); - _tiedProperties.Tie( layerNode->getNode( "visibility-m",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_visibility_m, - &FGEnvironmentMgr::set_cloud_layer_visibility_m); + _tiedProperties.Tie( layerNode->getNode( "visibility-m",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_visibility_m, + &FGEnvironmentMgr::set_cloud_layer_visibility_m); - _tiedProperties.Tie( layerNode->getNode( "alpha",true), this, i, - &FGEnvironmentMgr::get_cloud_layer_maxalpha, - &FGEnvironmentMgr::set_cloud_layer_maxalpha); + _tiedProperties.Tie( layerNode->getNode( "alpha",true), this, i, + &FGEnvironmentMgr::get_cloud_layer_maxalpha, + &FGEnvironmentMgr::set_cloud_layer_maxalpha); } _tiedProperties.setRoot( fgGetNode("/sim/rendering", true ) ); _tiedProperties.Tie( "clouds3d-enable", fgClouds, - &FGClouds::get_3dClouds, - &FGClouds::set_3dClouds); + &FGClouds::get_3dClouds, + &FGClouds::set_3dClouds); _tiedProperties.Tie( "clouds3d-density", thesky, - &SGSky::get_3dCloudDensity, - &SGSky::set_3dCloudDensity); + &SGSky::get_3dCloudDensity, + &SGSky::set_3dCloudDensity); _tiedProperties.Tie("clouds3d-vis-range", thesky, - &SGSky::get_3dCloudVisRange, - &SGSky::set_3dCloudVisRange); + &SGSky::get_3dCloudVisRange, + &SGSky::set_3dCloudVisRange); _tiedProperties.Tie("precipitation-enable", &sgEnviro, - &SGEnviro::get_precipitation_enable_state, - &SGEnviro::set_precipitation_enable_state); + &SGEnviro::get_precipitation_enable_state, + &SGEnviro::set_precipitation_enable_state); _tiedProperties.Tie("lightning-enable", &sgEnviro, - &SGEnviro::get_lightning_enable_state, - &SGEnviro::set_lightning_enable_state); + &SGEnviro::get_lightning_enable_state, + &SGEnviro::set_lightning_enable_state); sgEnviro.config(fgGetNode("/sim/rendering/precipitation")); } @@ -198,11 +202,38 @@ FGEnvironmentMgr::update (double dt) _environment->set_elevation_ft( _altitudeNode->getDoubleValue() ); simgear::Particles::setWindFrom( _environment->get_wind_from_heading_deg(), - _environment->get_wind_speed_kt() ); + _environment->get_wind_speed_kt() ); if( _cloudLayersDirty ) { _cloudLayersDirty = false; fgClouds->set_update_event( fgClouds->get_update_event()+1 ); } + + _positionTimeToLive -= dt; + if( _positionTimeToLive <= 0.0 ) + { + // update closest airport information + _positionTimeToLive = 30.0; + + SG_LOG(SG_ALL, SG_INFO, "FGEnvironmentMgr::update: updating closest airport"); + + SGGeod pos = SGGeod::fromDeg(_longitude_n->getDoubleValue(), + _latitude_n->getDoubleValue()); + + FGAirport * nearestAirport = FGAirport::findClosest(pos, 100.0); + if( nearestAirport == NULL ) + { + SG_LOG(SG_ALL,SG_WARN,"FGEnvironmentMgr::update: No airport within 100NM range"); + } + else + { + const string currentId = fgGetString("/sim/airport/closest-airport-id", ""); + if (currentId != nearestAirport->ident()) + { + fgSetString("/sim/airport/closest-airport-id", + nearestAirport->ident().c_str()); + } + } + } } FGEnvironment diff --git a/src/Environment/environment_mgr.hxx b/src/Environment/environment_mgr.hxx index e6041f813..67d929ec8 100644 --- a/src/Environment/environment_mgr.hxx +++ b/src/Environment/environment_mgr.hxx @@ -94,8 +94,11 @@ private: FGEnvironment * _environment; // always the same, for now FGClouds *fgClouds; - SGPropertyNode_ptr _altitudeNode; bool _cloudLayersDirty; + SGPropertyNode_ptr _altitudeNode; + SGPropertyNode_ptr _longitude_n; + SGPropertyNode_ptr _latitude_n; + double _positionTimeToLive; simgear::TiedPropertyList _tiedProperties; }; diff --git a/src/Instrumentation/groundradar.cxx b/src/Instrumentation/groundradar.cxx index ffa2e1fc9..c604cc43c 100644 --- a/src/Instrumentation/groundradar.cxx +++ b/src/Instrumentation/groundradar.cxx @@ -47,7 +47,7 @@ #include "groundradar.hxx" static const char* airport_source_node_name = "airport-id-source"; -static const char* default_airport_node_name = "/sim/tower/airport-id"; +static const char* default_airport_node_name = "/sim/airport/closest-airport-id"; static const char* texture_node_name = "texture-name"; static const char* default_texture_name = "Aircraft/Instruments/Textures/od_groundradar.rgb"; static const char* range_source_node_name = "range-source"; diff --git a/src/Main/fg_init.cxx b/src/Main/fg_init.cxx index 7d3e6ce28..bccabc3c9 100644 --- a/src/Main/fg_init.cxx +++ b/src/Main/fg_init.cxx @@ -794,14 +794,44 @@ static bool fgSetTowerPosFromAirportID( const string& id) { struct FGTowerLocationListener : SGPropertyChangeListener { void valueChanged(SGPropertyNode* node) { - const string id(node->getStringValue()); + string id(node->getStringValue()); + if (fgGetBool("/sim/tower/auto-position",true)) + { + // enforce using closest airport when auto-positioning is enabled + const char* closest_airport = fgGetString("/sim/airport/closest-airport-id", ""); + if (closest_airport && (id != closest_airport)) + { + id = closest_airport; + node->setStringValue(id); + } + } fgSetTowerPosFromAirportID(id); } }; +struct FGClosestTowerLocationListener : SGPropertyChangeListener +{ + void valueChanged(SGPropertyNode* ) + { + // closest airport has changed + if (fgGetBool("/sim/tower/auto-position",true)) + { + // update tower position + const char* id = fgGetString("/sim/airport/closest-airport-id", ""); + if (id && *id!=0) + fgSetString("/sim/tower/airport-id", id); + } + } +}; + void fgInitTowerLocationListener() { fgGetNode("/sim/tower/airport-id", true) ->addChangeListener( new FGTowerLocationListener(), true ); + FGClosestTowerLocationListener* ntcl = new FGClosestTowerLocationListener(); + fgGetNode("/sim/airport/closest-airport-id", true) + ->addChangeListener(ntcl , true ); + fgGetNode("/sim/tower/auto-position", true) + ->addChangeListener(ntcl, true ); } static void fgApplyStartOffset(const SGGeod& aStartPos, double aHeading, double aTargetHeading = HUGE_VAL) @@ -1164,6 +1194,7 @@ bool fgInitPosition() { // An airport + parking position is requested if ( fgSetPosFromAirportIDandParkpos( apt, parkpos ) ) { // set tower position + fgSetString("/sim/airport/closest-airport-id", apt.c_str()); fgSetString("/sim/tower/airport-id", apt.c_str()); set_pos = true; } @@ -1174,7 +1205,8 @@ bool fgInitPosition() { if ( fgSetPosFromAirportIDandRwy( apt, rwy_no, rwy_req ) ) { // set tower position (a little off the heading for single // runway airports) - fgSetString("/sim/tower/airport-id", apt.c_str()); + fgSetString("/sim/airport/closest-airport-id", apt.c_str()); + fgSetString("/sim/tower/airport-id", apt.c_str()); set_pos = true; } } @@ -1184,7 +1216,8 @@ bool fgInitPosition() { if ( fgSetPosFromAirportIDandHdg( apt, hdg ) ) { // set tower position (a little off the heading for single // runway airports) - fgSetString("/sim/tower/airport-id", apt.c_str()); + fgSetString("/sim/airport/closest-airport-id", apt.c_str()); + fgSetString("/sim/tower/airport-id", apt.c_str()); set_pos = true; } } diff --git a/src/Main/options.cxx b/src/Main/options.cxx index b4a3bc830..99ecbf43b 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -1150,12 +1150,22 @@ fgOptNAV2( const char * arg ) } static int -fgOptADF( const char * arg ) +fgOptADF1( const char * arg ) { double rot, freq; if (parse_colon(arg, &rot, &freq)) - fgSetDouble("/instrumentation/adf/rotation-deg", rot); - fgSetDouble("/instrumentation/adf/frequencies/selected-khz", freq); + fgSetDouble("/instrumentation/adf[0]/rotation-deg", rot); + fgSetDouble("/instrumentation/adf[0]/frequencies/selected-khz", freq); + return FG_OPTIONS_OK; +} + +static int +fgOptADF2( const char * arg ) +{ + double rot, freq; + if (parse_colon(arg, &rot, &freq)) + fgSetDouble("/instrumentation/adf[1]/rotation-deg", rot); + fgSetDouble("/instrumentation/adf[1]/frequencies/selected-khz", freq); return FG_OPTIONS_OK; } @@ -1493,7 +1503,9 @@ struct OptionDesc { {"com2", true, OPTION_DOUBLE, "/instrumentation/comm[1]/frequencies/selected-mhz", false, "", 0 }, {"nav1", true, OPTION_FUNC, "", false, "", fgOptNAV1 }, {"nav2", true, OPTION_FUNC, "", false, "", fgOptNAV2 }, - {"adf", true, OPTION_FUNC, "", false, "", fgOptADF }, + {"adf", /*legacy*/ true, OPTION_FUNC, "", false, "", fgOptADF1 }, + {"adf1", true, OPTION_FUNC, "", false, "", fgOptADF1 }, + {"adf2", true, OPTION_FUNC, "", false, "", fgOptADF2 }, {"dme", true, OPTION_FUNC, "", false, "", fgOptDME }, {"min-status", true, OPTION_STRING, "/sim/aircraft-min-status", false, "all", 0 }, {"livery", true, OPTION_FUNC, "", false, "", fgOptLivery },