1
0
Fork 0

Merge branch 'master' of gitorious.org:fg/fgdata

This commit is contained in:
Curtis L. Olson 2012-10-08 13:33:06 -05:00
commit 091fbf80f0
68 changed files with 4498 additions and 736 deletions

View file

@ -7,21 +7,21 @@
<label>Cessna C172P</label>
<enabled type="bool">true</enabled>
<item>
<label>Select Livery</label>
<name>select-livery</name>
<binding>
<command>nasal</command>
<script>aircraft.livery.dialog.toggle()</script>
</binding>
</item>
<item>
<label>Immatriculation</label>
<name>immatriculation</name>
<binding>
<command>nasal</command>
<script>c172p.immat_dialog.toggle()</script>
</binding>
</item>
<item>
<label>Show/hide yoke</label>
<name>show-hide-yokes</name>
<binding>
<command>property-toggle</command>
<property>sim/model/hide-yoke</property>

View file

@ -108,6 +108,10 @@
<name>Alt + mouse click</name>
<desc>move selected object(s) to new place</desc>
</key>
<key>
<name>Ctrl + Alt + mouse click</name>
<desc>Print lat/lon/alt and landclass of mouse click position</desc>
</key>
<key>
<name>g (gear) + click</name>
<desc>teleport to click position, looking at active object</desc>

View file

@ -435,6 +435,17 @@ var modelmgr = {
me.mouse_coord = mouse_coord;
status_dialog.open();
adjust_dialog.center_sliders();
if (KbdAlt.getValue() and KbdCtrl.getValue()) { # Provide information on the selected point
var geod = geodinfo(me.mouse_coord.lat(), me.mouse_coord.lon());
var landclass = string.join(" ", geod[1].names);
var str = sprintf("lat:%.4f lon:%.4f alt:%.0fm class(es): %s",
me.mouse_coord.lat(), me.mouse_coord.lon(),
me.mouse_coord.alt(), landclass);
gui.popupTip(str, 3);
print(str);
return;
}
if (KbdAlt.getValue()) { # move active object here (and other selected ones along with it)
(me.active == nil) and return;

View file

@ -143,6 +143,8 @@ alpha-test - children: active, comparison, reference
Valid values for comparision:
never, less, equal, lequal, greater, notequal, gequal,
always
alpha-to-coverage - true, false
blend - children: active, source, destination, source-rgb,
source-alpha, destination-rgb, destination-alpha

View file

@ -120,9 +120,25 @@ tree-height-m : The average height of the trees. Actual tree height will
tree-width-m : The average width of the tree cover. Actual tree width will
vary by +/- 50%. (default 0)
tree-max-density-angle-deg : The slope angle at which trees begin to thin out
as the slope is too steep to support the full coverage. Shallower
slopes have maximum wood-coverage. Steeper slopes have fewer trees.
(default : 45)
tree-zero-density-angle-deg : The angle at which the slope is too steep to
support significant vegetation. Steeper slopes have no trees.
(default : 60)
object-max-density-angle-deg : The angle at which objects and buildings become
less dense due to a steep slope. (default : 20)
object-zero-density-angle-deg : The angle at which the slope is too steep to build
on. No object/buildings will be placed on slopes steeper than this.
(default : 30)
object-group : A group of random objects to be placed on the surface. Contains
<range-m> and one or mode <object> children.
<range-m> and one or more <object> children.
range-m : The distance at which objects within this object-group become
visible. Note that for realism, 60% of the objects will become visible

View file

@ -68,6 +68,7 @@
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<snow_level><use>/environment/snow-level-m</use></snow_level>
<dust_cover_factor><use>/environment/surface/dust-cover-factor</use></dust_cover_factor>
<lichen_cover_factor><use>/environment/surface/lichen-cover-factor</use></lichen_cover_factor>
<wetness><use>/environment/surface/wetness</use></wetness>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<fogstructure><use>/environment/fog-structure</use></fogstructure>
@ -261,6 +262,11 @@
<type>float</type>
<value><use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>lichen_cover_factor</name>
<type>float</type>
<value> <use>lichen_cover_factor</use></value>
</uniform>
<uniform>
<name>wetness</name>
<type>float</type>

View file

@ -25,20 +25,131 @@
<terminator><use>/environment/terminator-relative-position-m</use></terminator>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<terrain_alt><use>/environment/mean-terrain-elevation-m</use></terrain_alt>
<overcast><use>/rendering/scene/overcast</use></overcast>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<overcast><use>/rendering/scene/overcast</use></overcast>
<eye_alt><use>/sim/rendering/eye-altitude-m</use></eye_alt>
<snow_level><use>/environment/snow-level-m</use></snow_level>
<dust_cover_factor><use>/environment/surface/dust-cover-factor</use></dust_cover_factor>
<fogtype><use>/sim/rendering/shaders/skydome</use></fogtype>
<fogstructure><use>/environment/fog-structure</use></fogstructure>
<quality_level><use>/sim/rendering/shaders/landmass</use></quality_level>
<!-- END fog include -->
</parameters>
<technique n="4">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<property>/sim/rendering/random-vegetation</property>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
<extension-supported>GL_ARB_multisample</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient type="vec4d">1.0 1.0 1.0 1.0</ambient>
<diffuse type="vec4d">1.0 1.0 1.0 1.0</diffuse>
<color-mode>off</color-mode>
</material>
<texture-unit>
<unit>0</unit>
<type>2d</type>
<image>
<use>texture[0]/image</use>
</image>
<wrap-s>clamp</wrap-s>
<wrap-t>clamp</wrap-t>
</texture-unit>
<alpha-to-coverage>true</alpha-to-coverage>
<program>
<vertex-shader>Shaders/tree-haze.vert</vertex-shader>
<fragment-shader>Shaders/tree-haze.frag</fragment-shader>
</program>
<uniform>
<name>visibility</name>
<type>float</type>
<value><use>visibility</use></value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value><use>avisibility</use></value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value><use>lthickness</use></value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value><use>scattering</use></value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value><use>ground_scattering</use></value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value><use>terminator</use></value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value><use>terrain_alt</use></value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value><use>overcast</use></value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value> <use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<uniform>
<name>colorMode</name>
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<uniform>
<name>quality_level</name>
<type>int</type>
<value> <use>quality_level</use></value>
</uniform>
</pass>
</technique>
<technique n="5">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<property>/sim/rendering/random-vegetation</property>
<property>/sim/rendering/random-vegetation</property>
<or>
<less-equal>
<value type="float">2.0</value>
@ -123,6 +234,11 @@
<type>float</type>
<value><use>eye_alt</use></value>
</uniform>
<uniform>
<name>dust_cover_factor</name>
<type>float</type>
<value> <use>dust_cover_factor</use></value>
</uniform>
<uniform>
<name>texture</name>
<type>sampler-2d</type>
@ -133,16 +249,15 @@
<type>int</type>
<value>2</value> <!-- AMBIENT_AND_DIFFUSE -->
</uniform>
<!--<depth>
<function>lequal</function>
<write-mask type="bool">false</write-mask>
</depth>-->
<uniform>
<name>quality_level</name>
<type>int</type>
<value> <use>quality_level</use></value>
</uniform>
</pass>
</technique>
<technique n="9">
<technique n="8">
<predicate>
<and>
<property>/sim/rendering/rembrandt/enabled</property>
@ -182,6 +297,95 @@
</uniform>
</pass>
</technique>
<technique n="9">
<predicate>
<and>
<property>/sim/rendering/random-vegetation</property>
<extension-supported>GL_ARB_multisample</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
<less-equal>
<value type="float">1.0</value>
<shader-language/>
</less-equal>
</and>
</predicate>
<pass n="0">
<lighting>true</lighting>
<material>
<ambient type="vec4d">1.0 1.0 1.0 1.0</ambient>
<diffuse type="vec4d">1.0 1.0 1.0 1.0</diffuse>
<color-mode>off</color-mode>
</material>
<alpha-to-coverage>true</alpha-to-coverage>
<texture-unit>
<unit>0</unit>
<type>2d</type>
<image>
<use>texture[0]/image</use>
</image>
<wrap-s>clamp</wrap-s>
<wrap-t>clamp</wrap-t>
</texture-unit>
<program>
<!-- <vertex-shader>Shaders/include_fog.vert</vertex-shader> -->
<vertex-shader>Shaders/tree.vert</vertex-shader>
<fragment-shader n="0">Shaders/include_fog.frag</fragment-shader>
<fragment-shader n="1">Shaders/tree.frag</fragment-shader>
</program>
<uniform>
<name>baseTexture</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>fogType</name>
<type>int</type>
<value>
<use>fogtype</use>
</value>
</uniform>
<!-- END fog include -->
</pass>
</technique>
<technique n="10">
<predicate>
<and>

View file

@ -146,6 +146,363 @@
</generate>
<technique n="2">
<predicate>
<and>
<property>/sim/rendering/shaders/skydome</property>
<less-equal>
<value type="float">5.0</value>
<float-property>/sim/rendering/shaders/water</float-property>
</less-equal>
<or>
<less-equal>
<value type="float">2.0</value>
<glversion/>
</less-equal>
<and>
<extension-supported>GL_ARB_shader_objects</extension-supported>
<extension-supported>GL_ARB_shading_language_100</extension-supported>
<extension-supported>GL_ARB_vertex_shader</extension-supported>
<extension-supported>GL_ARB_fragment_shader</extension-supported>
</and>
</or>
</and>
</predicate>
<pass>
<lighting>true</lighting>
<material>
<ambient>
<use>material/ambient</use>
</ambient>
<diffuse>
<use>material/diffuse</use>
</diffuse>
<specular>
<use>material/specular</use>
</specular>
<color-mode>ambient-and-diffuse</color-mode>
</material>
<blend>
<use>transparent</use>
</blend>
<alpha-test>
<use>transparent</use>
</alpha-test>
<shade-model>smooth</shade-model>
<cull-face>back</cull-face>
<render-bin>
<bin-number>
<use>render-bin/bin-number</use>
</bin-number>
<bin-name>
<use>render-bin/bin-name</use>
</bin-name>
</render-bin>
<!--<texture-unit>
<unit>0</unit>
<image>
<use>texture[0]/image</use>
</image>
<filter>
<use>texture[0]/filter</use>
</filter>
<wrap-s>
<use>texture[0]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[0]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[0]/internal-format</use>
</internal-format>
</texture-unit>-->
<texture-unit>
<unit>2</unit>
<image>
<use>texture[2]/image</use>
</image>
<filter>
<use>texture[2]/filter</use>
</filter>
<wrap-s>
<use>texture[2]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[2]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[2]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>3</unit>
<image>
<use>texture[3]/image</use>
</image>
<filter>
<use>texture[3]/filter</use>
</filter>
<wrap-s>
<use>texture[3]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[3]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[3]/internal-format</use>
</internal-format>
</texture-unit>
<!--<texture-unit>
<unit>4</unit>
<image>
<use>texture[4]/image</use>
</image>
<filter>
<use>texture[4]/filter</use>
</filter>
<wrap-s>
<use>texture[4]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[4]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[4]/internal-format</use>
</internal-format>
</texture-unit>-->
<texture-unit>
<unit>5</unit>
<image>
<use>texture[5]/image</use>
</image>
<filter>
<use>texture[5]/filter</use>
</filter>
<wrap-s>
<use>texture[5]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[5]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[5]/internal-format</use>
</internal-format>
</texture-unit>
<texture-unit>
<unit>6</unit>
<image>
<use>texture[6]/image</use>
</image>
<filter>
<use>texture[6]/filter</use>
</filter>
<wrap-s>
<use>texture[6]/wrap-s</use>
</wrap-s>
<wrap-t>
<use>texture[6]/wrap-t</use>
</wrap-t>
<internal-format>
<use>texture[6]/internal-format</use>
</internal-format>
</texture-unit>
<program>
<vertex-shader>Shaders/water_lightfield.vert</vertex-shader>
<fragment-shader>Shaders/water_lightfield.frag</fragment-shader>
</program>
<!--<uniform>
<name>water_reflection</name>
<type>sampler-2d</type>
<value type="int">0</value>
</uniform>-->
<uniform>
<name>water_normalmap</name>
<type>sampler-2d</type>
<value type="int">2</value>
</uniform>
<uniform>
<name>water_dudvmap</name>
<type>sampler-2d</type>
<value type="int">3</value>
</uniform>
<uniform>
<name>sea_foam</name>
<type>sampler-2d</type>
<value type="int">5</value>
</uniform>
<uniform>
<name>perlin_normalmap</name>
<type>sampler-2d</type>
<value type="int">6</value>
</uniform>
<!-- normalmap is .dds-->
<uniform>
<name>normalmap_dds</name>
<type>float</type>
<value>
<use>normalmap_dds</use>
</value>
</uniform>
<uniform>
<name>saturation</name>
<type>float</type>
<!--<value>0.4</value>-->
<value>
<use>saturation</use>
</value>
</uniform>
<uniform>
<name>WindE</name>
<type>float</type>
<value>
<use>windE</use>
</value>
</uniform>
<uniform>
<name>WindN</name>
<type>float</type>
<value>
<use>windN</use>
</value>
</uniform>
<uniform>
<name>WaveFreq</name>
<type>float</type>
<value>
<use>WaveFreq</use>
</value>
</uniform>
<uniform>
<name>WaveAmp</name>
<type>float</type>
<value>
<use>WaveAmp</use>
</value>
</uniform>
<uniform>
<name>WaveSharp</name>
<type>float</type>
<value>
<use>WaveSharp</use>
</value>
</uniform>
<uniform>
<name>WaveAngle</name>
<type>float</type>
<value>
<use>WaveAngle</use>
</value>
</uniform>
<uniform>
<name>WaveFactor</name>
<type>float</type>
<value>
<use>WaveFactor</use>
</value>
</uniform>
<uniform>
<name>WaveDAngle</name>
<type>float</type>
<value>
<use>WaveDAngle</use>
</value>
</uniform>
<!-- BEGIN fog include -->
<uniform>
<name>visibility</name>
<type>float</type>
<value>
<use>visibility</use>
</value>
</uniform>
<uniform>
<name>avisibility</name>
<type>float</type>
<value>
<use>avisibility</use>
</value>
</uniform>
<uniform>
<name>hazeLayerAltitude</name>
<type>float</type>
<value>
<use>lthickness</use>
</value>
</uniform>
<uniform>
<name>scattering</name>
<type>float</type>
<value>
<use>scattering</use>
</value>
</uniform>
<uniform>
<name>ground_scattering</name>
<type>float</type>
<value>
<use>ground_scattering</use>
</value>
</uniform>
<uniform>
<name>terminator</name>
<type>float</type>
<value>
<use>terminator</use>
</value>
</uniform>
<uniform>
<name>terrain_alt</name>
<type>float</type>
<value>
<use>terrain_alt</use>
</value>
</uniform>
<uniform>
<name>overcast</name>
<type>float</type>
<value>
<use>overcast</use>
</value>
</uniform>
<uniform>
<name>eye_alt</name>
<type>float</type>
<value>
<use>eye_alt</use>
</value>
</uniform>
<!-- sea colors -->
<uniform>
<name>sea_r</name>
<type>float</type>
<value>
<use>sea_r</use>
</value>
</uniform>
<uniform>
<name>sea_g</name>
<type>float</type>
<value>
<use>sea_g</use>
</value>
</uniform>
<uniform>
<name>sea_b</name>
<type>float</type>
<value>
<use>sea_b</use>
</value>
</uniform>
<!-- END fog include -->
</pass>
</technique>
<technique n="3">
<predicate>
<and>
@ -310,7 +667,7 @@
<program>
<vertex-shader>Shaders/water_lightfield.vert</vertex-shader>
<fragment-shader>Shaders/water_lightfield.frag</fragment-shader>
<fragment-shader>Shaders/water_lightfield_lr.frag</fragment-shader>
</program>
<!--<uniform>
<name>water_reflection</name>

View file

@ -36,13 +36,67 @@
<tile-management>METAR</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Core high pressure region</name>
<metar type="string">XXXX 012345Z 15003KT 19SM FEW072 FEW350 25/07 Q1028 NOSIG</metar>
<description type="string">The center of a high pressure region, characterized by descending air and hence only weak cloud development with high visibility.</description>
<local-weather>
<tile-type>High-pressure-core</tile-type>
<tile-management>realistic weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">High pressure region</name>
<metar type="string">XXXX 012345Z 15003KT 12SM SCT048 FEW300 20/08 Q1022 NOSIG</metar>
<description type="string">A high pressure region, characterized my moderate to strong Cumulus development in the afternoon and fairly good visibility conditions.</description>
<local-weather>
<tile-type>High-pressure</tile-type>
<tile-management>realistic weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Border of a high pressure region</name>
<metar type="string">XXXX 012345Z 15003KT 10SM SCT036 SCT150 17/08 Q1016 NOSIG</metar>
<description type="string">The border of a high pressure region, in which the airmass becomes unstable and various convective and stratiform clouds may appear.</description>
<local-weather>
<tile-type>High-pressure-border</tile-type>
<tile-management>realistic weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Border of a low pressure region</name>
<metar type="string">XXXX 012345Z 15003KT 9SM BKN028 SCT090 FEW160 15/08 Q1010 NOSIG</metar>
<description type="string">The border of a low pressure region, in which the airmass is unstable and convective clouds start to form layers and merge into stratiform clouds.</description>
<local-weather>
<tile-type>Low-pressure-border</tile-type>
<tile-management>realistic weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Low pressure region</name>
<metar type="string">XXXX 012345Z 15003KT 6SM SHRA BKN024 BKN053 FEW090 13/07 Q1004 NOSIG</metar>
<description type="string">A low pressure region, characterized by rising air, widespread formation of stratiform clouds and beginning rain.</description>
<local-weather>
<tile-type>Low-pressure</tile-type>
<tile-management>realistic weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Core low pressure region</name>
<metar type="string">XXXX 012345Z 15003KT 4SM RA OVC020 SCT050 07/02 Q0998 NOSIG</metar>
<description type="string">The core of a low pressure region, characterized by overcast clouds, bad visibility on the ground and significant rainfall.</description>
<local-weather>
<tile-type>Low-pressure-core</tile-type>
<tile-management>realistic weather</tile-management>
</local-weather>
</scenario>
<scenario>
<name type="string">Fair weather</name>
<metar type="string">XXXX 012345Z 15003KT 12SM SCT041 FEW200 20/08 Q1015 NOSIG</metar>
<description type="string">A lovely day for trip to your favorite 100$ hamburger airfield</description>
<local-weather>
<tile-type>High-pressure-core</tile-type>
<tile-management>realistic-weather</tile-management>
<tile-management>realistic weather</tile-management>
</local-weather>
</scenario>
<scenario>
@ -55,7 +109,7 @@
</description>
<local-weather>
<tile-type>Thunderstorms</tile-type>
<tile-management>realistic-weather</tile-management>
<tile-management>repeat tile</tile-management>
</local-weather>
</scenario>
<scenario>
@ -362,6 +416,7 @@
<surface>
<scattering type="double" userarchive="n">0.7</scattering>
<dust-cover-factor type="double" userarchive="y">0.0</dust-cover-factor>
<lichen-cover-factor type="double" userarchive="y">0.0</lichen-cover-factor>
<wetness type="double" userarchive="y">0.0</wetness>
</surface>
</PropertyList>

View file

@ -179,6 +179,7 @@
<!-- TODO: handle variable winds -->
<filter include="layer-heading-offset.xml"/>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_0</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -192,6 +193,7 @@
<output>/environment/config/aloft/entry[0]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_1</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -205,6 +207,7 @@
<output>/environment/config/aloft/entry[1]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_2</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -218,6 +221,7 @@
<output>/environment/config/aloft/entry[2]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_3</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -231,6 +235,7 @@
<output>/environment/config/aloft/entry[3]/wind-from-heading-deg</output>
</filter>
<filter include="layer-heading-offset.xml">
<name>MetarController:layer:wind-from-heading-deg_4</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -246,6 +251,7 @@
<filter include="layer-speed-change.xml"/>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_0</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -259,6 +265,7 @@
<output>/environment/config/aloft/entry[0]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_1</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -272,6 +279,7 @@
<output>/environment/config/aloft/entry[1]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_2</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -285,6 +293,7 @@
<output>/environment/config/aloft/entry[2]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_3</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -298,6 +307,7 @@
<output>/environment/config/aloft/entry[3]/wind-speed-kt</output>
</filter>
<filter include="layer-speed-change.xml">
<name>MetarController:layer:wind-speed-kt_4</name>
<enable>
<condition>
<property>/environment/metar/valid</property>
@ -314,24 +324,28 @@
<!-- Clouds -->
<filter include="clouds-altitude-interpolate.xml"/>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_0</name>
<params>
<from>/environment/metar/clouds/layer[1]/elevation-ft</from>
<to>/environment/clouds/layer[1]/elevation-ft</to>
</params>
</filter>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_1</name>
<params>
<from>/environment/metar/clouds/layer[2]/elevation-ft</from>
<to>/environment/clouds/layer[2]/elevation-ft</to>
</params>
</filter>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_2</name>
<params>
<from>/environment/metar/clouds/layer[3]/elevation-ft</from>
<to>/environment/clouds/layer[3]/elevation-ft</to>
</params>
</filter>
<filter include="clouds-altitude-interpolate.xml">
<name>MetarController:clouds:altitude_interpolate_3</name>
<params>
<from>/environment/metar/clouds/layer[4]/elevation-ft</from>
<to>/environment/clouds/layer[4]/elevation-ft</to>
@ -340,42 +354,50 @@
<filter include="clouds-thickness.xml"/>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_0</name>
<input>/environment/metar/clouds/layer[1]/thickness-ft</input>
<output>/environment/clouds/layer[1]/thickness-ft</output>
</filter>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_1</name>
<input>/environment/metar/clouds/layer[2]/thickness-ft</input>
<output>/environment/clouds/layer[2]/thickness-ft</output>
</filter>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_2</name>
<input>/environment/metar/clouds/layer[3]/thickness-ft</input>
<output>/environment/clouds/layer[3]/thickness-ft</output>
</filter>
<filter include="clouds-thickness.xml">
<name>MetarController:clouds:thickness_3</name>
<input>/environment/metar/clouds/layer[4]/thickness-ft</input>
<output>/environment/clouds/layer[4]/thickness-ft</output>
</filter>
<filter include="clouds-coverage.xml"/>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_0</name>
<params>
<from>/environment/metar/clouds/layer[1]/coverage-type</from>
<to>environment/clouds/layer[1]/coverage-type</to>
</params>
</filter>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_1</name>
<params>
<from>/environment/metar/clouds/layer[2]/coverage-type</from>
<to>environment/clouds/layer[2]/coverage-type</to>
</params>
</filter>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_2</name>
<params>
<from>/environment/metar/clouds/layer[3]/coverage-type</from>
<to>environment/clouds/layer[3]/coverage-type</to>
</params>
</filter>
<filter include="clouds-coverage.xml">
<name>MetarController:clouds:coverage_3</name>
<params>
<from>/environment/metar/clouds/layer[4]/coverage-type</from>
<to>environment/clouds/layer[4]/coverage-type</to>

View file

@ -12,6 +12,7 @@
<PropertyList>
<name>Logitech Attack 3</name>
<name>Logitech Logitech Attack 3</name>
<axis n="0">

View file

@ -1282,6 +1282,155 @@
<tree-width-m>12.0</tree-width-m>
</material>
<!-- REGIONAL DEFINITIONS - SOUTH AMERICAN RAINFOREST BELT -->
<material include="Materials/regions/tropical_south_america.xml">
<name>EvergreenBroadCover</name>
<name>EvergreenForest</name>
<effect>Effects/forest</effect>
<texture-set>
<texture>Terrain/rainforest-hawaii.png</texture>
<texture n="11">Terrain/rainforest-hawaii.png</texture>
<texture n="12">Terrain/dirtrock.png</texture>
</texture-set>
<xsize>2000</xsize>
<ysize>2000</ysize>
<light-coverage>10000000.0</light-coverage>
<wood-coverage>4000.0</wood-coverage>
<tree-texture>Trees/tropical-summer.png</tree-texture>
<tree-varieties>8</tree-varieties>
<tree-range-m alias="/params/forest/tree-range-m"/>
<tree-height-m>35.0</tree-height-m>
<tree-width-m>30.0</tree-width-m>
<rolling-friction>1</rolling-friction>
<bumpiness>1</bumpiness>
</material>
<material include="Materials/regions/tropical_south_america.xml">
<name>HerbTundraCover</name>
<name>HerbTundra</name>
<effect>Effects/herbtundra</effect>
<texture-set>
<texture>Terrain/herbtundra.png</texture>
<texture n="11">Terrain/grass_hires.png</texture>
<texture n="12">Terrain/dirtrock.png</texture>
</texture-set>
<xsize>2000</xsize>
<ysize>2000</ysize>
<light-coverage>4000000.0</light-coverage>
<diffuse>
<r>0.93</r>
<g>0.95</g>
<b>0.93</b>
<a>1.0</a>
</diffuse>
<specular>
<r>0.1</r>
<g>0.12</g>
<b>0.1</b>
<a>1.0</a>
</specular>
<shininess>1.2</shininess>
<solid>1</solid>
<friction-factor>0.8</friction-factor>
<rolling-friction>0.1</rolling-friction>
<bumpiness>0.15</bumpiness>
<load-resistance>1e30</load-resistance>
<wood-coverage>70000.0</wood-coverage>
<tree-texture>Trees/tropical-summer.png</tree-texture>
<tree-varieties>8</tree-varieties>
<tree-range-m alias="/params/forest/tree-range-m"/>
<tree-height-m>25.0</tree-height-m>
<tree-width-m>18.0</tree-width-m>
</material>
<material include="Materials/regions/tropical_south_america.xml">
<name>MixedCropPastureCover</name>
<name>MixedCrop</name>
<name>ComplexCrop</name>
<texture-set>
<texture>Terrain/shrub1.png</texture>
<texture n="11">Terrain/grass_hires.png</texture>
<texture n="12">Terrain/dirtrock.png</texture>
</texture-set>
<xsize>2000</xsize>
<ysize>2000</ysize>
<light-coverage>2000000.0</light-coverage>
<solid>1</solid>
<friction-factor>0.9</friction-factor>
<rolling-friction>0.1</rolling-friction>
<bumpiness>0.7</bumpiness>
<load-resistance>1e30</load-resistance>
<wood-coverage>10000.0</wood-coverage>
<tree-texture>Trees/tropical-summer.png</tree-texture>
<tree-varieties>8</tree-varieties>
<tree-range-m alias="/params/forest/tree-range-m"/>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
</material>
<material include="Materials/regions/tropical_south_america.xml">
<effect>Effects/crop</effect>
<name>DryCropPastureCover</name>
<name>DryCrop</name>
<texture-set>
<texture>Terrain/tundra-hawaii-green.png</texture>
<texture n="11">Terrain/grass_hires.png</texture>
<texture n="12">Terrain/dirtrock.png</texture>
</texture-set>
<xsize>2000</xsize>
<ysize>2000</ysize>
<solid>1</solid>
<friction-factor>0.9</friction-factor>
<rolling-friction>0.1</rolling-friction>
<bumpiness>0.6</bumpiness>
<load-resistance>1e30</load-resistance>
<light-coverage>2000000.0</light-coverage>
<wood-coverage>50000.0</wood-coverage>
<tree-texture>Trees/tropical-summer.png</tree-texture>
<tree-varieties>8</tree-varieties>
<tree-range-m alias="/params/forest/tree-range-m"/>
<tree-height-m>20.0</tree-height-m>
<tree-width-m>12.0</tree-width-m>
</material>
<material include="Materials/regions/tropical_south_america.xml">
<name>GrassCover</name>
<name>BareTundraCover</name>
<name>MixedTundraCover</name>
<name>Cemetery</name>
<effect>Effects/landmass-nowood</effect>
<texture-set>
<texture>Terrain/tundra-hawaii-green.png</texture>
<texture n="11">Terrain/rainforest-hawaii.png</texture>
<texture n="12">Terrain/dirtrock.png</texture>
</texture-set>
<xsize>2000</xsize>
<ysize>2000</ysize>
<light-coverage>4000000.0</light-coverage>
<diffuse>
<r>0.93</r>
<g>0.95</g>
<b>0.93</b>
<a>1.0</a>
</diffuse>
<specular>
<r>0.1</r>
<g>0.12</g>
<b>0.1</b>
<a>1.0</a>
</specular>
<shininess>1.2</shininess>
<solid>1</solid>
<friction-factor>0.7</friction-factor>
<rolling-friction>0.1</rolling-friction>
<bumpiness>0.15</bumpiness>
<load-resistance>1e30</load-resistance>
</material>
<!-- DEFAULT SUMMER DEFINITIONS -->
<material>

View file

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<!-- General settings for all tropical South American materials -->
<PropertyList>
<!-- Define tropical South America as a box with given latitude/longitude -->
<condition>
<and>
<greater-than>
<property>position/longitude-deg</property>
<value>-90.0</value>
</greater-than>
<less-than>
<property>position/longitude-deg</property>
<value>-30.0</value>
</less-than>
<greater-than>
<property>position/latitude-deg</property>
<value>-15.0</value>
</greater-than>
<less-than>
<property>position/latitude-deg</property>
<value>15.0</value>
</less-than>
</and>
</condition>
</PropertyList>

View file

@ -60,5 +60,10 @@ var PropertyElement = {
return node.getValue();
else
return default;
}
},
getBool: func(key)
{
me._node.getNode(key, 1).getBoolValue();
},
};

