Tutorials: Difference between revisions

Jump to navigation Jump to search
840 bytes added ,  20 April 2012
m
xml syntax highlighting
m (Robot: Cosmetic changes)
m (xml syntax highlighting)
Line 1: Line 1:
[[FlightGear]] offers a flexible '''tutorial''' system, entirely written in the [[Nasal]] language.
[[FlightGear]] offers a flexible '''tutorial''' system, entirely written in the [[Nasal]] scripting language.
Aircraft that provide support for these tutorials can be found in http://wiki.flightgear.org/index.php/Category:Interactive_Tutorial_Support
Aircraft that provide support for these scripted tutorials can be found in http://wiki.flightgear.org/index.php/Category:Interactive_Tutorial_Support




Tutorials can be started and stopped from the "Help" [[menubar|menu]]. They are defined in XML files. Each of them has to be loaded into <tt>/sim/tutorials/</tt> under a separate <tt>tutorial[n]/</tt> branch:
Tutorials can be started and stopped from the "Help" [[menubar|menu]]. They are defined in XML files. Each of them has to be loaded into <tt>/sim/tutorials/</tt> under a separate <tt>tutorial[n]/</tt> branch:
 
<syntaxhighlight lang="xml">
   <sim>
   <sim>
       <tutorials>
       <tutorials>
Line 11: Line 11:
       </tutorial>
       </tutorial>
   </sim>
   </sim>
</syntaxhighlight>


Alternatively, all tutorials can be defined in one file, with <tt><tutorial></tt> tags around each tutorial. This is then included like so:
Alternatively, all tutorials can be defined in a single file, with <tt><tutorial></tt> tags around each tutorial. This is then included like so:
 
<syntaxhighlight lang="xml">
   <sim>
   <sim>
       <tutorials include="foo-tutorials.xml"/>
       <tutorials include="foo-tutorials.xml"/>
   </sim>
   </sim>
</syntaxhighlight>


== Structure ==
== Structure ==
A tutorial has this structure, where some of the elements are described in detail below:
A tutorial has this structure, where some of the elements are described in detail below:


 
<syntaxhighlight lang="xml">
   <tutorial>
   <tutorial>
       <name>...</name>            mandatory; short identifier, also shown in the
       <name>...</name>            mandatory; short identifier, also shown in the
Line 132: Line 134:
       </end>
       </end>
   </tutorial>
   </tutorial>
</syntaxhighlight>


After the tutorial has finished initialization, it goes through all <steps>. For each it outputs the <message> or <audio>, optionally sets a <marker> and/or a <view>, then it checks all <error>s and, if an <error><condition> is fulfilled, outputs the respective <error><message>. If none of the <error>s occurred, then it checks if the <exit><condition> is true, and if so, it jumps to the next <step>. Otherwise the current <step> is endlessly repeated. Finally, after all <step>s were processed, the <end> group is executed.
After the tutorial has finished its initialization, it goes through all <steps>. For each, it outputs the <message> or <audio>, optionally sets a <marker> and/or a <view>, then it checks all <error>s and, if an <error><condition> is fulfilled, outputs the respective <error><message>. If none of the <error>s occurred, then it checks if the <exit><condition> is true, and if so, it jumps to the next <step>. Otherwise the current <step> is endlessly repeated. Finally, after all <step>s were processed, the <end> group is executed.


== Elements ==
== Elements ==
=== Nasal ===
=== Nasal ===
Embedded Nasal is supported on the top level, in <init> in each <step>, in a <step>'s <error> and <exit>, and in <end>. All Nasal runs in a separate namespace __tutorial, so it's possible to define a function in the <init>'s Nasal block, and to use this function in other blocks without prefix. The namespace is preloaded with some functions:
Embedded Nasal code is supported on the top level, in <init> in each <step>, in a <step>'s <error> and <exit>, and in <end>. All Nasal runs in a separate namespace __tutorial, so it's possible to define a function in the <init>'s Nasal block, and to use this function in other blocks without prefix. The namespace is preloaded with some functions:




Line 149: Line 152:
A Nasal group looks like this:
A Nasal group looks like this:


<syntaxhighlight lang="xml">
   <nasal>
   <nasal>
       <script>
       <script>
Line 155: Line 159:
       <module>__tutorial</module>          optional; preset with __tutorial
       <module>__tutorial</module>          optional; preset with __tutorial
   </nasal>
   </nasal>
</syntaxhighlight>


