Thorsten Renk: local weather 0.61
This commit is contained in:
parent
4add69ab57
commit
eb47297d94
20 changed files with 3603 additions and 323 deletions
|
@ -7,7 +7,7 @@
|
|||
|
||||
<body>
|
||||
|
||||
<h1>Local Weather Package - v0.5</h1>
|
||||
<h1>Local Weather Package - v0.61</h1>
|
||||
|
||||
<h2>1. Introduction</h2>
|
||||
|
||||
|
@ -15,13 +15,13 @@ The aim of a local weather system is to simulate weather phenomena tied to speci
|
|||
|
||||
This is in contrast to the current (v.2.0.0) weather system of Flightgear where weather changes affect the weather everywhere in the simulated world and are (with few exceptions) not tied to specific locations. In such a system, it is impossible to observe e.g. the approach of a rainfront while flying in sunshine.<p>
|
||||
|
||||
The local weather package ultimately aims to provide the functionality to simulate such local phenomena. In version 0.5, the package supplies various cloud placement algorithms, as well as local control over most major weather parameters (visibility, pressure, temperature, rain, snow, thermal lift...) through interpolation routines and event volumes. However, basically all features currently present can and will eventually be improved.<p>
|
||||
The local weather package ultimately aims to provide the functionality to simulate such local phenomena. In version 0.61, the package supplies various cloud placement algorithms, as well as local control over most major weather parameters (visibility, pressure, temperature, rain, snow, thermal lift...) through interpolation routines and event volumes. For long-range flights, it automatically provides transitions between different weather patterns. However, basically all features currently present can and will eventually be improved.<p>
|
||||
|
||||
As of version 0.5, the system does not contain dynamics (development of convective clouds, wind displacement of clouds...). Since wind and dynamics are closely related, any wind parameters can currently <i>not</i> be controlled from the local weather algorithms.<p>
|
||||
As of version 0.61, the system does not contain dynamics (development of convective clouds, wind displacement of clouds...). Since wind and dynamics are closely related, any wind parameters can currently <i>not</i> be controlled from the local weather algorithms.<p>
|
||||
|
||||
<h2>2. Installation</h2>
|
||||
|
||||
The package needs to be unpacked in the Flightgear root directory. It writes content into the <i>Nasal/, gui/, gui/dialogs/, Shaders, Effects/</i>, and <i>Models/Weather/</i> subdirectories. The installation does not overwrite any of the default Flightgear files, but to be accessible from the menu, one must copy <i>gui/menubar.xml.alt</i> to the default <i>menubar.xml</i> or copy the last two lines of the environemnt menu calling <i>local_weather</i> and <i>local_weather_tiles</i> into the default file.<p>
|
||||
The package needs to be unpacked in the Flightgear root directory. It writes content into the <i>Nasal/, gui/, gui/dialogs/, Shaders, Effects/, Docs/</i>, and <i>Models/Weather/</i> subdirectories. The installation does not overwrite any of the default Flightgear files, but to be accessible from the menu, one must copy <i>gui/menubar.xml.alt</i> to the default <i>menubar.xml</i> or copy the last two lines of the environemnt menu calling <i>local_weather</i> and <i>local_weather_tiles</i> into the default file.<p>
|
||||
|
||||
This adds the items <i>Local Weather</i> and <i>Local weather tiles</i> to the <i>Environment</i> menu when Flightgear is up. The central functionality is contained in <i>local_weather.nas</i> which is loaded at startup and identifies itself with a message, but does not start any functions unless called from the GUI.<p>
|
||||
|
||||
|
@ -29,7 +29,7 @@ This adds the items <i>Local Weather</i> and <i>Local weather tiles</i> to the <
|
|||
|
||||
The general rule is that the gui is not hardened against problematic user input, for example it will not reject meaningless input. It is recommended to watch the console, because some level of warnings and errors are passed to the console. Placement calls may sometimes take a significant time to execute especially for large numbers of clouds tied in a complicated way to the terrain. Placing 500 barrier clouds against a small barrier may take a minute to compute.<p>
|
||||
|
||||
The first menu contains the low level cloud placement functions. Currently four options are supported: <i>Place a single cloud</i>, <i>Place a cloud streak</i>, <i>Start the convective system</i>, <i>Create barrier clouds</i> and <i>Place a cloud layer</i>.<p>
|
||||
The first menu contains the low level cloud placement functions. Its purpose is mainly for developing cloud patterns without having to resort to re-type the underlying Nasal code every time. Currently four options are supported: <i>Place a single cloud</i>, <i>Place a cloud streak</i>, <i>Start the convective system</i>, <i>Create barrier clouds</i> and <i>Place a cloud layer</i>.<p>
|
||||
|
||||
<center>
|
||||
<img src="menu1.jpg">
|
||||
|
@ -83,31 +83,47 @@ The picture illustrates the result of a layer generation call for Nimbostratus c
|
|||
|
||||
<h3>Tile placement</h3>
|
||||
|
||||
The second menu is used to place complete weather tiles based on low-level calls. Currently it contains several demo tiles indicating what can be done. <p>
|
||||
The second menu is used to place complete weather tiles based on low-level calls. It is intended for the user to automatically create the various weather patterns during flight. <p>
|
||||
|
||||
<center>
|
||||
<img src="menu2.jpg">
|
||||
</center><p>
|
||||
|
||||
The dropdown menu is used to select the type of weather tile to build. In addition, two parameters can be entered. The first is the tile orientation. Some tiles, most notably incoming fronts, have a direction along which the weather changes. The tiles are set up in such a way that fronts come from north, changing orientation rotates the whole tile to the specified direction. As soon as wind is implemented in the local weather system, the tile orientation will essentially also govern the wind direction (clearly, there is a relation between from where a front comes and the wind direction).<p>
|
||||
The dropdown menu is used to select the type of weather tile to build. The menu contains two groups of tiles - the first six are classified by airmass, whereas the last two are scenarios intended for soaring. In addition, two parameters can be entered. The first is the tile orientation. Some tiles, most notably incoming fronts, have a direction along which the weather changes. The tiles are set up in such a way that fronts come from north, changing orientation rotates the whole tile to the specified direction. As soon as wind is implemented in the local weather system, the tile orientation will essentially also govern the wind direction (clearly, there is a relation between from where a front comes and the wind direction). Currently, the functionality of tile orientation is there, but mostly untested and at the moment not particularly useful.<p>
|
||||
|
||||
The second parameter, the altitude offset, is as of now a provisorium. Cloud layer placement calls are specified for absolute altitudes and calibrated at sea level. As a result, layers are placed too low in mountainous terrain. Eventually, the system is to receive a terrain presampling function to determine just where exactly low cloud layers should be placed when a weather tile is set up. Until this is in place, the user must manually specify a suitable altitude offset for all cloud layers.<p>
|
||||
|
||||
The following pictures show the results of tile setups 'Incoming rainfront' and 'Summer rain':<p>
|
||||
The dropdown menu for the tile selection mode controls the long-range behaviour of weather. It specifies according to what rules tiles are automatically generated once the aircraft reaches the border of the original tile. The option 'single tile' creates a single weather tile as specified without automatic generation of further tiles. The option 'repeat tile' creates new tiles of the same type as the originally selected tile. This does not mean that weather will be unchanged during flight, as both parameters like pressure, temperature and visibility as well as the positioning of cloud banks are randomized to some degree. In addition, each tile typically contains 2-5 different cloud scenarios, so five repeated generations of 'low-pressure-border' tiles may never result in the same arrangement of cloud layers. Necertheless, the option will keep weather conditions roughly the same. This is different with the (somewhat optimistically named) 'realistic weather'. This option allows transitions between different airmasses, thus one may select 'low-pressure-core' initially, but as the flight goes on, eventually a region of high pressure and clear skies may be reached. Currently this change between airmasses does not include transitions across fronts. Moreover, it does not cover arctic or tropical weather conditions - those will be covered in a future release. Note that 'realistic weather' does not work for the two soaring scenarios.<p>
|
||||
|
||||
The menu then contains four options. 'Terrain presampling' is currently not yet functional. 'Worker threads' is an option to distribute the work flow. Usually, the local weather package will compute a task till it is done before starting the next. Thus, creating a new weather tile may lead to a few seconds freeze, before Flightgear continues normally. With 'worker threads' selected, computations will be split across several frames. The advantage is that Flightgear stays responsive during loading and unloading of weather tiles, and in general the flight continues smoothly, albeit with reduced framerate. However, selecting this option does not guarantee that an operation is finished by the time another is beginning - thus there may be situations in which the loading of a new tile blocks unloading of an old one and so on, in essence leading to processes competing for access to the weather array, resulting in an extended period of very low framerates. Dependent on system performance, this may or may not be acceptable to the user. 'asymmetric range' is an experimental performance-improving option (see below). Finally, 'detailed clouds' will change the technique for generating Cumulus clouds from a multilayer model to multiple cloudlets filling a box. This improves the visual appearance of the clouds significantly, albeit at the expense of a (significant) loss of framerate. Rendering multiple tiles of dense Cumulus development with detailed clouds will quite possibly freeze even a powerful system. <p>
|
||||
|
||||
|
||||
|
||||
The following pictures show the results of tile setups 'Low-pressure-border' and 'High-pressure-border':<p>
|
||||
|
||||
<center>
|
||||
<img src="clouds-incoming-rainfront1.jpg">
|
||||
<img src="carrier-ops08.jpg">
|
||||
</center><p>
|
||||
|
||||
<center>
|
||||
<img src="clouds-summer-rain.jpg">
|
||||
<img src="clouds-lpb01.jpg">
|
||||
</center><p>
|
||||
|
||||
<h2>4. Cloud models</h2>
|
||||
|
||||
The package contains a number of different cloud models, both static ones for Cirrus and Cirrocumulus clouds as well as rotated ones for Altocumulus, Cumulus, Cumulonimbus, Stratus and Nimbostratus cloudlet models. Neither the cloud textures, nor the models nor the transformations are perfected, and any aspect can be improved. Currently the clouds cannot reach the sophistication of the shader-based standard 3-d clouds of Flightgear, but there is no reason in principle why they should not eventually reach that level. The problem is finding a good balance between spending a lot of CPU time to make a single cloud model appear perfect, and the performance degradation that occurs if hundreds of clouds are placed in the sky. The basic aim is to provide realistic appearance for clouds from a standard view position (in cockpit looking forward), to retain acceptable appearance from other positions and to allow large cloud layers.<p>
|
||||
The package contains a number of different cloud models, both static ones for Cirrus and Cirrocumulus clouds as well as rotated ones for Altocumulus, Cirrostratus, Cumulus, Cumulonimbus, Stratus and Nimbostratus cloudlet models. Neither the cloud textures, nor the models nor the transformations are perfected, and any aspect can be improved. Currently the standard clouds cannot quite reach the sophistication of the shader-based standard 3-d clouds of Flightgear, but the detailed Cumulus clouds are on the verge of catching up. <p>
|
||||
|
||||
Currently all clouds which need to be rotated are treated in the Shaders using a view-axis based rotation by two angles. This generally looks okay from a normal flight position, but rapid change of the view axis (looking around), especially straight up or down, causes unrealistic cloud movement. Any static picture of clouds however is (almost) guaranteed to look fine.<p>
|
||||
<center>
|
||||
<img src="clouds-detailed01.jpg">
|
||||
</center><p>
|
||||
|
||||
These are rendered by a different technique: While the default Cumulus models consist of multiple layers rotated around the center of the model, the detailed Cumulus clouds consist of multiple (up to 24) individual cloudlets, rotating each around its own center, randomly distributed into a box. This not only improves the visual appearance, but also leads to a more realistic distribution of cloud sizes and shapes in the sky. In addition, when circling below the cloud (as done when soaring) the effect of the cloudlet rotation is less pronounced. The price to pay is that rendering detailed clouds costs about a factor 4 more performance, so they may not be suitable for all systems.<p>
|
||||
|
||||
The general problem is finding a good balance between spending a lot of CPU time to make a single cloud model appear perfect, and the performance degradation that occurs if hundreds of clouds are placed in the sky. The basic aim is to provide realistic appearance for clouds from a standard view position (in cockpit looking forward), to retain acceptable appearance from other positions and to allow large cloud layers.<p>
|
||||
|
||||
|
||||
|
||||
Currently all clouds which need to be rotated are treated in the Shaders using a view-axis based rotation by two angles. This generally looks okay from a normal flight position, but rapid change of the view axis (looking around), especially straight up or down, causes unrealistic cloud movement. Any static picture of clouds however is (almost) guaranteed to look fine. This means that shader effects need to be 'on' in order to see most of the clouds.<p>
|
||||
|
||||
<h2>5. Local weather parameters</h2>
|
||||
|
||||
|
@ -141,16 +157,20 @@ Effect volumes are always specified between a minimum and a maximum altitude, an
|
|||
|
||||
where <i>geometry</i> is a flag (1: circular, 2: elliptical and 3: rectangular), <i>lat</i> and <i>lon</i> are the latitude and longitude, <i>r1</i> and <i>r2</i> are the two size parameters for the elliptic or rectangular shape (for the circular shape, only the first is used), <i>phi</i> is the rotation angle of the shape (not used for circular shape), <i>alt_low</i> and <i>alt_high</i> are the altitude boundaries, <i>vis, rain, snow, turb</i> and <i>lift</i> are weather parameters which are either set to the value they should assume, or to -1 if they are not to be used, or to -2 if a function instead of a parameter is to be used. Since thermal lift can be set to negative values in a sink, a separate flag is provided in this case.<p>
|
||||
|
||||
In version 0.61, thermal lift is implemented by function. There is no easy way to implement any weather parameter by function in an effect volume, as this requires some amount of Nasal coding.
|
||||
|
||||
<h2>6. Property tree structure</h2>
|
||||
|
||||
The internal state of the local weather system is found in the property tree under <i>local-weather/</i>. In this directory, various loop flags are found. They indicate the state of the main monitoring loops - they are set to 1 if a loop is running, setting them to zero terminates the loop.<p>
|
||||
|
||||
The <i>local-weather</i> folder contains various subdirectories. <i>clouds/</i> contains the record of all visible weather phenomena (clouds, precipitation layers, lightning...) in a subdirectory <i>cloud[i]/</i>. The total number of all models placed is accessible as <i>local-weather/clouds/cloud-number</i>. Inside each <i>cloud/</i> subdirectory, there is a string <i>type</i> specifying the type of object and subdirectories <i>position/</i> and <i>orientation</i> which contain the position and spatial orientation of the model inside the scenery. Note that the orientation property is obsolete for clouds which are rotated by the shader.<p>
|
||||
The <i>local-weather</i> folder contains various subdirectories. <i>clouds/</i> contains the record of all visible weather phenomena (clouds, precipitation layers, lightning...) in a subdirectory <i>tile[j]/cloud[i]/</i>. The total number of all models placed is accessible as <i>local-weather/clouds/cloud-number</i>. Inside each <i>cloud/</i> subdirectory, there is a string <i>type</i> specifying the type of object and subdirectories <i>position/</i> and <i>orientation</i> which contain the position and spatial orientation of the model inside the scenery. Note that the orientation property is obsolete for clouds which are rotated by the shader.<p>
|
||||
|
||||
The <i>local-weather/effect-volumes/</i> subfolder contains the management of the effect volumes. It has the total count of specified effect volumes, along with the count of currently active volumes for each property. If volumes are defined, their properties are stored under <i>local-weather/effect-volumes/effect-volume[i]/</i>. In each folder, there are <i>position/</i> and <i>volume/</i> storing the spatial position and extent of the volume, as well as the <i>active-flag</i> which is set to 1 if the airplane is in the volume and the <i>geometry</i> flag which determines if the volume has circular, elliptical or rectangular shape. Finally, the <i>effects/</i> subfolder holds flags determining of a property is to be set when the volume is active and the corresponding values. On entry, the effect volumes also create a subfolder <i>restore/</i> in which the conditions as they were when the volume was entered are saved.<p>
|
||||
|
||||
<i>local-weather/interpolation/</i> holds all properties which are set by the interpolation system, as well as subfolders <i>station[i]/</i> in which the weather station information for the interpolation are found. Basically, here is the state of the weather as it is outside of effect volumes. Since parameters may be set to different values in effect volumes, the folder <i>local-weather/current/</i> contains the weather as the local weather system currently thinks it should be. Currently, weather is actually passed to the Flightgear environment system through several workarounds. In a clean C++ supported version, the parameters should be read from here.<p>
|
||||
|
||||
<i>local-weather/tiles</i> stores the information of the 9 managed weather tiles (the one the airplane is currently in, and the 8 surrounding it). By default each directory contains the tile center coordinates and a flag if it has been generated. Tiles are not generated unless a minimum distance to the tile center has been reached. Once this happens, the tile type is written as a code, and the cloud, interpolation and effect volume information corresponding to the tile is generated. <p>
|
||||
|
||||
<h2>7. Weather tile setup</h2>
|
||||
|
||||
Examples for weather tile setup can be found in <i>Nasal/weather-tiles.nas</i>. Each tile is generated by a sequence of Nasal function calls to first set weather stations, then to draw the cloud layers, and effect volumes. Finally, all necessary loops must be started. It is a bit awkward to have to write in Nasal to customize the system, but I can't think of a reasonable GUI for the task, except marking every placement on a map which exceeds my coding skills a bit. The problem is that there is no real standard solution - every weather tile needs different calls, sometimes a large one generating many clouds, sometimes several smaller ones.<p>
|
||||
|
@ -165,8 +185,23 @@ If the cloud layer has an orientation, then all placement coordinates should be
|
|||
|
||||
To make your own tile visible, an entry in the menu <i>gui/dialogs/local_weather_tiles.xml</i> needs to be created and the name needs to be added with a tile setup call to the function <i>set_tile</i> in <i>Nasal/local_weather.nas</i>.
|
||||
|
||||
<h2>8. Performance tuning</h2>
|
||||
|
||||
<h2>8. Known issues</h2>
|
||||
With default settings, the local weather package generates a 40x40 km weather tile when the aircraft is closer than 35 km to the tile center and unloads it when the aircraft is more than 37 km away. This means that the system can generate at most 4 tiles at once and clouds are visible for at least 15 km and up to 30 km (the latter number determined by fading in the shaders). However, rendering and managing multiple overcast cloud layers in a region of 80x80 km is a significant drain on performance. For older systems, a few things can be tried:<p>
|
||||
|
||||
* the menu option 'asymmetric range' decreases loading and unloading ranges in a 45 degree sector behind the aircraft. This means that in straight flight, less tiles will be loaded at the same time, as tiles in the rear are unloaded more quickly. The option is currently experimental.<p>
|
||||
|
||||
* a further reduction in the amount of simultaneously generated tiles can be achieved by changing the ranges. These are exposed in the property tree as <i>local-weather/config/distance-to-load-tile-m</i> and <i>local-weather/config/distance-to-remove-tile-m</i>. Note that the removal range <b>must</b> be larger than the loading range - otherwise just generated tiles will be immediately unloaded! Ranges below 20 km will guarantee that only one tile is loaded at a time, but will create empty spots when no tile is loaded. A range above 28 km will guarantee that the aircraft never flies in an empty tile, but empty sky in front will be visible. Finally, ranges above 56 km guarantee that all 9 tiles (a region of 120x120 km) are managed at all times - but will most likely cause a severe drop in framerate for most scenarios.<p>
|
||||
|
||||
* if this does not help, try avoiding scenarios with large cloud count. As a rule, low pressure areas have high cloud count, high pressure areas have a low cloud count. <p>
|
||||
|
||||
* a drastic solution is to set the visual ranges lower. Currently, cloud models are set to be visible up to 30 km. Changing the visibility range in the range animation of all cloud model xml wrappers will improve performance accordingly. To achieve a nice fading into the background instead of a sudden disappearance, it is recommended to adjust the visibility range in the shaders accordingly. It would probably be good to expose the visual range as a property, but currently it's not yet done, as passing a property to the shader requires Flightgear CVS and cannot be done in 2.0.0.<p>
|
||||
|
||||
Performance for overcast layers currently is a limiting issue and there are a few ideas around how to improve it - dependent if these work or not, future releases may work better.<p>
|
||||
|
||||
* a different issue is a characteristic small pause every 3 seconds. This is caused by the interpolation loop resetting the weather parameters. Currently, a computationally expensive workaround is needed to do so, causing the problem. Work on a better environment controller is on the way, however until that modification to the core Flightgear code is implemented, the best solution is to set the loop time in <i>Nasal/local-weather.nas</i> to a larger value. <p>
|
||||
|
||||
<h2>9. Known issues</h2>
|
||||
|
||||
* The local weather system does not mix well with the standard weather system. 3d cloud layers can be placed in the absence of effect volumes, but any effect volume causing precipitation will let the layer behave in a strange way. Likewise, 2d cloud layers can be placed, but may or may not lead to strange rendering artefacts. Local weather, as long as interpolation and effect volumes are running, will in general overwrite all other settings - bother real weather METAR and user-specified settings from the menu. The results of mixing standard and local weather settings are unpredictable, and may not lead to the desired results.<p>
|
||||
|
||||
|
@ -174,8 +209,18 @@ To make your own tile visible, an entry in the menu <i>gui/dialogs/local_weather
|
|||
|
||||
* Rain and snow may not start properly. For me, rain is only generated when I switch 'Shader effects' on and off in the menu on startup, otherwise neither moving the menu slider nor entering an effect volume generate rain. This seems to be a bug of some Flightgear versions, not of the local weather system.<p>
|
||||
|
||||
* Especially with multiple overcast layers, loading and unloading weather tiles may take a long time / cause severe drops in framerate. Please refer to performance tuning to solve such problems. In general, overcast layers do require a system on the high end of the performance scale to render properly.<p>
|
||||
|
||||
Thorsten Renk, April 2010
|
||||
* The local weather package is able to occasionally trigger errors like 'Warning:: Picked up error in TriangleIntersect'. These seem to be a problem in the core Flightgear code - the package does nothing but placing normal (rather simple) AC3D models into the scenery.<p>
|
||||
|
||||
* The thermals in the soaring scenarios need a CVS patch to work.<p>
|
||||
|
||||
<h2>10. Credits</h2>
|
||||
|
||||
The model of a thermal has been developed by Patrice Poly. The shader code used to transform clouds is heavily based on prior work by Stuart Buchanan.<p>
|
||||
|
||||
|
||||
Thorsten Renk, May 2010
|
||||
|
||||
</body>
|
||||
|
||||
|
|
BIN
Docs/carrier-ops08.jpg
Normal file
BIN
Docs/carrier-ops08.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 42 KiB |
BIN
Docs/clouds-detailed01.jpg
Normal file
BIN
Docs/clouds-detailed01.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 93 KiB |
BIN
Docs/clouds-lpb01.jpg
Normal file
BIN
Docs/clouds-lpb01.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 99 KiB |
BIN
Docs/menu2.jpg
BIN
Docs/menu2.jpg
Binary file not shown.
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 17 KiB |
|
@ -1,68 +1,58 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PropertyList>
|
||||
<name>Effects/clouds-thin</name>
|
||||
<parameters>
|
||||
<texture n ="0">
|
||||
</texture>
|
||||
</parameters>
|
||||
<technique n="10">
|
||||
<predicate>
|
||||
<and>
|
||||
<property>/sim/rendering/shader-effects</property>
|
||||
<less-equal>
|
||||
<value type="float">1.0</value>
|
||||
<shader-language/>
|
||||
</less-equal>
|
||||
</and>
|
||||
</predicate>
|
||||
<pass n="0">
|
||||
<!-- This is apparently not used, so maybe we'll blow it way soon. -->
|
||||
<lighting>true</lighting>
|
||||
<material>
|
||||
<ambient type="vec4d">0.5 0.5 0.5 1.0</ambient>
|
||||
<diffuse type="vec4d">0.5 0.5 0.5 1.0</diffuse>
|
||||
<color-mode>off</color-mode>
|
||||
</material>
|
||||
<alpha-test>
|
||||
<comparison>greater</comparison>
|
||||
<reference type="float">0.01</reference>
|
||||
</alpha-test>
|
||||
<shade-model>smooth</shade-model>
|
||||
<blend>
|
||||
<source>src-alpha</source>
|
||||
<destination>one-minus-src-alpha</destination>
|
||||
</blend>
|
||||
<depth>
|
||||
<write-mask>false</write-mask>
|
||||
</depth>
|
||||
<render-bin>
|
||||
<bin-number>10</bin-number>
|
||||
<bin-name>DepthSortedBin</bin-name>
|
||||
</render-bin>
|
||||
<texture-unit>
|
||||
<unit>0</unit>
|
||||
<type>
|
||||
<use>texture[0]/type</use>
|
||||
</type>
|
||||
<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>
|
||||
<!--<wrap-s>clamp</wrap-s>
|
||||
<name>Effects/clouds-thin</name>
|
||||
<parameters>
|
||||
<texture n ="0">
|
||||
</texture>
|
||||
</parameters>
|
||||
<technique n="10">
|
||||
<predicate>
|
||||
<and>
|
||||
<property>/sim/rendering/shader-effects</property>
|
||||
<less-equal>
|
||||
<value type="float">1.0</value>
|
||||
<shader-language/>
|
||||
</less-equal>
|
||||
</and>
|
||||
</predicate>
|
||||
<pass n="0">
|
||||
<!-- This is apparently not used, so maybe we'll blow it way soon. -->
|
||||
<lighting>true</lighting>
|
||||
<material>
|
||||
<ambient type="vec4d">0.5 0.5 0.5 1.0</ambient>
|
||||
<diffuse type="vec4d">0.5 0.5 0.5 1.0</diffuse>
|
||||
<color-mode>off</color-mode>
|
||||
</material>
|
||||
<alpha-test>
|
||||
<comparison>greater</comparison>
|
||||
<reference type="float">0.01</reference>
|
||||
</alpha-test>
|
||||
<shade-model>smooth</shade-model>
|
||||
<blend>
|
||||
<source>src-alpha</source>
|
||||
<destination>one-minus-src-alpha</destination>
|
||||
</blend>
|
||||
<depth>
|
||||
<write-mask>false</write-mask>
|
||||
</depth>
|
||||
<render-bin>
|
||||
<bin-number>10</bin-number>
|
||||
<bin-name>DepthSortedBin</bin-name>
|
||||
</render-bin>
|
||||
<texture-unit>
|
||||
<unit>0</unit>
|
||||
<type><use>texture[0]/type</use></type>
|
||||
<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>
|
||||
<!--<wrap-s>clamp</wrap-s>
|
||||
<wrap-t>clamp</wrap-t>-->
|
||||
</texture-unit>
|
||||
<program>
|
||||
<vertex-shader>Shaders/clouds-thin.vert</vertex-shader>
|
||||
<fragment-shader>Shaders/clouds-thin.frag</fragment-shader>
|
||||
<!--<attribute>
|
||||
</texture-unit>
|
||||
<program>
|
||||
<vertex-shader>Shaders/clouds-thin.vert</vertex-shader>
|
||||
<fragment-shader>Shaders/clouds-thin.frag</fragment-shader>
|
||||
<!--<attribute>
|
||||
<name>usrAttr3</name>
|
||||
<index>10</index>
|
||||
</attribute>
|
||||
|
@ -70,13 +60,13 @@
|
|||
<name>usrAttr4</name>
|
||||
<index>11</index>
|
||||
</attribute>-->
|
||||
</program>
|
||||
<uniform>
|
||||
<name>baseTexture</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">0</value>
|
||||
</uniform>
|
||||
<vertex-program-two-side>true</vertex-program-two-side>
|
||||
</pass>
|
||||
</technique>
|
||||
</program>
|
||||
<uniform>
|
||||
<name>baseTexture</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">0</value>
|
||||
</uniform>
|
||||
<vertex-program-two-side>true</vertex-program-two-side>
|
||||
</pass>
|
||||
</technique>
|
||||
</PropertyList>
|
||||
|
|
64
Effects/clouds-thinlayer.eff
Normal file
64
Effects/clouds-thinlayer.eff
Normal file
|
@ -0,0 +1,64 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PropertyList>
|
||||
<name>Effects/clouds-layered</name>
|
||||
<parameters>
|
||||
<texture n ="0">
|
||||
</texture>
|
||||
</parameters>
|
||||
<technique n="10">
|
||||
<predicate>
|
||||
<and>
|
||||
<property>/sim/rendering/shader-effects</property>
|
||||
<less-equal>
|
||||
<value type="float">1.0</value>
|
||||
<shader-language/>
|
||||
</less-equal>
|
||||
</and>
|
||||
</predicate>
|
||||
<pass n="0">
|
||||
<!-- This is apparently not used, so maybe we'll blow it way soon. -->
|
||||
<lighting>true</lighting>
|
||||
<material>
|
||||
<ambient type="vec4d">0.5 0.5 0.5 1.0</ambient>
|
||||
<diffuse type="vec4d">0.5 0.5 0.5 1.0</diffuse>
|
||||
<color-mode>off</color-mode>
|
||||
</material>
|
||||
<alpha-test>
|
||||
<comparison>greater</comparison>
|
||||
<reference type="float">0.01</reference>
|
||||
</alpha-test>
|
||||
<shade-model>smooth</shade-model>
|
||||
<blend>
|
||||
<source>src-alpha</source>
|
||||
<destination>one-minus-src-alpha</destination>
|
||||
</blend>
|
||||
<depth>
|
||||
<write-mask>false</write-mask>
|
||||
</depth>
|
||||
<render-bin>
|
||||
<bin-number>10</bin-number>
|
||||
<bin-name>DepthSortedBin</bin-name>
|
||||
</render-bin>
|
||||
<texture-unit>
|
||||
<unit>0</unit>
|
||||
<type><use>texture[0]/type</use></type>
|
||||
<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>
|
||||
<!--<wrap-s>clamp</wrap-s>
|
||||
<wrap-t>clamp</wrap-t>-->
|
||||
</texture-unit>
|
||||
<program>
|
||||
<vertex-shader>Shaders/clouds-thinlayer.vert</vertex-shader>
|
||||
<fragment-shader>Shaders/clouds-thinlayer.frag</fragment-shader>
|
||||
</program>
|
||||
<uniform>
|
||||
<name>baseTexture</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">0</value>
|
||||
</uniform>
|
||||
<vertex-program-two-side>true</vertex-program-two-side>
|
||||
</pass>
|
||||
</technique>
|
||||
</PropertyList>
|
81
Effects/test.eff
Normal file
81
Effects/test.eff
Normal file
|
@ -0,0 +1,81 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PropertyList>
|
||||
<name>Effects/test</name>
|
||||
<parameters>
|
||||
<texture n ="0">
|
||||
</texture>
|
||||
</parameters>
|
||||
<technique n="10">
|
||||
<predicate>
|
||||
<and>
|
||||
<property>/sim/rendering/shader-effects</property>
|
||||
<less-equal>
|
||||
<value type="float">1.0</value>
|
||||
<shader-language/>
|
||||
</less-equal>
|
||||
</and>
|
||||
</predicate>
|
||||
<pass n="0">
|
||||
<!-- This is apparently not used, so maybe we'll blow it way soon. -->
|
||||
<lighting>true</lighting>
|
||||
<material>
|
||||
<ambient type="vec4d">0.5 0.5 0.5 1.0</ambient>
|
||||
<diffuse type="vec4d">0.5 0.5 0.5 1.0</diffuse>
|
||||
<color-mode>off</color-mode>
|
||||
</material>
|
||||
<alpha-test>
|
||||
<comparison>greater</comparison>
|
||||
<reference type="float">0.01</reference>
|
||||
</alpha-test>
|
||||
<shade-model>smooth</shade-model>
|
||||
<blend>
|
||||
<source>src-alpha</source>
|
||||
<destination>one-minus-src-alpha</destination>
|
||||
</blend>
|
||||
<depth>
|
||||
<write-mask>false</write-mask>
|
||||
</depth>
|
||||
<render-bin>
|
||||
<bin-number>10</bin-number>
|
||||
<bin-name>DepthSortedBin</bin-name>
|
||||
</render-bin>
|
||||
<texture-unit>
|
||||
<unit>0</unit>
|
||||
<type><use>texture[0]/type</use></type>
|
||||
<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>
|
||||
<!--<wrap-s>clamp</wrap-s>
|
||||
<wrap-t>clamp</wrap-t>-->
|
||||
</texture-unit>
|
||||
<!--<attribute>
|
||||
<mypars type="vec3">0 0 0</mypars>
|
||||
<value type="int">10</value>
|
||||
</attribute>-->
|
||||
<program>
|
||||
<vertex-shader>Shaders/test.vert</vertex-shader>
|
||||
<fragment-shader>Shaders/test.frag</fragment-shader>
|
||||
<!--<attribute>
|
||||
<name>usrAttr3</name>
|
||||
<index>10</index>
|
||||
</attribute>
|
||||
<attribute>
|
||||
<name>usrAttr4</name>
|
||||
<index>11</index>
|
||||
</attribute>-->
|
||||
</program>
|
||||
<uniform>
|
||||
<name>baseTexture</name>
|
||||
<type>sampler-2d</type>
|
||||
<value type="int">0</value>
|
||||
</uniform>
|
||||
<uniform>
|
||||
<name>shading</name>
|
||||
<type>float</type>
|
||||
<value type="float">0.5</value>
|
||||
</uniform>
|
||||
<vertex-program-two-side>true</vertex-program-two-side>
|
||||
</pass>
|
||||
</technique>
|
||||
</PropertyList>
|
File diff suppressed because it is too large
Load diff
539
Nasal/weather_tile_management.nas
Normal file
539
Nasal/weather_tile_management.nas
Normal file
|
@ -0,0 +1,539 @@
|
|||
########################################################
|
||||
# routines to set up, transform and manage weather tiles
|
||||
# Thorsten Renk, April 2010
|
||||
########################################################
|
||||
|
||||
|
||||
###################################
|
||||
# tile management loop
|
||||
###################################
|
||||
|
||||
var tile_management_loop = func {
|
||||
|
||||
var tNode = props.globals.getNode(lw~"tiles", 1).getChildren("tile");
|
||||
var viewpos = geo.aircraft_position(); # using viewpos here triggers massive tile ops for tower view...
|
||||
var code = getprop(lw~"tiles/code");
|
||||
var i = 0;
|
||||
var d_min = 100000.0;
|
||||
var i_min = 0;
|
||||
var distance_to_load = getprop(lw~"config/distance-to-load-tile-m");
|
||||
var distance_to_remove = getprop(lw~"config/distance-to-remove-tile-m");
|
||||
var current_heading = getprop("orientation/heading-deg");
|
||||
var loading_flag = getprop(lw~"tmp/asymmetric-tile-loading-flag");
|
||||
|
||||
foreach (var t; tNode) {
|
||||
|
||||
var tpos = geo.Coord.new();
|
||||
tpos.set_latlon(t.getNode("latitude-deg").getValue(),t.getNode("longitude-deg").getValue(),0.0);
|
||||
var d = viewpos.distance_to(tpos);
|
||||
if (d < d_min) {d_min = d; i_min = i;}
|
||||
var flag = t.getNode("generated-flag").getValue();
|
||||
|
||||
var dir = viewpos.course_to(tpos);
|
||||
var d_load = distance_to_load;
|
||||
var d_remove = distance_to_remove;
|
||||
if (loading_flag == 1)
|
||||
{
|
||||
if ((abs(dir-current_heading) > 135.0) and (abs(dir-current_heading) < 225.0))
|
||||
{
|
||||
d_load = 0.7 * d_load;
|
||||
d_remove = 0.7 * d_remove;
|
||||
}
|
||||
}
|
||||
|
||||
#print(d);
|
||||
if ((d < distance_to_load) and (flag==0)) # the tile needs to be generated, unless it already has been
|
||||
{
|
||||
setprop(lw~"tiles/tile-counter",getprop(lw~"tiles/tile-counter")+1);
|
||||
print("Building tile unique index ",getprop(lw~"tiles/tile-counter"));
|
||||
generate_tile(code, tpos.lat(), tpos.lon(),0);
|
||||
t.getNode("generated-flag").setValue(1);
|
||||
t.getNode("tile-index",1).setValue(getprop(lw~"tiles/tile-counter"));
|
||||
}
|
||||
|
||||
if ((d > distance_to_remove) and (flag==1)) # the tile needs to be deleted if it exists
|
||||
{
|
||||
print("Removing tile, unique index ", t.getNode("tile-index").getValue());
|
||||
remove_tile(t.getNode("tile-index").getValue());
|
||||
t.getNode("generated-flag").setValue(0);
|
||||
}
|
||||
i = i + 1;
|
||||
} # end foreach
|
||||
|
||||
#print("Minimum distance to: ",i_min);
|
||||
|
||||
if (i_min != 4) # we've entered a different tile
|
||||
{
|
||||
print("Changing active tile to direction ", i_min);
|
||||
change_active_tile(i_min);
|
||||
}
|
||||
|
||||
if (getprop(lw~"tile-loop-flag") ==1) {settimer(tile_management_loop, 5.0);}
|
||||
|
||||
}
|
||||
|
||||
|
||||
###################################
|
||||
# tile generation call
|
||||
###################################
|
||||
|
||||
var generate_tile = func (code, lat, lon, index) {
|
||||
|
||||
setprop(lw~"tiles/tmp/latitude-deg", lat);
|
||||
setprop(lw~"tiles/tmp/longitude-deg",lon);
|
||||
|
||||
if (getprop(lw~"tmp/tile-management") == "repeat tile")
|
||||
{
|
||||
if (code == "altocumulus_sky"){weather_tiles.set_altocumulus_tile();}
|
||||
else if (code == "broken_layers") {weather_tiles.set_broken_layers_tile();}
|
||||
else if (code == "stratus") {weather_tiles.set_overcast_stratus_tile();}
|
||||
else if (code == "cumulus_sky") {weather_tiles.set_fair_weather_tile();}
|
||||
else if (code == "gliders_sky") {weather_tiles.set_gliders_sky_tile();}
|
||||
else if (code == "blue_thermals") {weather_tiles.set_blue_thermals_tile();}
|
||||
else if (code == "summer_rain") {weather_tiles.set_summer_rain_tile();}
|
||||
else if (code == "high_pressure_core") {weather_tiles.set_high_pressure_core_tile();}
|
||||
else if (code == "high_pressure") {weather_tiles.set_high_pressure_tile();}
|
||||
else if (code == "high_pressure_border") {weather_tiles.set_high_pressure_border_tile();}
|
||||
else if (code == "low_pressure_border") {weather_tiles.set_low_pressure_border_tile();}
|
||||
else if (code == "low_pressure") {weather_tiles.set_low_pressure_tile();}
|
||||
else if (code == "low_pressure_core") {weather_tiles.set_low_pressure_core_tile();}
|
||||
}
|
||||
else if (getprop(lw~"tmp/tile-management") == "realistic weather")
|
||||
{
|
||||
var rn = rand();
|
||||
|
||||
if (code == "low_pressure_core")
|
||||
{
|
||||
if (rn > 0.3) {weather_tiles.set_low_pressure_core_tile();}
|
||||
else {weather_tiles.set_low_pressure_tile();}
|
||||
}
|
||||
else if (code == "low_pressure")
|
||||
{
|
||||
if (rn > 0.3) {weather_tiles.set_low_pressure_tile();}
|
||||
else if (rn > 0.15) {weather_tiles.set_low_pressure_core_tile();}
|
||||
else {weather_tiles.set_low_pressure_border_tile();}
|
||||
}
|
||||
else if (code == "low_pressure_border")
|
||||
{
|
||||
if (rn > 0.3) {weather_tiles.set_low_pressure_border_tile();}
|
||||
else if (rn > 0.15) {weather_tiles.set_low_pressure_tile();}
|
||||
else {weather_tiles.set_high_pressure_border_tile();}
|
||||
}
|
||||
else if (code == "high_pressure_border")
|
||||
{
|
||||
if (rn > 0.3) {weather_tiles.set_high_pressure_border_tile();}
|
||||
else if (rn > 0.15) {weather_tiles.set_high_pressure_tile();}
|
||||
else {weather_tiles.set_low_pressure_border_tile();}
|
||||
}
|
||||
else if (code == "high_pressure")
|
||||
{
|
||||
if (rn > 0.3) {weather_tiles.set_high_pressure_tile();}
|
||||
else if (rn > 0.15) {weather_tiles.set_high_pressure_border_tile();}
|
||||
else {weather_tiles.set_high_pressure_core_tile();}
|
||||
}
|
||||
else if (code == "high_pressure_core")
|
||||
{
|
||||
if (rn > 0.3) {weather_tiles.set_high_pressure_core_tile();}
|
||||
else {weather_tiles.set_high_pressure_tile();}
|
||||
}
|
||||
|
||||
} # end if mode == realistic weather
|
||||
}
|
||||
|
||||
|
||||
###################################
|
||||
# tile removal call
|
||||
###################################
|
||||
|
||||
|
||||
var remove_tile_loop = func (index) {
|
||||
|
||||
var n = 100;
|
||||
|
||||
var flag_mod = 0;
|
||||
|
||||
#var mvec = props.globals.getNode("models", 1).getChildren("model");
|
||||
#var msize = size(mvec);
|
||||
|
||||
var status = getprop(lw~"tmp/thread-status");
|
||||
|
||||
if ((status == "computing") or (status == "placing")) # the array is blocked
|
||||
{
|
||||
settimer( func {remove_tile_loop(index); },0); # try again next frame
|
||||
return;
|
||||
}
|
||||
else if (status == "idle") # we initialize the loop
|
||||
{
|
||||
mvec = props.globals.getNode("models", 1).getChildren("model");
|
||||
msize = size(mvec);
|
||||
setprop(lw~"tmp/last-reading-pos-mod", msize);
|
||||
setprop(lw~"tmp/thread-status", "removing");
|
||||
}
|
||||
|
||||
var lastpos = getprop(lw~"tmp/last-reading-pos-mod");
|
||||
|
||||
# print("msize: ", msize, "lastpos ", lastpos);
|
||||
|
||||
if (lastpos < (msize-1)) {var istart = lastpos;} else {var istart = (msize-1);}
|
||||
|
||||
if (istart<0) {istart=0;}
|
||||
|
||||
var i_min = istart - n;
|
||||
if (i_min < -1) {i_min =-1;}
|
||||
|
||||
for (var i = istart; i > i_min; i = i- 1)
|
||||
{
|
||||
m = mvec[i];
|
||||
if (m.getNode("legend",1).getValue() == "Cloud")
|
||||
{
|
||||
if (m.getNode("tile-index").getValue() == index)
|
||||
{
|
||||
m.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i<0) {flag_mod = 1;}
|
||||
|
||||
|
||||
if (flag_mod == 0) {setprop(lw~"tmp/last-reading-pos-mod",i); }
|
||||
|
||||
if (flag_mod == 0) # we still have work to do
|
||||
{settimer( func {remove_tile_loop(index); },0);}
|
||||
else
|
||||
{
|
||||
print("Tile deletion loop finished!");
|
||||
setprop(lw~"tmp/thread-status", "idle");
|
||||
setprop(lw~"clouds/placement-index",0);
|
||||
setprop(lw~"clouds/model-placement-index",0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
# this is to avoid two tile removal loops starting at the same time
|
||||
|
||||
var waiting_loop = func (index) {
|
||||
|
||||
var status = getprop(lw~"tmp/thread-status");
|
||||
|
||||
if (status == "idle") {remove_tile_loop(index);}
|
||||
|
||||
else {
|
||||
print("Removal of ",index, " waiting for idle thread...");
|
||||
settimer( func {waiting_loop(index); },1.0);
|
||||
}
|
||||
}
|
||||
|
||||
var remove_tile = func (index) {
|
||||
|
||||
var n = size(props.globals.getNode("local-weather/clouds").getChild("tile",index,1).getChildren("cloud"));
|
||||
props.globals.getNode("local-weather/clouds", 1).removeChild("tile",index);
|
||||
setprop(lw~"clouds/cloud-number",getprop(lw~"clouds/cloud-number")-n);
|
||||
|
||||
if (getprop(lw~"tmp/thread-flag") == 1)
|
||||
#{remove_tile_loop(index);}
|
||||
#{waiting_loop(index);}
|
||||
# call the model removal in the next frame, because its initialization takes time
|
||||
# and we do a lot in this frame
|
||||
{settimer( func {waiting_loop(index); },0);}
|
||||
else
|
||||
{
|
||||
var modelNode = props.globals.getNode("models", 1).getChildren("model");
|
||||
foreach (var m; modelNode)
|
||||
{
|
||||
if (m.getNode("legend").getValue() == "Cloud")
|
||||
{
|
||||
if (m.getNode("tile-index").getValue() == index)
|
||||
{
|
||||
m.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var effectNode = props.globals.getNode("local-weather/effect-volumes").getChildren("effect-volume");
|
||||
|
||||
foreach (var e; effectNode)
|
||||
{
|
||||
if (e.getNode("tile-index").getValue() == index)
|
||||
{
|
||||
e.remove();
|
||||
setprop(lw~"effect-volumes/number",getprop(lw~"effect-volumes/number")-1);
|
||||
}
|
||||
}
|
||||
|
||||
# set placement indices to zero to reinitiate search for free positions
|
||||
|
||||
setprop(lw~"clouds/placement-index",0);
|
||||
setprop(lw~"clouds/model-placement-index",0);
|
||||
setprop(lw~"effect-volumes/effect-placement-index",0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
###################################
|
||||
# active tile change and neighbour
|
||||
# recomputation
|
||||
###################################
|
||||
|
||||
var change_active_tile = func (index) {
|
||||
|
||||
var t = props.globals.getNode(lw~"tiles").getChild("tile",index,0);
|
||||
|
||||
var lat = t.getNode("latitude-deg").getValue();
|
||||
var lon = t.getNode("longitude-deg").getValue();
|
||||
var alpha = getprop(lw~"tmp/tile-orientation-deg");
|
||||
|
||||
if (index == 0)
|
||||
{
|
||||
copy_entry(4,8);
|
||||
copy_entry(3,7);
|
||||
copy_entry(1,5);
|
||||
copy_entry(0,4);
|
||||
create_neighbour(lat,lon,0,alpha);
|
||||
create_neighbour(lat,lon,1,alpha);
|
||||
create_neighbour(lat,lon,2,alpha);
|
||||
create_neighbour(lat,lon,3,alpha);
|
||||
create_neighbour(lat,lon,6,alpha);
|
||||
}
|
||||
else if (index == 1)
|
||||
{
|
||||
copy_entry(3,6);
|
||||
copy_entry(4,7);
|
||||
copy_entry(5,8);
|
||||
copy_entry(0,3);
|
||||
copy_entry(1,4);
|
||||
copy_entry(2,5);
|
||||
create_neighbour(lat,lon,0,alpha);
|
||||
create_neighbour(lat,lon,1,alpha);
|
||||
create_neighbour(lat,lon,2,alpha);
|
||||
}
|
||||
else if (index == 2)
|
||||
{
|
||||
copy_entry(4,6);
|
||||
copy_entry(1,3);
|
||||
copy_entry(2,4);
|
||||
copy_entry(5,7);
|
||||
create_neighbour(lat,lon,0,alpha);
|
||||
create_neighbour(lat,lon,1,alpha);
|
||||
create_neighbour(lat,lon,2,alpha);
|
||||
create_neighbour(lat,lon,5,alpha);
|
||||
create_neighbour(lat,lon,8,alpha);
|
||||
}
|
||||
else if (index == 3)
|
||||
{
|
||||
copy_entry(1,2);
|
||||
copy_entry(4,5);
|
||||
copy_entry(7,8);
|
||||
copy_entry(0,1);
|
||||
copy_entry(3,4);
|
||||
copy_entry(6,7);
|
||||
create_neighbour(lat,lon,0,alpha);
|
||||
create_neighbour(lat,lon,3,alpha);
|
||||
create_neighbour(lat,lon,6,alpha);
|
||||
}
|
||||
else if (index == 5)
|
||||
{
|
||||
copy_entry(1,0);
|
||||
copy_entry(4,3);
|
||||
copy_entry(7,6);
|
||||
copy_entry(2,1);
|
||||
copy_entry(5,4);
|
||||
copy_entry(8,7);
|
||||
create_neighbour(lat,lon,2,alpha);
|
||||
create_neighbour(lat,lon,5,alpha);
|
||||
create_neighbour(lat,lon,8,alpha);
|
||||
}
|
||||
else if (index == 6)
|
||||
{
|
||||
copy_entry(4,2);
|
||||
copy_entry(3,1);
|
||||
copy_entry(6,4);
|
||||
copy_entry(7,5);
|
||||
create_neighbour(lat,lon,0,alpha);
|
||||
create_neighbour(lat,lon,3,alpha);
|
||||
create_neighbour(lat,lon,6,alpha);
|
||||
create_neighbour(lat,lon,7,alpha);
|
||||
create_neighbour(lat,lon,8,alpha);
|
||||
}
|
||||
else if (index == 7)
|
||||
{
|
||||
copy_entry(3,0);
|
||||
copy_entry(4,1);
|
||||
copy_entry(5,2);
|
||||
copy_entry(6,3);
|
||||
copy_entry(7,4);
|
||||
copy_entry(8,5);
|
||||
create_neighbour(lat,lon,6,alpha);
|
||||
create_neighbour(lat,lon,7,alpha);
|
||||
create_neighbour(lat,lon,8,alpha);
|
||||
}
|
||||
else if (index == 8)
|
||||
{
|
||||
copy_entry(4,0);
|
||||
copy_entry(7,3);
|
||||
copy_entry(8,4);
|
||||
copy_entry(5,1);
|
||||
create_neighbour(lat,lon,2,alpha);
|
||||
create_neighbour(lat,lon,5,alpha);
|
||||
create_neighbour(lat,lon,6,alpha);
|
||||
create_neighbour(lat,lon,7,alpha);
|
||||
create_neighbour(lat,lon,8,alpha);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#####################################
|
||||
# copy tile info in neighbour matrix
|
||||
#####################################
|
||||
|
||||
var copy_entry = func (from_index, to_index) {
|
||||
|
||||
var tNode = props.globals.getNode(lw~"tiles");
|
||||
|
||||
var f = tNode.getChild("tile",from_index,0);
|
||||
var t = tNode.getChild("tile",to_index,0);
|
||||
|
||||
t.getNode("latitude-deg").setValue(f.getNode("latitude-deg").getValue());
|
||||
t.getNode("longitude-deg").setValue(f.getNode("longitude-deg").getValue());
|
||||
t.getNode("generated-flag").setValue(f.getNode("generated-flag").getValue());
|
||||
t.getNode("tile-index").setValue(f.getNode("tile-index").getValue());
|
||||
}
|
||||
|
||||
#####################################
|
||||
# create adjacent tile coordinates
|
||||
#####################################
|
||||
|
||||
var create_neighbour = func (blat, blon, index, alpha) {
|
||||
|
||||
var x = 0.0;
|
||||
var y = 0.0;
|
||||
var phi = alpha * math.pi/180.0;
|
||||
|
||||
calc_geo(blat);
|
||||
|
||||
if ((index == 0) or (index == 3) or (index == 6)) {x =-40000.0;}
|
||||
if ((index == 2) or (index == 5) or (index == 8)) {x = 40000.0;}
|
||||
|
||||
if ((index == 0) or (index == 1) or (index == 2)) {y = 40000.0;}
|
||||
if ((index == 6) or (index == 7) or (index == 8)) {y = -40000.0;}
|
||||
|
||||
var t = props.globals.getNode(lw~"tiles").getChild("tile",index,0);
|
||||
|
||||
t.getNode("latitude-deg",1).setValue(blat + get_lat(x,y,phi));
|
||||
t.getNode("longitude-deg",1).setValue(blon + get_lon(x,y,phi));
|
||||
t.getNode("generated-flag",1).setValue(0);
|
||||
t.getNode("tile-index",1).setValue(-1);
|
||||
}
|
||||
|
||||
#####################################
|
||||
# find the 8 adjacent tile coordinates
|
||||
# after the initial setup call
|
||||
#####################################
|
||||
|
||||
var create_neighbours = func (blat, blon, alpha) {
|
||||
|
||||
var x = 0.0;
|
||||
var y = 0.0;
|
||||
var phi = alpha * math.pi/180.0;
|
||||
|
||||
calc_geo(blat);
|
||||
|
||||
x = -40000.0; y = 40000.0;
|
||||
setprop(lw~"tiles/tile[0]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[0]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[0]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[0]/tile-index",-1);
|
||||
|
||||
x = 0.0; y = 40000.0;
|
||||
setprop(lw~"tiles/tile[1]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[1]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[1]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[1]/tile-index",-1);
|
||||
|
||||
x = 40000.0; y = 40000.0;
|
||||
setprop(lw~"tiles/tile[2]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[2]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[2]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[2]/tile-index",-1);
|
||||
|
||||
x = -40000.0; y = 0.0;
|
||||
setprop(lw~"tiles/tile[3]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[3]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[3]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[3]/tile-index",-1);
|
||||
|
||||
# this is the current tile
|
||||
x = 0.0; y = 0.0;
|
||||
setprop(lw~"tiles/tile[4]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[4]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[4]/generated-flag",1);
|
||||
setprop(lw~"tiles/tile[4]/tile-index",1);
|
||||
|
||||
x = 40000.0; y = 0.0;
|
||||
setprop(lw~"tiles/tile[5]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[5]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[5]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[5]/tile-index",-1);
|
||||
|
||||
x = -40000.0; y = -40000.0;
|
||||
setprop(lw~"tiles/tile[6]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[6]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[6]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[6]/tile-index",-1);
|
||||
|
||||
x = 0.0; y = -40000.0;
|
||||
setprop(lw~"tiles/tile[7]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[7]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[7]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[7]/tile-index",-1);
|
||||
|
||||
x = 40000.0; y = -40000.0;
|
||||
setprop(lw~"tiles/tile[8]/latitude-deg",blat + get_lat(x,y,phi));
|
||||
setprop(lw~"tiles/tile[8]/longitude-deg",blon + get_lon(x,y,phi));
|
||||
setprop(lw~"tiles/tile[8]/generated-flag",0);
|
||||
setprop(lw~"tiles/tile[8]/tile-index",-1);
|
||||
}
|
||||
|
||||
###################
|
||||
# global variables
|
||||
###################
|
||||
|
||||
# these already exist in different namespace, but for ease of typing we define them here as well
|
||||
|
||||
var lat_to_m = 110952.0; # latitude degrees to meters
|
||||
var m_to_lat = 9.01290648208234e-06; # meters to latitude degrees
|
||||
var ft_to_m = 0.30480;
|
||||
var m_to_ft = 1.0/ft_to_m;
|
||||
var inhg_to_hp = 33.76389;
|
||||
var hp_to_inhg = 1.0/inhg_to_hp;
|
||||
var lon_to_m = 0.0; #local_weather.lon_to_m;
|
||||
var m_to_lon = 0.0; # local_weather.m_to_lon;
|
||||
var lw = "/local-weather/";
|
||||
|
||||
# storage array for model vector
|
||||
|
||||
var mvec = [];
|
||||
var msize = 0;
|
||||
|
||||
###################
|
||||
# helper functions
|
||||
###################
|
||||
|
||||
var calc_geo = func(clat) {
|
||||
|
||||
lon_to_m = math.cos(clat*math.pi/180.0) * lat_to_m;
|
||||
m_to_lon = 1.0/lon_to_m;
|
||||
}
|
||||
|
||||
var get_lat = func (x,y,phi) {
|
||||
|
||||
return (y * math.cos(phi) - x * math.sin(phi)) * m_to_lat;
|
||||
}
|
||||
|
||||
var get_lon = func (x,y,phi) {
|
||||
|
||||
return (x * math.cos(phi) + y * math.sin(phi)) * m_to_lon;
|
||||
}
|
File diff suppressed because it is too large
Load diff
|
@ -3,8 +3,8 @@
|
|||
|
||||
varying float fogFactor;
|
||||
|
||||
float shade = 0.2;
|
||||
float cloud_height = 3000.0;
|
||||
float shade = 0.4;
|
||||
float cloud_height = 1000.0;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
@ -23,13 +23,15 @@ void main(void)
|
|||
// Do the matrix multiplication by [ u r w pos]. Assume no
|
||||
// scaling in the homogeneous component of pos.
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
gl_Position.xyz = gl_Vertex.x * u;
|
||||
gl_Position.xyz = gl_Vertex.x * u ;
|
||||
gl_Position.xyz += gl_Vertex.y * r * 1.0;
|
||||
gl_Position.xyz += gl_Vertex.z * w * 0.4;
|
||||
gl_Position.xyz += gl_Vertex.z * w * 1.0;//0.4;
|
||||
//gl_Position.xyz += gl_Vertex.y * r * wScale;
|
||||
//gl_Position.xyz += gl_Vertex.z * w * hScale;
|
||||
gl_Position.xyz += gl_Color.xyz;
|
||||
|
||||
gl_Position.z = gl_Position.z * 0.4;
|
||||
|
||||
// Determine a lighting normal based on the vertex position from the
|
||||
// center of the cloud, so that sprite on the opposite side of the cloud to the sun are darker.
|
||||
float n = dot(normalize(-gl_LightSource[0].position.xyz),
|
||||
|
@ -56,6 +58,6 @@ void main(void)
|
|||
gl_BackColor = gl_FrontColor;
|
||||
|
||||
// Fog doesn't affect clouds as much as other objects.
|
||||
fogFactor = exp( -gl_Fog.density * fogCoord * 0.2);
|
||||
fogFactor = exp( -gl_Fog.density * fogCoord * 0.5);
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
varying float fogFactor;
|
||||
|
||||
float shade = 0.5;
|
||||
float shade = 0.6;
|
||||
float cloud_height = 1000.0;
|
||||
|
||||
void main(void)
|
||||
|
|
11
Shaders/clouds-thinlayer.frag
Normal file
11
Shaders/clouds-thinlayer.frag
Normal file
|
@ -0,0 +1,11 @@
|
|||
uniform sampler2D baseTexture;
|
||||
varying float fogFactor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);
|
||||
vec4 finalColor = base * gl_Color;
|
||||
gl_FragColor.rgb = mix(gl_Fog.color.rgb, finalColor.rgb, fogFactor );
|
||||
gl_FragColor.a = mix(0.0, finalColor.a, fogFactor);
|
||||
}
|
||||
|
63
Shaders/clouds-thinlayer.vert
Normal file
63
Shaders/clouds-thinlayer.vert
Normal file
|
@ -0,0 +1,63 @@
|
|||
// -*-C++-*-
|
||||
#version 120
|
||||
|
||||
varying float fogFactor;
|
||||
|
||||
float shade = 0.7;
|
||||
float cloud_height = 1000.0;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
|
||||
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
|
||||
vec4 l = gl_ModelViewMatrixInverse * vec4(0.0,0.0,1.0,1.0);
|
||||
vec3 u = normalize(ep.xyz - l.xyz);
|
||||
|
||||
// Find a rotation matrix that rotates 1,0,0 into u. u, r and w are
|
||||
// the columns of that matrix.
|
||||
vec3 absu = abs(u);
|
||||
vec3 r = normalize(vec3(-u.y, u.x, 0));
|
||||
vec3 w = cross(u, r);
|
||||
|
||||
// Do the matrix multiplication by [ u r w pos]. Assume no
|
||||
// scaling in the homogeneous component of pos.
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
gl_Position.xyz = gl_Vertex.x * u ;
|
||||
gl_Position.xyz += gl_Vertex.y * r * 1.0;
|
||||
gl_Position.xyz += gl_Vertex.z * w * 1.0;//0.4;
|
||||
//gl_Position.xyz += gl_Vertex.y * r * wScale;
|
||||
//gl_Position.xyz += gl_Vertex.z * w * hScale;
|
||||
gl_Position.xyz += gl_Color.xyz;
|
||||
|
||||
gl_Position.z = gl_Position.z * 0.2;
|
||||
|
||||
// Determine a lighting normal based on the vertex position from the
|
||||
// center of the cloud, so that sprite on the opposite side of the cloud to the sun are darker.
|
||||
float n = dot(normalize(-gl_LightSource[0].position.xyz),
|
||||
normalize(mat3x3(gl_ModelViewMatrix) * (- gl_Position.xyz)));;
|
||||
|
||||
// Determine the position - used for fog and shading calculations
|
||||
vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Position);
|
||||
float fogCoord = abs(ecPosition.z);
|
||||
float fract = smoothstep(0.0, cloud_height, gl_Position.z + cloud_height);
|
||||
|
||||
// Final position of the sprite
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Position;
|
||||
|
||||
// Determine the shading of the sprite based on its vertical position and position relative to the sun.
|
||||
n = min(smoothstep(-0.5, 0.0, n), fract);
|
||||
// Determine the shading based on a mixture from the backlight to the front
|
||||
vec4 backlight = gl_LightSource[0].diffuse * shade;
|
||||
|
||||
gl_FrontColor = mix(backlight, gl_LightSource[0].diffuse, n);
|
||||
gl_FrontColor += gl_FrontLightModelProduct.sceneColor;
|
||||
|
||||
// As we get within 100m of the sprite, it is faded out. Equally at large distances it also fades out.
|
||||
gl_FrontColor.a = min(smoothstep(100.0, 300.0, fogCoord), 1 - smoothstep(25000.0, 30000.0, fogCoord));
|
||||
gl_BackColor = gl_FrontColor;
|
||||
|
||||
// Fog doesn't affect clouds as much as other objects.
|
||||
fogFactor = exp( -gl_Fog.density * fogCoord * 0.2);
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
}
|
11
Shaders/test.frag
Normal file
11
Shaders/test.frag
Normal file
|
@ -0,0 +1,11 @@
|
|||
uniform sampler2D baseTexture;
|
||||
varying float fogFactor;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec4 base = texture2D( baseTexture, gl_TexCoord[0].st);
|
||||
vec4 finalColor = base * gl_Color;
|
||||
gl_FragColor.rgb = mix(gl_Fog.color.rgb, finalColor.rgb, fogFactor );
|
||||
gl_FragColor.a = mix(0.0, finalColor.a, fogFactor);
|
||||
}
|
||||
|
91
Shaders/test.vert
Normal file
91
Shaders/test.vert
Normal file
|
@ -0,0 +1,91 @@
|
|||
// -*-C++-*-
|
||||
#version 120
|
||||
|
||||
varying float fogFactor;
|
||||
|
||||
//attribute vec3 usrAttr3;
|
||||
//attribute vec3 usrAttr4;
|
||||
|
||||
//float textureIndexX = usrAttr3.r;
|
||||
//float textureIndexY = usrAttr3.g;
|
||||
//float wScale = usrAttr3.b;
|
||||
//float hScale = usrAttr4.r;
|
||||
//float shade = usrAttr4.g;
|
||||
//float cloud_height = usrAttr4.b;
|
||||
|
||||
//float shade = usrAttr3.r;
|
||||
//float cloud_height = usrAttr3.g;
|
||||
//float scale = usrAttr3.b;
|
||||
|
||||
float shading;
|
||||
|
||||
float shade = 0.3;
|
||||
float cloud_height = 1000.0;
|
||||
float scale = 0.5;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
//shade = 0.1 * shade;
|
||||
//scale = 0.1 * scale;
|
||||
|
||||
gl_TexCoord[0] = gl_TextureMatrix[0] * gl_MultiTexCoord0;
|
||||
vec4 ep = gl_ModelViewMatrixInverse * vec4(0.0,0.0,0.0,1.0);
|
||||
vec4 l = gl_ModelViewMatrixInverse * vec4(0.0,0.0,1.0,1.0);
|
||||
vec3 view = normalize(ep.xyz - l.xyz);
|
||||
|
||||
vec4 posh = gl_ModelViewMatrixInverse * normalize(vec4(gl_Vertex.x,gl_Vertex.y,gl_Vertex.z,1.0));
|
||||
vec3 pos = normalize(ep.xyz - posh.xyz);
|
||||
|
||||
mat4 sprime = mat4(1.0,0.0,0.0,0.0,0.0,0.5,0.0,0.0,0.0,0.0,1.0,0.0,0.0,0.0,0.0,1.0);
|
||||
mat4 scale = gl_ModelViewMatrix * sprime * gl_ModelViewMatrixInverse;
|
||||
|
||||
float dist = sqrt(gl_Vertex.x * gl_Vertex.x + gl_Vertex.y * gl_Vertex.y + gl_Vertex.z * gl_Vertex.z);
|
||||
//vec3 u = normalize(smoothstep(500.0, 1500.0, dist) * pos + (1.0 - smoothstep(500.0, 1500.0, dist)) * view);
|
||||
//vec3 u = normalize(mix(pos, view, smoothstep(500.0,1500.0,dist)));
|
||||
vec3 u = view;
|
||||
|
||||
// Find a rotation matrix that rotates 1,0,0 into u. u, r and w are
|
||||
// the columns of that matrix.
|
||||
vec3 absu = abs(u);
|
||||
vec3 r = normalize(vec3(-u.y, u.x, 0));
|
||||
vec3 w = cross(u, r);
|
||||
|
||||
// Do the matrix multiplication by [ u r w pos]. Assume no
|
||||
// scaling in the homogeneous component of pos.
|
||||
gl_Position = vec4(0.0, 0.0, 0.0, 1.0);
|
||||
gl_Position.xyz = gl_Vertex.x * u;
|
||||
gl_Position.xyz += gl_Vertex.y * r * 1.0;
|
||||
gl_Position.xyz += gl_Vertex.z * w * scale;
|
||||
//gl_Position.xyz += gl_Vertex.y * r * wScale;
|
||||
//gl_Position.xyz += gl_Vertex.z * w * hScale;
|
||||
gl_Position.xyz += gl_Color.xyz;
|
||||
|
||||
// Determine a lighting normal based on the vertex position from the
|
||||
// center of the cloud, so that sprite on the opposite side of the cloud to the sun are darker.
|
||||
float n = dot(normalize(-gl_LightSource[0].position.xyz),
|
||||
normalize(mat3x3(gl_ModelViewMatrix) * (- gl_Position.xyz)));;
|
||||
|
||||
// Determine the position - used for fog and shading calculations
|
||||
vec3 ecPosition = vec3(gl_ModelViewMatrix * gl_Position);
|
||||
float fogCoord = abs(ecPosition.z);
|
||||
float fract = smoothstep(0.0, cloud_height, gl_Position.z + cloud_height);
|
||||
|
||||
// Final position of the sprite
|
||||
gl_Position = gl_ModelViewProjectionMatrix * gl_Position;
|
||||
|
||||
// Determine the shading of the sprite based on its vertical position and position relative to the sun.
|
||||
n = min(smoothstep(-0.5, 0.0, n), fract);
|
||||
// Determine the shading based on a mixture from the backlight to the front
|
||||
vec4 backlight = gl_LightSource[0].diffuse * shade;
|
||||
|
||||
gl_FrontColor = mix(backlight, gl_LightSource[0].diffuse, n);
|
||||
gl_FrontColor += gl_FrontLightModelProduct.sceneColor;
|
||||
|
||||
// As we get within 100m of the sprite, it is faded out. Equally at large distances it also fades out.
|
||||
gl_FrontColor.a = min(smoothstep(10.0, 100.0, fogCoord), 1 - smoothstep(15000.0, 20000.0, fogCoord));
|
||||
gl_BackColor = gl_FrontColor;
|
||||
|
||||
// Fog doesn't affect clouds as much as other objects.
|
||||
fogFactor = exp( -gl_Fog.density * fogCoord * 0.2);
|
||||
fogFactor = clamp(fogFactor, 0.0, 1.0);
|
||||
}
|
|
@ -74,9 +74,12 @@
|
|||
<value>Cirrus</value>
|
||||
<value>Cumulus</value>
|
||||
<value>Cumulonimbus</value>
|
||||
<value>Fog (thin)</value>
|
||||
<value>Fog (thick)</value>
|
||||
<value>Nimbus</value>
|
||||
<value>Stratus</value>
|
||||
<value>Stratus (structured)</value>
|
||||
<value>Stratus (thin)</value>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
|
@ -236,11 +239,15 @@
|
|||
<value>Altocumulus</value>
|
||||
<value>Cirrus</value>
|
||||
<value>Cumulus</value>
|
||||
<value>Cumulus (cloudlet)</value>
|
||||
<value>Cumulonimbus</value>
|
||||
<value>Cumulonimbus (rain)</value>
|
||||
<value>Fog (thin)</value>
|
||||
<value>Fog (thick)</value>
|
||||
<value>Nimbus</value>
|
||||
<value>Stratus</value>
|
||||
<value>Stratus (structured)</value>
|
||||
<value>Stratus (thin)</value>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
|
@ -647,10 +654,14 @@
|
|||
<value>Altocumulus</value>
|
||||
<value>Cirrus</value>
|
||||
<value>Cumulus</value>
|
||||
<value>Cumulus (cloudlet)</value>
|
||||
<value>Cumulonimbus</value>
|
||||
<value>Fog (thin)</value>
|
||||
<value>Fog (thick)</value>
|
||||
<value>Nimbus</value>
|
||||
<value>Stratus</value>
|
||||
<value>Stratus (structured)</value>
|
||||
<value>Stratus (thin)</value>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
|
|
|
@ -24,14 +24,23 @@
|
|||
<height>25</height>
|
||||
<live>true</live>
|
||||
<property>/local-weather/tmp/tile-type</property>
|
||||
<value>Altocumulus sky</value>
|
||||
<value>Broken layers</value>
|
||||
<value>Cirrus sky</value>
|
||||
<value>Fair weather</value>
|
||||
<value>High-pressure-core</value>
|
||||
<value>High-pressure</value>
|
||||
<value>High-pressure-border</value>
|
||||
<value>Low-pressure-border</value>
|
||||
<value>Low-pressure</value>
|
||||
<value>Low-pressure-core</value>
|
||||
<value>---</value>
|
||||
<!--<value>Altocumulus sky</value>-->
|
||||
<!--<value>Broken layers</value>-->
|
||||
<!--<value>Cirrus sky</value>-->
|
||||
<!--<value>Fair weather</value>-->
|
||||
<value>Glider's sky</value>
|
||||
<value>Incoming rainfront</value>
|
||||
<value>Overcast stratus sky</value>
|
||||
<value>Summer rain</value>
|
||||
<value>Blue thermals</value>
|
||||
<!--<value>Incoming rainfront</value>-->
|
||||
<!--<value>8/8 stratus sky</value>-->
|
||||
<!--<value>Test tile</value>-->
|
||||
<!--<value>Summer rain</value>-->
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
|
@ -44,27 +53,96 @@
|
|||
</text>
|
||||
|
||||
<input>
|
||||
<x>120</x>
|
||||
<x>115</x>
|
||||
<y>170</y>
|
||||
<width>50</width>
|
||||
<width>40</width>
|
||||
<height>25</height>
|
||||
<property>/local-weather/tmp/tile-orientation-deg</property>
|
||||
</input>
|
||||
|
||||
<text>
|
||||
<x>170</x>
|
||||
<x>155</x>
|
||||
<y>170</y>
|
||||
<label>alt. offset (ft)</label>
|
||||
</text>
|
||||
|
||||
<input>
|
||||
<x>250</x>
|
||||
<x>240</x>
|
||||
<y>170</y>
|
||||
<width>40</width>
|
||||
<width>50</width>
|
||||
<height>25</height>
|
||||
<property>/local-weather/tmp/tile-alt-offset-ft</property>
|
||||
</input>
|
||||
|
||||
<text>
|
||||
<x>10</x>
|
||||
<y>130</y>
|
||||
<label>tile selection mode</label>
|
||||
</text>
|
||||
|
||||
<combo>
|
||||
<x>150</x>
|
||||
<y>130</y>
|
||||
<width>140</width>
|
||||
<height>25</height>
|
||||
<live>true</live>
|
||||
<property>/local-weather/tmp/tile-management</property>
|
||||
<value>single tile</value>
|
||||
<value>repeat tile</value>
|
||||
<value>realistic weather</value>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</combo>
|
||||
|
||||
<checkbox>
|
||||
<x>10</x>
|
||||
<y>90</y>
|
||||
<width>15</width>
|
||||
<height>15</height>
|
||||
<label>Terrain presampling</label>
|
||||
<property>/local-weather/tmp/presampling-flag</property>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</checkbox>
|
||||
|
||||
<checkbox>
|
||||
<x>150</x>
|
||||
<y>90</y>
|
||||
<width>15</width>
|
||||
<height>15</height>
|
||||
<label>Worker threads</label>
|
||||
<property>/local-weather/tmp/thread-flag</property>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</checkbox>
|
||||
|
||||
<checkbox>
|
||||
<x>10</x>
|
||||
<y>60</y>
|
||||
<width>15</width>
|
||||
<height>15</height>
|
||||
<label>asymmetric range</label>
|
||||
<property>/local-weather/tmp/asymmetric-tile-loading-flag</property>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</checkbox>
|
||||
|
||||
<checkbox>
|
||||
<x>150</x>
|
||||
<y>60</y>
|
||||
<width>15</width>
|
||||
<height>15</height>
|
||||
<label>detailed clouds</label>
|
||||
<property>/local-weather/config/detailed-clouds-flag</property>
|
||||
<binding>
|
||||
<command>dialog-apply</command>
|
||||
</binding>
|
||||
</checkbox>
|
||||
|
||||
<group>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
|
|
654
gui/menubar.xml.alt
Normal file
654
gui/menubar.xml.alt
Normal file
|
@ -0,0 +1,654 @@
|
|||
<PropertyList>
|
||||
|
||||
<menu>
|
||||
<label>File</label>
|
||||
|
||||
<item>
|
||||
<label>Load</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.load_flight()</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Save</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.save_flight()</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Reset</label>
|
||||
<binding>
|
||||
<command>reset</command>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>High-Res Snapshot</label>
|
||||
<enabled>false</enabled>
|
||||
<binding>
|
||||
<command>hires-screen-capture</command>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Snapshot</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>
|
||||
var success = fgcommand("screen-capture");
|
||||
var path = getprop("/sim/paths/screenshot-last");
|
||||
if (success)
|
||||
gui.popupTip("Screenshot written to '" ~ path ~ "'");
|
||||
else
|
||||
gui.popupTip("Error writing screenshot '" ~ path ~ "'");
|
||||
</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Print Screen</label>
|
||||
<binding>
|
||||
<command>old-print-dialog</command>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Sound Configuration</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>sound-dialog</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Browse Internal Properties</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.property_browser()</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Logging</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>logging</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Quit</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>exit</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>View</label>
|
||||
|
||||
<item>
|
||||
<label>Display Options</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>display</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Rendering Options</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>rendering</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>View Options</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>view</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Cockpit View Options</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>cockpit-view</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Adjust View Position</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>pilot_offset</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Adjust HUD Properties</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>hud</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Instant Replay</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>replay</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Adjust LOD Ranges</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>static-lod</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>Location</label>
|
||||
|
||||
<item>
|
||||
<label>Position Aircraft (on ground)</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>location-on-ground</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Position Aircraft (in air)</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>location-in-air</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Select Airport from List</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>airports</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Random Attitude</label>
|
||||
<binding>
|
||||
<command>property-assign</command>
|
||||
<property>/sim/presets/trim</property>
|
||||
<value>false</value>
|
||||
</binding>
|
||||
<binding>
|
||||
<command>property-randomize</command>
|
||||
<property>/orientation/pitch-deg</property>
|
||||
<min>0</min>
|
||||
<max>360</max>
|
||||
</binding>
|
||||
<binding>
|
||||
<command>property-randomize</command>
|
||||
<property>/orientation/roll-deg</property>
|
||||
<min>0</min>
|
||||
<max>360</max>
|
||||
</binding>
|
||||
<binding>
|
||||
<command>property-randomize</command>
|
||||
<property>/orientation/heading-deg</property>
|
||||
<min>0</min>
|
||||
<max>360</max>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Tower position</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>location-of-tower</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>Autopilot</label>
|
||||
<name>autopilot</name>
|
||||
|
||||
<item>
|
||||
<label>Autopilot Settings</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>autopilot</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Route Manager</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>route-manager</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Pop Waypoint</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("/autopilot/route-manager/input", "@pop")</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Clear Route</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>setprop("/autopilot/route-manager/input", "@clear")</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Set Lat/Lon Format</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>
|
||||
var f = getprop(var d = "/sim/lon-lat-format") + 1;
|
||||
setprop(d, f < 0 ? 0 : f > 2 ? 0 : f);
|
||||
</script>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>Environment</label>
|
||||
|
||||
<item>
|
||||
<label>Weather Scenario</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>weather_scenario</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Weather Conditions</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>weather</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Clouds</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>clouds</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Time Settings</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>timeofday</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Rain/Snow Settings</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>rainsnow</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Wildfire Settings</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>wildfire.dialog.show()</script>
|
||||
</binding>
|
||||
</item>
|
||||
<item>
|
||||
<label>Local Weather</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>local_weather</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
<item>
|
||||
<label>Local Weather Tiles</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>local_weather_tiles</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>Equipment</label>
|
||||
|
||||
<item>
|
||||
<label>Fuel and Payload</label>
|
||||
<name>fuel-and-payload</name>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.showWeightDialog()</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Radio Settings</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>radios</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>GPS Settings</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>gps</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Instrument Settings</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>instruments</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Stopwatch</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>stopwatch-dialog</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Random Failures</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>random-failures</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>System Failures</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>system-failures</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Instrument Failures</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>instrument-failures</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>ATC/AI</label>
|
||||
|
||||
<item>
|
||||
<label>Frequencies</label>
|
||||
<binding>
|
||||
<command>ATC-freq-search</command>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Options</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>atc-ai</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Tanker</label>
|
||||
<name>tanker</name>
|
||||
<enabled>false</enabled>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>tanker</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>Network</label>
|
||||
<name>multiplayer</name>
|
||||
|
||||
<item>
|
||||
<label>Chat</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>chat-full</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Chat Menu</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>chat-menu</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Pilot List</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>multiplayer.dialog.show()</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>MPCarrier selection</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>
|
||||
if (contains(globals, "MPCarriers")) {
|
||||
MPCarriers.carrier_dialog.show();
|
||||
} else {
|
||||
gui.popupTip("No MPCarriers around at the moment.");
|
||||
}
|
||||
</script>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>Debug</label>
|
||||
|
||||
<item>
|
||||
<label>Reload GUI</label>
|
||||
<binding>
|
||||
<command>reinit</command>
|
||||
<subsystem>gui</subsystem>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Reload Input</label>
|
||||
<binding>
|
||||
<command>reinit</command>
|
||||
<subsystem>input</subsystem>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Reload Panel</label>
|
||||
<binding>
|
||||
<command>panel-load</command>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Reload Autopilot</label>
|
||||
<binding>
|
||||
<command>reinit</command>
|
||||
<subsystem>xml-autopilot</subsystem>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Reload Network</label>
|
||||
<binding>
|
||||
<command>reinit</command>
|
||||
<subsystem>io</subsystem>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Nasal Console</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>nasal-console</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Development Keys</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.showHelpDialog("/sim/help/debug")</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Configure Development Extensions</label>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>devel-extensions</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Display Tutorial Marker</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>tutorial.dialog()</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Dump Scene Graph</label>
|
||||
<binding>
|
||||
<command>dump-scenegraph</command>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Print Statistics</label>
|
||||
<binding>
|
||||
<command>property-assign</command>
|
||||
<property>/sim/rendering/print-statistics</property>
|
||||
<value>true</value>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Cycle On-Screen Statistics</label>
|
||||
<binding>
|
||||
<command>property-adjust</command>
|
||||
<property>/sim/rendering/on-screen-statistics</property>
|
||||
<step type="int">1</step>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
<menu>
|
||||
<label>Help</label>
|
||||
|
||||
<item>
|
||||
<label>Help</label>
|
||||
<binding>
|
||||
<command>old-help-dialog</command>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Joystick Information</label>
|
||||
<name>joystick-info</name>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>joystick-info</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Basic Keys</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.showHelpDialog("/sim/help/basic")</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Common Aircraft Keys</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.showHelpDialog("/sim/help/common")</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Aircraft Help</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>gui.showHelpDialog("/sim/help")</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Toggle Glide Slope Tunnel</label>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>
|
||||
var p = "/sim/rendering/glide-slope-tunnel";
|
||||
setprop(p, var i = !getprop(p));
|
||||
gui.popupTip("Glide slope tunnel " ~ (i ? "enabled" : "disabled"));
|
||||
</script>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>Start Tutorial</label>
|
||||
<name>tutorial-start</name>
|
||||
<binding>
|
||||
<command>dialog-show</command>
|
||||
<dialog-name>tutorial</dialog-name>
|
||||
</binding>
|
||||
</item>
|
||||
|
||||
<item>
|
||||
<label>End Tutorial</label>
|
||||
<name>tutorial-stop</name>
|
||||
<enabled>false</enabled>
|
||||
<binding>
|
||||
<command>nasal</command>
|
||||
<script>tutorial.stopTutorial()</script>
|
||||
</binding>
|
||||
</item>
|
||||
</menu>
|
||||
|
||||
</PropertyList>
|
Loading…
Reference in a new issue