View file

@ -218,10 +218,13 @@ var Element = {
{
me.setBool("visible", visible);
},
getVisible: func me.getBool("visible"),
# Hide element (Shortcut for setVisible(0))
hide: func me.setVisible(0),
# Show element (Shortcut for setVisible(1))
show: func me.setVisible(1),
# Toggle element visibility
toggleVisibility: func me.setVisible( !me.getVisible() ),
#
setGeoPosition: func(lat, lon)
{
@ -266,15 +269,18 @@ var Element = {
getBoundingBox: func()
{
var bb = me._node.getNode("bounding-box");
var min_x = bb.getNode("min-x").getValue();
if( min_x != nil )
return [ min_x,
bb.getNode("min-y").getValue(),
bb.getNode("max-x").getValue(),
bb.getNode("max-y").getValue() ];
else
return [0, 0, 0, 0];
if( bb != nil )
{
var min_x = bb.getNode("min-x").getValue();
if( min_x != nil )
return [ min_x,
bb.getNode("min-y").getValue(),
bb.getNode("max-x").getValue(),
bb.getNode("max-y").getValue() ];
}
return [0, 0, 0, 0];
},
# Set transformation center (currently only used for rotation)
setCenter: func()

23
Nasal/canvas/design.txt Normal file
View file

@ -0,0 +1,23 @@
Nothing set in stone yet, we'll document things once the API becomes more stable and once it has been used in several dialogs and instruments
At the moment, this implements the notion of a "LayeredMap", a LayeredMap is a conventional Canvas Map which has support for easily managing "Layers",
which are internally mapped to Canvas Groups. Each Group's "visible" property is managed by the LayeredMap, so that layers can be easily
toggled on/off, i.e. via checkboxes.
Basically, the idea is this, we'll have a MVC (Model/View/Controller) setup, where:
- the Model is mapped to the drawable's meta information (i.e. position)
- the View is mapped to a conventional canvas group
- the Controller is mapped to a bunch of property/timer callbacks to control the Model/View
Model = PositionedSource
View = Canvas
Controller = control properties (zoom, range etc)
LayerElement = callback to create a canvas group
Layer = canvas.Group
Map -> LayeredMap -> GenericMap -> AirportMap

View file

@ -0,0 +1,105 @@
<?xml version="1.0"?>
<!--
generic-canvas.map XML:
- to be used by dialogs and instruments to add a generic map (navaids, fixes, airports etc)
- with each feature put on a separate layer (canvas group)
- each layer being controllable via a boolean property
NOTE: This is still work in progress, and will be significantly refactored in the time to come
Current requirements: (these are subject to change)
Dialogs wanting to use this, MUST:
- set DIALOG_CANVAS in open block
- provide a helper function dialog_property(p) to return a property appended to the dialog root in /sim/gui/dialogs/FOO/
- to set up layer-checkboxes automatically, use canvas.GenericMap.setupGUICheckboxes(DIALOG_CANVAS, gui_group)
For example, add this to your dialogs Nasal/open block in "foo.xml":
var dialog_name = "foo";
var dialog_property = func(p) return "/sim/gui/dialogs/foo/"~p;
var DIALOG_CANVAS = gui.findElementByName(cmdarg(), "airport-selection");
canvas.GenericMap.setupGUICheckboxes(DIALOG_CANVAS, "canvas-control");
TODO: use a single "InitCanvasMapSupport();" helper
In the close block, you'll want to call "map.cleanup_listeners()" at the moment
-->
<PropertyList>
<!--FIXME: move somewhere else, this is GUI specific and not useful for canvas maps shown as instruments! -->
<checkbox-toggle-template>
<name></name>
<label></label>
<property></property>
<binding>
<command>dialog-apply</command>
<object-name></object-name>
</binding>
</checkbox-toggle-template>
<!-- will be procedurally added to the dialog -->
<zoom-template>
<button>
<name>zoomout</name>
<legend>-</legend>
<pref-width>22</pref-width>
<pref-height>22</pref-height>
<binding>
<command>property-adjust</command>
<property></property>
<min>0</min>
<step>-1</step>
</binding>
</button>
<text>
<label>MMMM</label>
<halign>center</halign>
<format>Zoom %d</format>
<property></property>
<live>true</live>
</text>
<button>
<name>zoomin</name>
<legend>+</legend>
<pref-width>22</pref-width>
<pref-height>22</pref-height>
<binding>
<command>property-adjust</command>
<property></property>
<step>1</step>
<max></max> <!-- FIXME: compute dynamically via Nasal size() or just a property-->
</binding>
</button>
<empty><stretch>true</stretch></empty>
</zoom-template>
<nasal>
<load><![CDATA[
var my_canvas = canvas.get(cmdarg());
my_canvas.setColorBackground(0.2, 0.5, 0.2, 0.5); #TODO: support customization in XML
var root = my_canvas.createGroup();
# the top level AirportMap element uses a "GenericMap" now:
#TODO: features should be procedurally enabled via params (WIP)
#TODO: use generic Map and instantiate via XML
var map = canvas.GenericMap.new(parent:root, name:dialog_name) # FIXME: We shouldn't be using AirportMap here:
# we need a high level wrapper that can instantiate
# all sorts of maps, not just AirportMaps
.setTranslation(300, 200) # TODO: move to Map class ctor!
.setupZoom( dialog:DIALOG_CANVAS ) # TODO: make zooming configurable for non GUI use
.pickupFeatures (DIALOG_CANVAS); # set up the features specified in the XML file
# FIXME: resource cleanup (listeners!)
update_info();
]]>
</load>
</nasal>
</PropertyList>

View file

@ -1,3 +1,89 @@
###
# map.nas - provide a high level method to create typical maps in FlightGear (airports, navaids, fixes and waypoints) for both, the GUI and instruments
# implements the notion of a "layer" by using canvas groups and adding geo-referenced elements to a layer
# layered maps are linked to boolean properties so that visibility can be easily toggled (GUI checkboxes or cockpit hotspots)
# without having to redraw other layers
#
# GOALS: have a single Nasal/Canvas wrapper for all sort of maps in FlightGear, that can be easily shared and reused for different purposes
#
# DESIGN: ... is slowly evolving, but still very much beta for the time being
#
# API: not yet documented, but see eventually design.txt (will need to add doxygen-strings then)
#
# PERFORMANCE: will be improved, probabaly by moving some features to C++ space and optimizing things there
#
#
# ISSUES: just look for the FIXME and TODO strings - currently, the priority is to create an OOP/MVC design with less specialized code in XML files
#
#
# ROADMAP: Generalize this further, so that:
#
# - it can be easily reused
# - use a MVC approach, where layer-specific data is provided by a Model object
# - other dialogs can use this without tons of custom code (airports.xml, route-manager.xml, map-canvas.xml)
# - generalize this further so that it can be used by instruments
# - implement additional layers (tcas, wxradar, agradar) - especially expose the required data to Nasal
# - implement better GUI support (events) so that zooming/panning via mouse can be supported
# - make the whole thing styleable
#
# - keep track of things getting added here and decide if they should better move to the core canvas module or the C++ code
#
#
# C++ RFEs:
# - overload findNavaidsWithinRange() to support an optional position argument, so that arbitrary navaids can be looked up
# - add Nasal extension function to get scenery vector data (landclass)
# -
# -
#
var DEBUG=0;
if (DEBUG) {
var benchmark = debug.benchmark;
}
else {
var benchmark = func(label, code) code(); # NOP
}
var assert = func(label, expr) expr and die(label);
# Mapping from surface codes to #TODO: make this XML-configurable
var SURFACECOLORS = {
1 : { type: "asphalt", r:0.2, g:0.2, b:0.2 },
2 : { type: "concrete", r:0.3, g:0.3, b:0.3 },
3 : { type: "turf", r:0.2, g:0.5, b:0.2 },
4 : { type: "dirt", r:0.4, g:0.3, b:0.3 },
5 : { type: "gravel", r:0.35, g:0.3, b:0.3 },
# Helipads
6 : { type: "asphalt", r:0.2, g:0.2, b:0.2 },
7 : { type: "concrete", r:0.3, g:0.3, b:0.3 },
8 : { type: "turf", r:0.2, g:0.5, b:0.2 },
9 : { type: "dirt", r:0.4, g:0.3, b:0.3 },
0 : { type: "gravel", r:0.35, g:0.3, b:0.3 },
};
###
# ALL LayeredMap "draws" go through this wrapper, which makes it easy to check what's going on:
var draw_layer = func(layer, callback, lod) {
var name= layer._view.get("id");
# print("Canvas:Draw op triggered"); # just to make sure that we are not adding unnecessary data when checking/unchecking a checkbox
if (DEBUG and name=="taxiways") fgcommand("profiler-start"); #without my patch, this is a no op, so no need to disable
#print("Work items:", size(layer._model._elements));
benchmark("Drawing Layer:"~layer._view.get("id"), func
foreach(var element; layer._model._elements) {
#print(typeof(layer._view));
#debug.dump(layer._view);
callback(layer._view, element, lod); # ISSUE here
});
if (! layer._model.hasData() ) print("Layer was EMPTY:", name);
if (DEBUG and name=="taxiways") fgcommand("profiler-stop");
layer._drawn=1; #TODO: this should be encapsulated
}
# Runway
#
var Runway = {
@ -29,154 +115,466 @@ var Runway = {
}
};
# AirportMap
var make = func return {parents:arg};
##
# TODO: Create a cache to reuse layers and layer data (i.e. runways)
##
# Todo: wrap parsesvg and return a function that memoizes the created canvas group, so that svg files only need to be parsed once
#
var AirportMap = {
# Create AirportMap from hash
#
# @param apt Hash containing airport data as returned from airportinfo()
new: func(apt)
{
return {
parents: [AirportMap],
_apt: apt
};
},
# Build the graphical representation of the represented airport
#
# @param layer_runways canvas.Group to attach airport map to
build: func(layer_runways)
{
var rws_done = {};
me.grp_apt = layer_runways.createChild("group", "apt-" ~ me._apt.id);
##
# TODO: Implement a real MVC design for "LayeredMaps" that have:
# - a "DataProvider" (i.e. Positioned objects)
# - a View (i.e. a Canvas)
# - a controller (i.e. input/output properties)
#
var MapModel = {}; # navaids, waypoints, fixes etc
MapModel.new = func make(MapModel);
foreach(var rw; keys(me._apt.runways))
{
var is_heli = substr(rw, 0, 1) == "H";
var rw_dir = is_heli ? nil : int(substr(rw, 0, 2));
var MapView = {}; # the canvas view, including a layer for each feature
MapView.new = func make(MapView);
var rw_rec = "";
var thresh_rec = 0;
if( rw_dir != nil )
{
rw_rec = sprintf("%02d", math.mod(rw_dir - 18, 36));
if( size(rw) == 3 )
{
var map_rec = {
"R": "L",
"L": "R",
"C": "C"
};
rw_rec ~= map_rec[substr(rw, 2)];
}
var MapController = {}; # the property tree interface to manipulate the model/view via properties
MapController.new = func make(MapController);
if( rws_done[rw_rec] != nil )
continue;
var LazyView = {}; # Gets drawables on demand from the model - via property toggle
var rw_rec = me._apt.runways[rw_rec];
if( rw_rec != nil )
thresh_rec = rw_rec.threshold;
}
var DataProvider = {};
DataProvider.new = func make(DataProvider);
rws_done[rw] = 1;
###
# for airports, navaids, fixes, waypoints etc
var PositionedProvider = {};
PositionedProvider.new = func make(DataProvider, PositionedProvider);
rw = me._apt.runways[rw];
var icon_rw =
me.grp_apt.createChild("path", "runway-" ~ rw.id)
.setStrokeLineWidth(0.5)
.setColor(1.0,1.0,1.0)
.setColorFill(0.2, 0.2, 0.2);
##
# Drawable
#
var rwy = Runway.new(rw);
var beg_thr = rwy.pointOffCenterline(rw.threshold);
var beg_thr1 = rwy.pointOffCenterline(rw.threshold, 0.5 * rw.width);
var beg_thr2 = rwy.pointOffCenterline(rw.threshold, -0.5 * rw.width);
var beg1 = rwy.pointOffCenterline(0, 0.5 * rw.width);
var beg2 = rwy.pointOffCenterline(0, -0.5 * rw.width);
## LayerElement (UNUSED ATM):
# for runways, navaids, fixes, waypoints etc
# TODO: we should differentiate between "fairly static" vs. "dynamic" layers - i.e. navaids vs. traffic
var LayerElement = {_drawable:nil};
LayerElement.new = func(drawable) {
var temp = make(LayerElement);
temp._drawable=drawable;
return temp;
}
# a drawable is either a Nasal callback or a scalar, i.e. a path to an SVG file
LayerElement.draw = func(group) {
(typeof(me._drawable)=='func') and drawable(group) or canvas.parsesvg(group,_drawable);
}
var end_thr = rwy.pointOffCenterline(rw.length - thresh_rec);
var end_thr1 = rwy.pointOffCenterline(rw.length - thresh_rec, 0.5 * rw.width);
var end_thr2 = rwy.pointOffCenterline(rw.length - thresh_rec, -0.5 * rw.width);
var end1 = rwy.pointOffCenterline(rw.length, 0.5 * rw.width);
var end2 = rwy.pointOffCenterline(rw.length, -0.5 * rw.width);
# For static targets like Navaids, Fixes - i.e. geographic position doesn't change
var StaticLayerElement = {};
icon_rw.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_CLOSE_PATH ],
[ beg1[0], beg1[1],
beg2[0], beg2[1],
end2[0], end2[1],
end1[0], end1[1] ]
);
# For moving targets such as aircraft, multiplayer, ai traffic etc
var DynamicLayerElement = {};
if( rw.length / rw.width > 3 and !is_heli )
{
# only runways which are much longer than wide are
# real runways, otherwise it's probably a heliport.
var icon_cl =
me.grp_apt.createChild("path", "centerline")
.setStrokeLineWidth(0.5)
.setColor(1,1,1)
.setStrokeDashArray([15, 10]);
var AnimatedLayerElement = {};
icon_cl.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO ],
[ beg_thr[0], beg_thr[1],
end_thr[0], end_thr[1] ]
);
# for elements whose appearance may change depending on selected range (i.e. LOD)
var RangeAwareLayerElement = {};
var icon_thr =
me.grp_apt.createChild("path", "threshold")
.setStrokeLineWidth(1.5)
.setColor(1,1,1);
icon_thr.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO ],
[ beg_thr1[0], beg_thr1[1],
beg_thr2[0], beg_thr2[1],
end_thr1[0], end_thr1[1],
end_thr2[0], end_thr2[1] ]
);
}
}
##
# A layer model is just a wrapper for a vector with elements
# either updated via a timer or via a listener
foreach(var park; me._apt.parking())
{
var icon_park =
me.grp_apt.createChild("text", "parking-" ~ park.name)
.setDrawMode( canvas.Text.ALIGNMENT
+ canvas.Text.TEXT )
.setText(park.name)
.setFont("LiberationFonts/LiberationMono-Bold.ttf")
.setGeoPosition(park.lat, park.lon)
.setFontSize(15, 1.3);
}
var icon_tower =
me.grp_apt.createChild("path", "tower")
.setStrokeLineWidth(1)
.setScale(1.5)
.setColor(0.2,0.2,1.0)
.moveTo(-3, 0)
.vert(-10)
.line(-3, -10)
.horiz(12)
.line(-3, 10)
.vert(10);
var pos = me._apt.tower();
icon_tower.setGeoPosition(pos.lat, pos.lon);
}
var LayerModel = {_elements:[], _view:, _controller: };
LayerModel.new = func make(LayerModel);
LayerModel.clear = func me._elements = [];
LayerModel.push = func (e) append(me._elements, e);
LayerModel.get = func me._elements;
LayerModel.update = func;
LayerModel.hasData = func size(me. _elements);
LayerModel.setView = func(v) me._view=v;
LayerModel.setController = func(c) me._controller=c;
var LayerController = {};
LayerController.new = func make(LayerController);
##
# use timers to update the model/view (canvas)
var TimeBasedLayerController = {};
LayerController.new = func make(TimeBasedLayerController);
##
# use listeners to update the model/view (canvas)
#
var ListenerBasedLayerController = {};
ListenerBasedLayerController.new = func make(ListenerBasedLayerController);
##
# Uses, both, listeners and timers to update the model/view (canvas)
#
var HybridLayerController = {};
HybridLayerController.new = func make(HybridLayerController);
var ModelEvents = {INIT:, RESET:, UPDATE:};
var ViewEvents = {INIT:, RESET:, UPDATE:};
var ControllerEvents = {INIT:, RESET: , UPDATE:, ZOOM:, PAN:, };
##
# A layer is mapped to a canvas group
# Layers are linked to a single boolean property to toggle them on/off
var Layer = { _model: ,
_view: ,
_controller: ,
_drawn:0,
};
Layer.new = func(group, name, model) {
#print("Setting up new Layer:", name);
var m = make(Layer);
m._model = model.new();
#print("Model name is:", m._model.name);
m._view = group.createChild("group",name);
m.name = name; #FIXME: not needed, there's already _view.get("id")
return m;
}
Layer.hide = func me._view.setVisible(0);
Layer.show = func me._view.setVisible(1);
#TODO: Unify toggle and update methods - and support lazy drawing (make it optional!)
Layer.toggle = func {
# print("Toggling layer");
var checkbox = getprop(me.display_layer);
if(checkbox and !me._drawn) {
# print("Lazy drawing");
me.draw();
}
#var state= me._view.getBool("visible");
#print("Toggle layer visibility ",me.display_layer," checkbox is", checkbox);
#print("Layer id is:", me._view.get("id"));
#print("Drawn is:", me._drawn);
checkbox?me._view.setVisible(1) : me._view.setVisible(0);
}
Layer.reset = func {
me._view.removeAllChildren(); # clear the "real" canvas drawables
me._model.clear(); # the vector is used for lazy rendering
assert("Model not emptied during layer reset!", me._model.hasData() );
me._drawn = 0;
}
#TODO: Unify toggle and update
Layer.update = func {
# print("Layer update: Check if layer is visible, if so, draw");
if (! getprop(me.display_layer)) return; # checkbox for layer not set
if (!me._model.hasData() ) return; # no data available
# print("Trying to draw");
me.draw();
}
Layer.setDraw = func(callback) me.draw = callback;
Layer.setController = func(c) me._controller=c; # TODO: implement
Layer.setModel = func(m) nil; # TODO: implement
##TODO: differentiate between layers with a single object (i.e. aircraft) and multiple objects (airports)
##
# We may need to display some stuff that isn't strictly a geopgraphic feature, but just a chart feature
#
var CartographicLayer = {};
#TODO:
var InteractiveLayer = {};
###
# PositionedLayer
#
# layer of positioned objects (i.e. have lat,lon,alt)
#
var PositionedLayer = {};
PositionedLayer.new = func() {
make( Layer.new() , PositionedLayer );
}
###
# CachedLayer
#
# when re-centering on an airport already loaded, we don't want to reload it
# but change the reference point and load missing airports
var CachedLayer = {};
##
#
var AirportProvider = {};
AirportProvider.new = func make(AirportProvider);
AirportProvider.get = func {
return airportinfo("ksfo");
}
### Data Providers (preparation for MVC version):
# TODO: should use the LayerModel class
#
##
# Manage a bunch of layers
#
var LayerManager = {};
# WXR ?
# TODO: Stub
var MapBehavior = {};
MapBehavior.new = make(MapBehavior);
MapBehavior.zoom = func;
MapBehavior.center = func;
##
# A layered map consists of several layers
# TODO: Support nested LayeredMaps, where a LayeredMap may contain other LayeredMaps
# TODO: use MapBehavior here and move the zoom/refpos methods there, so that map behavior can be easily customized
var LayeredMap = { ranges:[],
zoom_property:nil, listeners:[],
update_property:nil, layers:[],
};
LayeredMap.new = func(parent, name)
return make(LayeredMap, parent.createChild("map",name) );
LayeredMap.listen = func(p,c) { #FIXME: listening should be managed by each m/v/c separately
# print("Setting up LayeredMap-managed listener:", p);
append(me.listeners, setlistener(p, c));
}
LayeredMap.initializeLayers = func {
# print("initializing all layers and updating");
foreach(var l; me.layers)
l.update();
}
LayeredMap.setRefPos = func(lat, lon) {
# print("RefPos set");
me._node.getNode("ref-lat", 1).setDoubleValue(lat);
me._node.getNode("ref-lon", 1).setDoubleValue(lon);
me; # chainable
}
LayeredMap.setHdg = func(hdg) {
me._node.getNode("hdg",1).setDoubleValue(hdg);
me; # chainable
}
LayeredMap.updateZoom = func {
var z = getprop(me.zoom_property) or 0;
var zoom = me.ranges[ size(me.ranges)-1 -z];
# print("Setting zoom range to:", zoom);
benchmark("Zooming map:"~zoom, func
me._node.getNode("range", 1).setDoubleValue(zoom)
);
me; #chainable
}
# this is a huge hack at the moment, we need to encapsulate the setRefPos/setHdg methods, so that they are exposed to XML space
#
LayeredMap.updateState = func {
# center map on airport TODO: should be moved to a method and wrapped with a controller so that behavior can be customizeda
#var apt = me.layers[0]._model._elements[0];
# FIXME:
#me.setRefPos(lat:me._refpos.lat, lon:me._refpos.lon);
me.setHdg(0.0);
me.updateZoom();
}
#
# TODO: this is currently GUI specific and not re-usable for instruments
LayeredMap.setupZoom = func(dialog) {
var dlgroot = dialog.getNode("features/dialog-root").getValue();#FIXME: GUI specific - needs to be re-implemented for instruments
var zoom_property = dlgroot ~"/"~dialog.getNode("features/range-property").getValue(); #FIXME: this doesn't belong here, need to be in ctor instead !!!
ranges=dialog.getNode("features/ranges").getChildren("range");
foreach(var r; ranges)
append(me.ranges, r.getValue() );
# print("Setting up Zoom Ranges:", size(ranges)-1);
me.zoom_property=zoom_property;
me.listen(zoom_property, func me.updateZoom() );
me.updateZoom();
me; #chainable
}
LayeredMap.setZoom = func {} #TODO
LayeredMap.resetLayers = func {
benchmark("Resetting LayeredMap", func
foreach(var l; me.layers) { #TODO: hide all layers, hide map
l.reset();
}
);
}
#FIXME: listener management should be done at the MVC level, for each component - not as part of the LayeredMap!
LayeredMap.cleanup_listeners = func {
print("Cleaning up listeners");
foreach(var l; me.listeners)
removelistener(l);
}
###
# GenericMap: A generic map is a layered map that puts all supported features on a different layer (canvas group) so that
# they can be individually toggled on/off so that unnecessary updates are avoided, there are methods to link layers to boolean properties
# so that they can be easily associated with GUI properties (checkboxes) or cockpit hotspots
# TODO: generalize the XML-parametrization and move it to a helper class
var GenericMap = { };
GenericMap.new = func(parent, name) make(LayeredMap.new(parent:parent, name:name), GenericMap);
GenericMap.setupLayer = func(layer, property) {
var l = MAP_LAYERS[layer].new(me, layer); # Layer.new(me, layer);
l.display_layer = property; #FIXME: use controller object instead here and this overlaps with update_property
#print("Set up layer with toggle property=", property);
l._view.setVisible( getprop(property) ) ;
append(me.layers, l);
return l;
}
# features are layers - so this will do layer setup and then register listeners for each layer
GenericMap.setupFeature = func(layer, property, init ) {
var l=me.setupLayer( layer, property );
me.listen(property, func l.toggle() ); #TODO: should use the controller object here !
l._model._update_property=property; #TODO: move somewhere else - this is the property that is mapped to the CHECKBOX
l._model._view_handle = l; #FIXME: very crude, set a handle to the view(group), so that the model can notify it (for updates)
l._model._map_handle = me; #FIXME: added here so that layers can send update requests to the parent map
#print("Setting up layer init for property:", init);
l._model._input_property = init; # FIXME: init property = input property - needs to be improved!
me.listen(init, func l._model.init() ); #TODO: makes sure that the layer's init method for the MODEL is invoked
me; #chainable
};
# This will read in the config and procedurally instantiate all requested layers and link them to toggle properties
# FIXME: this is currently GUI specific and doesn't yet support instrument use, i.e. needs to be generalized further
GenericMap.pickupFeatures = func(DIALOG_CANVAS) {
var dlgroot = DIALOG_CANVAS.getNode("features/dialog-root").getValue();
# print("Picking up features for:", DIALOG_CANVAS.getPath() );
var layers=DIALOG_CANVAS.getNode("features").getChildren("layer");
foreach(var n; layers) {
var name = n.getNode("name").getValue();
var toggle = n.getNode("property").getValue();
var init = n.getNode("init-property").getValue();
init = dlgroot ~"/"~init;
var property = dlgroot ~"/"~toggle;
# print("Adding layer:",n.getNode("name").getValue() );
me.setupFeature(name, property, init);
}
me;
}
# NOT a method, cmdarg() is no longer meaningful when the canvas nasal block is executed
# so this needs to be called in the dialog's OPEN block instead - TODO: generalize
#FIXME: move somewhere else, this is a GUI helper and should probably be generalized and moved to gui.nas
GenericMap.setupGUI = func (dialog, group) {
var group = gui.findElementByName(cmdarg() , group);
var layers=dialog.getNode("features").getChildren("layer");
var template = dialog.getNode("checkbox-toggle-template");
var dlgroot = dialog.getNode("features/dialog-root").getValue();
var zoom = dlgroot ~"/"~ dialog.getNode("features/range-property").getValue();
var i=0;
foreach(var n; layers) {
var name = n.getNode("name").getValue();
var toggle = dlgroot ~ "/" ~ n.getNode("property").getValue();
var label = n.getNode("description",1).getValue() or name;
var default = n.getNode("default",1).getValue();
default = (default=="enabled")?1:0;
#print("Layer default for", name ," is:", default);
setprop(toggle, default); # set the checkbox to its default setting
var hide_checkbox = n.getNode("hide-checkbox",1).getValue();
hide_checkbox = (hide_checkbox=="true")?1:0;
var checkbox = group.getChild("checkbox",i, 1); #FIXME: compute proper offset dynamically, will currently overwrite other existing checkboxes!
props.copy(template, checkbox);
checkbox.getNode("name").setValue("display-"~name);
checkbox.getNode("label").setValue(label);
checkbox.getNode("property").setValue(toggle);
checkbox.getNode("binding/object-name").setValue("display-"~name);
checkbox.getNode("enabled",1).setValue(!hide_checkbox);
i+=1;
}
#add zoom buttons procedurally:
var template = dialog.getNode("zoom-template");
template.getNode("button[0]/binding[0]/property[0]").setValue(zoom);
template.getNode("text[0]/property[0]").setValue(zoom);
template.getNode("button[1]/binding[0]/property[0]").setValue(zoom);
template.getNode("button[1]/binding[0]/max[0]").setValue( i );
props.copy(template, group);
}
###
# TODO: StylableGenericMap (colors, fonts, symbols)
#
var AirportMap = {};
AirportMap.new = func(parent,name) make(GenericMap.new(parent,name), AirportMap);
#TODO: Use real MVC (DataProvider/PositionedProvider) here
# this is currently "directly" invoked via a listener, needs to be changed
# to use the controller object instead
# TODO: adopt real MVC here
# FIXME: this must currently be explicitly called by the model, we need to use a wrapper to call it automatically instead!
LayerModel.notifyView = func () {
# print("View notified");
me._view_handle.update(); # update the layer/group
me._map_handle.updateState(); # update the map
}
# ID
var SingleAirportProvider = {};
# inputs: position, range
var MultiAirportProvider = {};
#TODO: remove and unify with update()
AirportMap.init = func {
me.resetLayers();
me.updateState();
}
# MultiObjectLayer:
# - Airports
# - Traffic (MP/AI)
# - Navaids
#
# TODO: a "MapLayer" is a full MVC implementation that is owned by a "LayeredMap"
var MAP_LAYERS = {};
var register_layer = func(name, layer) MAP_LAYERS[name]=layer;
var MVC_FOLDER = getprop("/sim/fg-root") ~ "/Nasal/canvas/map/";
var load_modules = func(vec) foreach(var file; vec) io.load_nasal(MVC_FOLDER~file, "canvas");
# TODO: read in the file names dynamically: *.draw, *.model, *.layer
var DRAWABLES = ["navaid.draw", "parking.draw", "runways.draw", "taxiways.draw", "tower.draw"];
load_modules(DRAWABLES);
var MODELS = ["airports.model", "navaids.model",];
load_modules(MODELS);
var LAYERS = ["runways.layer", "taxiways.layer", "parking.layer", "tower.layer", "navaids.layer","test.layer",];
load_modules(LAYERS);
#TODO: Implement!
var CONTROLLERS = [];
load_modules(CONTROLLERS);

