Merge branch 'master' of git://gitorious.org/fg/fgdata
This commit is contained in:
commit
d6fafb5447
9 changed files with 546 additions and 132 deletions
|
@ -1,9 +1,107 @@
|
|||
Configuring 3D Clouds
|
||||
=====================
|
||||
|
||||
3D clouds are configured using the file data/cloudlayers.xml.
|
||||
3D clouds can be created in two ways:
|
||||
- By placing individual clouds using a command (e.g. from Nasal)
|
||||
- Using the global weather function, which reads cloud definition from
|
||||
an XML file.
|
||||
|
||||
This file has 3 distinct sections: layers, cloud boxes and clouds,
|
||||
Placing Clouds Individually
|
||||
===========================
|
||||
|
||||
Clouds are created using the "add-cloud" command, passing a property
|
||||
node defining the location and characterstics of the cloud.
|
||||
|
||||
Location is defined by the following properties:
|
||||
|
||||
<layer> - The cloud layer number to add the cloud to. (default 0)
|
||||
<index> - A unique identifier for the cloud in the layer. If a cloud
|
||||
already exists with this index, the new cloud will not be
|
||||
created, and 0 is returned.
|
||||
<lon-deg> - Longitude to place the cloud, in degrees (default 0)
|
||||
<lat-deg> - Latitude t place the cloud, in degrees (default 0)
|
||||
<alt-ft> - Altitude to place the cloud, relative to the layer (!) in ft
|
||||
(default 0)
|
||||
<x-offset-m> - Offset in m from the lon-deg. +ve is south (default 0)
|
||||
<y-offset-m> - Offset in m from the lat-deg. +ve is east (default 0)
|
||||
|
||||
The cloud itself is built up of a number of "sprites" - simple 2D textures
|
||||
that are always rotated to be facing the viewer. These sprites are handled
|
||||
by a OpenGL Shader - a small program that is run on your graphics card.
|
||||
|
||||
The cloud is defined by the following properties:
|
||||
|
||||
<min-cloud-width-m> - minimum width of the cloud in meters (default 500)
|
||||
<max-cloud-width-m> - maximum width of the cloud (default min-cloud-width-m)
|
||||
<min-cloud-height-m> - minimum height of the cloud (default min-cloud-width-m)
|
||||
<max-cloud-height-m> - maximum height of the cloud (default max-cloud-width-m)
|
||||
<texture> - texture file of sprites to use (default cl_cumulus.png)
|
||||
<num-textures-x> - number of cloud textures defined horizontally in the
|
||||
texture file (default 4)
|
||||
<num-textures-y> - number of cloud textures defined vertically in the
|
||||
texture file (default 4)
|
||||
<num-sprites> - Number of sprite to generate for the cloud (default 20)
|
||||
<bottom-shade> - Light multiplier for sprites at the bottom of the cloud
|
||||
(default 1.0)
|
||||
<min-sprite-width-m> - minimum width of the sprites used to create the cloud
|
||||
(default 200)
|
||||
<max-sprite-width-m> - maximum width of the sprites used to create the cloud
|
||||
(default min-sprite-width-m)
|
||||
<min-sprite-height-m> - minimum height of the spites used to create the cloud
|
||||
(default min-sprite-width-m)
|
||||
<max-sprite-height-m> - maximum height of the sprites used to create the cloud
|
||||
(default max-sprite-height-m)
|
||||
|
||||
The texture to use for the sprites is defined in the <texture> tag.
|
||||
To allow some variation, you can create a texture file containing multiple
|
||||
sprites in a grid, and define the <num-textures-x/y> tags. The code
|
||||
decides which texture to use for a given sprite : randomly in the x-direction
|
||||
and based on the altitude of the sprite within the cloud in the y-direction.
|
||||
Therefore, you should put sprite textures you want to use for the bottom of
|
||||
your cloud at the bottom of the texture file, and those you want to use for
|
||||
the top of the cloud at the top of the texture file.
|
||||
|
||||
For example, the following Nasal snippet will create a cloud immediately above the
|
||||
aircraft at an altitude of 1000 ft above /environment/clouds/layer[0]/elevation-ft :
|
||||
|
||||
var p = props.Node.new({ "layer" : 0,
|
||||
"index": 1,
|
||||
"lat-deg": getprop("/position/latitude-deg"),
|
||||
"lon-deg": getprop("/position/longitude-deg"),
|
||||
"alt-ft" : 1000 });
|
||||
fgcommand("add-cloud", p);
|
||||
|
||||
Moving Individual Clouds
|
||||
========================
|
||||
|
||||
Clouds may be moved by using the "move-cloud" command. This takes the following
|
||||
property arguments.
|
||||
|
||||
<layer> - The cloud layer number containing the cloud to move. (default 0)
|
||||
<index> - The unique identifier of the cloud to move.
|
||||
<lon-deg> - Longitude to place the cloud, in degrees (default 0)
|
||||
<lat-deg> - Latitude t place the cloud, in degrees (default 0)
|
||||
<alt-ft> - Altitude to place the cloud, relative to the layer (!) in ft
|
||||
(default 0)
|
||||
|
||||
TODO: Add offset arguments for consistency with add-cloud.
|
||||
|
||||
Deleting Individual Clouds
|
||||
===========================
|
||||
|
||||
Clouds may be deleted by using the "del-cloud" command. This takes the following
|
||||
property arguments.
|
||||
|
||||
<layer> - The cloud layer number containing the cloud to delet. (default 0)
|
||||
<index> - The unique identifier of the cloud to delete.
|
||||
|
||||
Global 3D Clouds
|
||||
================
|
||||
|
||||
The global weather system uses sets of clouds defined in cloudlayers.xml
|
||||
in your FG_ROOT.
|
||||
|
||||
The file has 3 distinct sections: layers, cloud boxes and clouds,
|
||||
described below.
|
||||
|
||||
Notes for those editing clouds:
|
||||
|
@ -23,41 +121,9 @@ Notes for those editing clouds:
|
|||
Clouds
|
||||
======
|
||||
|
||||
The <clouds> section contains definitions of clouds themselves, built
|
||||
up of a number of "sprites" - simple 2D textures that are always
|
||||
rotated to be facing the viewer. These sprites are handled by a OpenGL
|
||||
Shader - a small program that is run on your graphics card.
|
||||
|
||||
Sets of these clouds are be built up into bigger masses, described below.
|
||||
|
||||
Each cloud group has a completely user-defined name, and contains the
|
||||
following tags.
|
||||
|
||||
<min-cloud-width-m> - minimum width of the cloud
|
||||
<max-cloud-width-m> - maximum width of the cloud
|
||||
<min-cloud-height-m> - minimum height of the cloud
|
||||
<max-cloud-height-m> - maximum height of the cloud
|
||||
<texture> - texture file of sprites to use
|
||||
<num-textures-x> - number of cloud textures defined horizontally in the
|
||||
texture file
|
||||
<num-textures-y> - number of cloud textures defined vertically in the
|
||||
texture file
|
||||
<num-sprites> - Number of sprite to generate for the cloud
|
||||
<bottom-shade> - Light multiplier for sprites at the bottom of the cloud.
|
||||
<min-sprite-width-m> - minimum width of the sprites used to create the cloud
|
||||
<max-sprite-width-m> - maximum width of the sprites used to create the cloud
|
||||
<min-sprite-height-m> - minimum height of the spites used to create the cloud
|
||||
<max-sprite-height-m> - maximum height of the sprites used to create the cloud
|
||||
|
||||
|
||||
The texture to use for the sprites is defined in the XML <texture> tag.
|
||||
To allow some variation, you can create a texture file containing multiple
|
||||
sprites in a grid, and define the <num-textures-x/y> tags. The code
|
||||
decides which texture to use for a given sprite : randomly in the x-direction
|
||||
and based on the altitude of the sprite within the cloud in the y-direction.
|
||||
Therefore, you should put sprite textures you want to use for the bottom of
|
||||
your cloud at the bottom of the texture file, and those you want to use for
|
||||
the top of the cloud at the top of the texture file.
|
||||
The cloud definitions are as described above for placing individual
|
||||
clouds, but no position information is used (this is defined in the
|
||||
cloud box and layers below).
|
||||
|
||||
Cloud Boxes
|
||||
===========
|
||||
|
@ -81,7 +147,7 @@ Each <box> section contains the following tags:
|
|||
<hdist> - The horizontal distribution of the clouds within the area.
|
||||
Equates to a sum of random distributions. Defaults to 1.
|
||||
1 = even distribution, 2 = distributed towards the center.
|
||||
3 = very strongly distributed towards the center.
|
||||
3 = very strongly distributed towards the center.
|
||||
<vdist> - The vertical distribution of the clouds. As for hdist.
|
||||
|
||||
|
||||
|
@ -117,7 +183,7 @@ The layer type is derived from the METAR/Weather settings by FG itself.
|
|||
Each layer type is a named XML tag, i.e.: ns, sc, st, ac, cb, cu.
|
||||
If a layer type is not defined, then a 2D layer is used instead.
|
||||
|
||||
The layer type contains one or more <cloud> definitions. This
|
||||
The layer type contains one or more <cloud> definitions. This
|
||||
defines a type of cloud box, and a weighting for that type (<count>).
|
||||
|
||||
For example, the following XML fragment will produce 3 "cb" cloud boxes
|
||||
|
@ -134,4 +200,4 @@ for every 1 "cu":
|
|||
|
||||
Clouds are randomly distributed across the sky in the x/y plane, but the
|
||||
height of them is set by the weather conditions, with a random height range
|
||||
applied, defined by <grid-z-rand>
|
||||
applied, defined by <grid-z-rand>
|
||||
|
|
|
@ -1047,6 +1047,93 @@ var HUD = {
|
|||
},
|
||||
};
|
||||
|
||||
# crossfeed_valve
|
||||
# =============================================================================
|
||||
# class that creates a fuel tank cross-feed valve. Designed for YASim aircraft;
|
||||
# JSBSim aircraft can simply use systems code within the FDM (see 747-400 for
|
||||
# an example).
|
||||
#
|
||||
# WARNING: this class requires the tank properties to be ready, so call new()
|
||||
# after the FDM is initialized.
|
||||
#
|
||||
# SYNOPSIS:
|
||||
# crossfeed_valve.new(<max_flow_rate>, <property>, <tank>, <tank>, ... );
|
||||
# crossfeed_valve.open(<update>);
|
||||
# crossfeed_valve.close(<update>);
|
||||
#
|
||||
# <max_flow_rate> ... maximum transfer rate between the tanks in lbs/sec
|
||||
# <property> ... property path to use as switch - pass nil to use no such switch
|
||||
# <tank> ... number of a tank to connect - can have unlimited number of tanks connected
|
||||
# <update> ... update switch property when opening/closing valve via Nasal - 0 or 1; by default, 1
|
||||
#
|
||||
#
|
||||
# EXAMPLES:
|
||||
# aircraft.crossfeed_valve.new(0.5, "/controls/fuel/x-feed", 0, 1, 2);
|
||||
#-------
|
||||
# var xfeed = aircraft.crossfeed_valve.new(1, nil, 0, 1);
|
||||
# xfeed.open();
|
||||
#
|
||||
var crossfeed_valve = {
|
||||
new: func(flow_rate, path) {
|
||||
var m = { parents: [crossfeed_valve] };
|
||||
m.valve_open = 0;
|
||||
m.interval = 0.5;
|
||||
m.loopid = -1;
|
||||
m.flow_rate = flow_rate;
|
||||
if (path != nil) {
|
||||
m.switch_node = props.globals.initNode(path, 0, "BOOL");
|
||||
setlistener(path, func(node) {
|
||||
if (node.getBoolValue()) m.open(0);
|
||||
else m.close(0);
|
||||
}, 1, 0);
|
||||
}
|
||||
m.tanks = [];
|
||||
for (var i = 0; i < size(arg); i += 1) {
|
||||
var tank = props.globals.getNode("consumables/fuel/tank[" ~ arg[i] ~ "]");
|
||||
if (tank.getChild("level-lbs") != nil) append(m.tanks, tank);
|
||||
}
|
||||
return m;
|
||||
},
|
||||
open: func(update_prop = 1) {
|
||||
if (me.valve_open == 1) return;
|
||||
if (update_prop and contains(me, "switch_node")) me.switch_node.setBoolValue(1);
|
||||
me.valve_open = 1;
|
||||
me.loopid += 1;
|
||||
settimer(func me._loop_(me.loopid), me.interval);
|
||||
},
|
||||
close: func(update_prop = 1) {
|
||||
if (update_prop and contains(me, "switch_node")) me.switch_node.setBoolValue(0);
|
||||
me.valve_open = 0;
|
||||
},
|
||||
_loop_: func(id) {
|
||||
if (id != me.loopid) return;
|
||||
var average_level = 0;
|
||||
var count = size(me.tanks);
|
||||
for (var i = 0; i < count; i += 1) {
|
||||
var level_node = me.tanks[i].getChild("level-lbs");
|
||||
average_level += level_node.getValue();
|
||||
}
|
||||
average_level /= size(me.tanks);
|
||||
var highest_diff = 0;
|
||||
for (var i = 0; i < count; i += 1) {
|
||||
var level = me.tanks[i].getChild("level-lbs").getValue();
|
||||
var diff = math.abs(average_level - level);
|
||||
if (diff > highest_diff) highest_diff = diff;
|
||||
}
|
||||
for (var i = 0; i < count; i += 1) {
|
||||
var level_node = me.tanks[i].getChild("level-lbs");
|
||||
var capacity = me.tanks[i].getChild("capacity-gal_us").getValue() * me.tanks[i].getChild("density-ppg").getValue();
|
||||
var diff = math.abs(average_level - level_node.getValue());
|
||||
var min_level = math.max(0, level_node.getValue() - me.flow_rate * diff / highest_diff);
|
||||
var max_level = math.min(capacity, level_node.getValue() + me.flow_rate * diff / highest_diff);
|
||||
var level = level_node.getValue() > average_level ? math.max(min_level, average_level) : math.min(max_level, average_level);
|
||||
level_node.setValue(level);
|
||||
}
|
||||
if (me.valve_open) settimer(func me._loop_(id), me.interval);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
# module initialization
|
||||
|
|
|
@ -87,12 +87,24 @@ else
|
|||
{result = "yes"; features.terrain_presampling = 1;}
|
||||
print("* hard coded terrain presampling: "~result);
|
||||
|
||||
if ((props.globals.getNode("/environment/terrain/area[0]/enabled",1).getBoolValue() == 1) and (features.terrain_presampling ==1))
|
||||
{result = "yes"; features.terrain_presampling_active = 1;}
|
||||
else
|
||||
{result = "no"; features.terrain_presampling_active = 0;}
|
||||
print("* terrain presampling initialized: "~result);
|
||||
|
||||
|
||||
if (props.globals.getNode("/environment/config/enabled", 0) == nil)
|
||||
{result = "no"; features.can_disable_environment = 0;}
|
||||
else
|
||||
{result = "yes"; features.can_disable_environment = 1;}
|
||||
print("* can disable global weather: "~result);
|
||||
|
||||
#if (features.terrain_presampling_active == 1)
|
||||
# {
|
||||
# setlistener("/environment/terrain/area[0]/output/valid", func {local_weather.manage_hardcoded_presampling(); });
|
||||
# }
|
||||
|
||||
print("Compatibility layer: tests done.");
|
||||
});
|
||||
|
||||
|
|
|
@ -323,7 +323,6 @@ return res;
|
|||
|
||||
var wind_interpolation = func (lat, lon, alt) {
|
||||
|
||||
# var windNodes = props.globals.getNode(lw~"interpolation").getChildren("wind");
|
||||
var sum_norm = 0;
|
||||
var sum_wind = [0,0];
|
||||
|
||||
|
@ -331,8 +330,6 @@ var wsize = size(windIpointArray);
|
|||
|
||||
for (var i = 0; i < wsize; i=i+1) {
|
||||
|
||||
#var wlat = w.getNode("latitude-deg").getValue();
|
||||
#var wlon = w.getNode("longitude-deg").getValue();
|
||||
|
||||
var w = windIpointArray[i];
|
||||
|
||||
|
@ -403,9 +400,11 @@ else
|
|||
var f_slow = 1.0 - (0.2 + 0.17 * math.ln(boundary_alt/base_layer_thickness));
|
||||
}
|
||||
|
||||
print("Boundary layer thickness: ",base_layer_thickness);
|
||||
print("Boundary layer slowdown: ", f_slow);
|
||||
|
||||
if (debug_output_flag == 1)
|
||||
{
|
||||
print("Boundary layer thickness: ",base_layer_thickness);
|
||||
print("Boundary layer slowdown: ", f_slow);
|
||||
}
|
||||
return f_slow;
|
||||
}
|
||||
|
||||
|
@ -486,7 +485,7 @@ for (var i = 0; i < n_stations; i=i+1) {
|
|||
}
|
||||
}
|
||||
|
||||
setprop(lwi~"station-number", i);
|
||||
setprop(lwi~"station-number", i+1);
|
||||
|
||||
|
||||
var ialt = sum_alt/sum_norm;
|
||||
|
@ -2690,7 +2689,10 @@ for (var i=0; i<n_bottom; i=i+1)
|
|||
|
||||
var terrain_presampling_start = func (blat, blon, nc, size, alpha) {
|
||||
|
||||
|
||||
# terrain presampling start is always used the first time, and initializes
|
||||
# the hard-coded routine if that is available since the hard-coded routine cannot
|
||||
# be yet read out on startup
|
||||
|
||||
# initialize the result vector
|
||||
|
||||
setsize(terrain_n,20);
|
||||
|
@ -2716,6 +2718,20 @@ else
|
|||
terrain_presampling_analysis();
|
||||
setprop(lw~"tmp/presampling-status", "finished");
|
||||
}
|
||||
|
||||
if (compat_layer.features.terrain_presampling_active == 1)
|
||||
{
|
||||
print("Starting hard-coded terrain presampling");
|
||||
|
||||
setprop(lw~"tmp/presampling-status", "sampling");
|
||||
setprop("/environment/terrain/area[0]/input/latitude-deg", blat );
|
||||
setprop("/environment/terrain/area[0]/input/longitude-deg", blon );
|
||||
setprop("/environment/terrain/area[0]/input/use-aircraft-position",1);
|
||||
setprop("/environment/terrain/area[0]/input/radius-m",45000.0);
|
||||
|
||||
setprop("/environment/terrain/area[0]/output/valid", 0 );
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
###########################################################
|
||||
|
@ -2803,63 +2819,72 @@ for (i=0; i<ntries;i=i+1)
|
|||
|
||||
var terrain_presampling_analysis = func {
|
||||
|
||||
var sum = 0;
|
||||
var alt_mean = 0;
|
||||
var alt_med = 0;
|
||||
var alt_20 = 0;
|
||||
var alt_min = 0;
|
||||
var alt_low_min = 0;
|
||||
var alt_offset = 0;
|
||||
|
||||
# for (var i=0;i<20;i=i+1){print(500.0*i," ",terrain_n[i]);}
|
||||
|
||||
for (var i=0; i<20;i=i+1)
|
||||
{sum = sum + terrain_n[i];}
|
||||
|
||||
var n_tot = sum;
|
||||
|
||||
sum = 0;
|
||||
for (var i=0; i<20;i=i+1)
|
||||
if ((compat_layer.features.terrain_presampling_active == 0) or (getprop(lw~"tiles/tile-counter") == 0))
|
||||
{
|
||||
sum = sum + terrain_n[i];
|
||||
if (sum > int(0.5 *n_tot)) {alt_med = i * 500.0; break;}
|
||||
var sum = 0;
|
||||
var alt_mean = 0;
|
||||
var alt_med = 0;
|
||||
var alt_20 = 0;
|
||||
var alt_min = 0;
|
||||
var alt_low_min = 0;
|
||||
|
||||
|
||||
for (var i=0; i<20;i=i+1)
|
||||
{sum = sum + terrain_n[i];}
|
||||
|
||||
var n_tot = sum;
|
||||
|
||||
sum = 0;
|
||||
for (var i=0; i<20;i=i+1)
|
||||
{
|
||||
sum = sum + terrain_n[i];
|
||||
if (sum > int(0.5 *n_tot)) {alt_med = i * 500.0; break;}
|
||||
}
|
||||
|
||||
sum = 0;
|
||||
for (var i=0; i<20;i=i+1)
|
||||
{
|
||||
sum = sum + terrain_n[i];
|
||||
if (sum > int(0.3 *n_tot)) {alt_20 = i * 500.0; break;}
|
||||
}
|
||||
|
||||
|
||||
for (var i=0; i<20;i=i+1) {alt_mean = alt_mean + terrain_n[i] * i * 500.0;}
|
||||
alt_mean = alt_mean/n_tot;
|
||||
|
||||
for (var i=0; i<20;i=i+1) {if (terrain_n[i] > 0) {alt_min = i * 500.0; break;}}
|
||||
|
||||
var n_max = 0;
|
||||
sum = 0;
|
||||
|
||||
for (var i=0; i<19;i=i+1)
|
||||
{
|
||||
sum = sum + terrain_n[i];
|
||||
if (terrain_n[i] > n_max) {n_max = terrain_n[i];}
|
||||
if ((n_max > terrain_n[i+1]) and (sum > int(0.3*n_tot)))
|
||||
{alt_low_min = i * 500; break;}
|
||||
}
|
||||
}
|
||||
|
||||
sum = 0;
|
||||
for (var i=0; i<20;i=i+1)
|
||||
else
|
||||
{
|
||||
sum = sum + terrain_n[i];
|
||||
if (sum > int(0.3 *n_tot)) {alt_20 = i * 500.0; break;}
|
||||
}
|
||||
|
||||
|
||||
for (var i=0; i<20;i=i+1) {alt_mean = alt_mean + terrain_n[i] * i * 500.0;}
|
||||
alt_mean = alt_mean/n_tot;
|
||||
|
||||
for (var i=0; i<20;i=i+1) {if (terrain_n[i] > 0) {alt_min = i * 500.0; break;}}
|
||||
|
||||
var n_max = 0;
|
||||
sum = 0;
|
||||
|
||||
for (var i=0; i<19;i=i+1)
|
||||
{
|
||||
sum = sum + terrain_n[i];
|
||||
if (terrain_n[i] > n_max) {n_max = terrain_n[i];}
|
||||
if ((n_max > terrain_n[i+1]) and (sum > int(0.3*n_tot)))
|
||||
{alt_low_min = i * 500; break;}
|
||||
#print("Hard-coded sampling...");
|
||||
var n_tot = getprop("/environment/terrain/area[0]/input/max-samples");
|
||||
var alt_mean = getprop("/environment/terrain/area[0]/output/alt-mean-ft");
|
||||
var alt_med = getprop("/environment/terrain/area[0]/output/alt-median-ft");
|
||||
var alt_min = getprop("/environment/terrain/area[0]/output/alt-min-ft");
|
||||
var alt_20 = getprop("/environment/terrain/area[0]/output/alt-offset-ft");
|
||||
}
|
||||
|
||||
if (debug_output_flag == 1)
|
||||
{print("Terrain presampling analysis results:");
|
||||
print("total: ",n_tot," mean: ",alt_mean," median: ",alt_med," min: ",alt_min, " alt_20: ", alt_20);}
|
||||
|
||||
#if (alt_low_min < alt_med) {alt_offset = alt_low_min;}
|
||||
#else {alt_offset = alt_med;}
|
||||
|
||||
|
||||
setprop(lw~"tmp/tile-alt-offset-ft",alt_20);
|
||||
setprop(lw~"tmp/tile-alt-median-ft",alt_med);
|
||||
setprop(lw~"tmp/tile-alt-min-ft",alt_min);
|
||||
setprop(lw~"tmp/tile-alt-layered-ft",0.5 * (alt_min + alt_offset));
|
||||
setprop(lw~"tmp/tile-alt-layered-ft",0.5 * (alt_min + alt_20));
|
||||
|
||||
append(alt_50_array, alt_med);
|
||||
append(alt_20_array, alt_20);
|
||||
|
@ -2945,8 +2970,11 @@ return balt + shift_strength * alt_diff * fraction;
|
|||
|
||||
var manage_presampling = func {
|
||||
|
||||
|
||||
|
||||
var status = getprop(lw~"tmp/presampling-status");
|
||||
|
||||
|
||||
# we only take action when the analysis is done
|
||||
if (status != "finished") {return;}
|
||||
|
||||
|
@ -2969,6 +2997,32 @@ else # the tile setup call came from weather_tile_management
|
|||
|
||||
setprop(lw~"tmp/presampling-status", "idle");
|
||||
|
||||
}
|
||||
|
||||
|
||||
###########################################################
|
||||
# hardcoded terrain presampling listener dispatcher
|
||||
###########################################################
|
||||
|
||||
var manage_hardcoded_presampling = func {
|
||||
|
||||
var status = getprop("/environment/terrain/area[0]/enabled");
|
||||
|
||||
print("Hard-coded terrain presampling status: ", status);
|
||||
|
||||
# no action unless the sampler has finished
|
||||
if (status ==0) {return;}
|
||||
|
||||
# no action if the sampler hasn't been started
|
||||
|
||||
if (getprop(lw~"tmp/presampling-status") != "sampling") {return;}
|
||||
|
||||
terrain_presampling_analysis();
|
||||
if (debug_output_flag == 1)
|
||||
{print("Presampling done!");}
|
||||
setprop(lw~"tmp/presampling-status", "finished");
|
||||
|
||||
|
||||
}
|
||||
|
||||
###########################################################
|
||||
|
@ -3800,25 +3854,12 @@ var lon = getprop("position/longitude-deg");
|
|||
|
||||
var pos = geo.aircraft_position();
|
||||
|
||||
props.globals.getNode("/environment/terrain/area/enabled",1).setBoolValue(1);
|
||||
|
||||
setprop("/environment/terrain/area/input/analyse-every",200);
|
||||
setprop("/environment/terrain/area/input/elevation-histogram-count",20);
|
||||
setprop("/environment/terrain/area/input/elevation-histogram-max-ft",10000);
|
||||
setprop("/environment/terrain/area/input/elevation-histogram-step-ft",500);
|
||||
setprop("/environment/terrain/area/input/heading-deg",0.0);
|
||||
setprop("/environment/terrain/area/input/speed-kt",-.0);
|
||||
setprop("/environment/terrain/area/input/latitude-deg",lat);
|
||||
setprop("/environment/terrain/area/input/longitude-deg",lon);
|
||||
setprop("/environment/terrain/area/input/max-samples",1000);
|
||||
setprop("/environment/terrain/area/input/max-samples-per-frame",20);
|
||||
setprop("/environment/terrain/area/input/orientation-deg",0);
|
||||
setprop("/environment/terrain/area/input/radius-m",40000);
|
||||
setprop("/environment/terrain/area[0]/input/latitude-deg", lat );
|
||||
setprop("/environment/terrain/area[0]/input/longitude-deg", lon );
|
||||
|
||||
props.globals.getNode("/environment/terrain/area/input/use-aircraft-position",1).setBoolValue(0);
|
||||
setprop("/environment/terrain/area[0]/output/valid", 0 );
|
||||
|
||||
|
||||
fgcommand("reinit", props.Node.new({subsystem:"environment"}));
|
||||
}
|
||||
|
||||
|
||||
|
@ -4057,7 +4098,7 @@ var ec = "/environment/config/";
|
|||
|
||||
# a hash map of the strength for convection associated with terrain types
|
||||
|
||||
var landcover_map = {BuiltUpCover: 0.35, Town: 0.35, Freeway:0.35, BarrenCover:0.3, HerbTundraCover: 0.25, GrassCover: 0.2, CropGrassCover: 0.2, EvergreenBroadCover: 0.2, EvergreenNeedleCover: 0.2, Sand: 0.25, Grass: 0.2, Ocean: 0.01, Marsh: 0.05, Lake: 0.01, ShrubCover: 0.15, Landmass: 0.2, CropWoodCover: 0.15, MixedForestCover: 0.1, DryCropPastureCover: 0.25, MixedCropPastureCover: 0.2, IrrCropPastureCover: 0.15, DeciduousBroadCover: 0.1, Bog: 0.05, pa_taxiway : 0.35, pa_tiedown: 0.35, pc_taxiway: 0.35, pc_tiedown: 0.35, Glacier: 0.01, DryLake: 0.3, IntermittentStream: 0.2};
|
||||
var landcover_map = {BuiltUpCover: 0.35, Town: 0.35, Freeway:0.35, BarrenCover:0.3, HerbTundraCover: 0.25, GrassCover: 0.2, CropGrassCover: 0.2, EvergreenBroadCover: 0.2, EvergreenNeedleCover: 0.2, Sand: 0.25, Grass: 0.2, Ocean: 0.01, Marsh: 0.05, Lake: 0.01, ShrubCover: 0.15, Landmass: 0.2, CropWoodCover: 0.15, MixedForestCover: 0.1, DryCropPastureCover: 0.25, MixedCropPastureCover: 0.2, IrrCropPastureCover: 0.15, DeciduousBroadCover: 0.1, DeciduousNeedleCover: 0.1, Bog: 0.05, pa_taxiway : 0.35, pa_tiedown: 0.35, pc_taxiway: 0.35, pc_tiedown: 0.35, Glacier: 0.01, DryLake: 0.3, IntermittentStream: 0.2};
|
||||
|
||||
# a hash map of average vertical cloud model sizes
|
||||
|
||||
|
|
|
@ -2,6 +2,31 @@ var abs = func(n) { n < 0 ? -n : n }
|
|||
|
||||
var sgn = func(x) { x < 0 ? -1 : x > 0 }
|
||||
|
||||
var max = func(x) {
|
||||
var n = x;
|
||||
for (var i = 0; i < size(arg); i += 1) {
|
||||
if (arg[i] > n) n = arg[i];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
var min = func(x) {
|
||||
var n = x;
|
||||
for (var i = 0; i < size(arg); i += 1) {
|
||||
if (arg[i] < n) n = arg[i];
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
var avg = func {
|
||||
var x = 0;
|
||||
for (var i = 0; i < size(arg); i += 1) {
|
||||
x += arg[i];
|
||||
}
|
||||
x /= size(arg);
|
||||
return x;
|
||||
}
|
||||
|
||||
var pow = func(x, y) { exp(y * ln(x)) }
|
||||
|
||||
var mod = func(n, m) {
|
||||
|
|
|
@ -411,11 +411,13 @@ if (((local_weather.presampling_flag == 1) and (getprop(lw~"tmp/presampling-stat
|
|||
|
||||
# now see if we need to presample the terrain
|
||||
|
||||
if ((local_weather.presampling_flag == 1) and (getprop(lw~"tmp/presampling-status") == "idle"))
|
||||
if ((local_weather.presampling_flag == 1) and (getprop(lw~"tmp/presampling-status") == "idle") and (compat_layer.features.terrain_presampling_active == 0))
|
||||
{
|
||||
local_weather.terrain_presampling_start(lat, lon, 1000, 40000, getprop(lw~"tmp/tile-orientation-deg"));
|
||||
return;
|
||||
}
|
||||
else if (compat_layer.features.terrain_presampling_active == 1)# we have hard-coded values available and use those
|
||||
{local_weather.terrain_presampling_analysis();}
|
||||
|
||||
|
||||
if (local_weather.debug_output_flag == 1)
|
||||
|
@ -439,6 +441,7 @@ if (getprop(lw~"tmp/tile-management") == "repeat tile")
|
|||
else if (code == "cold_sector") {weather_tiles.set_cold_sector_tile();}
|
||||
else if (code == "warm_sector") {weather_tiles.set_warm_sector_tile();}
|
||||
else if (code == "tropical_weather") {weather_tiles.set_tropical_weather_tile();}
|
||||
#else if (code == "test") {weather_tiles.set_4_8_stratus_tile;}
|
||||
else
|
||||
{
|
||||
print("Repeat tile not implemented with this tile type!");
|
||||
|
@ -916,7 +919,7 @@ if ((index == 2) or (index == 5) or (index == 8)) {x = 40000.0;}
|
|||
if ((index == 0) or (index == 1) or (index == 2)) {y = 40000.0;}
|
||||
if ((index == 6) or (index == 7) or (index == 8)) {y = -40000.0;}
|
||||
|
||||
var t = props.globals.getNode(lw~"tiles").getChild("tile",index,0);
|
||||
var t = props.globals.getNode(lw~"tiles").getChild("tile",index,1);
|
||||
|
||||
# use the last built tile code as default, in case a tile isn't formed when reached,
|
||||
# the code is not empty but has a plausible value
|
||||
|
@ -1263,6 +1266,73 @@ var i = 0;
|
|||
|
||||
print("====================");
|
||||
|
||||
var viewpos = geo.aircraft_position();
|
||||
var n_stations = size(local_weather.weatherStationArray);
|
||||
|
||||
var sum_T = 0.0;
|
||||
var sum_p = 0.0;
|
||||
var sum_D = 0.0;
|
||||
var sum_norm = 0.0;
|
||||
|
||||
var sum_wind = [0,0];
|
||||
|
||||
var wsize = size(local_weather.windIpointArray);
|
||||
|
||||
var alt = getprop("position/altitude-ft");
|
||||
|
||||
for (var i = 0; i < wsize; i=i+1) {
|
||||
|
||||
|
||||
var w = local_weather.windIpointArray[i];
|
||||
|
||||
var wpos = geo.Coord.new();
|
||||
wpos.set_latlon(w.lat,w.lon,1000.0);
|
||||
|
||||
|
||||
|
||||
var d = viewpos.distance_to(wpos);
|
||||
if (d <100.0) {d = 100.0;} # to prevent singularity at zero
|
||||
|
||||
sum_norm = sum_norm + (1./d);
|
||||
|
||||
var res = local_weather.wind_altitude_interpolation(alt,w);
|
||||
|
||||
sum_wind = local_weather.add_vectors(sum_wind[0], sum_wind[1], res[0], (res[1]/d));
|
||||
|
||||
print(i, " dir: ", res[0], " speed: ", res[1], " d: ",d);
|
||||
}
|
||||
|
||||
print("dir_int: ", sum_wind[0], " speed_int: ", sum_wind[1]/sum_norm);
|
||||
|
||||
if (0==1)
|
||||
{
|
||||
for (var i = 0; i < n_stations; i=i+1) {
|
||||
|
||||
s = local_weather.weatherStationArray[i];
|
||||
|
||||
|
||||
var stpos = geo.Coord.new();
|
||||
stpos.set_latlon(s.lat,s.lon,0.0);
|
||||
|
||||
var d = viewpos.distance_to(stpos);
|
||||
if (d <100.0) {d = 100.0;} # to prevent singularity at zero
|
||||
|
||||
sum_norm = sum_norm + 1./d * s.weight;
|
||||
|
||||
sum_T = sum_T + (s.T/d) * s.weight;
|
||||
sum_D = sum_D + (s.D/d) * s.weight;
|
||||
sum_p = sum_p + (s.p/d) * s.weight;
|
||||
|
||||
print(i, " p: ", s.p, " T: ", s.T, " D: ", s.D, " d: ",d);
|
||||
|
||||
}
|
||||
|
||||
print("p_int: ", sum_p/sum_norm, " T_int: ", sum_T/sum_norm, " D_int: ", sum_D/sum_norm);
|
||||
}
|
||||
|
||||
if (0==1)
|
||||
{
|
||||
|
||||
foreach(t; tNode)
|
||||
{
|
||||
var code = t.getNode("code").getValue();
|
||||
|
@ -1283,6 +1353,8 @@ var res = local_weather.wind_interpolation(lat,lon,0.0);
|
|||
|
||||
print("Wind: ", res[0], " tile alpha: ", getprop(lw~"tiles/tile[4]/orientation-deg"));
|
||||
print("Mismatch: ", relangle(res[0], getprop(lw~"tiles/tile[4]/orientation-deg")));
|
||||
}
|
||||
|
||||
|
||||
print("====================");
|
||||
|
||||
|
|
|
@ -95,6 +95,7 @@ calc_geo(blat);
|
|||
|
||||
local_weather.set_weather_station(blat, blon, alt_offset, 20000.0, 14.0, 12.0, 29.78);
|
||||
|
||||
create_8_8_nimbus_var3(blat, blon, 2000.0 + alt_offset+local_weather.cloud_vertical_size_map["Nimbus"] * 0.5 * m_to_ft, 0.0);
|
||||
|
||||
#create_2_8_sstratus_streak(blat, blon,5000.0,0.0);
|
||||
|
||||
|
@ -106,10 +107,11 @@ local_weather.set_weather_station(blat, blon, alt_offset, 20000.0, 14.0, 12.0, 2
|
|||
|
||||
#create_detailed_stratocumulus_bank(blat, blon,5000.0+alt_offset,0.0);
|
||||
|
||||
create_4_8_altocumulus_perlucidus(blat, blon, 10000.0, 0.0);
|
||||
#create_4_8_altocumulus_perlucidus(blat, blon, 10000.0, 0.0);
|
||||
|
||||
local_weather.create_effect_volume(3, blat, blon, 20000.0, 7000.0, alpha, 0.0, 80000.0, -1, -1, -1, -1, 15.0, -3,-1);
|
||||
#local_weather.create_effect_volume(3, blat, blon, 20000.0, 7000.0, alpha, 0.0, 80000.0, -1, -1, -1, -1, 15.0, -3,-1);
|
||||
|
||||
create_1_8_contrails(blat, blon, 30000.0, 0.0);
|
||||
|
||||
# store convective altitude and strength
|
||||
|
||||
|
@ -2121,7 +2123,7 @@ var set_METAR_weather_station = func {
|
|||
|
||||
# if we use aloft interpolated winds with METAR, also set a new wind interpolation point
|
||||
|
||||
if (local_weather.wind_model_flag == 5)
|
||||
if ((local_weather.wind_model_flag == 5) and (getprop(lw~"tiles/tile-counter") !=1))
|
||||
{
|
||||
# if zero winds are reported, we do not rotate the tile to face north but use the last value
|
||||
|
||||
|
@ -2187,19 +2189,84 @@ local_weather.create_streak("Cirrostratus",lat,lon,alt,500.0,30,1250.0,0.0,400.0
|
|||
var create_8_8_nimbus = func (lat, lon, alt, alpha) {
|
||||
|
||||
local_weather.create_streak("Nimbus",lat, lon, alt,500.0,32,1250.0,0.0,200.0,32,1250.0,0.0,200.0,alpha,1.0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
var create_8_8_nimbus_var1 = func (lat, lon, alt, alpha) {
|
||||
|
||||
var phi = alpha * math.pi/180.0;
|
||||
|
||||
local_weather.create_streak("Nimbus",lat, lon, alt,500.0,35,1111.0,0.0,200.0,35,1111.0,0.0,200.0,alpha,1.0);
|
||||
|
||||
for (var i = 0; i < 3; i=i+1)
|
||||
{
|
||||
var x = -15000.0 + 30000.0 * rand();
|
||||
var y = -15000.0 + 30000.0 * rand();
|
||||
local_weather.create_streak("Stratocumulus",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt+600.0,200.0,11,1100.0,0.1,800.0,8,1100.0,0.1,800.0,alpha,1.4);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
var create_8_8_nimbus_var2 = func (lat, lon, alt, alpha) {
|
||||
|
||||
var phi = alpha * math.pi/180.0;
|
||||
|
||||
local_weather.create_streak("Nimbus",lat, lon, alt,500.0,35,1111.0,0.0,200.0,35,1111.0,0.0,200.0,alpha,1.0);
|
||||
|
||||
for (var i=0; i<8; i=i+1)
|
||||
{
|
||||
var x = 2.0 * (rand()-0.5) * 18000;
|
||||
var y = 2.0 * (rand()-0.5) * 18000;
|
||||
var beta = (rand() -0.5) * 180.0;
|
||||
local_weather.create_streak("Stratus (structured)",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt+1200.0,300.0,5,900.0,0.2,500.0,7,900.0,0.2,500.0,alpha+beta,1.0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
var create_8_8_nimbus_var3 = func (lat, lon, alt, alpha) {
|
||||
|
||||
var phi = alpha * math.pi/180.0;
|
||||
|
||||
local_weather.create_streak("Nimbus",lat, lon, alt,500.0,35,1111.0,0.0,200.0,35,1111.0,0.0,200.0,alpha,1.0);
|
||||
|
||||
for (var i=0; i<6; i=i+1)
|
||||
{
|
||||
var x = 2.0 * (rand()-0.5) * 18000;
|
||||
var y = 2.0 * (rand()-0.5) * 18000;
|
||||
var beta = (rand() -0.5) * 180.0;
|
||||
local_weather.create_streak("Stratus",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt+1600.0,300.0,6,1200.0,0.2,700.0,6,1200.0,0.2,700.0,alpha+beta,1.0);
|
||||
}
|
||||
|
||||
# reduced visibility in layer
|
||||
#local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, alt-1500.0, alt+900.0, 2000.0, -1 , -1, -1, -1,0 ,-1);
|
||||
# cloud shade
|
||||
#local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, 0.0, alt, -1, -1 , -1, -1, -1,0 ,0.8);
|
||||
|
||||
}
|
||||
|
||||
var create_8_8_nimbus_rain = func (lat, lon, alt, alpha, rain) {
|
||||
|
||||
local_weather.create_streak("Nimbus",lat, lon, alt,500.0,32,1250.0,0.0,200.0,32,1250.0,0.0,200.0,alpha,1.0);
|
||||
if (local_weather.detailed_clouds_flag == 0)
|
||||
{local_weather.create_streak("Nimbus",lat, lon, alt,500.0,32,1250.0,0.0,200.0,32,1250.0,0.0,200.0,alpha,1.0);}
|
||||
else
|
||||
{
|
||||
var rn = rand();
|
||||
if (rn > 0.66) {create_8_8_nimbus_var1(lat, lon, alt, alpha);}
|
||||
else if (rn > 0.33) {create_8_8_nimbus_var2(lat, lon, alt, alpha);}
|
||||
else {create_8_8_nimbus_var3(lat, lon, alt, alpha);}
|
||||
}
|
||||
|
||||
if (rain > 0.1)
|
||||
{
|
||||
local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, 0.0, alt, 500.0 + (1.0 - 0.5 * rain) * 5500.0, 0.5 * rain , -1, -1, -1,0 ,0.95);
|
||||
local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, 0.0, alt+900.0, 500.0 + (1.0 - 0.5 * rain) * 5500.0, 0.5 * rain , -1, -1, -1,0 ,0.95);
|
||||
local_weather.create_effect_volume(3, lat , lon, 16000.0, 16000.0, alpha, 0.0, alt - 300.0, 500.0 + (1.0-rain) * 5500.0, rain, -1, -1, -1,0 ,0.8);
|
||||
}
|
||||
else
|
||||
{
|
||||
local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, alt-1500.0, alt+900.0, 2000.0, -1 , -1, -1, -1,0 ,-1);
|
||||
local_weather.create_effect_volume(3, lat, lon, 20000.0, 20000.0, alpha, 0.0, alt, -1, rain , -1, -1, -1,0 ,0.8);
|
||||
}
|
||||
|
||||
|
@ -2245,12 +2312,13 @@ for (var i = 0; i < 3; i = i + 1)
|
|||
|
||||
if (rain > 0.1)
|
||||
{
|
||||
local_weather.create_effect_volume(2, lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), 10000.0, 6000.0, beta, 0.0, alt, 500.0 + (1.0-0.5*rain) * 5500.0, 0.5 * rain, -1, -1, -1,0,0.95 );
|
||||
local_weather.create_effect_volume(2, lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), 10000.0, 6000.0, beta, 0.0, alt+900, 500.0 + (1.0-0.5*rain) * 5500.0, 0.5 * rain, -1, -1, -1,0,0.95 );
|
||||
local_weather.create_effect_volume(2, lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), 9000.0, 5000.0, beta, 0.0, alt-300.0, 500.0 + (1.0-rain) * 5500.0, rain, -1, -1, -1,0,0.8);
|
||||
}
|
||||
else
|
||||
{
|
||||
local_weather.create_effect_volume(2, lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), 10000.0, 6000.0, beta, 0.0, alt, -1, rain, -1, -1, -1,0, 0.8 );
|
||||
local_weather.create_effect_volume(2, lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), 10000.0, 6000.0, beta, alt-1500.0, alt+900.0, 2000.0, -1, -1, -1, -1,0, 0.8 );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2708,6 +2776,27 @@ for (var i = 0; i < 2; i = i + 1)
|
|||
|
||||
}
|
||||
|
||||
|
||||
var create_1_8_contrails = func (lat, lon, alt, alpha) {
|
||||
|
||||
|
||||
var phi = alpha * math.pi/180.0;
|
||||
|
||||
var n_contrails = int(rand() * 3.0) + 1;
|
||||
|
||||
for (var i=0; i<n_contrails; i=i+1)
|
||||
{
|
||||
var x = 2.0 * (rand()-0.5) * 5000;
|
||||
var y = 2.0 * (rand()-0.5) * 5000;
|
||||
var alt_variation = 2.0 * (rand()-0.5) * 4000.0;
|
||||
var beta = rand() * 180;
|
||||
var contrail_length = 20 + int(rand() * 30);
|
||||
|
||||
local_weather.create_streak("Cirrocumulus (cloudlet)",lat+get_lat(x,y,phi), lon+get_lon(x,y,phi), alt+alt_variation,100.0,contrail_length,500.0,0.2,50.0,2,100.0,0.0,300.0,alpha+beta,1.0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var create_thunderstorm_scenario = func (lat, lon, alt, alpha) {
|
||||
|
||||
var phi = alpha * math.pi/180.0;
|
||||
|
|
|
@ -35,15 +35,34 @@
|
|||
<group>
|
||||
<layout>table</layout>
|
||||
|
||||
<checkbox>
|
||||
<name>auto-tower</name>
|
||||
<row>0</row>
|
||||
<col>0</col>
|
||||
<colspan>2</colspan>
|
||||
<label>Always use nearest tower</label>
|
||||
<property>/sim/tower/auto-position</property>
|
||||
<live>true</live>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
<object-name>auto-tower</object-name>
|
||||
</binding>
|
||||
</checkbox>
|
||||
|
||||
<text>
|
||||
<row>0</row><col>0</col>
|
||||
<row>1</row><col>0</col>
|
||||
<halign>right</halign>
|
||||
<label>Airport ID:</label>
|
||||
</text>
|
||||
<input>
|
||||
<name>airport-id</name>
|
||||
<row>0</row><col>1</col>
|
||||
<row>1</row><col>1</col>
|
||||
<property>/sim/tower/airport-id</property>
|
||||
<enable>
|
||||
<not>
|
||||
<property>/sim/tower/auto-position</property>
|
||||
</not>
|
||||
</enable>
|
||||
</input>
|
||||
<empty>
|
||||
<row>0</row><col>3</col>
|
||||
|
@ -54,7 +73,7 @@
|
|||
are not filled in on the COM radio retuning...
|
||||
I'm working on that part now.
|
||||
<button>
|
||||
<row>1</row><col>0</col>
|
||||
<row>2</row><col>0</col>
|
||||
<legend>COM1</legend>
|
||||
<binding>
|
||||
<command>property-assign</command>
|
||||
|
@ -67,22 +86,22 @@
|
|||
</binding>
|
||||
</button>
|
||||
<text>
|
||||
<row>1</row><col>2</col>
|
||||
<row>2</row><col>2</col>
|
||||
<property>/instrumentation/comm[0]/frequencies/selected-mhz</property>
|
||||
<label>MHz</label>
|
||||
<format>%-0.2f</format>
|
||||
</text>
|
||||
<text>
|
||||
<row>1</row><col>1</col>
|
||||
<row>2</row><col>1</col>
|
||||
<property>/instrumentation/comm[0]/airport-id</property>
|
||||
</text>
|
||||
<empty>
|
||||
<row>1</row><col>3</col>
|
||||
<row>2</row><col>3</col>
|
||||
<stretch>true</stretch>
|
||||
</empty>
|
||||
|
||||
<button>
|
||||
<row>2</row><col>0</col>
|
||||
<row>3</row><col>0</col>
|
||||
<legend>COM2</legend>
|
||||
<binding>
|
||||
<command>property-assign</command>
|
||||
|
@ -95,24 +114,24 @@
|
|||
</binding>
|
||||
</button>
|
||||
<text>
|
||||
<row>2</row><col>2</col>
|
||||
<row>3</row><col>2</col>
|
||||
<property>/instrumentation/comm[1]/frequencies/selected-mhz</property>
|
||||
<label>MHz</label>
|
||||
<format>%-0.2f</format>
|
||||
</text>
|
||||
<text>
|
||||
<row>2</row><col>1</col>
|
||||
<row>3</row><col>1</col>
|
||||
<property>/instrumentation/comm[1]/airport-id</property>
|
||||
</text>
|
||||
<empty>
|
||||
<row>2</row><col>3</col>
|
||||
<row>3</row><col>3</col>
|
||||
<stretch>true</stretch>
|
||||
</empty>
|
||||
-->
|
||||
|
||||
<button>
|
||||
<legend>Preset</legend>
|
||||
<row>3</row><col>0</col>
|
||||
<row>4</row><col>0</col>
|
||||
<!--
|
||||
Is there a way in the GUI (other than via a dynamic
|
||||
NASAL dialog) to assign text to the widget rather
|
||||
|
@ -120,6 +139,9 @@
|
|||
|
||||
The way it is now CANCEL doesn't undo PRESET :-(
|
||||
-->
|
||||
<enable>
|
||||
<not><property>sim/tower/auto-position</property></not>
|
||||
</enable>
|
||||
<binding>
|
||||
<command>property-assign</command>
|
||||
<property>/sim/tower/airport-id</property>
|
||||
|
@ -131,11 +153,11 @@
|
|||
</binding>
|
||||
</button>
|
||||
<text>
|
||||
<row>3</row><col>1</col>
|
||||
<row>4</row><col>1</col>
|
||||
<property>/sim/presets/airport-id</property>
|
||||
</text>
|
||||
<empty>
|
||||
<row>3</row><col>3</col>
|
||||
<row>4</row><col>3</col>
|
||||
<stretch>true</stretch>
|
||||
</empty>
|
||||
</group>
|
||||
|
|
|
@ -410,10 +410,10 @@ Started September 2000 by David Megginson, david@megginson.com
|
|||
<roll-deg type="double">0</roll-deg>
|
||||
<pitch-deg type="double">0</pitch-deg>
|
||||
<heading-deg type="double">0</heading-deg>
|
||||
<auto-position type="bool" userarchive="y">true</auto-position>
|
||||
</tower>
|
||||
|
||||
<view-name-popup type="bool"
|
||||
userarchive="y">true</view-name-popup>
|
||||
<view-name-popup type="bool" userarchive="y">true</view-name-popup>
|
||||
|
||||
<view>
|
||||
<name>Cockpit View</name>
|
||||
|
|
Loading…
Add table
Reference in a new issue