=== Models ===
=== Models ===
This loads models into the scenery. It can be used to place, for example, a helicopter landing pad at an airport where normally none is, so that the tutorial can train landing. The layout is the following, with <path> being relative to $FG_ROOT:
This loads models into the scenery. It can be used to place, for example, a helicopter landing pad at an airport where normally none is, so that the tutorial can train landing. The layout is the following, with <path> being relative to $FG_ROOT:


<syntaxhighlight lang="xml">
   <models>
   <models>
       <model>
       <model>
Line 174: Line 180:
       </model>
       </model>
   </models>
   </models>
</syntaxhighlight>


The models are only removed before a new tutorial is loaded. Otherwise they remain in the scenery for the whole FlightGear session. They aren't permanently added.
The models are only removed before a new tutorial is loaded. Otherwise they remain in the scenery for the whole FlightGear session. They aren't permanently added.
Line 180: Line 187:
These are simple pairs of longitude/latitude under an arbitrary name (here "hospital" and "helipad"):
These are simple pairs of longitude/latitude under an arbitrary name (here "hospital" and "helipad"):


<syntaxhighlight lang="xml">
   <targets>
   <targets>
       <hospital>
       <hospital>
Line 190: Line 198:
       </helipad>
       </helipad>
   </targets>
   </targets>
 
<syntaxhighlight>


The tutorial system will for each calculate how the user's aircraft is positioned relative to the respective target, and offer the information in this structure:
The tutorial system will for each calculate how the user's aircraft is positioned relative to the respective target, and offer the information in this structure:


<syntaxhighlight lang="xml">
   <sim>
   <sim>
       <tutorials>
       <tutorials>
Line 210: Line 219:
       </tutorials>
       </tutorials>
   </sim>
   </sim>
 
<syntaxhighlight>


Where:
Where:
Line 235: Line 244:
These set the initial simulator state. All properties are optional. The last three entries are to define the position relative to the airport/runway or the longitude/latitude.
These set the initial simulator state. All properties are optional. The last three entries are to define the position relative to the airport/runway or the longitude/latitude.


<syntaxhighlight lang="xml">
   <presets>
   <presets>
       <airport-id>KHAF</airport-id>
       <airport-id>KHAF</airport-id>
Line 250: Line 260:
       <offset-distance>0</offset-distance>
       <offset-distance>0</offset-distance>
   </presets>
   </presets>
</syntaxhighlight>


=== Set ===
=== Set ===
<set> groups can be used in <init>, <step>, and <end>. They set a <property> to a given <value> or to the value that a second <property> points to. They can also reset values that were only temporarily changed for the duration of the tutorial. This is desirable for properties that are saved to the aircraft config file or to ~/.fgfs/autosave.xml.
<set> groups can be used in <init>, <step>, and <end>. They set a <property> to a given <value> or to the value that a second <property> points to. They can also reset values that were only temporarily changed for the duration of the tutorial. This is desirable for properties that are saved to the aircraft config file or to ~/.fgfs/autosave.xml.


<syntaxhighlight lang="xml">
   <set>
   <set>
       <property>/foo/bar</property>        set /foo/bar to 123
       <property>/foo/bar</property>        set /foo/bar to 123
Line 263: Line 275:
       <property>/test</property>
       <property>/test</property>
   </set>
   </set>
</syntaxhighlight>


=== View ===
=== View ===
These groups can be used in <init>, <step>, and <end>. They smoothly move the view to a new view position/direction. All parameters are optional. If, for example, only <field-of-view> is set, then the view will only zoom in -- the direction and position will remain the same. This feature is meant for cockpit tutorials, where the pilot's view is directed to some switch or instrument.
These groups can be used in <init>, <step>, and <end>. They smoothly move the view to a new view position/direction. All parameters are optional. If, for example, only <field-of-view> is set, then the view will only zoom in -- the direction and position will remain the same. This feature is meant for cockpit tutorials, where the pilot's view is directed to some switch or instrument.


<syntaxhighlight lang="xml">
   <view>
   <view>
       <heading-offset-deg>20</heading-offset-deg>  positive is left
       <heading-offset-deg>20</heading-offset-deg>  positive is left
Line 276: Line 290:
       <field-of-view>55</field-of-view>            default: 55; smaller zooms in
       <field-of-view>55</field-of-view>            default: 55; smaller zooms in
   </view>     
   </view>     
</syntaxhighlight>


=== Marker ===
=== Marker ===
These are supported in <init>, <step>, and <end>. They show a magenta colored circle at given position (relative to aircraft origin) in given size. See the last section for how to conveniently find the proper coordinates.
These are supported in <init>, <step>, and <end>. They show a magenta colored circle at given position (relative to aircraft origin) in given size. See the last section for how to conveniently find the proper coordinates.