View file

View file

@ -0,0 +1,27 @@
var AirportModel = {};
AirportModel.new = func make(AirportModel, LayerModel);
# FIXME: Just testing for now: This really shouldn't be part of the core LayerModel, needs to go to "AirportModel" instead
# FIXME: This will get called ONCE for EACH layer that uses the AirportModel, so VERY inefficient ATM! => should be shared among layers
AirportModel.init = func {
# print("AirportModel initialized!");
# me._map_handle.resetLayers();
me._view_handle.reset();
var id = getprop(me._input_property); # HACK: this needs to be handled via the controller - introduce "input_property"
#print("ID is:", id);
(id == "") and return;
var apt=airportinfo(id); # FIXME: replace with controller call to update the model
#var airports = findAirportsWithinRange(apt.lat, apt.lon, 10); # HACK: expose the range !!
foreach(var a; [ apt ]) #FIXME: move to separate method: "populate"
# print("storing:", a.id) and
me.push(a);
#print("Work items in Model:", me.hasData() );
#print("Model updated!!");
# set RefPos and hdg to apt !!
me._map_handle.setRefPos(apt.lat, apt.lon);
#TODO: Notify view on update - use proper NOTIFICATIONS (INIT; UPDATE etc)
me.notifyView();
}

View file

View file

@ -0,0 +1,15 @@
##
# FIXME: until we have better instancing support for symbols, it would be better to return a functor here
# so that symbols are only parsed once
var NAVAID_CACHE = {};
var draw_navaid = func (group, navaid, lod) {
#var group = group.createChild("group", "navaid");
DEBUG and print("Drawing navaid:", navaid.id);
var symbols = {NDB:"/gui/dialogs/images/ndb_symbol.svg"}; # TODO: add more navaid symbols here
if (symbols[navaid.type] == nil) return print("Missing svg image for navaid:", navaid.type);
var symbol_navaid = group.createChild("group", "navaid");
canvas.parsesvg(symbol_navaid, symbols[navaid.type]);
symbol_navaid.setGeoPosition(navaid.lat, navaid.lon);
}

View file

@ -0,0 +1,9 @@
var NavLayer = {};
NavLayer.new = func(group,name) {
var m=Layer.new(group, name, NavaidModel);
m.setDraw (func draw_layer(layer:m, callback: draw_navaid, lod:0) );
return m;
}
register_layer("navaids", NavLayer);

View file

@ -0,0 +1,11 @@
var NavaidModel = {};
NavaidModel.new = func make(LayerModel, NavaidModel);
NavaidModel.init = func {
me._view_handle.reset();
var navaids = findNavaidsWithinRange(15);
foreach(var n; navaids)
me.push(n);
me.notifyView();
}

View file

@ -0,0 +1,15 @@
var draw_parking = func(group, apt, lod) {
var group = group.createChild("group", "apt-"~apt.id);
foreach(var park; apt.parking())
{
var icon_park =
group.createChild("text", "parking-" ~ park.name)
.setDrawMode( canvas.Text.ALIGNMENT
+ canvas.Text.TEXT )
.setText(park.name)
.setFont("LiberationFonts/LiberationMono-Bold.ttf")
.setGeoPosition(park.lat, park.lon)
.setFontSize(15, 1.3);
}
}

View file

@ -0,0 +1,9 @@
#TODO: use custom Model/DataProvider
var ParkingLayer = {}; # make(Layer);
ParkingLayer.new = func(group, name) {
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_parking, lod:0 ) );
return m;
}
register_layer("parkings", ParkingLayer);

View file

@ -0,0 +1,113 @@
#TODO: split: draw_single_runway(pos)
var draw_runways = func(group, apt,lod) {
DEBUG and print("Drawing runways for:", apt.id);
# var group = group.createChild("group", "apt-"~apt.id);
# group = group.createChild("group", "runways");
var rws_done = {};
foreach(var rw; keys(apt.runways))
{
var is_heli = substr(rw, 0, 1) == "H";
var rw_dir = is_heli ? nil : int(substr(rw, 0, 2));
var rw_rec = "";
var thresh_rec = 0;
if( rw_dir != nil )
{
rw_rec = sprintf("%02d", math.mod(rw_dir - 18, 36));
if( size(rw) == 3 )
{
var map_rec = {
"R": "L",
"L": "R",
"C": "C"
};
rw_rec ~= map_rec[substr(rw, 2)];
}
if( rws_done[rw_rec] != nil )
continue;
var rw_rec = apt.runways[rw_rec];
if( rw_rec != nil )
thresh_rec = rw_rec.threshold;
}
rws_done[rw] = 1;
rw = apt.runways[rw];
var clr = SURFACECOLORS[rw.surface];
if (clr == nil) { clr = SURFACECOLORS[0]};
var icon_rw =
group.createChild("path", "runway-" ~ rw.id)
.setStrokeLineWidth(0.5)
.setColor(1.0,1.0,1.0)
.setColorFill(clr.r, clr.g, clr.b);
var rwy = Runway.new(rw);
var beg_thr = rwy.pointOffCenterline(rw.threshold);
var beg_thr1 = rwy.pointOffCenterline(rw.threshold, 0.5 * rw.width);
var beg_thr2 = rwy.pointOffCenterline(rw.threshold, -0.5 * rw.width);
var beg1 = rwy.pointOffCenterline(0, 0.5 * rw.width);
var beg2 = rwy.pointOffCenterline(0, -0.5 * rw.width);
var end_thr = rwy.pointOffCenterline(rw.length - thresh_rec);
var end_thr1 = rwy.pointOffCenterline(rw.length - thresh_rec, 0.5 * rw.width);
var end_thr2 = rwy.pointOffCenterline(rw.length - thresh_rec, -0.5 * rw.width);
var end1 = rwy.pointOffCenterline(rw.length, 0.5 * rw.width);
var end2 = rwy.pointOffCenterline(rw.length, -0.5 * rw.width);
icon_rw.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_CLOSE_PATH ],
[ beg1[0], beg1[1],
beg2[0], beg2[1],
end2[0], end2[1],
end1[0], end1[1] ]
);
if( rw.length / rw.width > 3 and !is_heli )
{
# only runways which are much longer than wide are
# real runways, otherwise it's probably a heliport.
var icon_cl =
group.createChild("path", "centerline")
.setStrokeLineWidth(0.5)
.setColor(1,1,1)
.setStrokeDashArray([15, 10]);
icon_cl.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO ],
[ beg_thr[0], beg_thr[1],
end_thr[0], end_thr[1] ]
);
var icon_thr =
group.createChild("path", "threshold")
.setStrokeLineWidth(1.5)
.setColor(1,1,1);
icon_thr.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO ],
[ beg_thr1[0], beg_thr1[1],
beg_thr2[0], beg_thr2[1],
end_thr1[0], end_thr1[1],
end_thr2[0], end_thr2[1] ]
);
}
}
}

View file

@ -0,0 +1,10 @@
#TODO: use custom Model/DataProvider
var RunwayLayer = {}; # make(Layer);
RunwayLayer.new = func(group, name) {
# print("Setting up new TestLayer");
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_runways, lod:0 ) );
return m;
}
register_layer("runways", RunwayLayer);

View file

@ -0,0 +1,40 @@
var draw_taxiways = func(group, apt, lod) { # TODO: the LOD arg isn't stricly needed here,
# the layer is a conventional canvas group, so it can access its map
# parent and just read the "range" property to do LOD handling
group.set("z-index",-100); # HACK: we need to encapsulate this
# var group = group.createChild("group", "apt-"~apt.id); #FIXME: we don't need to use two nested groups for each taxiway - performance?
# group = group.createChild("group", "taxiways");
# print("drawing taxiways for:", apt.id);
# Taxiways drawn first so the runways and parking positions end up on top.
foreach(var taxi; apt.taxiways)
{
var clr = SURFACECOLORS[taxi.surface];
if (clr == nil) { clr = SURFACECOLORS[0]};
var icon_taxi =
group.createChild("path", "taxi")
.setStrokeLineWidth(0)
.setColor(clr.r, clr.g, clr.b)
.setColorFill(clr.r, clr.g, clr.b);
var txi = Runway.new(taxi);
var beg1 = txi.pointOffCenterline(0, 0.5 * taxi.width);
var beg2 = txi.pointOffCenterline(0, -0.5 * taxi.width);
var end1 = txi.pointOffCenterline(taxi.length, 0.5 * taxi.width);
var end2 = txi.pointOffCenterline(taxi.length, -0.5 * taxi.width);
icon_taxi.setDataGeo
(
[ canvas.Path.VG_MOVE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_LINE_TO,
canvas.Path.VG_CLOSE_PATH ],
[ beg1[0], beg1[1],
beg2[0], beg2[1],
end2[0], end2[1],
end1[0], end1[1] ]
);
}
}

View file

@ -0,0 +1,11 @@
#TODO: use custom Model/DataProvider
var TaxiwayLayer = {}; # make(Layer);
TaxiwayLayer.new = func(group, name) {
# print("Setting up new TestLayer");
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_taxiways, lod:0 ) );
return m;
}
register_layer("taxiways", TaxiwayLayer);

View file

@ -0,0 +1,11 @@
#TODO: use custom Model/DataProvider
var TestLayer = {}; # make(Layer);
TestLayer.new = func(group, name) {
# print("Setting up new TestLayer");
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: MAP_LAYERS["runways"], lod:0 ) );
return m;
}
register_layer("airport_test", TestLayer);

View file

@ -0,0 +1,19 @@
var draw_tower = func (group, apt,lod) {
var group = group.createChild("group", "tower");
# TODO: move to map_elements.nas (tower, runway, parking etc)
# i.e.: set_element(group, "tower", "style");
var icon_tower =
group.createChild("path", "tower")
.setStrokeLineWidth(1)
.setScale(1.5)
.setColor(0.2,0.2,1.0)
.moveTo(-3, 0)
.vert(-10)
.line(-3, -10)
.horiz(12)
.line(-3, 10)
.vert(10);
icon_tower.setGeoPosition(apt.lat, apt.lon);
}

View file

@ -0,0 +1,8 @@
var TowerLayer = {};
TowerLayer.new = func(group, name) {
var m=Layer.new(group, name, AirportModel ); #FIXME: AirportModel can be shared by Taxiways, Runways etc!!
m.setDraw( func draw_layer(layer: m, callback: draw_tower, lod:0 ) );
return m;
}
register_layer("towers", TowerLayer);

View file

View file

@ -159,6 +159,7 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
menuEnable("rendering-buffers", getprop("/sim/rendering/rembrandt/enabled"));
menuEnable("rembrandt-buffers-choice", getprop("/sim/rendering/rembrandt/enabled"));
menuEnable("stereoscopic-options", !getprop("/sim/rendering/rembrandt/enabled"));
menuEnable("sound-config", getprop("/sim/sound/working"));
# frame-per-second display
var fps = props.globals.getNode("/sim/rendering/fps-display", 1);

View file