<syntaxhighlight lang="xml">
   <marker>
   <marker>
       <x-m>1.3</x-m>                              positive is back
       <x-m>1.3</x-m>                              positive is back
Line 286: Line 302:
       <scale>1.3</scale>                          optional; default: 1
       <scale>1.3</scale>                          optional; default: 1
   </marker>
   </marker>
 
</syntaxhighlight>


For this to work, the aircraft model needs to include the tutorial marker model in its animation xml file:
For this to work, the aircraft model needs to include the tutorial marker model in its animation xml file:


<syntaxhighlight lang="xml">
   <PropertyList>
   <PropertyList>
       <path>lightning-f1a.ac</path>
       <path>lightning-f1a.ac</path>
Line 299: Line 316:
       ...
       ...
   </PropertyList>
   </PropertyList>
</syntaxhighlight


==== Finding marker coordinates ====
==== Finding marker coordinates ====
If an aircraft tutorial wants to use the marker, then the aircraft animation file needs to include the marker model (see above). If this is done, then one can use the "marker-adjust" dialog to find the respective <marker> coordinates. Just type this into the "Help->Nasal Console" dialog:
If an aircraft tutorial wants to use the marker, then the aircraft animation file needs to include the marker model (see above). If this is done, then one can use the "marker-adjust" dialog to find the respective <marker> coordinates. Just type this into the "Help->Nasal Console" dialog:


<syntaxhighlight lang="php">
   tutorial.dialog()
   tutorial.dialog()
</syntaxhighlight>




Or temporarily add a key binding to the *-set.xml file:
Or temporarily add a key binding to the *-set.xml file:


<syntaxhighlight lang="xml">
   <key n="96">
   <key n="96">
       <name>Backtick</name>
       <name>Backtick</name>
Line 316: Line 337:
       </binding>
       </binding>
   </key>
   </key>
 
</syntaxhighlight>


The dialog allows to move a red cross around, which has the blinking marker circle in the middle. Note that ctrl- and shift-modifiers modulate the slider movements. Ctrl makes positioning coarser, and shift finer. The [Reset] button moves the marker back to aircraft origin, the [Center] button centers the sliders, and the [Dump] button dumps the marker coordinates to the terminal, for example:
The dialog allows to move a red cross around, which has the blinking marker circle in the middle. Note that ctrl- and shift-modifiers modulate the slider movements. Ctrl makes positioning coarser, and shift finer. The [Reset] button moves the marker back to aircraft origin, the [Center] button centers the sliders, and the [Dump] button dumps the marker coordinates to the terminal, for example:


<syntaxhighlight lang="xml">
   <marker>
   <marker>
       <x-m>1.1425</x-m>
       <x-m>1.1425</x-m>
Line 326: Line 348:
       <scale>2.0489</scale>
       <scale>2.0489</scale>
   </marker>
   </marker>
</syntaxhighlight>


This just needs to be copied to the tutorial XML file.
This just needs to be copied to the tutorial XML file.
Line 334: Line 357:
Because one and the same <message> string can be displayed *and* be synthesized, which can be problematic in some cases, there is a way to specify parts for either display *or* voice synthesizer: "{<display part>|<voice part}". Example:
Because one and the same <message> string can be displayed *and* be synthesized, which can be problematic in some cases, there is a way to specify parts for either display *or* voice synthesizer: "{<display part>|<voice part}". Example:


<syntaxhighlight lang="xml">
   <message>Press the {No1|number one} button!</message>
   <message>Press the {No1|number one} button!</message>
</syntaxhighlight>


Here, "No1" would be displayed on the screen, but "number one" would be sent to the speech synthesis system. This can also be used to add invisible but audible exclamation marks: "Press the button{|!}"
Here, "No1" would be displayed on the screen, but "number one" would be sent to the speech synthesis system. This can also be used to add invisible but audible exclamation marks: "Press the button{|!}"
Line 341: Line 366:
These are explained in detail in $FG_ROOT/Docs/README.conditions. Here's just one example:
These are explained in detail in $FG_ROOT/Docs/README.conditions. Here's just one example:


<syntaxhighlight lang="xml">
   <condition>
   <condition>
       <less-than>
       <less-than>
Line 347: Line 373:
       </less-than>
       </less-than>
   </condition>
   </condition>
</syntaxhighlight>


This condition is true when the value of /foo/bar is less than 12, and false otherwise.
This condition is true when the value of /foo/bar is less than 12, and false otherwise.

Navigation menu