@ -611,7 +611,7 @@ var readConfig = func(dialog_root="/sim/gui/dialogs/joystick-config") {
if (a != nil) {
# Read properties from bindings
props.copy(a, p.getNode("original_binding", 1));
props.copy(a, btn.getNode("original_binding", 1));
var binding = nil;
foreach (var b; joystick.buttonBindings) {
if ((binding == nil) and (a != nil) and b.match(a)) {

View file

@ -6,7 +6,7 @@
var index = nil; # current view index
var views = nil; # list of all view branches (/sim/view[n]) as props.Node
var current = nil; # current view branch (e.g. /sim/view[1]) as props.Node
var fovProp = nil;
var hasmember = func(class, member) {
if (contains(class, member))
@ -235,6 +235,7 @@ var manager = {
me.current.handler.start();
if (hasmember(me.current.handler, "update"))
me._loop_(me.loopid += 1);
resetFOV();
},
reset : func {
if (hasmember(me.current.handler, "reset"))
@ -638,7 +639,61 @@ var point = {
var fovProp = nil;
##
# view.ScreenWidthCompens: optional FOV compensation for wider screens.
# It keeps an equivalent of 55° FOV on a 4:3 zone centered on the screen
# whichever is the screen width/height ratio. Works only if width >= height.
#
# status: 0=Init, 1=toggle option, 2=waiting for the window size to change.
var defaultFov = nil;
var oldW = 0;
var oldH = 0;
var fovStore = {};
var screenWidthCompens = func(status) {
var opt = getprop("/sim/current-view/field-of-view-compensation");
if (status == 0) {
defaultFov = getprop("/sim/current-view/config/default-field-of-view-deg");
forindex (var i; views) {
var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
fovStore[i] = defaultFovNode.getValue();
}
} elsif (status == 1) {
opt = ! opt;
setprop("/sim/current-view/field-of-view-compensation", opt);
if (! opt) {
forindex (var i; views) {
var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
defaultFovNode.setValue(fovStore[i]);
}
var vn = getprop("/sim/current-view/view-number");
setprop("/sim/current-view/field-of-view", fovStore[vn]);
}
} elsif (status == 2 and ! opt) {
return;
}
var w = getprop("/sim/rendering/camera-group/camera/viewport/width");
var h = getprop("/sim/rendering/camera-group/camera/viewport/height");
if (! opt) {
setprop("/sim/current-view/config/default-field-of-view-deg", defaultFov);
return;
}
if ( w != oldW or h != oldH or status == 1) {
oldW = w;
oldH = h;
d = 1.28066 * h; # 1.28066 = 4/3 (width/height ratio) / 2 / tan(55°)
newFov = 2 * math.atan2( w / h * h / 2, d) * R2D;
setprop("/sim/current-view/config/default-field-of-view-deg", newFov);
forindex (var i; views) {
var defaultFovNode = views[i].getNode("config/default-field-of-view-deg", 1);
defaultFovNode.setValue(newFov);
}
fovProp.setValue(newFov);
}
settimer(func { screenWidthCompens(2); }, 1);
}
_setlistener("/sim/signals/nasal-dir-initialized", func {
@ -654,6 +709,7 @@ _setlistener("/sim/signals/nasal-dir-initialized", func {
manager.init();
manager.register("Fly-By View", fly_by_view_handler);
manager.register("Model View", model_view_handler);
screenWidthCompens(0);
});

View file

@ -175,7 +175,7 @@ void main (void)
//adding snow and permanent snow/glacier
if (vegetationlevel > snowlevel || vegetationlevel > 3100.0) {
if (vegetationlevel > snowlevel) {
c3 = mix(vec4(n+1.0, n+1.0, n+1.0, 0.0), c1, smoothstep(0.990, 0.965, abs(normalize(Normal).z)+nvL[2]*1.3));
c4 = mix(vec4(n+1.0, n+1.0, n+1.0, 0.0), c1, smoothstep(0.990, 0.965, abs(normalize(Normal).z)+nvL[2]*0.9));
c5 = mix(c3, c4, 1.0);

View file

@ -30,6 +30,7 @@ uniform float overcast;
uniform float eye_alt;
uniform float snowlevel;
uniform float dust_cover_factor;
uniform float lichen_cover_factor;
uniform float wetness;
uniform float fogstructure;
uniform int quality_level;
@ -51,53 +52,53 @@ float cosine_interpolate(in float a, in float b, in float x)
{
float ft = x * 3.1415927;
float f = (1.0 - cos(ft)) * .5;
return a*(1.0-f) + b*f;
}
float simple_interpolate(in float a, in float b, in float x)
{
return a + smoothstep(0.0,1.0,x) * (b-a);
//return mix(a,b,x);
return a + smoothstep(0.0,1.0,x) * (b-a);
//return mix(a,b,x);
}
float interpolatedNoise2D(in float x, in float y)
{
float integer_x = x - fract(x);
float fractional_x = x - integer_x;
float integer_y = y - fract(y);
float fractional_y = y - integer_y;
float v1 = rand2D(vec2(integer_x, integer_y));
float v2 = rand2D(vec2(integer_x+1.0, integer_y));
float v3 = rand2D(vec2(integer_x, integer_y+1.0));
float v4 = rand2D(vec2(integer_x+1.0, integer_y +1.0));
float i1 = simple_interpolate(v1 , v2 , fractional_x);
float i2 = simple_interpolate(v3 , v4 , fractional_x);
return simple_interpolate(i1 , i2 , fractional_y);
float integer_x = x - fract(x);
float fractional_x = x - integer_x;
float integer_y = y - fract(y);
float fractional_y = y - integer_y;
float v1 = rand2D(vec2(integer_x, integer_y));
float v2 = rand2D(vec2(integer_x+1.0, integer_y));
float v3 = rand2D(vec2(integer_x, integer_y+1.0));
float v4 = rand2D(vec2(integer_x+1.0, integer_y +1.0));
float i1 = simple_interpolate(v1 , v2 , fractional_x);
float i2 = simple_interpolate(v3 , v4 , fractional_x);
return simple_interpolate(i1 , i2 , fractional_y);
}
float Noise2D(in vec2 coord, in float wavelength)
{
return interpolatedNoise2D(coord.x/wavelength, coord.y/wavelength);
return interpolatedNoise2D(coord.x/wavelength, coord.y/wavelength);
}
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
x = x - 0.5;
// use the asymptotics to shorten computations
if (x > 30.0) {return e;}
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
x = x - 0.5;
// use the asymptotics to shorten computations
if (x > 30.0) {return e;}
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
// this determines how light is attenuated in the distance
@ -106,32 +107,39 @@ float light_func (in float x, in float a, in float b, in float c, in float d, in
float fog_func (in float targ)
{
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
if (alt < 30000.0) {
return exp(-targ - targ * targ * targ * targ);
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ * smoothstep(0.04,0.06,targ); // need to sync with the distance to which terrain is drawn
if (alt < 30000.0)
{return exp(-targ - targ * targ * targ * targ);}
else if (alt < 50000.0)
{
fade_mix = (alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
}
else if (alt < 50000.0) {
fade_mix = (alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
else
{
return exp(- targ * targ - pow(targ,4.0));
}
else {
return exp(- targ * targ - pow(targ,4.0));
}
}
void main()
{
float dist = length(relPos);
// this is taken from default.frag
float dist = length(relPos);
// this is taken from default.frag
vec3 n;
float NdotL, NdotHV, fogFactor;
vec4 color = gl_Color;
@ -146,347 +154,362 @@ void main()
vec4 specular = vec4(0.0);
float intensity;
// get noise at different wavelengths
// used: 5m, 5m gradient, 10m, 10m gradient: heightmap of the closeup terrain, 10m also snow
// 50m: detail texel
// 250m: detail texel
// 500m: distortion and overlay
// 1500m: overlay, detail, dust, fog
// 2000m: overlay, detail, snow, fog
float noise_10m;
float noise_5m;
noise_10m = Noise2D(rawPos.xy, 10.0);
noise_5m = Noise2D(rawPos.xy ,5.0);
float noisegrad_10m;
float noisegrad_5m;
float noise_50m;
float noise_250m;
float noise_500m = Noise2D(rawPos.xy, 500.0);
float noise_1500m = Noise2D(rawPos.xy, 1500.0);
float noise_2000m = Noise2D(rawPos.xy, 2000.0);
//
// get the texels
// get noise at different wavelengths
// used: 5m, 5m gradient, 10m, 10m gradient: heightmap of the closeup terrain, 10m also snow
// 50m: detail texel
// 250m: detail texel
// 500m: distortion and overlay
// 1500m: overlay, detail, dust, fog
// 2000m: overlay, detail, snow, fog
float noise_10m;
float noise_5m;
noise_10m = Noise2D(rawPos.xy, 10.0);
noise_5m = Noise2D(rawPos.xy ,5.0);
float noisegrad_10m;
float noisegrad_5m;
float noise_50m;
float noise_250m;
float noise_500m = Noise2D(rawPos.xy, 500.0);
float noise_1500m = Noise2D(rawPos.xy, 1500.0);
float noise_2000m = Noise2D(rawPos.xy, 2000.0);
//
// get the texels
texel = texture2D(texture, gl_TexCoord[0].st);
float distortion_factor = 1.0;
vec2 stprime;
int flag = 1;
int mix_flag = 1;
if (quality_level > 3)
{
snow_texel = texture2D(snow_texture, gl_TexCoord[0].st);
snow_texel = texture2D(snow_texture, gl_TexCoord[0].st);
//snow_texel = vec4 (0.9, 0.9, 0.95, 1.0) * (0.8 + 0.2* noise_500m + 0.1* (1.0 - noise_10m) );
}
if (tquality_level > 2)
{
mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3);
if (mix_texel.a <0.1) {mix_flag = 0;}
}
if (tquality_level > 3)
mix_texel = texture2D(mix_texture, gl_TexCoord[0].st * 1.3);
if (mix_texel.a <0.1) {mix_flag = 0;}
}
if (tquality_level > 3)
{
stprime = vec2 (0.86*gl_TexCoord[0].s + 0.5*gl_TexCoord[0].t, 0.5*gl_TexCoord[0].s - 0.86*gl_TexCoord[0].t);
//distortion_factor = 0.9375 + (1.0 * nvL[2]);
distortion_factor = 0.97 + 0.06 * noise_500m;
stprime = stprime * distortion_factor * 15.0;
if (quality_level > 4)
stprime = vec2 (0.86*gl_TexCoord[0].s + 0.5*gl_TexCoord[0].t, 0.5*gl_TexCoord[0].s - 0.86*gl_TexCoord[0].t);
//distortion_factor = 0.9375 + (1.0 * nvL[2]);
distortion_factor = 0.97 + 0.06 * noise_500m;
stprime = stprime * distortion_factor * 15.0;
if (quality_level > 4)
{
stprime = stprime + normalize(relPos).xy * 0.02 * (noise_10m + 0.5 * noise_5m - 0.75);
stprime = stprime + normalize(relPos).xy * 0.02 * (noise_10m + 0.5 * noise_5m - 0.75);
}
detail_texel = texture2D(detail_texture, stprime);
if (detail_texel.a <0.1) {flag = 0;}
detail_texel = texture2D(detail_texture, stprime);
if (detail_texel.a <0.1) {flag = 0;}
}
// texture preparation according to detail level
// mix in hires texture patches
float dist_fact;
float nSum;
float mix_factor;
if (tquality_level > 2)
// texture preparation according to detail level
// mix in hires texture patches
float dist_fact;
float nSum;
float mix_factor;
if (tquality_level > 2)
{
// first the second texture overlay
if (mix_flag == 1)
{
// first the second texture overlay
if (mix_flag == 1)
{
nSum = nSum + 0.2 * (2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m);
nSum = nSum + 0.2 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
mix_factor = smoothstep(0.5, 0.54, nSum);
texel = mix(texel, mix_texel, mix_factor);
}
// then the detail texture overlay
nSum = 0.18 * (2.0 * noise_2000m + 2.0 * noise_1500m + noise_500m);
nSum = nSum + 0.4 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
mix_factor = smoothstep(0.5, 0.54, nSum);
texel = mix(texel, mix_texel, mix_factor);
}
if (tquality_level > 3)
{
if (dist < 40000.0)
// then the detail texture overlay
}
if (tquality_level > 3)
{
if (dist < 40000.0)
{
if (flag == 1)
{
if (flag == 1)
{
noise_50m = Noise2D(rawPos.xy, 50.0);
noise_250m = Noise2D(rawPos.xy, 250.0);
dist_fact = 0.1 * smoothstep(15000.0,40000.0, dist) - 0.03 * (1.0 - smoothstep(500.0,5000.0, dist));
nSum = ((1.0 -noise_2000m) + noise_1500m + 2.0 * noise_250m +noise_50m)/5.0;
nSum = nSum - 0.03 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
mix_factor = smoothstep(0.47, 0.54, nSum - dist_fact);
if (mix_factor > 0.8) {mix_factor = 0.8;}
texel = mix(texel, detail_texel,mix_factor);
}
noise_50m = Noise2D(rawPos.xy, 50.0);
noise_250m = Noise2D(rawPos.xy, 250.0);
dist_fact = 0.1 * smoothstep(15000.0,40000.0, dist) - 0.03 * (1.0 - smoothstep(500.0,5000.0, dist));
nSum = ((1.0 -noise_2000m) + noise_1500m + 2.0 * noise_250m +noise_50m)/5.0;
nSum = nSum - 0.08 * (1.0 -smoothstep(0.9,0.95, abs(steepness)));
mix_factor = smoothstep(0.47, 0.54, nSum - dist_fact);
if (mix_factor > 0.8) {mix_factor = 0.8;}
texel = mix(texel, detail_texel,mix_factor);
}
}
vec4 dust_color;
float snow_alpha;
if (quality_level > 3)
}
const vec4 dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
const vec4 lichen_color = vec4 (0.17, 0.20, 0.06, 1.0);;
float snow_alpha;
if (quality_level > 3)
{
// mix dust
dust_color = vec4 (0.76, 0.71, 0.56, 1.0);
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * (((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
// mix snow
snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
texel = mix(texel, snow_texel, smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (relPos.z + eye_alt)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
// mix vegetation
texel = mix(texel, lichen_color, 0.4 * lichen_cover_factor + 0.8 * lichen_cover_factor * 0.5 * (noise_10m + (1.0 - noise_5m)) );
// mix dust
texel = mix(texel, dust_color, clamp(0.5 * dust_cover_factor + 3.0 * dust_cover_factor * (((noise_1500m - 0.5) * 0.125)+0.125 ),0.0, 1.0) );
// mix snow
snow_alpha = smoothstep(0.75, 0.85, abs(steepness));
texel = mix(texel, snow_texel, smoothstep(snowlevel, snowlevel+200.0, snow_alpha * (relPos.z + eye_alt)+ (noise_2000m + 0.1 * noise_10m -0.55) *400.0));
}
// get distribution of water when terrain is wet
float water_threshold1;
float water_threshold2;
float water_factor =0.0;
if ((dist < 5000.0)&& (quality_level > 3) && (wetness>0.0))
{
// get distribution of water when terrain is wet
float water_threshold1;
float water_threshold2;
float water_factor =0.0;
if ((dist < 5000.0)&& (quality_level > 3) && (wetness>0.0))
{
water_threshold1 = 1.0-0.5* wetness;
water_threshold2 = 1.0 - 0.3 * wetness;
water_factor = smoothstep(water_threshold1, water_threshold2 , (0.3 * (2.0 * (1.0-noise_10m) + (1.0 -noise_5m)) * (1.0 - smoothstep(2000.0, 5000.0, dist))) - 5.0 * (1.0 -steepness));
}
// darken wet terrain
texel.rgb = texel.rgb * (1.0 - 0.6 * wetness);
// light computations
vec4 light_specular = gl_LightSource[0].specular;
// If gl_Color.a == 0, this is a back-facing polygon and the
// normal should be reversed.
n = (2.0 * gl_Color.a - 1.0) * normal;
n = normalize(n);
NdotL = dot(n, lightDir);
if ((tquality_level > 3) && (mix_flag ==1)&& (dist < 2000.0) && (quality_level > 4))
// darken wet terrain
texel.rgb = texel.rgb * (1.0 - 0.6 * wetness);
// light computations
vec4 light_specular = gl_LightSource[0].specular;
// If gl_Color.a == 0, this is a back-facing polygon and the
// normal should be reversed.
n = (2.0 * gl_Color.a - 1.0) * normal;
n = normalize(n);
NdotL = dot(n, lightDir);
if ((tquality_level > 3) && (mix_flag ==1)&& (dist < 2000.0) && (quality_level > 4))
{
noisegrad_10m = (noise_10m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0))/0.05;
noisegrad_5m = (noise_5m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),5.0))/0.05;
NdotL = NdotL + 1.0 * (noisegrad_10m + 0.5* noisegrad_5m) * mix_factor/0.8 * (1.0 - smoothstep(1000.0, 2000.0, dist));
noisegrad_10m = (noise_10m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),10.0))/0.05;
noisegrad_5m = (noise_5m - Noise2D(rawPos.xy+ 0.05 * normalize(lightDir.xy),5.0))/0.05;
NdotL = NdotL + 1.0 * (noisegrad_10m + 0.5* noisegrad_5m) * mix_factor/0.8 * (1.0 - smoothstep(1000.0, 2000.0, dist));
}
if (NdotL > 0.0) {
color += diffuse_term * NdotL;
NdotHV = max(dot(n, halfVector), 0.0);
if (gl_FrontMaterial.shininess > 0.0) {
specular.rgb = ((gl_FrontMaterial.specular.rgb + (water_factor * vec3 (1.0, 1.0, 1.0)))
* light_specular.rgb
* pow(NdotHV, gl_FrontMaterial.shininess + (20.0 * water_factor)));
}
}
color.a = diffuse_term.a;
// This shouldn't be necessary, but our lighting becomes very
// saturated. Clamping the color before modulating by the texture
// is closer to what the OpenGL fixed function pipeline does.
color = clamp(color, 0.0, 1.0);
fragColor = color * texel + specular;
// here comes the terrain haze model
float delta_z = hazeLayerAltitude - eye_alt;
if (dist > max(40.0, 0.04 * min(visibility,avisibility)))
//if ((gl_FragCoord.y > ylimit) || (gl_FragCoord.x < zlimit1) || (gl_FragCoord.x > zlimit2))
//if (dist > 40.0)
if (NdotL > 0.0) {
color += diffuse_term * NdotL;
NdotHV = max(dot(n, halfVector), 0.0);
if (gl_FrontMaterial.shininess > 0.0)
specular.rgb = ((gl_FrontMaterial.specular.rgb + (water_factor * vec3 (1.0, 1.0, 1.0)))
* light_specular.rgb
* pow(NdotHV, gl_FrontMaterial.shininess + (20.0 * water_factor)));
}
color.a = diffuse_term.a;
// This shouldn't be necessary, but our lighting becomes very
// saturated. Clamping the color before modulating by the texture
// is closer to what the OpenGL fixed function pipeline does.
color = clamp(color, 0.0, 1.0);
fragColor = color * texel + specular;
// here comes the terrain haze model
float delta_z = hazeLayerAltitude - eye_alt;
if (dist > max(40.0, 0.04 * min(visibility,avisibility)))
//if ((gl_FragCoord.y > ylimit) || (gl_FragCoord.x < zlimit1) || (gl_FragCoord.x > zlimit2))
//if (dist > 40.0)
{
alt = eye_alt;
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
// angle with horizon
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
if (delta_z > 0.0) // we're inside the layer
{
alt = eye_alt;
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
// angle with horizon
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
if (delta_z > 0.0) // we're inside the layer
if (ct < 0.0) // we look down
{
if (ct < 0.0) // we look down
{
distance_in_layer = dist;
vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
delta_zv = delta_z - vAltitude;
}
else // we may look through upper layer edge
{
H = dist * ct;
if (H > delta_z) {
distance_in_layer = dist/H * delta_z;
}
else {
distance_in_layer = dist;
}
vAltitude = min(distance_in_layer,visibility) * ct;
delta_zv = delta_z - vAltitude;
}
distance_in_layer = dist;
vAltitude = min(distance_in_layer,min(visibility, avisibility)) * ct;
delta_zv = delta_z - vAltitude;
}
else // we see the layer from above, delta_z < 0.0
{
H = dist * -ct;
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
{
distance_in_layer = 0.0;
delta_zv = 0.0;
}
else
{
vAltitude = H + delta_z;
distance_in_layer = vAltitude/H * dist;
vAltitude = min(distance_in_layer,visibility) * (-ct);
delta_zv = vAltitude;
}
}
// ground haze cannot be thinner than aloft visibility in the model,
// so we need to use aloft visibility otherwise
transmission_arg = (dist-distance_in_layer)/avisibility;
float eqColorFactor;
if (visibility < avisibility)
else // we may look through upper layer edge
{
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/visibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -scattering);
H = dist * ct;
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
else {distance_in_layer = dist;}
vAltitude = min(distance_in_layer,visibility) * ct;
delta_zv = delta_z - vAltitude;
}
else
{
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -scattering);
}
transmission = fog_func(transmission_arg);
// there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
float lightArg = (terminator-yprime_alt)/100000.0;
vec3 hazeColor;
hazeColor.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0);
hazeColor.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
// now dim the light for haze
eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
// Mie-like factor
if (lightArg < 5.0)
{
intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
// high altitude desaturation of the haze color
intensity = length(hazeColor);
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
// blue hue of haze
hazeColor.x = hazeColor.x * 0.83;
hazeColor.y = hazeColor.y * 0.9;
// additional blue in indirect light
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 1.5* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,eShade) ));
// change haze color to blue hue for strong fogging
hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0-smoothstep(0.3,0.8,eqColorFactor))));
// reduce haze intensity when looking at shaded surfaces, only in terminator region
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
fragColor.xyz = mix(eqColorFactor * hazeColor * eShade, fragColor.xyz,transmission);
gl_FragColor = fragColor;
}
else // if dist < threshold no fogging at all
else // we see the layer from above, delta_z < 0.0
{
H = dist * -ct;
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
{
distance_in_layer = 0.0;
delta_zv = 0.0;
}
else
{
vAltitude = H + delta_z;
distance_in_layer = vAltitude/H * dist;
vAltitude = min(distance_in_layer,visibility) * (-ct);
delta_zv = vAltitude;
}
}
// ground haze cannot be thinner than aloft visibility in the model,
// so we need to use aloft visibility otherwise
transmission_arg = (dist-distance_in_layer)/avisibility;
float eqColorFactor;
if (visibility < avisibility)
{
gl_FragColor = fragColor;
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * visibility + 1.0 * visibility * fogstructure * 0.06 * (noise_1500m + noise_2000m -1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/visibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -scattering);
}
else
{
if (quality_level > 3)
{
transmission_arg = transmission_arg + (distance_in_layer/(1.0 * avisibility + 1.0 * avisibility * fogstructure * 0.06 * (noise_1500m + noise_2000m - 1.0) ));
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
}
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -scattering);
}
transmission = fog_func(transmission_arg);
// there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
float lightArg = (terminator-yprime_alt)/100000.0;
vec3 hazeColor;
hazeColor.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0);
hazeColor.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
// now dim the light for haze
eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
// Mie-like factor
if (lightArg < 10.0)
{intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
// high altitude desaturation of the haze color
intensity = length(hazeColor);
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, alt)));
// blue hue of haze
hazeColor.x = hazeColor.x * 0.83;
hazeColor.y = hazeColor.y * 0.9;
// additional blue in indirect light
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 1.5* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,eShade) ));
// change haze color to blue hue for strong fogging
hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0-smoothstep(0.3,0.8,eqColorFactor))));
// reduce haze intensity when looking at shaded surfaces, only in terminator region
float shadow = mix( min(1.0 + dot(normal,lightDir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
fragColor.xyz = mix(eqColorFactor * hazeColor * eShade, fragColor.xyz,transmission);
gl_FragColor = fragColor;
}
else // if dist < threshold no fogging at all
{
gl_FragColor = fragColor;
}
}

View file

@ -160,7 +160,7 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
lightArg = (terminator-yprime_alt)/100000.0;
// directional scattering for low sun
if (lightArg < 5.0)
if (lightArg < 10.0)
{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
else
{mie_angle = 1.0;}

View file

@ -22,7 +22,9 @@ uniform float terrain_alt;
uniform float hazeLayerAltitude;
uniform float overcast;
uniform float eye_alt;
uniform float dust_cover_factor;
uniform int quality_level;
const float EarthRadius = 5800000.0;
const float terminator_width = 200000.0;
@ -88,6 +90,13 @@ void main()
vec4 fragColor = gl_Color * texture2D(texture, gl_TexCoord[0].st);
if (quality_level > 3)
{
// mix dust
vec4 dust_color = vec4 (0.76, 0.71, 0.56, fragColor.a);
fragColor = mix(fragColor, dust_color, clamp(0.6 * dust_cover_factor ,0.0, 1.0) );
}
// here comes the terrain haze model

View file

@ -38,7 +38,7 @@ varying vec4 waterTex1; //moving texcoords
varying vec4 waterTex2; //moving texcoords
varying vec3 viewerdir;
varying vec3 normal;
varying vec3 Vnormal;
varying vec3 rawNormal;
varying vec3 VTangent;
varying vec3 VBinormal;
@ -65,7 +65,7 @@ void main(void)
vec3 E = normalize(viewerdir);
vec3 Normal = normalize(normal);
vec3 vNormal = normalize(Vnormal);
vec3 vNormal = normalize(rawNormal);
const float water_shininess = 240.0;
@ -171,7 +171,8 @@ void main(void)
vec3 N2 = normalize(mix(N0, N1, mixFactor) * waveRoughness);
Normal = normalize(N2.x * VTangent + N2.y * VBinormal + N2.z * Normal);
vNormal = normalize(mix(vNormal + N0, vNormal + N1, mixFactor) * waveRoughness);
//vNormal = normalize(mix(vNormal + N0, vNormal + N1, mixFactor) * waveRoughness);
vNormal = normalize(N2.x * vec3(1.,0.,0.) + N2.y * vec3(0.,1.,0.) + N2.z * vNormal);
if (normalmap_dds > 0){
Normal = -Normal; //dds fix

View file

@ -13,6 +13,7 @@ varying vec4 waterTex2;
varying vec3 viewerdir;
varying vec3 lightdir;
varying vec3 normal;
varying vec3 rawNormal;
varying vec3 VTangent;
varying vec3 VBinormal;
@ -37,6 +38,7 @@ void rotationmatrix(in float angle, out mat4 rotmat)
void main(void)
{
mat4 RotationMatrix;
rawNormal= gl_Normal;
normal = gl_NormalMatrix * gl_Normal;
VTangent = normalize(gl_NormalMatrix * tangent);
VBinormal = normalize(gl_NormalMatrix * binormal);

View file

@ -163,11 +163,11 @@ if (terminator < 1000000.0) // the full, sunrise and sunset computation
if (earthShade < 0.5)
{
intensity = length(specular_light.rgb);
specular_light.xyz = intensity * normalize(mix(specular_light.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.5,earthShade) ));
specular_light.xyz = intensity * normalize(mix(specular_light.xyz, vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.1, 0.7,earthShade) ));
}
// directional scattering for low sun
if (lightArg < 5.0)
if (lightArg < 10.0)
//{mie_angle = (0.5 * dot(normalize(relPos), normalize(lightFull)) ) + 0.5;}
{mie_angle = (0.5 * dot(normalize(relPos), lightdir) ) + 0.5;}
else

View file

@ -0,0 +1,567 @@
// This shader is mostly an adaptation of the shader found at
// http://www.bonzaisoftware.com/water_tut.html and its glsl conversion
// available at http://forum.bonzaisoftware.com/viewthread.php?tid=10
// © Michael Horsch - 2005
// Major update and revisions - 2011-10-07
// © Emilian Huminiuc and Vivian Meazza
// ported to lightfield shading Thorsten Renk 2012
#version 120
uniform sampler2D water_normalmap;
uniform sampler2D water_dudvmap;
uniform sampler2D sea_foam;
uniform sampler2D perlin_normalmap;
uniform sampler3D Noise;
uniform float saturation, Overcast, WindE, WindN;
uniform float osg_SimulationTime;
varying vec4 waterTex1; //moving texcoords
varying vec4 waterTex2; //moving texcoords
varying vec4 waterTex4; //viewts
varying vec3 viewerdir;
varying vec3 lightdir;
varying vec3 specular_light;
varying vec3 relPos;
varying float earthShade;
varying float yprime_alt;
varying float mie_angle;
uniform float WaveFreq ;
uniform float WaveAmp ;
uniform float WaveSharp ;
uniform float WaveAngle ;
uniform float WaveFactor ;
uniform float WaveDAngle ;
uniform float normalmap_dds;
uniform float hazeLayerAltitude;
uniform float terminator;
uniform float terrain_alt;
uniform float avisibility;
uniform float visibility;
uniform float overcast;
uniform float scattering;
uniform float ground_scattering;
uniform float eye_alt;
uniform float sea_r;
uniform float sea_g;
uniform float sea_b;
uniform float ylimit;
uniform float zlimit1;
uniform float zlimit2;
//uniform int wquality_level;
const float terminator_width = 200000.0;
const float EarthRadius = 5800000.0;
////fog "include" /////
//uniform int fogType;
vec3 fog_Func(vec3 color, int type);
//////////////////////
/////// functions /////////
void rotationmatrix(in float angle, out mat4 rotmat)
{
rotmat = mat4( cos( angle ), -sin( angle ), 0.0, 0.0,
sin( angle ), cos( angle ), 0.0, 0.0,
0.0 , 0.0 , 1.0, 0.0,
0.0 , 0.0 , 0.0, 1.0 );
}
// wave functions ///////////////////////
struct Wave {
float freq; // 2*PI / wavelength
float amp; // amplitude
float phase; // speed * 2*PI / wavelength
vec2 dir;
};
Wave wave0 = Wave(1.0, 1.0, 0.5, vec2(0.97, 0.25));
Wave wave1 = Wave(2.0, 0.5, 1.3, vec2(0.97, -0.25));
Wave wave2 = Wave(1.0, 1.0, 0.6, vec2(0.95, -0.3));
Wave wave3 = Wave(2.0, 0.5, 1.4, vec2(0.99, 0.1));
float evaluateWave(in Wave w, vec2 pos, float t)
{
return w.amp * sin( dot(w.dir, pos) * w.freq + t * w.phase);
}
// derivative of wave function
float evaluateWaveDeriv(Wave w, vec2 pos, float t)
{
return w.freq * w.amp * cos( dot(w.dir, pos)*w.freq + t*w.phase);
}
// sharp wave functions
float evaluateWaveSharp(Wave w, vec2 pos, float t, float k)
{
return w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k);
}
float evaluateWaveDerivSharp(Wave w, vec2 pos, float t, float k)
{
return k*w.freq*w.amp * pow(sin( dot(w.dir, pos)*w.freq + t*w.phase)* 0.5 + 0.5 , k - 1) * cos( dot(w.dir, pos)*w.freq + t*w.phase);
}
void sumWaves(float angle, float dangle, float windScale, float factor, out float ddx, float ddy)
{
mat4 RotationMatrix;
float deriv;
vec4 P = waterTex1 * 1024;
rotationmatrix(radians(angle + dangle * windScale + 0.6 * sin(P.x * factor)), RotationMatrix);
P *= RotationMatrix;
P.y += evaluateWave(wave0, P.xz, osg_SimulationTime);
deriv = evaluateWaveDeriv(wave0, P.xz, osg_SimulationTime );
ddx = deriv * wave0.dir.x;
ddy = deriv * wave0.dir.y;
P.y += evaluateWave(wave1, P.xz, osg_SimulationTime);
deriv = evaluateWaveDeriv(wave1, P.xz, osg_SimulationTime);
ddx += deriv * wave1.dir.x;
ddy += deriv * wave1.dir.y;
P.y += evaluateWaveSharp(wave2, P.xz, osg_SimulationTime, WaveSharp);
deriv = evaluateWaveDerivSharp(wave2, P.xz, osg_SimulationTime, WaveSharp);
ddx += deriv * wave2.dir.x;
ddy += deriv * wave2.dir.y;
//P.y += evaluateWaveSharp(wave3, P.xz, osg_SimulationTime, WaveSharp);
//deriv = evaluateWaveDerivSharp(wave3, P.xz, osg_SimulationTime, WaveSharp);
//ddx += deriv * wave3.dir.x;
//ddy += deriv * wave3.dir.y;
}
float light_func (in float x, in float a, in float b, in float c, in float d, in float e)
{
x = x - 0.5;
// use the asymptotics to shorten computations
if (x > 30.0) {return e;}
if (x < -15.0) {return 0.0;}
return e / pow((1.0 + a * exp(-b * (x-c)) ),(1.0/d));
}
// this determines how light is attenuated in the distance
// physically this should be exp(-arg) but for technical reasons we use a sharper cutoff
// for distance > visibility
float fog_func (in float targ)
{
float fade_mix;
// for large altitude > 30 km, we switch to some component of quadratic distance fading to
// create the illusion of improved visibility range
targ = 1.25 * targ; // need to sync with the distance to which terrain is drawn
if (eye_alt < 30000.0)
{return exp(-targ - targ * targ * targ * targ);}
else if (eye_alt < 50000.0)
{
fade_mix = (eye_alt - 30000.0)/20000.0;
return fade_mix * exp(-targ*targ - pow(targ,4.0)) + (1.0 - fade_mix) * exp(-targ - pow(targ,4.0));
}
else
{
return exp(- targ * targ - pow(targ,4.0));
}
}
void main(void)
{
if ((gl_FragCoord.y < ylimit) && (gl_FragCoord.x > zlimit1) && (gl_FragCoord.x < zlimit2))
{discard;}
float dist = length(relPos);
const vec4 sca = vec4(0.005, 0.005, 0.005, 0.005);
const vec4 sca2 = vec4(0.02, 0.02, 0.02, 0.02);
const vec4 tscale = vec4(0.25, 0.25, 0.25, 0.25);
mat4 RotationMatrix;
// compute direction to viewer
vec3 E = normalize(viewerdir);
// compute direction to light source
vec3 L = lightdir; // normalize(lightdir);
// half vector
vec3 Hv = normalize(L + E);
//vec3 Normal = normalize(normal);
vec3 Normal = vec3 (0.0, 0.0, 1.0);
const float water_shininess = 240.0;
// approximate cloud cover
//float cover = 0.0;
//bool Status = true;
float windEffect = sqrt( WindE*WindE + WindN*WindN ) * 0.6; //wind speed in kt
float windScale = 15.0/(3.0 + windEffect); //wave scale
float windEffect_low = 0.3 + 0.7 * smoothstep(0.0, 5.0, windEffect); //low windspeed wave filter
float waveRoughness = 0.01 + smoothstep(0.0, 40.0, windEffect); //wave roughness filter
float mixFactor = 0.2 + 0.02 * smoothstep(0.0, 50.0, windEffect);
//mixFactor = 0.2;
mixFactor = clamp(mixFactor, 0.3, 0.8);
// there's no need to do wave patterns or foam for pixels which are so far away that we can't actually see them
// we only need detail in the near zone or where the sun reflection is
int detail_flag;
if ((dist > 15000.0) && (dot(normalize(vec3 (lightdir.x, lightdir.y, 0.0) ), normalize(relPos)) < 0.7 )) {detail_flag = 0;}
else {detail_flag = 1;}
//detail_flag = 1;
// sine waves
float ddx, ddx1, ddx2, ddx3, ddy, ddy1, ddy2, ddy3;
float angle;
if (detail_flag == 1)
{
angle = 0.0;
wave0.freq = WaveFreq ;
wave0.amp = WaveAmp;
wave0.dir = vec2 (0.0, 1.0); //vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = WaveAmp * 1.25;
wave1.dir = vec2(0.70710, -0.7071); //vec2(cos(radians(angle)), sin(radians(angle)));
angle += 30;
wave2.freq = WaveFreq * 3.5;
wave2.amp = WaveAmp * 0.75;
wave2.dir = vec2(0.96592, -0.2588);// vec2(cos(radians(angle)), sin(radians(angle)));
//angle -= 50;
//wave3.freq = WaveFreq * 3.0 ;
//wave3.amp = WaveAmp * 0.75;
//wave3.dir = vec2(0.42261, -0.9063); //vec2(cos(radians(angle)), sin(radians(angle)));
// sum waves
ddx = 0.0, ddy = 0.0;
sumWaves(WaveAngle, -1.5, windScale, WaveFactor, ddx, ddy);
ddx1 = 0.0, ddy1 = 0.0;
sumWaves(WaveAngle, 1.5, windScale, WaveFactor, ddx1, ddy1);
//reset the waves
/*
angle = 0.0;
float waveamp = WaveAmp * 0.75;
wave0.freq = WaveFreq ;
wave0.amp = waveamp;
wave0.dir = vec2 (0.0, 1.0); //vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 20;
wave1.freq = WaveFreq * 2.0 ;
wave1.amp = waveamp * 1.25;
wave1.dir = vec2(0.93969, -0.34202);// vec2(cos(radians(angle)), sin(radians(angle)));
angle += 35;
wave2.freq = WaveFreq * 3.5;
wave2.amp = waveamp * 0.75;
wave2.dir = vec2(0.965925, 0.25881); //vec2(cos(radians(angle)), sin(radians(angle)));
angle -= 45;
wave3.freq = WaveFreq * 3.0 ;
wave3.amp = waveamp * 0.75;
wave3.dir = vec2(0.866025, -0.5); //vec2(cos(radians(angle)), sin(radians(angle)));
*/
//ddx2 = 0.0, ddy2 = 0.0;
//sumWaves(WaveAngle + WaveDAngle, -1.5, windScale, WaveFactor, ddx2, ddy2);
//ddx3 = 0.0, ddy3 = 0.0;
//sumWaves(WaveAngle + WaveDAngle, 1.5, windScale, WaveFactor, ddx3, ddy3);
}
// end sine stuff
//cover = 5.0 * smoothstep(0.6, 1.0, scattering);
//cover = 5.0 * ground_scattering;
vec4 viewt = normalize(waterTex4);
vec4 disdis = texture2D(water_dudvmap, vec2(waterTex2 * tscale)* windScale) * 2.0 - 1.0;
vec4 vNorm;
//normalmaps
vec4 nmap = texture2D(water_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0;
vec4 nmap1 = texture2D(perlin_normalmap, vec2(waterTex1 + disdis * sca2) * windScale) * 2.0 - 1.0;
rotationmatrix(radians(3.0 * sin(osg_SimulationTime * 0.0075)), RotationMatrix);
nmap += texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix * tscale) * windScale) * 2.0 - 1.0;
nmap1 += texture2D(perlin_normalmap, vec2(waterTex2 * RotationMatrix * tscale) * windScale) * 2.0 - 1.0;
nmap *= windEffect_low;
nmap1 *= windEffect_low;
// mix water and noise, modulated by factor
vNorm = normalize(mix(nmap, nmap1, mixFactor) * waveRoughness);
if (detail_flag == 1) {vNorm.r += ddx + ddx1;}
if (normalmap_dds > 0)
{vNorm = -vNorm;} //dds fix
//load reflection
vec4 refl ;
refl.r = sea_r;
refl.g = sea_g;
refl.b = sea_b;
refl.a = 1.0;
float intensity;
// de-saturate for reduced light
refl.rgb = mix(refl.rgb, vec3 (0.248, 0.248, 0.248), 1.0 - smoothstep(0.1, 0.8, ground_scattering));
// de-saturate light for overcast haze
intensity = length(refl.rgb);
refl.rgb = mix(refl.rgb, intensity * vec3 (1.0, 1.0, 1.0), 0.5 * smoothstep(0.1, 0.9, overcast));
vec3 N;
rotationmatrix(radians(2.0 * sin(osg_SimulationTime * 0.005)), RotationMatrix);
vec3 N0 = vec3(texture2D(water_normalmap, vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale) * 2.0 - 1.0);
vec3 N1 = vec3(texture2D(perlin_normalmap, vec2(waterTex2 * RotationMatrix * (tscale + sca2)) * windScale) * 2.0 - 1.0);
N0 *= windEffect_low;
N1 *= windEffect_low;
N0.r += (ddx + ddx1);
N0.g += (ddy + ddy1);
N = normalize(mix(Normal + N0, Normal + N1, mixFactor) * waveRoughness);
if (normalmap_dds > 0)
{N = -N;} //dds fix
vec3 specular_color = vec3(specular_light)
* pow(max(0.0, dot(N, Hv)), water_shininess) * 6.0;
vec4 specular = vec4(specular_color, 0.5);
specular = specular * saturation * 0.3 * earthShade ;
//calculate fresnel
vec4 invfres = vec4( dot(vNorm, viewt) );
vec4 fres = vec4(1.0) + invfres;
refl *= fres;
vec4 ambient_light;
ambient_light.rgb = max(specular_light.rgb, vec3(0.1, 0.1, 0.1));
ambient_light.a = 1.0;
vec4 finalColor;
finalColor = refl + specular * smoothstep(0.3, 0.6, ground_scattering);
//add foam
if (dist < 10000.0)
{
float foamSlope = 0.12 + 0.1 * windScale;
vec4 foam_texel = texture2D(sea_foam, vec2(waterTex2 * tscale) * 25.0);
float waveSlope = N.g;
if (windEffect >= 8.0)
if (waveSlope >= foamSlope){
finalColor = mix(finalColor, max(finalColor, finalColor + foam_texel), smoothstep(0.01, 0.50, N.g));
}
}
finalColor *= ambient_light;
// here comes the terrain haze model
float delta_z = hazeLayerAltitude - eye_alt;
if (dist > 40.0)
{
float transmission;
float vAltitude;
float delta_zv;
float H;
float distance_in_layer;
float transmission_arg;
// angle with horizon
float ct = dot(vec3(0.0, 0.0, 1.0), relPos)/dist;
// we solve the geometry what part of the light path is attenuated normally and what is through the haze layer
if (delta_z > 0.0) // we're inside the layer
{
if (ct < 0.0) // we look down
{
distance_in_layer = dist;
//lambda = visibility;
vAltitude = min(distance_in_layer,min(visibility,avisibility)) * ct;
delta_zv = delta_z - vAltitude;
}
else // we may look through upper layer edge
{
H = dist * ct;
if (H > delta_z) {distance_in_layer = dist/H * delta_z;}
else {distance_in_layer = dist;}
//lambda = visibility;
vAltitude = min(distance_in_layer,visibility) * ct;
delta_zv = delta_z - vAltitude;
}
}
else // we see the layer from above, delta_z < 0.0
{
H = dist * -ct;
if (H < (-delta_z)) // we don't see into the layer at all, aloft visibility is the only fading
{
distance_in_layer = 0.0;
delta_zv = 0.0;
}
else
{
vAltitude = H + delta_z;
distance_in_layer = vAltitude/H * dist;
vAltitude = min(distance_in_layer,visibility) * (-ct);
delta_zv = vAltitude;
}
}
// ground haze cannot be thinner than aloft visibility in the model,
// so we need to use aloft visibility otherwise
transmission_arg = (dist-distance_in_layer)/avisibility;
float eqColorFactor;
if (visibility < avisibility)
{
transmission_arg = transmission_arg + (distance_in_layer/visibility);
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/visibility - (1.0 -scattering);
}
else
{
transmission_arg = transmission_arg + (distance_in_layer/avisibility);
// this combines the Weber-Fechner intensity
eqColorFactor = 1.0 - 0.1 * delta_zv/avisibility - (1.0 -scattering);
}
transmission = fog_func(transmission_arg);
// there's always residual intensity, we should never be driven to zero
if (eqColorFactor < 0.2) eqColorFactor = 0.2;
float lightArg = (terminator-yprime_alt)/100000.0;
vec3 hazeColor;
//hazeColor.rgb = specular_light.rgb;
hazeColor.b = light_func(lightArg, 1.330e-05, 0.264, 2.527, 1.08e-05, 1.0);
hazeColor.g = light_func(lightArg, 3.931e-06, 0.264, 3.827, 7.93e-06, 1.0);
hazeColor.r = light_func(lightArg, 8.305e-06, 0.161, 3.827, 3.04e-05, 1.0);
// now dim the light for haze
float eShade = 0.9 * smoothstep(terminator_width+ terminator, -terminator_width + terminator, yprime_alt) + 0.1;
// Mie-like factor
if (lightArg < 10.0)
{intensity = length(hazeColor);
float mie_magnitude = 0.5 * smoothstep(350000.0, 150000.0, terminator-sqrt(2.0 * EarthRadius * terrain_alt));
hazeColor = intensity * ((1.0 - mie_magnitude) + mie_magnitude * mie_angle) * normalize(mix(hazeColor, vec3 (0.5, 0.58, 0.65), mie_magnitude * (0.5 - 0.5 * mie_angle)) );
}
// high altitude desaturation of the haze color
intensity = length(hazeColor);
hazeColor = intensity * normalize (mix(hazeColor, intensity * vec3 (1.0,1.0,1.0), 0.7* smoothstep(5000.0, 50000.0, eye_alt)));
// blue hue of haze
hazeColor.x = hazeColor.x * 0.83;
hazeColor.y = hazeColor.y * 0.9;
// additional blue in indirect light
float fade_out = max(0.65 - 0.3 *overcast, 0.45);
intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 1.5* vec3 (0.45, 0.6, 0.8), 1.0 -smoothstep(0.25, fade_out,eShade) ));
// change haze color to blue hue for strong fogging
//intensity = length(hazeColor);
hazeColor = intensity * normalize(mix(hazeColor, 2.0 * vec3 (0.55, 0.6, 0.8), (1.0-smoothstep(0.3,0.8,eqColorFactor))));
// reduce haze intensity when looking at shaded surfaces, only in terminator region
//float shadow = mix( min(1.0 + dot(normal,lightdir),1.0), 1.0, 1.0-smoothstep(0.1, 0.4, transmission));
//hazeColor = mix(shadow * hazeColor, hazeColor, 0.3 + 0.7* smoothstep(250000.0, 400000.0, terminator));
finalColor.rgb = mix(eqColorFactor * hazeColor * eShade, finalColor.rgb,transmission);
}
gl_FragColor = finalColor;
}

View file

@ -46,7 +46,7 @@ varying vec4 waterTex2 ; //moving texcoords
varying vec3 viewerdir ;
varying vec3 lightdir ;
varying vec3 normal ;
varying vec3 Vnormal ;
varying vec3 rawNormal ;
varying vec3 VTangent ;
varying vec3 VBinormal ;
@ -147,8 +147,8 @@ void main(void)
//vec3 H = normalize(L + E);
vec3 Normal = normalize(normal) ;
vec3 vNormal = normalize(Vnormal) ;
const float water_shininess = 128.0 ;
vec3 vNormal = normalize(rawNormal) ;
const float water_shininess = 240.0 ;
// float range = gl_ProjectionMatrix[3].z/(gl_FragCoord.z * -2.0 + 1.0 - gl_ProjectionMatrix[2].z);
@ -334,7 +334,8 @@ void main(void)
N0.g += ddySum;
vec3 N2 = normalize(mix(N0, N1, mixFactor) * waveRoughness);
Normal = normalize(N2.x * VTangent + N2.y * VBinormal + N2.z * Normal);
vNormal = normalize(mix(vNormal + N0, vNormal + N1, mixFactor) * waveRoughness);
//vNormal = normalize(mix(vNormal + N0, vNormal + N1, mixFactor) * waveRoughness);
vNormal = normalize(N2.x * vec3(1.0, 0.0, 0.0) + N2.y * vec3(0.0, 1., 0.0) + N2.z * vNormal);
if (normalmap_dds > 0){ //dds fix
Normal = -Normal;
vNormal = -vNormal;
@ -379,5 +380,5 @@ void main(void)
vec3( 0.3, 0.59, 0.11 )
);
float specular = smoothstep(0.0, 3.5, cover);
encode_gbuffer(Normal, finalColor.rgb, 254, specular, water_shininess, emission, gl_FragCoord.z);
encode_gbuffer(Normal, finalColor.rgb, 254, specular, water_shininess, emission, gl_FragCoord.z);
}

View file

@ -123,11 +123,21 @@
<!-- Help menu -->
<help>Hilfe</help> <!-- English: "Help" -->
<help-browser>Hilfe (im Browser)</help-browser> <!-- English: "Help (opens in browser)" -->
<doc-browser>Erweiterte Dokumentation</doc-browser> <!-- English: "Documentation Browser" -->
<aircraft-keys>Flugzeug Hilfe</aircraft-keys> <!-- English: "Aircraft Help" -->
<aircraft-checklists>Flugzeug Checklisten</aircraft-checklists> <!-- English: "Aircraft Checklists" -->
<common-keys>Tastenbelegung (Flugzeugsteuerung)</common-keys> <!-- English: "Common Aircraft Keys" -->
<basic-keys>Tastenbelegung (allgemein)</basic-keys> <!-- English: "Basic Simulator Keys" -->
<joystick-info>Joystick Informationen</joystick-info> <!-- English: "Joystick Information" -->
<tutorial-start>Tutorials</tutorial-start> <!-- English: "Tutorials" -->
<menu-about>Über FlightGear</menu-about> <!-- English: "About" -->
<!-- Aircraft menu (only frequent/common custom menu entries are supported) -->
<select-livery>Lackierung auswählen</select-livery>
<show-hide-yokes>Steuerhorn aus-/einblenden</show-hide-yokes>
<immatriculation>Luftfahrzeugkennzeichen</immatriculation>
<pushback>Flugzeugschlepper</pushback>
<autostart>Autostart</autostart>
<tiller-steering>Bugradsteuerung</tiller-steering>
</PropertyList>

38
Translations/de/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: German language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<init>Initialisiere</init> <!-- English: "initializing" -->
<loading-aircraft-list>Lade Flugzeugliste</loading-aircraft-list> <!-- English: "loading aircraft list" -->
<loading-aircraft>Lade Flugzeug</loading-aircraft> <!-- English: "loading aircraft" -->
<loading-nav-dat>Lade Navigationsdaten</loading-nav-dat> <!-- English: "loading navigation data" -->
<init-scenery>Initialisiere Szenerie</init-scenery> <!-- English: "initializing scenery" -->
<creating-subsystems>Erzeuge Subsysteme</creating-subsystems> <!-- English: "creating subsystems" -->
<init-subsystems>Initialisiere Subsysteme</init-subsystems> <!-- English: "initializing subsystems" -->
<binding-subsystems>Binde Subsysteme</binding-subsystems> <!-- English: "binding subsystems" -->
<finishing-subsystems>Finalisiere Subsysteme</finishing-subsystems> <!-- English: "finalizing subsystems" -->
<init-graphics>Initialisiere Grafik</init-graphics> <!-- English: "initializing graphics engine" -->
<loading-scenery>Lade Szenerie</loading-scenery> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

View file

@ -108,8 +108,9 @@
<!-- Help menu -->
<help>Help</help>
<help-browser>Help (opens in browser)</help-browser>
<doc-browser>Documentation Browser</doc-browser>
<aircraft-keys>Aircraft Help</aircraft-keys>
<aircraft-checklists>Aircraft Checklists</aircraft-checklists>
<aircraft-checklists>Aircraft Checklists</aircraft-checklists>
<common-keys>Common Aircraft Keys</common-keys>
<basic-keys>Basic Simulator Keys</basic-keys>
<joystick-config>Joystick Configuration</joystick-config>
@ -117,4 +118,12 @@
<tutorial-start>Tutorials</tutorial-start>
<menu-about>About</menu-about>
<!-- Aircraft menu (only frequent/common custom menu entries are supported) -->
<select-livery>Select livery</select-livery>
<show-hide-yokes>Show/hide yokes</show-hide-yokes>
<immatriculation>Immatriculation</immatriculation>
<pushback>Pushback</pushback>
<autostart>Autostart</autostart>
<tiller-steering>Tiller Steering</tiller-steering>
</PropertyList>

21
Translations/en/sys.xml Normal file
View file

@ -0,0 +1,21 @@
<?xml version="1.0"?>
<!-- FlightGear system messages: English (=default) language resource -->
<PropertyList>
<splash>
<init>initializing</init>
<loading-aircraft-list>loading aircraft list</loading-aircraft-list>
<loading-aircraft>loading aircraft</loading-aircraft>
<loading-nav-dat>loading navigation data</loading-nav-dat>
<init-scenery>initializing scenery</init-scenery>
<creating-subsystems>creating subsystems</creating-subsystems>
<init-subsystems>initializing subsystems</init-subsystems>
<binding-subsystems>binding subsystems</binding-subsystems>
<finishing-subsystems>finalizing subsystems</finishing-subsystems>
<init-graphics>initializing graphics engine</init-graphics>
<loading-scenery>loading scenery</loading-scenery>
</splash>
</PropertyList>

38
Translations/es/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Spanish language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/fr/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: French language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<init>Réinitialiser</init> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/it/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Italian language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

View file

@ -15,6 +15,7 @@
<strings>
<options>Translations/en/options.xml</options>
<menu>Translations/en/menu.xml</menu>
<sys>Translations/en/sys.xml</sys>
</strings>
</locale>
@ -27,6 +28,7 @@
<strings>
<options>Translations/es/options.xml</options>
<menu>Translations/es/menu.xml</menu>
<sys>Translations/es/sys.xml</sys>
</strings>
</locale>
@ -39,6 +41,7 @@
<strings>
<options>Translations/de/options.xml</options>
<menu>Translations/de/menu.xml</menu>
<sys>Translations/de/sys.xml</sys>
</strings>
</locale>
@ -52,6 +55,7 @@
<strings>
<options>Translations/fr/options.xml</options>
<menu>Translations/fr/menu.xml</menu>
<sys>Translations/fr/sys.xml</sys>
</strings>
</locale>
@ -64,6 +68,7 @@
<strings>
<options>Translations/it/options.xml</options>
<menu>Translations/it/menu.xml</menu>
<sys>Translations/it/sys.xml</sys>
</strings>
</locale>
@ -75,6 +80,7 @@
<strings>
<options>Translations/nl/options.xml</options>
<menu>Translations/nl/menu.xml</menu>
<sys>Translations/nl/sys.xml</sys>
</strings>
</locale>
@ -85,6 +91,7 @@
<strings>
<options>Translations/pl/options.xml</options>
<menu>Translations/pl/menu.xml</menu>
<sys>Translations/pl/sys.xml</sys>
</strings>
</locale>
@ -104,6 +111,7 @@
<strings>
<options>Translations/cs/options.xml</options>
<menu>Translations/cs/menu.xml</menu>
<sys>Translations/cs/sys.xml</sys>
</strings>
</locale>
@ -113,6 +121,7 @@
<strings>
<options>Translations/da/options.xml</options>
<menu>Translations/da/menu.xml</menu>
<sys>Translations/da/sys.xml</sys>
</strings>
</locale>

41
Translations/nl/sys.xml Normal file
View file

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Dutch language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- I know, this isn't really Dutch. Just a stub until Gijs has time to work on this new file :). -->
<init>initialisere</init> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<loading-aircraft>vliegtuig laden</loading-aircraft> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<init-subsystems>initialisere subsysteme</init-subsystems> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<init-graphics>initialisere grafiek</init-graphics> <!-- English: "initializing graphics engine" -->
<loading-scenery>scenerie laden</loading-scenery> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/pl/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Polish language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

38
Translations/pt/sys.xml Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="ISO-8859-1" ?>
<!-- FlightGear system messages: Portuguese language resource -->
<!-- ###
### This file is automatically synchronized with the master (=English language) resource.
### Please do not add comments, change order or restructure the file.
###
### To translate:
### * Replace "???" entries with appropriate translation.
### * Keep untranslated items unmodified (leave the "???"). English original is the
### automatic default.
### * Remove enclosing "<!-_ ... _->" tags for completed translations.
### * Keep the original English text unmodified (the '<!-_ English: "..." -_>)',
### so we know which version of the English original the translation is based upon
### (and we can identify translations which need to be updated, when the original changes).
### * Replace "-_" occurences with a double "-" in all translations (XML does not allow
### consecutive "-" characters in comments).
###
### Last synchronized with English master resource on 2012-September-21 for FlightGear 2.9.0
### -->
<PropertyList>
<splash>
<!-- <init>???</init> --> <!-- English: "initializing" -->
<!-- <loading-aircraft-list>???</loading-aircraft-list> --> <!-- English: "loading aircraft list" -->
<!-- <loading-aircraft>???</loading-aircraft> --> <!-- English: "loading aircraft" -->
<!-- <loading-nav-dat>???</loading-nav-dat> --> <!-- English: "loading navigation data" -->
<!-- <init-scenery>???</init-scenery> --> <!-- English: "initializing scenery" -->
<!-- <creating-subsystems>???</creating-subsystems> --> <!-- English: "creating subsystems" -->
<!-- <init-subsystems>???</init-subsystems> --> <!-- English: "initializing subsystems" -->
<!-- <binding-subsystems>???</binding-subsystems> --> <!-- English: "binding subsystems" -->
<!-- <finishing-subsystems>???</finishing-subsystems> --> <!-- English: "finalizing subsystems" -->
<!-- <init-graphics>???</init-graphics> --> <!-- English: "initializing graphics engine" -->
<!-- <loading-scenery>???</loading-scenery> --> <!-- English: "loading scenery" -->
</splash>
</PropertyList>

View file

@ -24,19 +24,49 @@
<binding>
<command>dialog-close</command>
</binding>
<binding>
<command>property-toggle</command>
<property>/sim/gui/dialogs/airports/signals/dialog-close</property>
</binding>
</button>
</group>
<hrule/>
<nasal>
<open>
<!-- Generalize all this, turn into helpers and load defaults via XML -->
<open><![CDATA[
## "prologue" currently required by the canvas-generic-map
var dialog_name ="airports"; #TODO: use substr() and cmdarg() to get this dynamically
var dialog_property = func(p) return "/sim/gui/dialogs/airports/"~p; #TODO: generalize using cmdarg
var DIALOG_CANVAS = gui.findElementByName(cmdarg(), "airport-selection");
canvas.GenericMap.setupGUI(DIALOG_CANVAS, "canvas-control"); #TODO: this is not a method!
## end of canvas-generic-map prologue
setprop("/sim/gui/dialogs/airports/selected-airport/rwy", "");
setprop("/sim/gui/dialogs/airports/selected-airport/parkpos", "");
setprop("/sim/gui/dialogs/airports/mode", "search");
setprop("/sim/gui/dialogs/airports/list", "");
var airport_id = getprop("/sim/presets/airport-id");
if (airport_id == nil) { airport_id = "KSFO"; }
if (getprop("/sim/gui/dialogs/airports/display-taxiways") == "") {
setprop("/sim/gui/dialogs/airports/display-taxiways", "1");
}
if (getprop("/sim/gui/dialogs/airports/display-parking") == "") {
setprop("/sim/gui/dialogs/airports/display-parking", "0");
}
if (getprop("/sim/gui/dialogs/airports/display-tower") == "") {
setprop("/sim/gui/dialogs/airports/display-tower", "1");
}
# Start with the closest airport
var airport_id = airportinfo().id;
# Retrieve METAR
fgcommand("request-metar", var n = props.Node.new({ "path": "/sim/gui/dialogs/airports/selected-airport/metar",
"station": airport_id}));
var dlg = props.globals.getNode("/sim/gui/dialogs/airports", 1);
var avail_runways = dlg.getNode("available-runways", 1);
@ -75,12 +105,24 @@
var info = airportinfo(airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/id", airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/name", info.name ~ " (" ~ airport_id ~ ")");
setprop("/sim/gui/dialogs/airports/selected-airport/location", sprintf("%.3f / %.3f", info.lon, info.lat));
setprop("/sim/gui/dialogs/airports/selected-airport/location", sprintf("%.3f / %.3f", info.lat, info.lon));
setprop("/sim/gui/dialogs/airports/selected-airport/lon", info.lon);
setprop("/sim/gui/dialogs/airports/selected-airport/elevation-ft", 3.28 * info.elevation);
setprop("/sim/gui/dialogs/airports/selected-airport/rwy", "");
setprop("/sim/gui/dialogs/airports/selected-airport/parkpos", "");
if (info.has_metar) {
# Retrieve an updated METAR, and indicate that we've not got one currently.
setprop("/sim/gui/dialogs/airports/selected-airport/metar/station-id", airport_id);
setprop("/sim/gui/dialogs/airports/selected-airport/metar/time-to-live", 0);
setprop("/sim/gui/dialogs/airports/selected-airport/metar/data", "Retrieving METAR, please wait.");
} else {
# This airport has no METAR. Ratehr than cancelling the retrieve-metar command, simply set the TTL
# to a very long time so it won't over-ride our message.
setprop("/sim/gui/dialogs/airports/selected-airport/metar/data", "No METAR available from this airport");
setprop("/sim/gui/dialogs/airports/selected-airport/metar/time-to-live", 9999);
}
var longest_runway = 0;
var runway_string = "";
var runways = info.runways;
@ -105,6 +147,15 @@
setprop("/sim/gui/dialogs/airports/selected-airport/longest-runway", longest_runway);
var airport_pos = geo.Coord.new();
airport_pos.set_latlon(info.lat, info.lon);
var pos = geo.aircraft_position();
var dst = pos.distance_to(airport_pos) / 1852.0;
var crs = pos.course_to(airport_pos);
setprop("/sim/gui/dialogs/airports/selected-airport/distance-nm", dst);
setprop("/sim/gui/dialogs/airports/selected-airport/course-deg", crs);
gui.dialog_update("airports", "runway-list");
gui.dialog_update("airports", "parking-list");
}
@ -136,13 +187,18 @@
} else {
setprop("/sim/presets/runway", "");
setprop("/sim/presets/parkpos", getprop("/sim/gui/dialogs/airports/selected-airport/parkpos"));
}
}
}
update_info();
]]>
</open>
<close>
fgcommand("clear-metar", var n = props.Node.new({ "path": "/sim/gui/dialogs/airports/selected-airport/metar",
"station": airport_id}));
# map.cleanup_listeners(); #TODO: We should be setting a signal when closing the dialog, so that cleanup code can be invoked automatically
</close>
</nasal>
<group>
@ -178,6 +234,11 @@
<button>
<legend>Clear</legend>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/mode</property>
<value>search</value>
</binding>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/list</property>
@ -196,6 +257,11 @@
<button>
<legend>Search</legend>
<default>true</default>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/mode</property>
<value>search</value>
</binding>
<binding>
<command>dialog-apply</command>
<object-name>input</object-name>
@ -206,25 +272,91 @@
</binding>
</button>
</group>
<button>
<legend>Within 100nm</legend>
<binding>
<command>property-assign</command>
<property>/sim/gui/dialogs/airports/mode</property>
<value>100nm</value>
</binding>
<binding>
<command>nasal</command>
<script>
var airports = findAirportsWithinRange(100);
var list = dlg.getNode("close-airports", 1);
list.removeChildren("value");
forindex (var idx; airports) {
list.getNode("value["~ idx ~ "]", 1).setValue(airports[idx].name ~ " (" ~ airports[idx].id ~ ")");
}
</script>
</binding>
<binding>
<command>dialog-update</command>
<object-name>close-airport-list</object-name>
</binding>
</button>
<airport-list>
<name>airport-list</name>
<pref-width>300</pref-width>
<pref-height>260</pref-height>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<binding>
<command>dialog-apply</command>
<object-name>airport-list</object-name>
</binding>
<binding>
<command>nasal</command>
<script>listbox()</script>
</binding>
</airport-list>
</group>
<group>
<layout>table</layout>
<default-padding>0</default-padding>
<list>
<row>0</row><col>0</col>
<visible>
<equals>
<property>/sim/gui/dialogs/airports/mode</property>
<value>100nm</value>
</equals>
</visible>
<name>close-airport-list</name>
<pref-width>300</pref-width>
<pref-height>260</pref-height>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<properties>/sim/gui/dialogs/airports/close-airports</properties>
<binding>
<command>dialog-apply</command>
<object-name>close-airport-list</object-name>
</binding>
<binding>
<command>nasal</command>
<script>listbox()</script>
</binding>
</list>
<airport-list>
<row>0</row><col>0</col>
<visible>
<equals>
<property>/sim/gui/dialogs/airports/mode</property>
<value>search</value>
</equals>
</visible>
<name>airport-list</name>
<pref-width>300</pref-width>
<pref-height>260</pref-height>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<property>/sim/gui/dialogs/airports/list</property>
<binding>
<command>dialog-apply</command>
<object-name>airport-list</object-name>
</binding>
<binding>
<command>nasal</command>
<script>listbox()</script>
</binding>
</airport-list>
</group>
<hrule/>
@ -234,7 +366,7 @@
<text>
<row>0</row>
<col>0</col>
<width>200</width>
<width>100</width>
<halign>right</halign>
<label>Airport:</label>
</text>
@ -251,7 +383,7 @@
<row>1</row>
<col>0</col>
<halign>right</halign>
<label>Lon/Lat:</label>
<label>Lat / Lon:</label>
</text>
<text>
<row>1</row>
@ -263,16 +395,16 @@
<text>
<row>1</row>
<col>3</col>
<col>2</col>
<halign>right</halign>
<label>Elevation (ft):</label>
<label>Elevation:</label>
</text>
<text>
<row>1</row>
<col>4</col>
<col>3</col>
<halign>left</halign>
<live>true</live>
<format>%.0f</format>
<format>%.0f ft</format>
<property>/sim/gui/dialogs/airports/selected-airport/elevation-ft</property>
</text>
@ -280,17 +412,72 @@
<row>2</row>
<col>0</col>
<halign>right</halign>
<label>Longest runway (ft):</label>
<label>Longest runway:</label>
</text>
<text>
<row>2</row>
<col>1</col>
<halign>left</halign>
<live>true</live>
<format>%.0f</format>
<format>%.0f ft</format>
<property>/sim/gui/dialogs/airports/selected-airport/longest-runway</property>
</text>
<text>
<row>3</row>
<col>0</col>
<halign>right</halign>
<label>Distance:</label>
</text>
<text>
<row>3</row>
<col>1</col>
<halign>left</halign>
<live>true</live>
<format>%.1f nm</format>
<property>/sim/gui/dialogs/airports/selected-airport/distance-nm</property>
</text>
<text>
<row>3</row>
<col>2</col>
<halign>right</halign>
<label>Course:</label>
</text>
<text>
<row>3</row>
<col>3</col>
<halign>left</halign>
<live>true</live>
<format>%.0f deg</format>
<property>/sim/gui/dialogs/airports/selected-airport/course-deg</property>
</text>
<text>
<row>4</row>
<col>0</col>
<colspan>3</colspan>
<halign>left</halign>
<live>true</live>
<label>METAR:</label>
</text>
<textbox>
<name>metar</name>
<row>5</row>
<col>0</col>
<colspan>4</colspan>
<halign>fill</halign>
<stretch>true</stretch>
<pref-width>300</pref-width>
<pref-height>60</pref-height>
<slider>0</slider>
<editable>false</editable>
<wrap>true</wrap>
<live>true</live>
<property>/sim/gui/dialogs/airports/selected-airport/metar/data</property>
</textbox>
</group>
<hrule/>
@ -404,8 +591,11 @@
<group>
<layout>vbox</layout>
<canvas>
<name>map-dialog</name>
<!-- Instantiate a generic canvas map and parametrize it via inclusion -->
<!-- TODO: use params and aliasing -->
<canvas include="/Nasal/canvas/generic-canvas-map.xml">
<name>airport-selection</name>
<valign>fill</valign>
<halign>fill</halign>
<stretch>true</stretch>
@ -413,161 +603,77 @@
<pref-height>400</pref-height>
<view n="0">600</view>
<view n="1">400</view>
<nasal>
<load><![CDATA[
var my_canvas = canvas.get(cmdarg());
my_canvas.setColorBackground(0.2, 0.5, 0.2, 0.5);
var root = my_canvas.createGroup();
var map = root.createChild("map", "map-test")
.setTranslation(300, 200);
var layer_runways = map.createChild("group", "runways");
var updateMap = func() {
var id = getprop("/sim/gui/dialogs/airports/selected-airport/id");
if (id != "") {
var apt = airportinfo(id);
map.removeAllChildren();
layer_runways = map.createChild("group", "runways");
var airport = canvas.AirportMap.new(apt);
airport.build(layer_runways);
<features>
<!-- TODO: use params and aliases to make this shorter -->
<!-- TODO: support styling, i.e. image sets/fonts and colors to be used -->
<!-- this will set up individual "layers" and map them to boolean "toggle" properties -->
<!-- providing an optional "description" tag here allows us to create all checkboxes procedurally -->
<dialog-root>/sim/gui/dialogs/airports</dialog-root>
<range-property>zoom</range-property>
map._node.getNode("ref-lat", 1).setDoubleValue(apt.lat);
map._node.getNode("ref-lon", 1).setDoubleValue(apt.lon);
map._node.getNode("hdg", 1).setDoubleValue(0.0);
}
}
var ranges = [0.1, 0.25, 0.5, 1, 2.5, 5];
var updateZoom = func()
{
var z = getprop("/sim/gui/dialogs/airports/zoom");
if( z == nil )
z = 0;
var zoom = ranges[4 - z];
map._node.getNode("range", 1).setDoubleValue(zoom);
settimer(updateZoom, 0.5, 1);
};
var updateRunwayHighlight = func()
{
var selected_rwy = getprop("/sim/gui/dialogs/airports/selected-airport/rwy");
var selected_apt = getprop("/sim/gui/dialogs/airports/selected-airport/id");
var is_heli = substr(selected_rwy, 0, 1) == "H";
var rw_dir = is_heli ? nil : int(substr(selected_rwy, 0, 2));
var rw_rec = "";
if( rw_dir != nil ) {
rw_rec = sprintf("%02d", math.mod(rw_dir - 18, 36));
if( size(selected_rwy) == 3 ) {
var map_rec = {
"R": "L",
"L": "R",
"C": "C"
};
rw_rec ~= map_rec[substr(selected_rwy, 2)];
}
}
foreach (var apt; layer_runways.getChildren()) {
if (apt.get("id") == "apt-" ~ selected_apt) {
foreach (var rwy; apt.getChildren()) {
if ((rwy.get("id") == "runway-" ~ selected_rwy) or
(rwy.get("id") == "runway-" ~ rw_rec) )
{
rwy.setColor(1.0,0.0,0.0);
} else {
rwy.setColor(1.0,1.0,1.0);
}
}
}
}
}
<!-- These are the ranges available for the map: var ranges = [0.1, 0.25, 0.5, 1, 2.5, 5] -->
var updateParkingHighlight = func()
{
var selected_parkpos = getprop("/sim/gui/dialogs/airports/selected-airport/parkpos");
var selected_apt = getprop("/sim/gui/dialogs/airports/selected-airport/id");
foreach (var apt; layer_runways.getChildren()) {
if (apt.get("id") == "apt-" ~ selected_apt) {
foreach (var rwy; apt.getChildren()) {
if (rwy.get("id") == "parking-" ~ selected_parkpos) {
rwy.setColor(1.0,0.0,0.0);
} else {
rwy.setColor(1.0,1.0,1.0);
}
}
}
}
}
var aptlistener = setlistener("/sim/gui/dialogs/airports/selected-airport/id", updateMap);
var rwylistener = setlistener("/sim/gui/dialogs/airports/selected-airport/rwy", updateRunwayHighlight);
var parkposlistener = setlistener("/sim/gui/dialogs/airports/selected-airport/parkpos", updateParkingHighlight);
update_info();
updateZoom();
]]>
</load>
<close>
removelistener(aptlistener);
removelistener(rwylistener);
removelistener(parkposlistener);
</close>
</nasal>
<ranges>
<range>0.1</range>
<range>0.25</range>
<range>0.5</range>
<range>1</range>
<range>2.5</range>
<range>5</range>
</ranges>
<!-- available layers and their toggle property (appended to dialog-root specified above) -->
<layer>
<name>runways</name> <!-- the name of the layer -->
<init-property>selected-airport/id</init-property> <!-- the init/input property that re-inits the layer MODEL -->
<property>display-runways</property> <!-- the property switch that toggles the layer on/off (show/hide) -->
<description>Show Runways</description> <!-- the checkbox label for the property -->
<default>enabled</default> <!-- default state -->
<hide-checkbox>true</hide-checkbox> <!-- if the checkbox should be shown or hidden -->
</layer>
<layer>
<name>taxiways</name>
<init-property>selected-airport/id</init-property>
<property>display-taxiways</property>
<description>Show Taxiways</description>
<default>disabled</default>
</layer>
<layer>
<name>parkings</name>
<init-property>selected-airport/id</init-property>
<property>display-parking</property>
<description>Show Parking</description>
<default>disabled</default>
</layer>
<layer>
<name>towers</name>
<init-property>selected-airport/id</init-property>
<property>display-tower</property>
<description>Show Tower</description>
<default>enabled</default>
</layer>
<!-- Uncomment this to add a navaid layer (not yet fully implemented, and no LOD yet)
<layer>
<name>navaids</name>
<init-property>selected-airport/id</init-property>
<property>display-navaids</property>
<description>Display Navaids within current range</description>
<default>disabled</default>
</layer>
-->
</features>
</canvas>
<hrule/>
<group>
<name>canvas-control</name> <!-- this is the handle we use to procedurally add all "toggle layer" checkboxes and the zoom control-->
<layout>hbox</layout>
<button>
<name>zoomout</name>
<legend>-</legend>
<pref-width>22</pref-width>
<pref-height>22</pref-height>
<binding>
<command>property-adjust</command>
<property>/sim/gui/dialogs/airports/zoom</property>
<min>0</min>
<step>-1</step>
</binding>
</button>
<text>
<label>MMM</label>
<format>Zoom %d</format>
<property>/sim/gui/dialogs/airports/zoom</property>
<live>true</live>
</text>
<button>
<name>zoomin</name>
<legend>+</legend>
<pref-width>22</pref-width>
<pref-height>22</pref-height>
<binding>
<command>property-adjust</command>
<property>//sim/gui/dialogs/airports/zoom</property>
<step>1</step>
<max>4</max>
</binding>
</button>
</group>
</group>
</group>
@ -581,7 +687,7 @@
<empty><stretch>true</stretch></empty>
<button>
<legend>OK</legend>
<legend>Go To Airport</legend>
<equal>true</equal>
<binding>
<command>dialog-apply</command>
@ -602,7 +708,7 @@
<empty><stretch>true</stretch></empty>
<button>
<legend>Cancel</legend>
<legend>Close</legend>
<equal>true</equal>
<key>Esc</key>
<binding>

View file

@ -33,6 +33,7 @@
<group>
<layout>vbox</layout>
<halign>center</halign>
<padding>4</padding>
<checkbox>
<halign>left</halign>
@ -90,6 +91,7 @@
<group>
<layout>hbox</layout>
<padding>0</padding>
<checkbox>
<label>Autohide cursor in</label>

140
gui/dialogs/doc-browser.xml Normal file
View file

@ -0,0 +1,140 @@
<?xml version="1.0"?>
<PropertyList>
<x>-20</x>
<y>-20</y>
<name>doc-browser</name>
<dialog-name>doc-browser</dialog-name>
<layout>vbox</layout>
<resizable>true</resizable>
<group>
<layout>hbox</layout>
<empty>
<stretch>1</stretch>
</empty>
<text>
<label>Documentation Browser</label>
</text>
<empty>
<stretch>1</stretch>
</empty>
<button>
<pref-width>16</pref-width>
<pref-height>16</pref-height>
<legend/>
<keynum>27</keynum>
<border>2</border>
<binding>
<command>dialog-close</command>
</binding>
</button>
</group>
<hrule/>
<group>
<layout>hbox</layout>
<list>
<pref-width>170</pref-width>
<pref-height>500</pref-height>
<name>filename</name>
<halign>fill</halign>
<property>/sim/gui/dialogs/doc-browser/filename</property>
<value>clear</value>
<binding>
<command>dialog-apply</command>
<object-name>filename</object-name>
</binding>
<binding>
<command>dialog-update</command>
<object-name>editfield</object-name>
</binding>
</list>
<textbox>
<name>editfield</name>
<halign>fill</halign>
<valign>fill</valign>
<stretch>true</stretch>
<pref-width>600</pref-width>
<pref-height>250</pref-height>
<padding>6</padding>
<slider>20</slider>
<editable>falsee</editable>
<wrap>false</wrap>
<font>
<name>FIXED_8x13</name>
</font>
<property>/sim/gui/dialogs/doc-browser/edit</property>
</textbox>
</group>
<nasal>
<open>
var self = cmdarg();
var dlg = props.globals.getNode("/sim/gui/dialogs/doc-browser", 1);
var edit = dlg.getNode("edit", 1);
if( !contains(globals, "__doc_browser") )
globals["__doc_browser"] = {};
var path = getprop("/sim/fg-root") ~ "/Docs/";
# hard coded list of file names, because not all files are plain text - not even the README* files
# TODO: it would probably make sense to sort these files (README, introduction, properties etc)
var doc_files = [
"README",
"README.introduction",
"README.fgjs",
"README.xmlsyntax",
"README.multiscreen",
"README.properties",
"README.IO",
"README.logging",
"README.protocol",
"README.scenery",
"README.materials",
"README.yasim",
"README.JSBsim",
"README.submodels",
"README.3DClouds",
"README.flightrecorder",
"README.jsclient",
"README.multiplayer",
"README.tutorials",
"README.conditions",
"README.commands",
"README.digitalfilters",
"README.airspeed-indicator",
"README.hud",
# "README.xmlhud", deprecated?
"README.gui",
"README.layout",
"README.osgtext",
"README.wildfire",
"README.electrical",
"README.effects",
"README.xmlparticles",
"README.sound",
"README.xmlsound",
"README.xmlpanel",
"README.minipanel"
];
var filename_list = self.getNode("group[1]/list");
var n=0;
# add the filenames to the list box
foreach(var file; doc_files)
{
filename_list.getChild("value",n,1).setValue( file );
n+=1;
}
var filename_property = "/sim/gui/dialogs/doc-browser/filename";
var update = func {
var file = getprop(filename_property);
var doc_file = path ~ file;
setprop("/sim/gui/dialogs/doc-browser/edit", io.readfile(doc_file));
}
var listener = setlistener(filename_property, update);
setprop("/sim/gui/dialogs/doc-browser/filename", "README.introduction");
</open>
<close>removelistener(listener);</close>
</nasal>
</PropertyList>

View file

@ -216,6 +216,42 @@
<col>3</col>
</text>
<text>
<label>Vegetation</label>
<halign>left</halign>
<row>5</row>
<col>0</col>
</text>
<text>
<label>none</label>
<halign>right</halign>
<row>5</row>
<col>1</col>
</text>
<slider>
<name>lichen-level</name>
<row>5</row>
<col>2</col>
<min>0.0</min>
<max>0.7</max>
<live>true</live>
<property>/environment/surface/lichen-cover-factor</property>
<binding>
<command>dialog-apply</command>
<object-name>lichen-level</object-name>
</binding>
</slider>
<text>
<label>mossy</label>
<halign>left</halign>
<row>5</row>
<col>3</col>
</text>
</group>
<hrule/>

View file

@ -0,0 +1,744 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://web.resource.org/cc/"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="50"
height="50"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.45.1"
sodipodi:docbase="C:\Documents and Settings\JJB\My Documents"
sodipodi:docname="NDB Symbol.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape"
version="1.0">
<defs
id="defs4" />
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="3.1"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="4"
inkscape:cx="71.027314"
inkscape:cy="17.078887"
inkscape:document-units="px"
inkscape:current-layer="g3816"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1404"
inkscape:window-height="874"
inkscape:window-x="28"
inkscape:window-y="0"
width="50px"
height="50px"
showgrid="false"
inkscape:grid-points="true"
gridspacingx="5px"
gridspacingy="5px"
inkscape:guide-points="false" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<g
id="g2842"
transform="matrix(0.9655323,-0.2602834,0.2602834,0.9655323,-98.55675,-17.522102)"
inkscape:transform-center-y="-186.61497"
inkscape:transform-center-x="50.854555" />
<g
id="g4183"
transform="translate(6.3118628,-54.869792)">
<g
transform="translate(-56.311844,-45.130208)"
id="g3816">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:3;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3586"
sodipodi:cx="75"
sodipodi:cy="125"
sodipodi:rx="5"
sodipodi:ry="5"
d="M 80 125 A 5 5 0 1 1 70,125 A 5 5 0 1 1 80 125 z" />
<path
sodipodi:type="arc"
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3588"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,98.125)" />
<g
id="g3652">
<path
transform="matrix(0.25,0,0,0.25,63.125,88.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3648"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,108.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3650"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3656"
transform="matrix(0.8660254,-0.5,0.5,0.8660254,-52.451905,54.246825)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3658"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,88.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3660"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,108.125)" />
</g>
<g
transform="matrix(0.5,-0.8660254,0.8660254,0.5,-70.753175,127.45191)"
id="g3662">
<path
transform="matrix(0.25,0,0,0.25,63.125,88.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3664"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,108.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3666"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3668"
transform="matrix(0,-1,1,0,-50,200)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3670"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,88.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3672"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,108.125)" />
</g>
<g
transform="matrix(-0.5,-0.8660254,0.8660254,-0.5,4.2468245,252.45191)"
id="g3674">
<path
transform="matrix(0.25,0,0,0.25,63.125,88.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3676"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,108.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3678"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3680"
transform="matrix(-0.8660254,-0.5,0.5,-0.8660254,77.451905,270.75318)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3682"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,88.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3684"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,108.125)" />
</g>
<g
id="g3690"
transform="matrix(0.9063078,-0.4226182,0.4226182,0.9063078,-45.800367,43.407896)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3686"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3688"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(0.7071067,-0.7071068,0.7071068,0.7071067,-66.421357,89.644658)"
id="g3694">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3696"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3698"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3700"
transform="matrix(0.4226183,-0.9063078,0.9063078,0.4226183,-69.984843,140.1458)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3702"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3704"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(8.715577e-2,-0.9961946,0.9961946,8.715577e-2,-56.061019,188.82012)"
id="g3706">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3708"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3710"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3712"
transform="matrix(-0.258819,-0.9659258,0.9659258,-0.258819,-26.329304,229.7968)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3714"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3716"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(-0.5735763,-0.819152,0.819152,-0.5735763,15.624218,258.13344)"
id="g3718">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3720"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3722"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3724"
transform="matrix(-0.8191519,-0.5735764,0.5735764,-0.8191519,64.739336,270.41222)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3726"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3728"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
transform="matrix(-0.9659257,-0.2588191,0.2588191,-0.9659257,115.09204,265.15215)"
id="g3730">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3732"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,83.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3734"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,113.125)" />
</g>
<g
id="g3736"
transform="matrix(-0.9961946,8.715564e-2,-8.715564e-2,-0.9961946,160.60905,242.98766)">
<path
transform="matrix(0.25,0,0,0.25,63.125,83.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3738"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,113.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3740"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3746">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3742"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3744"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3750"
transform="matrix(0.9659258,-0.258819,0.258819,0.9659258,-29.796818,23.6707)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3752"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3754"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(0.8660254,-0.4999999,0.4999999,0.8660254,-52.451906,54.246822)"
id="g3756">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3758"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3760"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3762"
transform="matrix(0.7071068,-0.7071067,0.7071067,0.7071068,-66.421359,89.644655)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3764"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3766"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(0.5,-0.8660253,0.8660253,0.5,-70.753181,127.4519)"
id="g3768">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3770"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3772"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3774"
transform="matrix(0.2588191,-0.9659257,0.9659257,0.2588191,-65.152165,165.09205)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3776"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3778"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(8.5712909e-8,-0.9999999,0.9999999,8.5712909e-8,-50.000013,199.99999)"
id="g3780">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3782"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3784"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3786"
transform="matrix(-0.2588189,-0.9659258,0.9659258,-0.2588189,-26.329318,229.79681)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3788"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3790"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(-0.4999999,-0.8660254,0.8660254,-0.4999999,4.2468015,252.4519)"
id="g3792">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3794"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3796"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3798"
transform="matrix(-0.7071067,-0.7071068,0.7071068,-0.7071067,39.644635,266.42135)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3800"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3802"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
<g
transform="matrix(-0.8660253,-0.5,0.5,-0.8660253,77.451877,270.75317)"
id="g3804">
<path
transform="matrix(0.25,0,0,0.25,63.125,118.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3806"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
<path
transform="matrix(0.25,0,0,0.25,63.125,78.125)"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
sodipodi:ry="2.5"
sodipodi:rx="2.5"
sodipodi:cy="107.5"
sodipodi:cx="47.5"
id="path3808"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
sodipodi:type="arc" />
</g>
<g
id="g3810"
transform="matrix(-0.9659257,-0.2588191,0.2588191,-0.9659257,115.09202,265.15215)">
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3812"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,118.125)" />
<path
sodipodi:type="arc"
style="opacity:1;fill:none;fill-opacity:1;stroke:#000000;stroke-width:8;stroke-linecap:square;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="path3814"
sodipodi:cx="47.5"
sodipodi:cy="107.5"
sodipodi:rx="2.5"
sodipodi:ry="2.5"
d="M 50 107.5 A 2.5 2.5 0 1 1 45,107.5 A 2.5 2.5 0 1 1 50 107.5 z"
transform="matrix(0.25,0,0,0.25,63.125,78.125)" />
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 35 KiB

View file

@ -13,7 +13,7 @@
</empty>
<text>
<label>Rendering options</label>
<label>Rendering Options</label>
</text>
<empty>
@ -193,6 +193,16 @@
-->
<checkbox>
<halign>left</halign>
<label>Compensate field of view for wider screens</label>
<property>sim/current-view/field-of-view-compensation</property>
<binding>
<command>nasal</command>
<script>view.screenWidthCompens(1)</script>
</binding>
</checkbox>
<group>
<layout>hbox</layout>
<text>
@ -206,11 +216,46 @@
<group>
<layout>table</layout>
<checkbox>
<text>
<row>0</row>
<col>0</col>
<halign>left</halign>
<label>Texture set</label>
</text>
<combo>
<row>0</row>
<col>1</col>
<colspan>3</colspan>
<name>texture-set</name>
<halign>fill</halign>
<stretch>true</stretch>
<pref-width>150</pref-width>
<property>sim/gui/dialogs/rendering/texture-set</property>
<value>Region-specific</value>
<value>Global</value>
<value>DDS</value>
<binding>
<command>dialog-apply</command>
<object-name>texture-set</object-name>
</binding>
<binding>
<command>nasal</command>
<script>
var file = materials[getprop("/sim/gui/dialogs/rendering/texture-set")];
setprop("/sim/rendering/materials-file", file);
</script>
</binding>
<binding>
<command>reload-materials</command>
</binding>
</combo>
<checkbox>
<row>1</row>
<col>0</col>
<halign>left</halign>
<label>Animated jetways</label>
<name>jetways</name>
<property>/nasal/jetways/enabled</property>
@ -221,7 +266,7 @@
</checkbox>
<checkbox>
<row>1</row>
<row>2</row>
<col>0</col>
<halign>left</halign>
<label>Random buildings</label>
@ -234,7 +279,7 @@
</checkbox>
<text>
<row>1</row>
<row>2</row>
<col>1</col>
<colspan>3</colspan>
<color>
@ -246,7 +291,7 @@
</text>
<checkbox>
<row>2</row>
<row>3</row>
<col>0</col>
<halign>left</halign>
<label>Random objects</label>
@ -259,7 +304,7 @@
</checkbox>
<checkbox>
<row>3</row>
<row>4</row>
<col>0</col>
<halign>left</halign>
<label>Random vegetation</label>
@ -271,7 +316,7 @@
</binding>
</checkbox>
<text>
<row>3</row>
<row>4</row>
<col>1</col>
<label>density</label>
<enable>
@ -279,7 +324,7 @@
</enable>
</text>
<slider>
<row>3</row>
<row>4</row>
<col>2</col>
<name>vegetation-density</name>
<min>0</min>
@ -292,7 +337,7 @@
</binding>
</slider>
<text>
<row>3</row>
<row>4</row>
<col>3</col>
<label>12345678</label>
<format>%.1f</format>
@ -699,9 +744,22 @@
<nasal>
<open>
var materials = { "Region-specific" : "Materials/regions/materials.xml",
"Global" : "Materials/default/materials.xml",
"DDS" : "Materials/dds/materials.xml" };
gui.enable_widgets(cmdarg(), "shadows-debug", getprop("/sim/gui/devel-widgets"));
props.globals.getNode("/sim/rendering/shaders/quality-level", 1).setAttribute("userarchive", 0);
setprop("/sim/gui/frame-rate-throttled", (getprop("/sim/frame-rate-throttle-hz") > 0));
var matfile = getprop("/sim/rendering/materials-file");
foreach (var name; keys(materials)) {
if (matfile == materials[name]) {
setprop("/sim/gui/dialogs/rendering/texture-set", name);
}
}
</open>
</nasal>
</PropertyList>

View file

@ -38,7 +38,9 @@ command interface /autopilot/route-manager/input:
}
var clear = func {
#cmd.setValue("@clear");
# deactive first, see http://https://code.google.com/p/flightgear-bugs/issues/detail?id=885
fgcommand("activate-flightplan", props.Node.new({"activate": 0}));
flightplan().cleanPlan();
selection.setIntValue(-1);
}
@ -60,13 +62,10 @@ command interface /autopilot/route-manager/input:
}
var remove = func {
#cmd.setValue("@delete" ~ sel_index());
flightplan().deleteWP(sel_index());
}
var route = func {
#cmd.setValue("@route" ~ sel_index());
var route = func {
var fp = flightplan();
var from = fp.getWP(sel_index() - 1);
var to = fp.getWP(sel_index());
@ -81,7 +80,6 @@ command interface /autopilot/route-manager/input:
}
var jump_to = func {
#cmd.setValue("@jump" ~ sel_index());
flightplan().current = sel_index();
}
@ -101,7 +99,7 @@ command interface /autopilot/route-manager/input:
var save_selector = gui.FileSelector.new(save_route, "Save flight-plan", "Save");
var activate_fp = func {
cmd.setValue("@activate");
fgcommand("activate-flightplan", props.Node.new({"activate": 1}));
}
var departureRunways = dlg.getNode("departure-runways", 1);

View file

@ -356,6 +356,7 @@
if (cmp(current, new) != 0) {
setprop("sim/sound/devices/name", new);
setprop("sim/sound/device-name", new);
fgcommand("reinit", props.Node.new({ "subsystem" : "sound" }));
}
}

View file

@ -166,7 +166,7 @@
setprop("/nasal/local_weather/enabled", "true");
# Re-initialize local weather.
local_weather.set_tile();
settimer( func {local_weather.set_tile();}, 0.2);
}
},

View file

@ -64,6 +64,7 @@
<command>dialog-show</command>
<dialog-name>sound-dialog</dialog-name>
</binding>
<enabled>false</enabled>
</item>
<item>
@ -703,6 +704,14 @@
</binding>
</item>
<item>
<name>doc-browser</name>
<binding>
<command>dialog-show</command>
<dialog-name>doc-browser</dialog-name>
</binding>
</item>
<item>
<key>?</key>
<name>aircraft-keys</name>

View file

@ -153,7 +153,7 @@ Started September 2000 by David Megginson, david@megginson.com
<mie type="float" userarchive="y">0.003</mie>
<rayleigh type="float" userarchive="y">0.0003</rayleigh>
<dome-density type="float" userarchive="y">0.5</dome-density>
<!-- multithreading-mode>AutomaticSelection</multithreading-mode -->
<multithreading-mode>AutomaticSelection</multithreading-mode>
<!--
Uncomment the above element to select OSG multi-threading mode.
This may improve performance on multi-core, multi-CPU
@ -346,6 +346,7 @@ Started September 2000 by David Megginson, david@megginson.com
<speed-up type="double">1.0</speed-up>
<current-view>
<field-of-view type="double">55.0</field-of-view>
<field-of-view-compensation type="bool" userarchive="y">false</field-of-view-compensation>
<aspect-ratio-multiplier type="double">1.0</aspect-ratio-multiplier>
<dynamic-view type="bool" userarchive="y">false</dynamic-view>
</current-view>