<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.flightgear.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Melchior+FRANZ</id>
	<title>FlightGear wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.flightgear.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Melchior+FRANZ"/>
	<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/Special:Contributions/Melchior_FRANZ"/>
	<updated>2026-04-09T02:47:58Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.6</generator>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=12341</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=12341"/>
		<updated>2009-05-01T16:09:10Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: Reverted edits by Scotth1 (Talk); changed back to last version by Melchior FRANZ&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11718</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11718"/>
		<updated>2009-04-01T21:02:58Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;           # same as airport.LOXL!&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace (''data''), its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
In the section about hashes it was said that hash members can be accessed in two alternative ways, and that's also true for methods. &amp;lt;tt&amp;gt;object.write()&amp;lt;/tt&amp;gt; could also be called as &amp;lt;tt&amp;gt;object[&amp;quot;write&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first form will members also be searched in parent hashes if not found in the base hash, whereas the second form creates an error if it's not a direct member.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handling ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11648</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11648"/>
		<updated>2009-03-27T22:20:15Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: fix bug in multiple-inheritance example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value),&lt;br /&gt;
 },&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11647</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11647"/>
		<updated>2009-03-27T22:16:16Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: some more multiple-inheritance tweaks&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more other classes. It can then access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test() and B.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.test()               # use C.test()&lt;br /&gt;
 c.parents[0].test();   # use C.test()&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11646</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11646"/>
		<updated>2009-03-27T21:54:35Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: fix heading&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class that inherits from one or more other classes can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11645</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11645"/>
		<updated>2009-03-27T21:49:56Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: another wording fix  (saving often so as not to get thrown out by the annoying wiki software)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class that inherits from one or more other classes can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by built-in extension functions or Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11644</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11644"/>
		<updated>2009-03-27T21:42:09Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: wording&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class that inherits from one or more other classes can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11643</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11643"/>
		<updated>2009-03-27T21:32:33Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: remove garbage&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11642</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11642"/>
		<updated>2009-03-27T21:29:34Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: move &amp;quot;exception handling&amp;quot; block before listeners&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11641</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11641"/>
		<updated>2009-03-27T21:24:54Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: /* Exception handing */ : make Error really a class (with parents)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { parents: [Error], message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11640</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11640"/>
		<updated>2009-03-27T21:13:28Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: cosmetics&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11639</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11639"/>
		<updated>2009-03-27T21:05:26Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: /* Exception handing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, dies with an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception and sets the 'err' vector instead. That vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11638</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11638"/>
		<updated>2009-03-27T20:58:49Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: fixes to &amp;quot;more on methods&amp;quot;; move that block down&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to the return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... triggered at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message.&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11637</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11637"/>
		<updated>2009-03-27T20:42:23Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: /* More on methods */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11636</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11636"/>
		<updated>2009-03-27T19:51:29Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: more info about methods; improve multiple inheritance example&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== More on methods ===&lt;br /&gt;
&lt;br /&gt;
Methods are function members of a class hash. They can access other class members via the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable, which is a reference to the class hash. For this reason, a method returning &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; can be used like the class itself, and one can apply further methods to return value:&lt;br /&gt;
&lt;br /&gt;
 var Object = {&lt;br /&gt;
     new: func(coords...) {&lt;br /&gt;
         return { parents: [Object], coords: coords };&lt;br /&gt;
     },&lt;br /&gt;
     rotate: func(angle) {&lt;br /&gt;
         # do the rotation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     scale: func(factor) {&lt;br /&gt;
         # do the scaling&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
     translate: func(x, y) {&lt;br /&gt;
         # do the translation&lt;br /&gt;
         return me;&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var triangle = Object.new([0, 0], [10, 0], [5, 7]);&lt;br /&gt;
 triangle.translate(-9, -4).scale(5).rotate(33).translate(9, 4);    # concatenated methods thanks to &amp;quot;me&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;, however, is only known in the scope of the class. If a method is to be called as a listener callback or a timer function, &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; has to get wrapped in a function, so that it's stored in the function closure.&lt;br /&gt;
&lt;br /&gt;
 var Manager = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [Manager] };&lt;br /&gt;
     },&lt;br /&gt;
     start_timers: func {  &lt;br /&gt;
         settimer(do_stuff, 5);            # BAD: there's no &amp;quot;do_stuff&amp;quot; function in the scope&lt;br /&gt;
         settimer(me.do_stuff, 5);         # BAD: function exists, but &amp;quot;me&amp;quot; won't be known&lt;br /&gt;
                                           #      when the timer function is actually executed&lt;br /&gt;
         settimer(func me.do_stuff(), 5);  # GOOD: new function object packs &amp;quot;me&amp;quot; in the closure&lt;br /&gt;
 &lt;br /&gt;
         setlistener(&amp;quot;/sim/foo&amp;quot;, func me.do_stuff());  # GOOD  (same as with timers) &lt;br /&gt;
         return m;&lt;br /&gt;
     },         &lt;br /&gt;
     do_stuff: func {&lt;br /&gt;
         print(&amp;quot;doing stuff&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var manager = Manager.new();&lt;br /&gt;
 manager.start_timers();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                            # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                            # simple class B&lt;br /&gt;
     new: func(v) {                                   # ... whose constructor takes an argument&lt;br /&gt;
         return { parents: [B], value: v };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test:  func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
     write: func print(&amp;quot;\tmy value is: &amp;quot;, me.value);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                            # class C that inherits ...&lt;br /&gt;
     new: func(v) {&lt;br /&gt;
         return { parents: [C, A.new(), B.new(v)] };  # ... from class A and B&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test:    func print(&amp;quot;\tthis is C.test&amp;quot;),         # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new(123);&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 b.write();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new(456);&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
 c.write();&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[1].test();   # use A.test()&lt;br /&gt;
 c.parents[2].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11631</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11631"/>
		<updated>2009-03-27T02:12:10Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: /* Exception handing */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class C that inherits&lt;br /&gt;
     parents: [A, B],                         # from classes A and B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),    # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
 c.parents[0].parents[1].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line is not reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot;; bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11630</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11630"/>
		<updated>2009-03-27T02:03:47Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: /* Multiple inheritance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class C that inherits&lt;br /&gt;
     parents: [A, B],                         # from classes A and B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),    # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
 c.parents[0].parents[1].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line isn't reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot; (bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11629</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11629"/>
		<updated>2009-03-27T02:03:07Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: /* Multiple inheritance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class that inherits&lt;br /&gt;
     parents: [A, B],                         # from A and B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),    # overrides A.test() and B.test()&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
 c.parents[0].parents[1].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line isn't reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot; (bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11628</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11628"/>
		<updated>2009-03-27T02:01:14Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: /* Multiple inheritance */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is B.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class that inherits&lt;br /&gt;
     parents: [A, B],                         # from A and B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),   # overrides A.test&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
 c.parents[0].parents[1].test();   # use B.test()&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line isn't reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot; (bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11627</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11627"/>
		<updated>2009-03-27T01:56:46Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class that inherits&lt;br /&gt;
     parents: [A, B],                         # from A and B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),   # overrides A.test&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line isn't reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot; (bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11626</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11626"/>
		<updated>2009-03-27T01:55:40Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class that inherits from A and B&lt;br /&gt;
     parents: [A, B],&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),   # overrides A.test&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; aborts a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''&amp;quot;name must begin with alpha or '_'&amp;quot;''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the property's value in a popup dialog. What if the user typed an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display a nice error message instead. The &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function can catch &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; exceptions:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);      # catches invalid-property-exception and continues&lt;br /&gt;
&lt;br /&gt;
The second line calls getprop(property) just like the first, and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead, while that vector remains empty on success.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {                                                             # exception class&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw Error&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line isn't reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try B(-4)&lt;br /&gt;
 &lt;br /&gt;
 if (size(err)) {                                                          # catch (...)&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot; (bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11625</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11625"/>
		<updated>2009-03-27T01:41:31Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: add subsection about exception handling (call/die)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class that inherits from A and B&lt;br /&gt;
     parents: [A, B],&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),   # overrides A.test&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exception handing ==&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; function can be used to abort a function with an error message:&lt;br /&gt;
&lt;br /&gt;
 var divide = func(a, b) {&lt;br /&gt;
     if (b == 0)&lt;br /&gt;
         die(&amp;quot;division by zero&amp;quot;);&lt;br /&gt;
     return a / b;     # this line won't be reached if b == 0&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
die() is also used internally by Nasal core functions. &amp;lt;tt&amp;gt;getprop(&amp;quot;/4me&amp;quot;)&amp;lt;/tt&amp;gt;, for example, issues an error message ''name must begin with alpha or '_' ''. Now assume we want to write a dialog where the user can type a property path into an input field, and we display the value of this property. What if the user types an invalid path and we hand that over to &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt;? We don't want Nasal to abort our code because of that. We want to display an error message instead. This can be done with the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
 var value = getprop(property);                                    # dies if 'property' is invalid&lt;br /&gt;
 var value = call(func getprop(property), nil, var err = []);&lt;br /&gt;
&lt;br /&gt;
The second line also calls getprop(property), and returns its value. But if 'property' was invalid then the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; catches the exception (&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt;) and sets the 'err' vector instead. Otherwise the vector remains empty.&lt;br /&gt;
&lt;br /&gt;
 if (size(err))&lt;br /&gt;
     print(&amp;quot;ERROR: bad property &amp;quot;, property, &amp;quot; (&amp;quot;, err[0], &amp;quot;)&amp;quot;);   # err[0] contains the die() message&lt;br /&gt;
 else&lt;br /&gt;
     print(&amp;quot;value of &amp;quot;, property, &amp;quot; is &amp;quot;, value);&lt;br /&gt;
&lt;br /&gt;
The first argument of &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; is a function object, the second a vector of function arguments (or ''nil''), and the third a vector where the function will return a possible error. For more information on the &amp;lt;tt&amp;gt;call()&amp;lt;/tt&amp;gt; function see the [http://plausible.org/nasal/lib.html Nasal library documentation]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;die()&amp;lt;/tt&amp;gt; doesn't really care about what its argument is. It doesn't have to be a string, and can be any variable, for example a class. This can be used to pass values through a chain of functions.&lt;br /&gt;
&lt;br /&gt;
 var Error = {&lt;br /&gt;
     new: func(msg, number) {&lt;br /&gt;
         return { message: msg, number: number };&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var A = func(a) {&lt;br /&gt;
     if (a &amp;lt; 0)&lt;br /&gt;
         die(Error.new(&amp;quot;negative argument to A&amp;quot;, a));                      # throw&lt;br /&gt;
     return &amp;quot;A received &amp;quot; ~ a;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var B = func(val) {&lt;br /&gt;
     var result = A(val);&lt;br /&gt;
     print(&amp;quot;B finished&amp;quot;);      # this line isn't reached if A threw an exception&lt;br /&gt;
     return result;&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var value = call(B, [-4], var err = []);                                  # try&lt;br /&gt;
&lt;br /&gt;
 if (size(err)) {                                                          # catch&lt;br /&gt;
     print(&amp;quot;ERROR: &amp;quot;, err[0].message, &amp;quot; (bad value was &amp;quot;, err[0].number);&lt;br /&gt;
     die(err[0]);                                                          # re-throw&lt;br /&gt;
 } else {&lt;br /&gt;
     print(&amp;quot;SUCCESS: &amp;quot;, value);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11624</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11624"/>
		<updated>2009-03-27T00:55:48Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: better example for multiple inheritance&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from one or more classes, that is: it can access all methods and class members of all parent classes, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var A = {                                    # simple class A&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is A.test&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var B = {                                    # simple class B&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;);&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var C = {                                    # class that inherits from A and B&lt;br /&gt;
     parents: [A, B],&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
     test: func print(&amp;quot;\tthis is C.test&amp;quot;),   # overrides A.test&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
 &lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();                        # use alpha from the A parent&lt;br /&gt;
 c.bravo();                        # use bravo from the B parent&lt;br /&gt;
 c.charlie();                      # use charlie from C itself&lt;br /&gt;
 c.test();                         # use C.test(), which overrides A.test()&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 c.parents[0].parents[0].test();   # use A.test()&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11623</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11623"/>
		<updated>2009-03-27T00:44:55Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Single Inheritance/Subclassing ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from another class, that is: it can access all methods and class members of the parent class, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name),&lt;br /&gt;
     printtype: func print(&amp;quot;TYPE: aircraft&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     parents: [Aircraft],           # Helicopters are also Aircraft&lt;br /&gt;
&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = { parents: [Helicopter] };&lt;br /&gt;
         m.name = name;&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors),&lt;br /&gt;
     printtype: func print(&amp;quot;TYPE: helicopter&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                            # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].parents[0].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
As we noted above, an object can have more than one parent. &lt;br /&gt;
&lt;br /&gt;
 var A = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [A] };&lt;br /&gt;
     },&lt;br /&gt;
     alpha: func print(&amp;quot;\tALPHA&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var B = {&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [B] };&lt;br /&gt;
     },&lt;br /&gt;
     bravo: func print(&amp;quot;\tBRAVO&amp;quot;);&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var C = {&lt;br /&gt;
     parents: [A, B],&lt;br /&gt;
     new: func {&lt;br /&gt;
         return { parents: [C] };&lt;br /&gt;
     },&lt;br /&gt;
     charlie: func print(&amp;quot;\tCHARLIE&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;A instance&amp;quot;);&lt;br /&gt;
 var a = A.new();&lt;br /&gt;
 a.alpha();&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;B instance&amp;quot;);&lt;br /&gt;
 var b = B.new();&lt;br /&gt;
 b.bravo();&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;C instance&amp;quot;);&lt;br /&gt;
 var c = C.new();&lt;br /&gt;
 c.alpha();&lt;br /&gt;
 c.bravo();&lt;br /&gt;
 c.charlie();&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11622</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11622"/>
		<updated>2009-03-27T00:33:40Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Single Inheritance/Subclassing ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from another class, that is: it can access all methods and class members of the parent class, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name),&lt;br /&gt;
     printtype: func print(&amp;quot;TYPE: aircraft&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     parents: [Aircraft],           # Helicopters are also Aircraft&lt;br /&gt;
&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = { parents: [Helicopter] };&lt;br /&gt;
         m.name = name;&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors),&lt;br /&gt;
     printtype: func print(&amp;quot;TYPE: helicopter&amp;quot;),&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                           # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].parents[1]printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
As we noted above, an object can have more than one parent. &lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func {&lt;br /&gt;
         print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: aircraft&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = Aircraft.new(name);&lt;br /&gt;
         m.parents = [Helicopter, Aircraft];&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func {&lt;br /&gt;
         print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: helicopter&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via parents vector. &lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                 # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].printtype();      # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[1].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11621</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=11621"/>
		<updated>2009-03-26T22:25:28Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: intermediate saving: inheritance fixes &amp;amp; cleanup; more to come&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;[http://wiki.flightgear.org/index.php/Talk:Nasal_scripting_language discussion]&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various [[XML]] files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
Note that this page is mostly about FlightGear-specific APIs/extension functions and usage pattern. See the Nasal webpage for [http://plausible.org/nasal/lib.html core language/library documentation] and [http://plausible.org/nasal/sample.nas source code examples].&lt;br /&gt;
&lt;br /&gt;
In addition, the 'Nasal' directory in the FlightGear base package contains a wealth of tested, proven and usually well-commented source code that you may want to check out for additional examples of using the Nasal scripting language in FlightGear [http://cvs.flightgear.org/viewvc/data/Nasal/].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;. There is a difference, though, which is described in the next section.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can reference their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the first case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt; and, if not found, in parent hashes (see next section), whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; does now have its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
Because the class generating function &amp;lt;tt&amp;gt;new_class()&amp;lt;/tt&amp;gt; really belongs to class &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, it would be nicer to put it into the class hash as well. In this case we call it a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name ''new''. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Single Inheritance/Subclassing ===&lt;br /&gt;
&lt;br /&gt;
A class can inherit from another class, that is: it can access all methods and class members of the parent class, but also override them and add additional members.&lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func {&lt;br /&gt;
         print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: aircraft&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     parents: [Aircraft],           # Helicopters are also Aircraft&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = { parents: [Helicopter] };&lt;br /&gt;
         m.name = name;&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func {&lt;br /&gt;
         print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: helicopter&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                 # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].printtype();      # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[1].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
As we noted above, an object can have more than one parent. &lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func {&lt;br /&gt;
         print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: aircraft&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = Aircraft.new(name);&lt;br /&gt;
         m.parents = [Helicopter, Aircraft];&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func {&lt;br /&gt;
         print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: helicopter&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via parents vector. &lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                 # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].printtype();      # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[1].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Walk_view&amp;diff=11617</id>
		<title>Walk view</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Walk_view&amp;diff=11617"/>
		<updated>2009-03-26T19:08:58Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: don't query same property multiple times; don't use fixed view index numbers, but view names&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{stub}}&lt;br /&gt;
&lt;br /&gt;
==Easy walk==&lt;br /&gt;
This is the most easy walk mode: you just walk at the same level (compared to the plane) and you will not fall if you get outside the plane.&lt;br /&gt;
===walk.nas===&lt;br /&gt;
 # view nodes and offsets --------------------------------------------&lt;br /&gt;
 var zNoseNode = props.globals.getNode(&amp;quot;sim/view/config/y-offset-m&amp;quot;, 1);&lt;br /&gt;
 var xViewNode = props.globals.getNode(&amp;quot;sim/current-view/z-offset-m&amp;quot;, 1);&lt;br /&gt;
 var yViewNode = props.globals.getNode(&amp;quot;sim/current-view/x-offset-m&amp;quot;, 1);&lt;br /&gt;
 var hViewNode = props.globals.getNode(&amp;quot;sim/current-view/heading-offset-deg&amp;quot;, 1);&lt;br /&gt;
 &lt;br /&gt;
 var walk_about = func(wa_distance) {&lt;br /&gt;
 	var i = getprop(&amp;quot;sim/current-view/view-number&amp;quot;);&lt;br /&gt;
 	if (i == view.indexof(&amp;quot;Pilot View&amp;quot;) or i == view.indexof(&amp;quot;Model View&amp;quot;) or i == view.indexof(&amp;quot;View 8&amp;quot;)) {&lt;br /&gt;
 		var wa_heading_rad = hViewNode.getValue() * 0.01745329252;&lt;br /&gt;
 		var new_x_position = xViewNode.getValue() - (math.cos(wa_heading_rad) * wa_distance);&lt;br /&gt;
 		var new_y_position = yViewNode.getValue() - (math.sin(wa_heading_rad) * wa_distance);&lt;br /&gt;
 		xViewNode.setValue(new_x_position);&lt;br /&gt;
 		yViewNode.setValue(new_y_position);&lt;br /&gt;
 	}&lt;br /&gt;
 }&lt;br /&gt;
===-set.xml===&lt;br /&gt;
 &amp;lt;input&amp;gt;&lt;br /&gt;
  &amp;lt;keyboard&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;119&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;w&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;desc&amp;gt;Walk forward toward view&amp;lt;/desc&amp;gt;&lt;br /&gt;
     &amp;lt;repeatable&amp;gt;true&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
     &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;walk.walk_about(0.1)&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;/binding&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;87&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;name&amp;gt;W&amp;lt;/name&amp;gt;&lt;br /&gt;
    &amp;lt;desc&amp;gt;Walk backward from view&amp;lt;/desc&amp;gt;&lt;br /&gt;
    &amp;lt;repeatable&amp;gt;true&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
    &amp;lt;binding&amp;gt;&lt;br /&gt;
     &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
     &amp;lt;script&amp;gt;walk.walk_about(-0.1)&amp;lt;/script&amp;gt;&lt;br /&gt;
    &amp;lt;/binding&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
  &amp;lt;/keyboard&amp;gt;&lt;br /&gt;
 &amp;lt;/input&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Advanced walk with jump and parachute==&lt;br /&gt;
This advanced mode is way more complicated than the easy walk (see above). With this mode you can jump out of the plane and land with a parachute.&lt;br /&gt;
===walk.nas===&lt;br /&gt;
''See the [[Pilatus PC-6 Porter‎]]'s &amp;lt;tt&amp;gt;PC-6/Nasal/walk.nas&amp;lt;/tt&amp;gt;''&lt;br /&gt;
&lt;br /&gt;
===-set.xml===&lt;br /&gt;
 &amp;lt;walker&amp;gt;&lt;br /&gt;
  &amp;lt;outside type=&amp;quot;bool&amp;quot;&amp;gt;false&amp;lt;/outside&amp;gt;&lt;br /&gt;
  &amp;lt;walking type=&amp;quot;bool&amp;quot;&amp;gt;false&amp;lt;/walking&amp;gt;&lt;br /&gt;
  &amp;lt;speed type=&amp;quot;double&amp;quot;&amp;gt;0.000006&amp;lt;/speed&amp;gt;&lt;br /&gt;
  &amp;lt;latitude-deg type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/latitude-deg&amp;gt;&lt;br /&gt;
  &amp;lt;longitude-deg type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/longitude-deg&amp;gt;&lt;br /&gt;
  &amp;lt;altitude-at-exit-ft type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/altitude-at-exit-ft&amp;gt;&lt;br /&gt;
  &amp;lt;altitude-ft type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/altitude-ft&amp;gt;&lt;br /&gt;
  &amp;lt;heading-deg type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/heading-deg&amp;gt;&lt;br /&gt;
  &amp;lt;pitch-deg type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/pitch-deg&amp;gt;&lt;br /&gt;
  &amp;lt;roll-deg type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/roll-deg&amp;gt;&lt;br /&gt;
  &amp;lt;internal&amp;gt;&lt;br /&gt;
   &amp;lt;x-offset-m type=&amp;quot;double&amp;quot;&amp;gt;4.3&amp;lt;/x-offset-m&amp;gt;&lt;br /&gt;
   &amp;lt;y-offset-m type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/y-offset-m&amp;gt;&lt;br /&gt;
   &amp;lt;z-offset-m type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/z-offset-m&amp;gt;&lt;br /&gt;
   &amp;lt;heading-deg type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/heading-deg&amp;gt;&lt;br /&gt;
  &amp;lt;/internal&amp;gt;&lt;br /&gt;
  &amp;lt;keep-inside-offset-x type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/keep-inside-offset-x&amp;gt;&lt;br /&gt;
  &amp;lt;keep-inside-offset-y type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/keep-inside-offset-y&amp;gt;&lt;br /&gt;
  &amp;lt;keep-inside-offset-z type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/keep-inside-offset-z&amp;gt;&lt;br /&gt;
  &amp;lt;keep-pitch-offset-deg type=&amp;quot;double&amp;quot;&amp;gt;0.0&amp;lt;/keep-pitch-offset-deg&amp;gt;&lt;br /&gt;
  &amp;lt;key-triggers&amp;gt;&lt;br /&gt;
   &amp;lt;forward type=&amp;quot;double&amp;quot;&amp;gt;0&amp;lt;/forward&amp;gt;&lt;br /&gt;
   &amp;lt;outside-toggle type=&amp;quot;bool&amp;quot;&amp;gt;0&amp;lt;/outside-toggle&amp;gt;&lt;br /&gt;
   &amp;lt;slide type=&amp;quot;double&amp;quot;&amp;gt;0&amp;lt;/slide&amp;gt;&lt;br /&gt;
  &amp;lt;/key-triggers&amp;gt;&lt;br /&gt;
  &amp;lt;parachute-opened-altitude-ft type=&amp;quot;double&amp;quot;&amp;gt;0&amp;lt;/parachute-opened-altitude-ft&amp;gt;&lt;br /&gt;
  &amp;lt;parachute-opened-sec type=&amp;quot;double&amp;quot;&amp;gt;0&amp;lt;/parachute-opened-sec&amp;gt;&lt;br /&gt;
  &amp;lt;starting-trajectory-lat type=&amp;quot;double&amp;quot;&amp;gt;0&amp;lt;/starting-trajectory-lat&amp;gt;&lt;br /&gt;
  &amp;lt;starting-trajectory-lon type=&amp;quot;double&amp;quot;&amp;gt;0&amp;lt;/starting-trajectory-lon&amp;gt;&lt;br /&gt;
  &amp;lt;time-of-exit-sec type=&amp;quot;double&amp;quot;&amp;gt;0&amp;lt;/time-of-exit-sec&amp;gt;&lt;br /&gt;
 &amp;lt;/walker&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;keyboard&amp;gt;&lt;br /&gt;
  &amp;lt;/input&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;111&amp;quot;&amp;gt;&lt;br /&gt;
   	&amp;lt;name&amp;gt;o&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Toggle walker outside/inside&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-toggle&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/outside-toggle&amp;lt;/property&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;119&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;w&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Walk forward&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/forward&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;binding n=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/speed&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;0.000006&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;mod-up&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/key-triggers/forward&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding n=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/speed&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0.000006&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;/mod-up&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;87&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;W&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Run forward&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/forward&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;binding n=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/speed&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;0.000018&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;mod-up&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding n=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/key-triggers/forward&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding n=&amp;quot;1&amp;quot;&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/speed&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0.000006&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;/mod-up&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;115&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;s&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Walk backward&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/forward&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;-1&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;mod-up&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/key-triggers/forward&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;/mod-up&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;97&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;a&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Slide left&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;-1&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;mod-up&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;/mod-up&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;65&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;A&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Slide left2, override default assignment&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;-1&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;mod-up&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;/mod-up&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;100&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;d&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Slide right&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;mod-up&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;/mod-up&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;68&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;D&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;Slide right2&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   &amp;lt;value&amp;gt;1&amp;lt;/value&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;mod-up&amp;gt;&lt;br /&gt;
   	   &amp;lt;binding&amp;gt;&lt;br /&gt;
   	   	&amp;lt;command&amp;gt;property-assign&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   	&amp;lt;property&amp;gt;sim/walker/key-triggers/slide&amp;lt;/property&amp;gt;&lt;br /&gt;
   	   	&amp;lt;value&amp;gt;0&amp;lt;/value&amp;gt;&lt;br /&gt;
   	   &amp;lt;/binding&amp;gt;&lt;br /&gt;
   	&amp;lt;/mod-up&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
   &amp;lt;key n=&amp;quot;114&amp;quot;&amp;gt; &lt;br /&gt;
   	&amp;lt;name&amp;gt;r&amp;lt;/name&amp;gt;&lt;br /&gt;
   	&amp;lt;desc&amp;gt;open parachute&amp;lt;/desc&amp;gt;&lt;br /&gt;
   	&amp;lt;repeatable&amp;gt;false&amp;lt;/repeatable&amp;gt;&lt;br /&gt;
   	&amp;lt;binding&amp;gt;&lt;br /&gt;
   	   &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
   	   &amp;lt;script&amp;gt;walk.open_chute()&amp;lt;/script&amp;gt;&lt;br /&gt;
   	&amp;lt;/binding&amp;gt;&lt;br /&gt;
   &amp;lt;/key&amp;gt;&lt;br /&gt;
  &amp;lt;/input&amp;gt;&lt;br /&gt;
 &amp;lt;keyboard&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Aircraft enhancement]]&lt;br /&gt;
[[Category:Nasal]]&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Portal:Developer&amp;diff=11616</id>
		<title>Portal:Developer</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Portal:Developer&amp;diff=11616"/>
		<updated>2009-03-26T19:02:08Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{cleanup}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
[[Portal:Developer|Developer]] - [[Portal:User|User]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|style=&amp;quot;border-spacing:8px; margin:0px -8px;&amp;quot;&lt;br /&gt;
|class=&amp;quot;MainPageBG&amp;quot; style=&amp;quot;width:100%; border:1px solid #d9e2e2; background:#efefef; vertical-align:top; color:#000;&amp;quot;|&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;1&amp;quot; cellspacing=&amp;quot;5&amp;quot; style=&amp;quot;vertical-align:top; background:#efefef;&amp;quot;&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;The Developer Portal&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
This portal is for developers contributing to FlightGear. If you want to help with FlightGears development, it's a good idea to subscribe yourself to the [http://lists.sourceforge.net/lists/listinfo/flightgear-devel FlightGear devel] mailing list. The [http://sourceforge.net/mailarchive/forum.php?forum_name=flightgear-devel list archive] is also available and should be searched before posting the same question.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''Please choose a sub-portal:'''&lt;br /&gt;
* [[Portal:Developer/Aircraft|Aircraft]]&lt;br /&gt;
* [[Portal:Developer/Scenery|Scenery]]&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
'''The FlightGear project is looking for organizations/individuals who would be willing to help sponsor a fulltime project coordinator/manager to help oversee the overall development process If you are interested in helping or have anything else to contribute to this issue, please subscribe to the the [http://www.mail-archive.com/flightgear-devel@lists.sourceforge.net/msg11813.html FlightGear Devel mailing list] to discuss details.''' (Note that the FlightGear project can apply for free funding/sponsoring with [http://www.nlnet.nl nlnet]-applications are to be sent [http://www.nlnet.nl/foundation/request/index.html here]-you can help prepare a template for applying: [[Funding Application]])&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&lt;br /&gt;
-------------------------Today's featured article, Did you know------------------------&amp;gt;&lt;br /&gt;
{|style=&amp;quot;border-spacing:8px; margin:0px -8px;&amp;quot;&lt;br /&gt;
|class=&amp;quot;MainPageBG&amp;quot; style=&amp;quot;width:50%; border:1px solid #d9e2e2; background:#efefef; vertical-align:top; color:#000;&amp;quot;|&lt;br /&gt;
{|width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;5&amp;quot; style=&amp;quot;vertical-align:top; background:#efefef;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Current Events, Efforts/Branches &amp;amp; Work in Progress&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
*[[FlightGear Package Manager]] (New! Alpha release of [[Java]]/[[XML]] package manager!)&lt;br /&gt;
*[[Walk View‎]] (New! walk view code!)&lt;br /&gt;
*[[FlightGear Contest]]&lt;br /&gt;
'''[[Work in progress|More...]]'''&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Latest Organizational Issues&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Project Infrastructure Enhancements ]]&lt;br /&gt;
* [[Google Summer of Code Candidate Projects]] - application template to allow community members to prepare a possible application to decrease the effort required to actually apply&lt;br /&gt;
* [[Pending Patches]] (2 listed for the moment)&lt;br /&gt;
* [[Segfaults]] - Reproducible Critical Bugs in FlightGear&lt;br /&gt;
* [[Showstoppers]] - Annoying Issues in FlightGear&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Background Info&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[Programming Resources]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Compiling&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Building Flightgear ]]&lt;br /&gt;
* [[ Building Flightgear - Windows]]&lt;br /&gt;
* [http://macflightgear.sourceforge.net/home/documents/how-to-build-flightgear-cvs-on-mac-os-x/ Building Flightgear - Mac OS X]&lt;br /&gt;
* [[ Building FlightGear Launch Control ]]&lt;br /&gt;
* [[ Building Terragear ]]&lt;br /&gt;
* [[ Keeping FlightGear (win32) up to date without compiling]]&lt;br /&gt;
* [[ OpenSceneGraph ]]&lt;br /&gt;
* [[ Tools of the Trade ]]&lt;br /&gt;
* [[ Using TortoiseCVS with FlightGear ]]&lt;br /&gt;
* [[ Flightgear and Git ]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Contributing&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Code Cleanup ]] &lt;br /&gt;
* [[ Contributor Repositories ]] mirrors, branches and forks privately maintained by contributors&lt;br /&gt;
* [[ Development Resources ]]&lt;br /&gt;
* [[ Extension Support ]]&lt;br /&gt;
* [[ Submitting Patches ]] &lt;br /&gt;
* [[ Technical Reports ]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Code Internals&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[Command Parameters]] &lt;br /&gt;
* [[ FDM API ]]&lt;br /&gt;
* [[ File Formats ]]&lt;br /&gt;
* [[ Initialization Sequence ]]&lt;br /&gt;
* [[ Nasal scripting language ]]&lt;br /&gt;
* [[ Property Tree ]]&lt;br /&gt;
* [[ Subsystems ]] &lt;br /&gt;
* [[ UML Diagrams ]]&lt;br /&gt;
* [[ YASim ]]&lt;br /&gt;
* [[ FlightGear 1.0 aircraft names for command line‎|1.0.0 a/c names for command line]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|class=&amp;quot;MainPageBG&amp;quot; style=&amp;quot;width:50%; border:1px solid #d9e2e2; background:#efefef; vertical-align:top&amp;quot;|&lt;br /&gt;
{| width=&amp;quot;100%&amp;quot; cellpadding=&amp;quot;2&amp;quot; cellspacing=&amp;quot;5&amp;quot; style=&amp;quot;vertical-align:top; background:#efefef;&amp;quot;&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Todo&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Bugs ]]&lt;br /&gt;
* [[ Feature Requests / Proposals / Ideas ]]&lt;br /&gt;
* [[ FGFS Todo ]]&lt;br /&gt;
* [[ FlightGear Expo Checklist ]]&lt;br /&gt;
* [[ Long Term Goals ]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Done&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Changes since 0.9.10 ]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;HowTos&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[Howto: Add smooth (&amp;quot;Ambient Occlusion&amp;quot;) shadows in Blender|Add smooth shadows in Blender]]&lt;br /&gt;
* [[Howto: 3D Aircraft Models|3D Aircraft Models]]&lt;br /&gt;
* [[Howto: Add aircraft lights|Add aircraft lights]]&lt;br /&gt;
* [[Howto: Edit a livery|Edit a livery]]&lt;br /&gt;
* [[Howto: Illuminate faces|Illuminate faces]]&lt;br /&gt;
* [[Howto: Make a helicopter|Make a helicopter]]&lt;br /&gt;
* [[Howto: Set up a multiplayer server|Set up a multiplayer server]]&lt;br /&gt;
'''[[:Category:Howto|More...]]'''&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Instrumentation&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Creating instruments for FG ]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Nasal scripting&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Nasal scripting language ]]&lt;br /&gt;
* [[ Writing simple scripts in %22nasal%22 ]]&lt;br /&gt;
* [[ Walk View‎]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Autopilot configuration&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [http://www.flightgear.org/Docs/XMLAutopilot/ FlightGear Autopilot] (Theory, Configuration, and Tuning)&lt;br /&gt;
* [[ Autopilot Tuning Resources ]]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;3D Modeling&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [http://www.linuxhaxor.net/2009/02/19/25-tutorials-to-get-you-started-with-blender/ 25 tutorials to get you started with blender]&lt;br /&gt;
* [http://www.linuxhaxor.net/2009/02/09/50-tutorials-to-get-you-started-with-gimp/ 50 tutorials to get started with blender]&lt;br /&gt;
* [[ Howto: 3D Aircraft Models|3D Aircraft Models]] (howto)&lt;br /&gt;
* [[ Aircraft Information Resources ]]&lt;br /&gt;
* [[ Model Import and Export ]]&lt;br /&gt;
* [[ Modeling - FAQ ]]&lt;br /&gt;
* [[ Modeling - Getting Started ]]&lt;br /&gt;
* [[ Modeling Resources ]]&lt;br /&gt;
* [[ Modeling - SketchUp]]&lt;br /&gt;
* [[ Normals and Transparency Tutorial ]]&lt;br /&gt;
* [http://en.wikibooks.org/wiki/Blender_3D:_Noob_to_Pro Blender3D Modeling]&lt;br /&gt;
|-&lt;br /&gt;
! &amp;lt;h2 style=&amp;quot;margin:0; background:#0f7a71; font-size:120%; font-weight:bold; border:1px solid #d9e2e2; text-align:left; color:white; padding:0.2em 0.4em;&amp;quot;&amp;gt;Scenery&amp;lt;/h2&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;color:#000;&amp;quot;| &lt;br /&gt;
* [[ Blender Ground Signs Tutorial]]&lt;br /&gt;
* [[ Placing 3D Objects with the UFO ]]&lt;br /&gt;
* [[ Signs ]] (placing and explanation)&lt;br /&gt;
* [[ Using Terragear ]]&lt;br /&gt;
* [[ Using the Custom Scenery TerraGear Toolset ]]&lt;br /&gt;
* [[ Building_terragear-cs_in_Ubuntu_64|Building Terragear-cs in Ubuntu Hardy]]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
__NOTOC__&lt;br /&gt;
__NOEDITSECTION__&lt;br /&gt;
&lt;br /&gt;
== Developer Documentation ==&lt;br /&gt;
=== RFC Topics ===&lt;br /&gt;
'''Clarification:'''In its current form, the RFC section is exclusively based on and covered by previous mailing list and forum discussions (as well as various wiki entries), as such it is not supposed to reflect work in progress (RFC=&amp;quot;Request For Comments&amp;quot; and not WIP), but is rather to be seen as an attempt to provide comprehensive analyses and summaries of key issues identified in various FlightGear related discussions and feature requests (which are to be linked to in the corresponding resource sections, if that didn't yet take place, it's because of most of these RFCs being indeed WIP).&lt;br /&gt;
 &lt;br /&gt;
Thus, RFC entries are not meant to imply anyone &amp;quot;working&amp;quot; on any of these issues, in fact only because an RFC entry is listed here doesn't necessarily mean that work on that particular issue is prioritized or generally endorsed by the FlightGear community. &lt;br /&gt;
These RFC documents are however intended to hopefully help increase and maintain awareness of long-standing issues and challenges affecting FlightGear's evolution and overall development progress in order to solicit community feedback about possible approaches to address these in an efficient and structured fashion.&lt;br /&gt;
Anybody is welcome to comment on, help refine and develop new strategies to tackle the challenges presented in these and future RFCs.&lt;br /&gt;
&lt;br /&gt;
* [[Autopilot Enhancements]] - enhancing the autopilot infrastructure.&lt;br /&gt;
* [[Backwards Compatibility Initiative]] - discussing possible ways to improve FlightGear's backwards compatibility.&lt;br /&gt;
* [[Distributed Interactive Simulation|Multiplayer Enhancements]] - discussing possible steps to enhance FlightGear's Multiplayer support.&lt;br /&gt;
* [[FDM engine feature standardization]] - discussing possible steps to standardize feature support of mainstream FlightGear FDM engines.&lt;br /&gt;
* [[FlightGear Glass Cockpits]] - discussing required infrastructure changes to enable non-developers to easily access FlightGear-internals in order to enable them to model complex glass cockpit-type aircraft instrumentation systems.&lt;br /&gt;
* [[FlightGear Headless]] - discussing required steps to enable FlightGear to be used as its own regression testing framework&lt;br /&gt;
* [[FlightGear Sessions]] - discussing possible steps to finally allow aircraft to be reliably switched at runtime.&lt;br /&gt;
* [[Formalizing Aircraft Status]] - discussing suggestions about how to more properly describe aircraft development status.&lt;br /&gt;
* [[Keyboard function priority list]] - reorganizing FlightGear keybindings.&lt;br /&gt;
* [[Next Generation Scenery ]] - revamping the FG scenery engine.&lt;br /&gt;
* [[Property Tree Reorganization]] - reorganizing the property tree (i.e. implementing and enforcing existing property/node naming conventions).&lt;br /&gt;
* [[Recommended Property Tree Enhancements]] - discussing possible property tree enhancements to help ensure integrity of crucial runtime state.&lt;br /&gt;
* [[Recommended Project Policies]] - discussing recommended policies for future contributions to the project.&lt;br /&gt;
* [[Simplifying Aircraft Deployment]] - identifying potential steps to simplify deployment of FlightGear aircraft.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9824</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9824"/>
		<updated>2008-11-25T12:17:14Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder[1],&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2].&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshot for private, non-commercial purposes,&lt;br /&gt;
** to use the screenshot in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL (GNU General Public License),&lt;br /&gt;
*** the screenshot remains unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 2.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL (GNU General Public License),&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9823</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9823"/>
		<updated>2008-11-25T08:51:46Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder[1],&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2].&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshot for private, non-commercial purposes,&lt;br /&gt;
** to use the screenshot in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL (GNU General Public License),&lt;br /&gt;
*** the screenshot remains unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 2.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9822</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9822"/>
		<updated>2008-11-25T08:18:43Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder[1],&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2].&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshots for private, non-commercial purposes,&lt;br /&gt;
** to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL (GNU General Public License),&lt;br /&gt;
*** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 2.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9821</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9821"/>
		<updated>2008-11-25T08:16:42Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder[1],&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2].&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshots for private, non-commercial purposes,&lt;br /&gt;
** to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL (GNU General Public License),&lt;br /&gt;
*** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 2.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9820</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9820"/>
		<updated>2008-11-25T08:16:04Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,[1]&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2]&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshots for private, non-commercial purposes&lt;br /&gt;
** to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL (GNU General Public License),&lt;br /&gt;
*** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 2.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9819</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9819"/>
		<updated>2008-11-25T08:15:02Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project:&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,[1]&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2]&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshots for private, non-commercial purposes&lt;br /&gt;
** to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL (GNU General Public License),&lt;br /&gt;
*** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 2.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9818</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9818"/>
		<updated>2008-11-25T08:12:45Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project:&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,[1]&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2]&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshots for private, non-commercial purposes&lt;br /&gt;
** to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
*** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 2.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9817</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9817"/>
		<updated>2008-11-25T08:07:40Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revocable and non-exclusive copyright, which permits the project:&lt;br /&gt;
** to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,[1]&lt;br /&gt;
** to persecute copyright infringement on behalf of the screenshot creator[2]&lt;br /&gt;
* The creator grants anyone the non-revocable, perpetual right&lt;br /&gt;
** to use the screenshots for private, non-commercial purposes&lt;br /&gt;
** to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
*** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
*** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
*** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 1: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 3.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 2: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its official name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9816</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9816"/>
		<updated>2008-11-25T01:14:11Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revokable and non-exclusive copyright, which permits the project:&lt;br /&gt;
*# to use the screenshot in documentation and promotion of the FlightGear simulator, including the display on the FlightGear website and all authorized mirrors (including mirrors which are translated to other languages and may include additional services like forums),&lt;br /&gt;
*# to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,&lt;br /&gt;
*# to persecute copyright infringement on behalf of the screenshot creator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 2: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 3.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 3: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. This is not a promise that the project ''will'' persecute infringement. We'd probably use other means to achieve the goal.  :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its offical name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9815</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9815"/>
		<updated>2008-11-25T00:55:32Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: cosmetics ...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revokable and non-exclusive copyright, which permits the project:&lt;br /&gt;
*# to use the screenshot in documentation and promotion of the FlightGear simulator, including the display on the FlightGear website and all authorized mirrors (including mirrors which are translated to other languages and may include additional services like forums),&lt;br /&gt;
*# to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,&lt;br /&gt;
*# to persecute copyright infringement on behalf of the screenshot creator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 2: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 3.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 3: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. A litigation is unlikely, though. We'd use other means to achieve the goal. :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its offical name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9814</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9814"/>
		<updated>2008-11-25T00:53:53Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revokable and non-exclusive copyright, which permits the project:&lt;br /&gt;
*# to use the screenshot in documentation and promotion of the FlightGear simulator, including the display on the FlightGear website and all authorized mirrors (including mirrors which are translated to other languages and may include additional services like forums),&lt;br /&gt;
*# to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,&lt;br /&gt;
*# to persecute copyright infringement on behalf of the screenshot creator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 2: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 3.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 3: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. A litigation is very unlikely, though. We'd use other means to achieve the goal. :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its offical name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licensed under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9813</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9813"/>
		<updated>2008-11-25T00:07:30Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these terms:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revokable and non-exclusive copyright, which permits the project:&lt;br /&gt;
*# to use the screenshot in documentation and promotion of the FlightGear simulator, including the display on the FlightGear website and all authorized mirrors (including mirrors which are translated to other languages and may include additional services like forums),&lt;br /&gt;
*# to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,&lt;br /&gt;
*# to persecute copyright infringement on behalf of the screenshot creator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 2: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 3.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 3: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. A litigation is very unlikely, though. We'd use other means to achieve the goal. :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following:'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its offical name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licenced under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9812</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9812"/>
		<updated>2008-11-24T23:46:31Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and technical image properties. It is therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public, not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license etc.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these rules:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revokable and non-exclusive copyright, which permits the project:&lt;br /&gt;
*# to use the screenshot in documentation and promotion of the FlightGear simulator, including the display on the FlightGear website and all authorized mirrors (including mirrors which are translated to other languages and may include additional services like forums),&lt;br /&gt;
*# to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder,&lt;br /&gt;
*# to persecute copyright infringement on behalf of the screenshot creator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 2: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 3.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 3: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. A litigation is very unlikely, though. We'd use other means to achieve the goal. :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page there would be a copyright notice like the following (suggestion):'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its offical name &amp;quot;FlightGear&amp;quot;,&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licenced under the GPL,&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling.&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9811</id>
		<title>Submitting Screenshots</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Submitting_Screenshots&amp;diff=9811"/>
		<updated>2008-11-24T23:42:17Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: legal status of submitted screenshots (draft)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The FlightGear project always needs screenshots for the website, which show features that were added since the last release. These shots should be of good quality -- regarding contents and image quality. It's therefore recommended to use the best viable filter settings (antialiasing, texture sharpening, etc.). Screenshots should only show features that are actually available to the public,&lt;br /&gt;
not models that are private and can't be distributed due to a non-GPL-compatible, restrictive license.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''By submitting a screenshot the submitter agrees to these rules:'''&lt;br /&gt;
&lt;br /&gt;
* The creator of the screenshot retains full ownership and copyright.&lt;br /&gt;
* The creator grants the FlightGear project a revokable and non-exclusive copyright, which permits the project:&lt;br /&gt;
*# to use the screenshot in documentation and promotion of the FlightGear simulator, including the display on the FlightGear website and all authorized mirrors (including mirrors which are translated to other languages and may include additional services like forums).&lt;br /&gt;
*# to add a copyright notice to the screenshot, which denotes the FlightGear project as a copyright holder.&lt;br /&gt;
*# to persecute copyright infringement on behalf of the screenshot creator.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
ad 2: This is meant to guarantee consistent look and easier maintenance, and to strengthen the project's position in cases of 3.&amp;lt;br&amp;gt;&lt;br /&gt;
ad 3: This should make it easier to demand of infringers that they take all screenshots down from a web page. We can't do that if we don't have a mandate. A litigation is very unlikely, though. We'd use other means to achieve the goal. :-)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''On the screenshot page we would put a copyright notice like the following (suggestion):'''&lt;br /&gt;
&lt;br /&gt;
All screenshots displayed on this website are copyright of their respective creators. Permission is granted to anyone:&lt;br /&gt;
* to use the screenshots for private, non-commercial purposes&lt;br /&gt;
* to use the screenshots in articles ''about'', and reviews, announcements, documentation and promotion ''of'' the FlightGear simulator, provided that:&lt;br /&gt;
** the simulator is presented under its offical name &amp;quot;FlightGear&amp;quot;&lt;br /&gt;
** it is mentioned in that work that the simulator is Free and licenced under the GPL&lt;br /&gt;
** the screenshots remain unchanged, with the sole exception of optional scaling&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8720</id>
		<title>Livery over MP</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8720"/>
		<updated>2008-10-20T07:49:06Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: comments about the (non-)structure of an XML overlay file&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Livery_selection_dialog.jpg|thumb|270px|The livery selection dialog of the [[Sikorsky S76C]].]]&lt;br /&gt;
&lt;br /&gt;
On this page we describe how you make use of a script to get a '''livery selection dialog''' for a [[Aircraft|plane]] in [[FlightGear]]. To get new liveries into [[FlightGear CVS]], you need to have them availabe with this script.&lt;br /&gt;
&lt;br /&gt;
The examples are based on the [[Robin DR400]].&lt;br /&gt;
&lt;br /&gt;
==Files==&lt;br /&gt;
There are a few files we need to make (or edit), namely:&lt;br /&gt;
* &amp;lt;tt&amp;gt;dr400-set.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Models/dr400.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Nasal/liveries.nas&amp;lt;/tt&amp;gt;&lt;br /&gt;
We also have to make a new directory to store our liveries in. Let's make it &amp;lt;tt&amp;gt;Aircraft/DR400/Models/Liveries&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Models/Liveries===&lt;br /&gt;
For every livery we need to make a file. Let's say we got a Rescue livery, we then need to make a file called Rescue.xml in our &amp;lt;tt&amp;gt;Models/Liveries&amp;lt;/tt&amp;gt; directory. When a particular livery gets selected, its XML file is copied to the aircraft's property tree. On the pilot's side this is the main property tree &amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;, and on all remote machines on the MP network it's one of the multiplayer branches in &amp;lt;tt&amp;gt;/ai/models/multiplayer[]&amp;lt;/tt&amp;gt;. The structure of livery XML files is completely free. There just has to be a property containing a name for the selection dialog, and &amp;lt;tt&amp;gt;aircraft.livery.init()&amp;lt;/tt&amp;gt; must be told which it is. By default it is &amp;lt;tt&amp;gt;sim/model/livery/name&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;sim&amp;gt;&lt;br /&gt;
   &amp;lt;model&amp;gt;&lt;br /&gt;
    &amp;lt;livery&amp;gt;&lt;br /&gt;
     &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Default&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
    &amp;lt;/livery&amp;gt;&lt;br /&gt;
   &amp;lt;/model&amp;gt;&lt;br /&gt;
  &amp;lt;/sim&amp;gt;&lt;br /&gt;
 &amp;lt;/PropertyList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===dr400.xml===&lt;br /&gt;
The first part is related to the nasal script. &amp;lt;tt&amp;gt;(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&amp;lt;/tt&amp;gt; points FlightGear to the directory where we store our liveries. This is a different directory for every plane, but there should be only one folder for one plane, containing all the liveries for that plane.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nasal&amp;gt;&lt;br /&gt;
  &amp;lt;load&amp;gt;&lt;br /&gt;
   var livery_update = aircraft.livery_update.new(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
  &amp;lt;/load&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  &amp;lt;unload&amp;gt;&lt;br /&gt;
   livery_update.stop();&lt;br /&gt;
  &amp;lt;/unload&amp;gt;&lt;br /&gt;
 &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second part is very important and probably the hardest of all. We need to set which parts of the model should change when you select a new livery. To find the object-names, you could make use of software like [[Blender]] or [[AC3D]]. The &amp;lt;tt&amp;gt;&amp;lt;texture&amp;gt;S76livery.rgb&amp;lt;/texture&amp;gt;&amp;lt;/tt&amp;gt; part points FlightGear to the livery that should be shown on startup.&lt;br /&gt;
&lt;br /&gt;
'''Warning: be sure you don't have a slash (/) in front of sim/model/livery in the &amp;lt;property-base&amp;gt; tag! Otherwise, all planes will get the same livery!'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;animation&amp;gt;&lt;br /&gt;
  &amp;lt;type&amp;gt;material&amp;lt;/type&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;S76C&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Rr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Lr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;property-base&amp;gt;sim/model/livery&amp;lt;/property-base&amp;gt;&lt;br /&gt;
   &amp;lt;texture-prop&amp;gt;texture&amp;lt;/texture-prop&amp;gt;&lt;br /&gt;
   &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
 &amp;lt;/animation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===liveries.nas===&lt;br /&gt;
The only thing you might change in the nasal file is the directory of the liveries. If you don't have the livery name in &amp;lt;tt&amp;gt;sim/model/livery/name&amp;lt;/tt&amp;gt;, then you have to add this as second function argument.&lt;br /&gt;
&lt;br /&gt;
 aircraft.livery.init(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===s76c-set.xml===&lt;br /&gt;
 &amp;lt;model&amp;gt;&lt;br /&gt;
  &amp;lt;path&amp;gt;Aircraft/DR400/models/dr400.xml&amp;lt;/path&amp;gt;&lt;br /&gt;
  &amp;lt;livery&amp;gt;&lt;br /&gt;
   &amp;lt;file type=&amp;quot;string&amp;quot;/&amp;gt;&lt;br /&gt;
  &amp;lt;/livery&amp;gt;&lt;br /&gt;
 &amp;lt;/model&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make a nice button in the [[menubar]] we need to add the following code, just above the &amp;lt;tt&amp;gt;&amp;lt;/sim&amp;gt;&amp;lt;/tt&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;menubar&amp;gt;&lt;br /&gt;
  &amp;lt;default&amp;gt;&lt;br /&gt;
   &amp;lt;menu n=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;Robin DR 400&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;enabled type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;
    &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Select Livery&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;aircraft.livery.dialog.open()&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;/item&amp;gt;&lt;br /&gt;
   &amp;lt;/menu&amp;gt;&lt;br /&gt;
  &amp;lt;/default&amp;gt;&lt;br /&gt;
 &amp;lt;/menubar&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
To ensure that your livery setup works correctly over MP, start two instances of FlightGear locally, one with&lt;br /&gt;
&lt;br /&gt;
 fgfs --multiplay=out,10,localhost,5702 --multiplay=in,10,localhost,5701&lt;br /&gt;
&lt;br /&gt;
and one with&lt;br /&gt;
&lt;br /&gt;
 fgfs --multiplay=out,10,localhost,5701 --multiplay=in,10,localhost,5702&lt;br /&gt;
&lt;br /&gt;
[[Category:Aircraft enhancement]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Menubar]]&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8719</id>
		<title>Livery over MP</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8719"/>
		<updated>2008-10-19T11:34:00Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: menu entries should always open() the dialog (not toggle it)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Livery_selection_dialog.jpg|thumb|270px|The livery selection dialog of the [[Sikorsky S76C]].]]&lt;br /&gt;
&lt;br /&gt;
On this page we describe how you make use of a script to get a '''livery selection dialog''' for a [[Aircraft|plane]] in [[FlightGear]]. To get new liveries into [[FlightGear CVS]], you need to have them availabe with this script.&lt;br /&gt;
&lt;br /&gt;
The examples are based on the [[Robin DR400]].&lt;br /&gt;
&lt;br /&gt;
==Files==&lt;br /&gt;
There are a few files we need to make (or edit), namely:&lt;br /&gt;
* &amp;lt;tt&amp;gt;dr400-set.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Models/dr400.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Nasal/liveries.nas&amp;lt;/tt&amp;gt;&lt;br /&gt;
We also have to make a new directory to store our liveries in. Let's make it &amp;lt;tt&amp;gt;Aircraft/DR400/Models/Liveries&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Models/Liveries===&lt;br /&gt;
For every livery we need to make a file. Let's say we got a Rescue livery, we than need to make a file called Rescue.xml into our &amp;lt;tt&amp;gt;Models/Liveries directory&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;sim&amp;gt;&lt;br /&gt;
   &amp;lt;model&amp;gt;&lt;br /&gt;
    &amp;lt;livery&amp;gt;&lt;br /&gt;
     &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Default&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
    &amp;lt;/livery&amp;gt;&lt;br /&gt;
   &amp;lt;/model&amp;gt;&lt;br /&gt;
  &amp;lt;/sim&amp;gt;&lt;br /&gt;
 &amp;lt;/PropertyList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===dr400.xml===&lt;br /&gt;
The first part is related to the nasal script. &amp;lt;tt&amp;gt;(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&amp;lt;/tt&amp;gt; points FlightGear to the directory where we store our liveries. This is a different directory for every plane, but there should be only one folder for one plane, containing all the liveries for that plane.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nasal&amp;gt;&lt;br /&gt;
  &amp;lt;load&amp;gt;&lt;br /&gt;
   var livery_update = aircraft.livery_update.new(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
  &amp;lt;/load&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  &amp;lt;unload&amp;gt;&lt;br /&gt;
   livery_update.stop();&lt;br /&gt;
  &amp;lt;/unload&amp;gt;&lt;br /&gt;
 &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second part is very important and probably the hardest of all. We need to set which parts of the model should change when you select a new livery. To find the object-names, you could make use of software like [[Blender]] or [[AC3D]]. The &amp;lt;tt&amp;gt;&amp;lt;texture&amp;gt;S76livery.rgb&amp;lt;/texture&amp;gt;&amp;lt;/tt&amp;gt; part points FlightGear to the livery that should be shown on startup.&lt;br /&gt;
&lt;br /&gt;
'''Warning: be sure you don't have a slash (/) in front of sim/model/livery in the &amp;lt;property-base&amp;gt; tag! Otherwise, all planes will get the same livery!'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;animation&amp;gt;&lt;br /&gt;
  &amp;lt;type&amp;gt;material&amp;lt;/type&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;S76C&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Rr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Lr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;property-base&amp;gt;sim/model/livery&amp;lt;/property-base&amp;gt;&lt;br /&gt;
   &amp;lt;texture-prop&amp;gt;texture&amp;lt;/texture-prop&amp;gt;&lt;br /&gt;
   &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
 &amp;lt;/animation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===liveries.nas===&lt;br /&gt;
The only thing you might change in the nasal file is the directory of the liveries.&lt;br /&gt;
&lt;br /&gt;
 aircraft.livery.init(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===s76c-set.xml===&lt;br /&gt;
 &amp;lt;model&amp;gt;&lt;br /&gt;
  &amp;lt;path&amp;gt;Aircraft/DR400/models/dr400.xml&amp;lt;/path&amp;gt;&lt;br /&gt;
  &amp;lt;livery&amp;gt;&lt;br /&gt;
   &amp;lt;file type=&amp;quot;string&amp;quot;&amp;gt;default&amp;lt;/file&amp;gt;&lt;br /&gt;
  &amp;lt;/livery&amp;gt;&lt;br /&gt;
 &amp;lt;/model&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make a nice button in the [[menubar]] we need to add the following code, just above the &amp;lt;tt&amp;gt;&amp;lt;/sim&amp;gt;&amp;lt;/tt&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;menubar&amp;gt;&lt;br /&gt;
  &amp;lt;default&amp;gt;&lt;br /&gt;
   &amp;lt;menu n=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;Robin DR 400&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;enabled type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;
    &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Select Livery&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;aircraft.livery.dialog.open()&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;/item&amp;gt;&lt;br /&gt;
   &amp;lt;/menu&amp;gt;&lt;br /&gt;
  &amp;lt;/default&amp;gt;&lt;br /&gt;
 &amp;lt;/menubar&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Testing==&lt;br /&gt;
To ensure that your livery setup works correctly over MP, start two instances of FlightGear locally, one with&lt;br /&gt;
&lt;br /&gt;
 fgfs --multiplay=out,10,localhost,5702 --multiplay=in,10,localhost,5701&lt;br /&gt;
&lt;br /&gt;
and one with&lt;br /&gt;
&lt;br /&gt;
 fgfs --multiplay=out,10,localhost,5701 --multiplay=in,10,localhost,5702&lt;br /&gt;
&lt;br /&gt;
[[Category:Aircraft enhancement]]&lt;br /&gt;
[[Category:Modeling]]&lt;br /&gt;
[[Category:Menubar]]&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8709</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8709"/>
		<updated>2008-10-18T00:59:29Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;discussion&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various XML files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if the key is a valid variable name or a number. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can access their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the former case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;, and if not found in the parents, whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) }&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; has its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method now, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
With this instance generating function we have now two elements referring to a class, which belong together: the class hash itself, and the generator function. But aren't objects about keeping things together that belong together? It would be nicer to just put this generator function into the class hash as well. We call this function a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
As we noted above, an object can have more than one parent.&lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func {&lt;br /&gt;
         print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: aircraft&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = Aircraft.new(name);&lt;br /&gt;
         m.parents = [Helicopter, Aircraft];&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func {&lt;br /&gt;
         print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: helicopter&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                 # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].printtype();      # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[1].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8707</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8707"/>
		<updated>2008-10-17T15:38:40Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: turn &amp;quot;paragraphs&amp;quot; into paragraphs (I had written the OOP parts in an external editor); use '' instead of &amp;lt;em&amp;gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;''Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;discussion&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal.''&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which supports reading and writing of internal properties, accessing internal data via extension functions, creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files, and it can be embedded in various XML files (dialog files, animation files, bindings for joysticks, keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;, and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only be used for instantaneous operations that don't take too long. For operations that should continue over a longer period, one needs a non-blocking solution. This is done by letting functions call themselves after a timed delay: &lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call (&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked. But one can let the loop function check an outside variable and refuse calling itself, which makes the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop call, which should really finish this chain, would happily continue. And the new loop chain would start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit the chain id. So, every time the global loop id is increased, all loop chains die, and a new one can immediately be started.&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get a better understanding of the concept, let's start with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL are data structures that hold key/value pairs in a way that allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition if they are valid variable names or numbers. This works just as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;, but as we'll later see, it has an additional property.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does never ''copy'' the contents. It only creates another reference to the same data structure. So manipulating the hash via its new name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice: &amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type ''function''. Member functions (&amp;quot;methods&amp;quot;) can access their own enclosing hash via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;. But only in the former case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in &amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;, and if not found in the parents, whereas in the second case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It has its own variable namespace, its own methods, and it can be passed around by-reference as one unit. Such classes are sometimes called ''singleton classes'', as they are unique, with no independent class instances. They mostly serve as a way to keep data and methods nicely encapsulated within a Nasal module. Often they contain a method for initializing, which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword. It denotes a vector referencing other object hashes, which are &amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;, it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is a vector that can contain several parent objects. These are then searched in the order from left to right, until a matching member variable or method is found. Each of the parents can itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of these three objects. The following will redefine the parent's &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) };&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) };&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; has its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method now, the parents won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple assignment, because, as we learned above, this wouldn't create a separate copy of the Class object. All &amp;quot;instances&amp;quot; would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash with parents is clumsy. It is nicer to have a function that does that for us. Then we can also use function arguments to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
With this instance generating function we have now two elements referring to a class, which belong together: the class hash itself, and the generator function. But aren't objects about keeping things together that belong together? It would be nicer to just put this generator function into the class hash as well. We call this function a class &amp;quot;constructor&amp;quot;, and as a convention, give it the name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;. It could have any name, though, and there could be more than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but rather a small hash that contains only a list of parents and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they contain several members, of which some may have yet to be calculated in the constructor. In that case it's easier to create a local object hash first, and to let the constructor finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically called when the class gets destroyed, so that memory and other resources that were allocated by the constructor can be freed. In Nasal that's all done by the Garbage Collector (GC), anyway. In the FlightGear context, however, there ''are'' resources that should get freed. Listeners should get removed, self-calling functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;, similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
As we noted above, an object can have more than one parent.&lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func {&lt;br /&gt;
         print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: aircraft&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = Aircraft.new(name);&lt;br /&gt;
         m.parents = [Helicopter, Aircraft];&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func {&lt;br /&gt;
         print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: helicopter&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name, the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                 # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].printtype();      # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[1].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8706</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8706"/>
		<updated>2008-10-17T14:59:39Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: replace intro with something that refers to FlightGear and Nasal, rather than what other applications do or don't do&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;em&amp;gt;(Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;discussion&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal).&amp;lt;/em&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] offers a powerful scripting language called [http://plausible.org/nasal/ &amp;quot;Nasal&amp;quot;], which&lt;br /&gt;
supports reading and writing of internal properties, accessing internal data via extension functions,&lt;br /&gt;
creating dialogs and much more. It uses some of the concepts of ECMA/JavaScript, Python and Perl and implements a simple&lt;br /&gt;
but complete way of Object Oriented Programming. Nasal code can be run by aircraft configuration files,&lt;br /&gt;
and it can be embedded in various XML files (dialog files, animation files, bindings for joysticks, &lt;br /&gt;
keyboard and cockpit controls). Nasal is platform independent.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;,&lt;br /&gt;
and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only&lt;br /&gt;
be used for instantaneous operations that don't take too long. For operations that should continue over a&lt;br /&gt;
longer period, one needs a non-blocking solution. This is done by letting functions call themselves after&lt;br /&gt;
a timed delay: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call&lt;br /&gt;
(&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops&lt;br /&gt;
only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked.&lt;br /&gt;
But one can let the loop function check an outside variable and refuse calling itself, which makes&lt;br /&gt;
the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance&lt;br /&gt;
immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop&lt;br /&gt;
call, which should really finish this chain, would happily continue. And the new loop chain would&lt;br /&gt;
start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function&lt;br /&gt;
end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit&lt;br /&gt;
the chain id. So, every time the global loop id is increased, all loop chains die, and a new one&lt;br /&gt;
can immediately be started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference&lt;br /&gt;
and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get better understanding of the concept, let's start&lt;br /&gt;
with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL&lt;br /&gt;
are data structures that hold key/value pairs in a way that&lt;br /&gt;
allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition&lt;br /&gt;
if they are valid variable names or numbers. This works just&lt;br /&gt;
as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the&lt;br /&gt;
keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used&lt;br /&gt;
instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;, but as we'll later see, it&lt;br /&gt;
has an additional property.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does&lt;br /&gt;
never &amp;lt;em&amp;gt;copy&amp;lt;/em&amp;gt; the contents. It only creates another reference to&lt;br /&gt;
the same data structure. So manipulating the hash via its new&lt;br /&gt;
name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice:&lt;br /&gt;
&amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type &amp;lt;em&amp;gt;function&amp;lt;/em&amp;gt;.&lt;br /&gt;
Member functions (&amp;quot;methods&amp;quot;) can access their own enclosing hash&lt;br /&gt;
via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword&lt;br /&gt;
in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access&lt;br /&gt;
hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
But only in the former case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in&lt;br /&gt;
&amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;, and if not found in the parents, whereas in the second&lt;br /&gt;
case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being&lt;br /&gt;
unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It&lt;br /&gt;
has its own variable namespace, its own methods, and it can be&lt;br /&gt;
passed around by-reference as one unit. Such classes are&lt;br /&gt;
sometimes called &amp;lt;em&amp;gt;singleton classes&amp;lt;/em&amp;gt;, as they are unique,&lt;br /&gt;
with no independent class instances. They mostly serve as a&lt;br /&gt;
way to keep data and methods nicely encapsulated within a&lt;br /&gt;
Nasal module. Often they contain a method for initializing,&lt;br /&gt;
which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half&lt;br /&gt;
truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also&lt;br /&gt;
one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword.&lt;br /&gt;
It denotes a vector referencing other object hashes, which are&lt;br /&gt;
&amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;,&lt;br /&gt;
it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is&lt;br /&gt;
a vector that can contain several parent objects. These are&lt;br /&gt;
then searched in the order from left to right, until a matching&lt;br /&gt;
member variable or method is found. Each of the parents can&lt;br /&gt;
itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and&lt;br /&gt;
create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent&lt;br /&gt;
objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from&lt;br /&gt;
object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of&lt;br /&gt;
these three objects. The following will redefine the parent's&lt;br /&gt;
&amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this&lt;br /&gt;
new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) };&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) };&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; has its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method now, the parents&lt;br /&gt;
won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden&lt;br /&gt;
by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it&lt;br /&gt;
will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple&lt;br /&gt;
assignment, because, as we learned above, this wouldn't&lt;br /&gt;
create a separate copy of the Class object. All &amp;quot;instances&amp;quot;&lt;br /&gt;
would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash&lt;br /&gt;
with parents is clumsy. It is nicer to have a function that&lt;br /&gt;
does that for us. Then we can also use function arguments&lt;br /&gt;
to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
With this instance generating function we have now two&lt;br /&gt;
elements referring to a class, which belong together: the&lt;br /&gt;
class hash itself, and the generator function. But aren't&lt;br /&gt;
objects about keeping things together that belong together?&lt;br /&gt;
It would be nicer to just put this generator function into&lt;br /&gt;
the class hash as well. We call this function a class&lt;br /&gt;
&amp;quot;constructor&amp;quot;, and as a convention, give it the name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
It could have any name, though, and there could be more&lt;br /&gt;
than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but&lt;br /&gt;
rather a small hash that contains only a list of parents&lt;br /&gt;
and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they&lt;br /&gt;
contain several members, of which some may have yet to be&lt;br /&gt;
calculated in the constructor. In that case it's easier to&lt;br /&gt;
create a local object hash first, and to let the constructor&lt;br /&gt;
finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as&lt;br /&gt;
a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class&lt;br /&gt;
definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically&lt;br /&gt;
called when the class gets destroyed, so that memory and other resources that were&lt;br /&gt;
allocated by the constructor can be freed. In Nasal that's all done by the Garbage&lt;br /&gt;
Collector (GC), anyway. In the FlightGear context, however, there &amp;lt;em&amp;gt;are&amp;lt;/em&amp;gt;&lt;br /&gt;
resources that should get freed. Listeners should get removed, self-calling&lt;br /&gt;
functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor&lt;br /&gt;
function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;,&lt;br /&gt;
similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
As we noted above, an object can have more than one parent.&lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func {&lt;br /&gt;
         print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: aircraft&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = Aircraft.new(name);&lt;br /&gt;
         m.parents = [Helicopter, Aircraft];&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func {&lt;br /&gt;
         print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: helicopter&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name,&lt;br /&gt;
the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                 # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].printtype();      # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[1].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8546</id>
		<title>Nasal scripting language</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Nasal_scripting_language&amp;diff=8546"/>
		<updated>2008-10-12T18:53:46Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''(Please note that a considerable amount of resources has not yet been incorporated here, you can check these out by going to the &amp;quot;discussion&amp;quot; page, where we are collecting links to webpages and mailing list discussions/postings related to Nasal)'''&lt;br /&gt;
&lt;br /&gt;
Many applications today support scripting as a means of &amp;quot;gluing&amp;quot; the application together and enabling users to extend functionality of the application. For example, the 3d modeling application Blender implements most of its import and export filters as user contributed Python scripts, which are automatically integrated into the menu system. Many games are also integrating a scripting language to make it easier for modders to add features.&lt;br /&gt;
&lt;br /&gt;
[[FlightGear]] has a scripting language called '''Nasal'''.  Elements of the graphical user interface, [[aircraft]] instruments and flight performance can be scripted.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Loops ==&lt;br /&gt;
&lt;br /&gt;
Nasal has several ways to implement an iteration. Loops using &amp;lt;tt&amp;gt;while&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;for&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;foreach&amp;lt;/tt&amp;gt;,&lt;br /&gt;
and &amp;lt;tt&amp;gt;forindex&amp;lt;/tt&amp;gt; block all of FlightGear's subsystems that run in the main thread, and can, thus, only&lt;br /&gt;
be used for instantaneous operations that don't take too long. For operations that should continue over a&lt;br /&gt;
longer period, one needs a non-blocking solution. This is done by letting functions call themselves after&lt;br /&gt;
a timed delay: &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
     settimer(loop, 2);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;lt;tt&amp;gt;settimer&amp;lt;/tt&amp;gt; function expects a ''function object'' (&amp;lt;tt&amp;gt;loop&amp;lt;/tt&amp;gt;), not a function call&lt;br /&gt;
(&amp;lt;tt&amp;gt;loop()&amp;lt;/tt&amp;gt;). The fewer code FlightGear has to execute, the better, so it is desirable to run loops&lt;br /&gt;
only when they are needed. But how does one stop a loop? A once triggered timer function can't be revoked.&lt;br /&gt;
But one can let the loop function check an outside variable and refuse calling itself, which makes&lt;br /&gt;
the loop chain die off:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 var running = 1;&lt;br /&gt;
 var loop = func {&lt;br /&gt;
     if (running) {&lt;br /&gt;
         print(&amp;quot;this line appears once every two seconds&amp;quot;);&lt;br /&gt;
         settimer(loop, 2);&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop();        # start loop ...&lt;br /&gt;
 ...&lt;br /&gt;
 running = 0;   # ... and let it die&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Unfortunately, this method is rather unreliable. What if the loop is &amp;quot;stopped&amp;quot; and a new instance&lt;br /&gt;
immediately started again? Then the ''running'' variable would be ''1'' again, and a pending old loop&lt;br /&gt;
call, which should really finish this chain, would happily continue. And the new loop chain would&lt;br /&gt;
start, too, so that we would end up with two loop chains.&lt;br /&gt;
&lt;br /&gt;
This can be solved by providing each loop chain with a ''loop identifier'' and letting the function&lt;br /&gt;
end itself if the id doesn't match the global loop-id. Self-called loop functions need to inherit&lt;br /&gt;
the chain id. So, every time the global loop id is increased, all loop chains die, and a new one&lt;br /&gt;
can immediately be started.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
 var loopid = 0;&lt;br /&gt;
 var loop = func(id) {&lt;br /&gt;
     id == loopid or return;           # stop here if the id doesn't match the global loop-id&lt;br /&gt;
     ...&lt;br /&gt;
     settimer(func { loop(id) }, 2);   # call self with own loop id&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 loop(loopid);       # start loop&lt;br /&gt;
 ...&lt;br /&gt;
 loopid += 1;        # this kills off all pending loops, as none can have this new identifier yet&lt;br /&gt;
 ...&lt;br /&gt;
 loop(loopid);       # start new chain; this can also be abbreviated to:  loop(loopid += 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== OOP - Object Oriented Programming ==&lt;br /&gt;
&lt;br /&gt;
In Nasal, objects (&amp;quot;classes&amp;quot;) are regular hashes. Self-reference&lt;br /&gt;
and inheritance are implemented through special variables &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and&lt;br /&gt;
&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;. To get better understanding of the concept, let's start&lt;br /&gt;
with the very basics.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Hashes ===&lt;br /&gt;
&lt;br /&gt;
Hashes, also known as &amp;quot;dictionaries&amp;quot; in Python or &amp;quot;maps&amp;quot; in C++/STL&lt;br /&gt;
are data structures that hold key/value pairs in a way that&lt;br /&gt;
allows quick access to a value via its key.&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     &amp;quot;LOXZ&amp;quot;: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
     &amp;quot;LOWI&amp;quot;: &amp;quot;Innsbruck&amp;quot;,&lt;br /&gt;
     &amp;quot;LOXL&amp;quot;: &amp;quot;Linz Hoersching&amp;quot;,     # the last comma is optional&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 print(airport[&amp;quot;LOXZ&amp;quot;]);            # prints &amp;quot;Zeltweg&amp;quot;&lt;br /&gt;
 airport[&amp;quot;LOXA&amp;quot;] = &amp;quot;Aigen&amp;quot;;         # adds LOXA to the hash&lt;br /&gt;
&lt;br /&gt;
The quotes around keys can be left away in a hash definition&lt;br /&gt;
if they are valid variable names or numbers. This works just&lt;br /&gt;
as well:&lt;br /&gt;
&lt;br /&gt;
 var airport = {&lt;br /&gt;
     LOXZ: &amp;quot;Zeltweg&amp;quot;,&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
There's also an alternative way to access hash members if the&lt;br /&gt;
keys are valid variable names: &amp;lt;tt&amp;gt;airport.LOXI&amp;lt;/tt&amp;gt; can be used&lt;br /&gt;
instead of &amp;lt;tt&amp;gt;airport[&amp;quot;LOXI&amp;quot;]&amp;lt;/tt&amp;gt;, but as we'll later see, it&lt;br /&gt;
has an additional property.&lt;br /&gt;
&lt;br /&gt;
Note that assigning a hash (or a vector) to another variable does&lt;br /&gt;
never &amp;lt;em&amp;gt;copy&amp;lt;/em&amp;gt; the contents. It only creates another reference to&lt;br /&gt;
the same data structure. So manipulating the hash via its new&lt;br /&gt;
name does in fact change the one, original hash.&lt;br /&gt;
&lt;br /&gt;
 var a = airport;&lt;br /&gt;
 a.LOXL = &amp;quot;Linz&amp;quot;;&lt;br /&gt;
 print(airport.LOXL);       # prints now &amp;quot;Linz&amp;quot;, not &amp;quot;Linz Hoersching&amp;quot;&lt;br /&gt;
&lt;br /&gt;
(True copies of vectors can be made by assigning a full slice:&lt;br /&gt;
&amp;lt;tt&amp;gt;var copy = vec[:]&amp;lt;/tt&amp;gt;. There's no such method for hashes.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Self-reference: &amp;quot;&amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Values stored in a hash can be of any type, even of type &amp;lt;em&amp;gt;function&amp;lt;/em&amp;gt;.&lt;br /&gt;
Member functions (&amp;quot;methods&amp;quot;) can access their own enclosing hash&lt;br /&gt;
via reserved keyword &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;. This is comparable to the &amp;lt;tt&amp;gt;this&amp;lt;/tt&amp;gt; keyword&lt;br /&gt;
in C++ classes, or the &amp;lt;tt&amp;gt;self&amp;lt;/tt&amp;gt; keyword in Python.&lt;br /&gt;
&lt;br /&gt;
 var value = &amp;quot;test&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 var data = {&lt;br /&gt;
     value: 23,                         # scalar member variable&lt;br /&gt;
     write1: func { print(value); },    # function member&lt;br /&gt;
     write2: func { print(me.value); }, # function member&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 data.write1();     # prints &amp;quot;test&amp;quot;&lt;br /&gt;
 data.write2();     # prints 23&lt;br /&gt;
&lt;br /&gt;
In the last section we learned that there are two ways to access&lt;br /&gt;
hash members: &amp;lt;tt&amp;gt;data.write2()&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;data[&amp;quot;write2&amp;quot;]()&amp;lt;/tt&amp;gt;.&lt;br /&gt;
But only in the former case &amp;lt;tt&amp;gt;write2&amp;lt;/tt&amp;gt; is first searched in&lt;br /&gt;
&amp;lt;tt&amp;gt;data&amp;lt;/tt&amp;gt;, and if not found in the parents, whereas in the second&lt;br /&gt;
case we'd get an error message about the &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; variable being&lt;br /&gt;
unknown. It's only usable for accessing direct hash members.&lt;br /&gt;
&lt;br /&gt;
The above example is already a simple form of an object. It&lt;br /&gt;
has its own variable namespace, its own methods, and it can be&lt;br /&gt;
passed around by-reference as one unit. Such classes are&lt;br /&gt;
sometimes called &amp;lt;em&amp;gt;singleton classes&amp;lt;/em&amp;gt;, as they are unique,&lt;br /&gt;
with no independent class instances. They mostly serve as a&lt;br /&gt;
way to keep data and methods nicely encapsulated within a&lt;br /&gt;
Nasal module. Often they contain a method for initializing,&lt;br /&gt;
which is usually called &amp;lt;tt&amp;gt;init&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Inheritance: &amp;quot;&amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt;&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
What we learned about &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; in the last section is only the half&lt;br /&gt;
truth. &amp;quot;me&amp;quot; doesn't only reference an object's own hash, but also&lt;br /&gt;
one or more parent hashes. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is another reserved keyword.&lt;br /&gt;
It denotes a vector referencing other object hashes, which are&lt;br /&gt;
&amp;quot;inherited&amp;quot; that way.&lt;br /&gt;
&lt;br /&gt;
 var parent_object = {&lt;br /&gt;
     value: 123,&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var object = {&lt;br /&gt;
     parents: [parent_object],&lt;br /&gt;
     write: func { print(me.value) },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 object.write();    # prints 123&lt;br /&gt;
&lt;br /&gt;
Even though &amp;lt;tt&amp;gt;object&amp;lt;/tt&amp;gt; itself doesn't contain a member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;,&lt;br /&gt;
it finds and uses the one of its parent object. &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; is&lt;br /&gt;
a vector that can contain several parent objects. These are&lt;br /&gt;
then searched in the order from left to right, until a matching&lt;br /&gt;
member variable or method is found. Each of the parents can&lt;br /&gt;
itself have parents, which are all recursively searched.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Creating class instances ===&lt;br /&gt;
&lt;br /&gt;
With &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt; and &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; we can implement a class object and&lt;br /&gt;
create independent instances from that:&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     write:     func { print(me.value); },&lt;br /&gt;
     increment: func { me.value += 1; },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = { parents: [Class], value: 123 };&lt;br /&gt;
 var instance2 = { parents: [Class], value: 456 };&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();    # prints 123&lt;br /&gt;
 instance2.write();    # prints 456&lt;br /&gt;
&lt;br /&gt;
As you can see, the two class instances are separate, independent&lt;br /&gt;
objects, which share another object as parent -- they &amp;quot;inherit&amp;quot; from&lt;br /&gt;
object &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;. One can now easily change members of any of&lt;br /&gt;
these three objects. The following will redefine the parent's&lt;br /&gt;
&amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method, and all instances will automatically use this&lt;br /&gt;
new version:&lt;br /&gt;
&lt;br /&gt;
 Class.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) };&lt;br /&gt;
&lt;br /&gt;
But one can also add a method to just one instance:&lt;br /&gt;
&lt;br /&gt;
 instance1.write = func { print(&amp;quot;VALUE = &amp;quot; ~ me.value) };&lt;br /&gt;
&lt;br /&gt;
Because &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt; has its own &amp;lt;tt&amp;gt;write&amp;lt;/tt&amp;gt; method now, the parents&lt;br /&gt;
won't be searched for one, so &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; is now overridden&lt;br /&gt;
by &amp;lt;tt&amp;gt;instance1&amp;lt;/tt&amp;gt;'s own method. Nothing changed for &amp;lt;tt&amp;gt;instance2&amp;lt;/tt&amp;gt; -- it&lt;br /&gt;
will still only find and use &amp;lt;tt&amp;gt;Class.write&amp;lt;/tt&amp;gt; via its parent.&lt;br /&gt;
&lt;br /&gt;
Note, the we couldn't create a class instance by simple&lt;br /&gt;
assignment, because, as we learned above, this wouldn't&lt;br /&gt;
create a separate copy of the Class object. All &amp;quot;instances&amp;quot;&lt;br /&gt;
would reference the same hash!&lt;br /&gt;
&lt;br /&gt;
 var bad_instance1 = Class;   # bad&lt;br /&gt;
 var bad_instance2 = Class;   # bad&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.value = 123;   # sets Class.value to 123&lt;br /&gt;
 bad_instance2.value = 456;   # sets Class.value to 456&lt;br /&gt;
 &lt;br /&gt;
 bad_instance1.write();       # prints 456, not 123&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Constructor ===&lt;br /&gt;
&lt;br /&gt;
Defining each class instance by explicitly creating a hash&lt;br /&gt;
with parents is clumsy. It is nicer to have a function that&lt;br /&gt;
does that for us. Then we can also use function arguments&lt;br /&gt;
to initialize members of this instance.&lt;br /&gt;
&lt;br /&gt;
 var new_class = func(val) {&lt;br /&gt;
     return { parents: [Class], value: val };&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = new_class(123);&lt;br /&gt;
 var instance2 = new_class(456);&lt;br /&gt;
 &lt;br /&gt;
 instance1.write();   # prints 123&lt;br /&gt;
 instance2.write();   # prints 456&lt;br /&gt;
&lt;br /&gt;
With this instance generating function we have now two&lt;br /&gt;
elements referring to a class, which belong together: the&lt;br /&gt;
class hash itself, and the generator function. But aren't&lt;br /&gt;
objects about keeping things together that belong together?&lt;br /&gt;
It would be nicer to just put this generator function into&lt;br /&gt;
the class hash as well. We call this function a class&lt;br /&gt;
&amp;quot;constructor&amp;quot;, and as a convention, give it the name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
It could have any name, though, and there could be more&lt;br /&gt;
than one constructor.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         return { parents: [Class], value: val };&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var instance1 = Class.new(123);&lt;br /&gt;
 var instance2 = Class.new(456);&lt;br /&gt;
&lt;br /&gt;
As you can see, &amp;lt;tt&amp;gt;new()&amp;lt;/tt&amp;gt; doesn't return a copy of &amp;lt;tt&amp;gt;Class&amp;lt;/tt&amp;gt;, but&lt;br /&gt;
rather a small hash that contains only a list of parents&lt;br /&gt;
and one individual member &amp;lt;tt&amp;gt;value&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Classes aren't always as simple as in our example. Usually they&lt;br /&gt;
contain several members, of which some may have yet to be&lt;br /&gt;
calculated in the constructor. In that case it's easier to&lt;br /&gt;
create a local object hash first, and to let the constructor&lt;br /&gt;
finally return it. Such local hashes are often named &amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt; (as&lt;br /&gt;
a short reference to &amp;lt;tt&amp;gt;me&amp;lt;/tt&amp;gt;), or &amp;lt;tt&amp;gt;obj&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 var Class = {&lt;br /&gt;
     new: func(val) {&lt;br /&gt;
         var m = { parents: [Class] };&lt;br /&gt;
         m.value = val;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     write: func {&lt;br /&gt;
         print(&amp;quot;VALUE=&amp;quot; ~ me.value);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
&lt;br /&gt;
This last example is the most frequently used form of class&lt;br /&gt;
definitions in FlightGear-Nasal.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Destructor ===&lt;br /&gt;
&lt;br /&gt;
There's no such thing in Nasal. In other languages destructors are automatically&lt;br /&gt;
called when the class gets destroyed, so that memory and other resources that were&lt;br /&gt;
allocated by the constructor can be freed. In Nasal that's all done by the Garbage&lt;br /&gt;
Collector (GC), anyway. In the FlightGear context, however, there &amp;lt;em&amp;gt;are&amp;lt;/em&amp;gt;&lt;br /&gt;
resources that should get freed. Listeners should get removed, self-calling&lt;br /&gt;
functions (&amp;quot;loops&amp;quot;) stopped. For that it's recommended to create a destructor&lt;br /&gt;
function and to call that manually. Such functions are often called &amp;lt;tt&amp;gt;del&amp;lt;/tt&amp;gt;,&lt;br /&gt;
similar to Python and to pair nicely with the three-letter constructor name &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Multiple inheritance ===&lt;br /&gt;
&lt;br /&gt;
As we noted above, an object can have more than one parent.&lt;br /&gt;
&lt;br /&gt;
 var Aircraft = {&lt;br /&gt;
     new: func(name) {&lt;br /&gt;
         return { parents: [Aircraft], name: name };&lt;br /&gt;
     },&lt;br /&gt;
     printname: func {&lt;br /&gt;
         print(&amp;quot;AIRCRAFT NAME: &amp;quot; ~ me.name);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: aircraft&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var Helicopter = {&lt;br /&gt;
     new: func(name, numrotors) {&lt;br /&gt;
         var m = Aircraft.new(name);&lt;br /&gt;
         m.parents = [Helicopter, Aircraft];&lt;br /&gt;
         m.type = &amp;quot;helicopter&amp;quot;;&lt;br /&gt;
         m.numrotors = numrotors;&lt;br /&gt;
         return m;&lt;br /&gt;
     },&lt;br /&gt;
     printrotors: func {&lt;br /&gt;
         print(&amp;quot;NUMBER OF ROTORS: &amp;quot; ~ me.numrotors);&lt;br /&gt;
     },&lt;br /&gt;
     printtype: func {&lt;br /&gt;
         print(&amp;quot;TYPE: helicopter&amp;quot;);&lt;br /&gt;
     },&lt;br /&gt;
 };&lt;br /&gt;
 &lt;br /&gt;
 var bo = Helicopter.new(&amp;quot;bo105&amp;quot;, 2);&lt;br /&gt;
 bo.printname();&lt;br /&gt;
 bo.printrotors();&lt;br /&gt;
 bo.name = &amp;quot;Eurocopter Bo105CBS&amp;quot;;&lt;br /&gt;
 print(bo.type);                   # prints &amp;quot;helicopter&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Even if a class overrides a method of a parent with the same name,&lt;br /&gt;
the parent's version can still be accessed via &amp;lt;tt&amp;gt;parents&amp;lt;/tt&amp;gt; vector.&lt;br /&gt;
&lt;br /&gt;
 bo.printtype();                 # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[0].printtype();      # prints &amp;quot;TYPE: helicopter&amp;quot;&lt;br /&gt;
 bo.parents[1].printtype();      # prints &amp;quot;TYPE: aircraft&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Listeners and Signals ==&lt;br /&gt;
&lt;br /&gt;
Listeners are callback functions that are attached to property nodes. They are triggered whenever the node is written to, or, depending on the listener type, also when children are added or removed, and when children are written to. Unlike polling loops, listeners don't have the least effect on the frame rate when they aren't triggered, which makes them preferable to monitor properties that aren't written to frequently. Unfortunately, listeners don't work on so-called &amp;quot;tied&amp;quot; properties when the node value isn't set via property methods. (You can spot such tied properties by Ctrl-clicking the &amp;quot;.&amp;quot; entry in the property browser: they are marked with a &amp;quot;T&amp;quot;.) Most of the FDM properties are &amp;quot;tied&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var listener_id = setlistener(&amp;lt;property&amp;gt;, &amp;lt;function&amp;gt; [, &amp;lt;startup=0&amp;gt; [, &amp;lt;runtime=1&amp;gt;]]);&lt;br /&gt;
&lt;br /&gt;
The first argument is a property node object (&amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash) or a property path. Because the node hash depends on the props.nas module being loaded, &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; calls need to be deferred when used in an $FG_ROOT/Nasal/*.nas file, usually by calling them in a &amp;lt;tt&amp;gt;settimer(func {}, 0)&amp;lt;/tt&amp;gt; construction. To avoid that, one can use the raw &amp;lt;tt&amp;gt;_setlistener()&amp;lt;/tt&amp;gt; function directly, for which &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; is a wrapper. The raw function does only accept node paths (e.g. &amp;quot;/sim/menubar/visibility&amp;quot;), but not props.Node() objects.&lt;br /&gt;
&lt;br /&gt;
The second argument is a function object (not a function call!). The &amp;lt;tt&amp;gt;func&amp;lt;/tt&amp;gt; keyword turns code into a function object.&lt;br /&gt;
&lt;br /&gt;
The third argument is optional. If it is non-null, then it causes the listener to be called initially. This is useful to let the callback function pick up the node value at startup.&lt;br /&gt;
&lt;br /&gt;
The fourth argument is optional, and defaults to 1. This means that the callback function will be executed whenever the property is written to, independent of the value. If the argument is set to 0, then the function will only get triggered if a value other than the current value is written to the node. This should be used for properties that are written to in every frame, although the written value is mostly the same. If the argument is 2, then also write access to children will get reported, as well as the creation and removal of children nodes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; returns a unique listener id on success, and &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error. The id is nothing else than a counter that is 0 for the first Nasal listener, 1 for the second etc. You need this id number to remove the listener. Most listeners are never removed, so that one doesn't assign the return value, but simply drop it.&lt;br /&gt;
&lt;br /&gt;
Listener callback functions can access up to four values via regular function arguments, the first two of which are property nodes in the form of a &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; object hash.&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 callback([&amp;lt;changed_node&amp;gt; [, &amp;lt;listened_to_node&amp;gt; [, &amp;lt;operation&amp;gt; [, &amp;lt;is_child_event&amp;gt;]]]])&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
Syntax:&lt;br /&gt;
&lt;br /&gt;
 var num_listeners = removelistener(&amp;lt;listener id&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; takes one argument: the unique listener id that a &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call returned. It returns the number of remaining active Nasal listeners on success,  &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; on error, or -1 if a listener function applies &amp;lt;tt&amp;gt;removelistener()&amp;lt;/tt&amp;gt; to itself. The fact that a listener can remove itself, can be used to implement a one-shot listener function:&lt;br /&gt;
&lt;br /&gt;
 var L = setlistener(&amp;quot;/some/property&amp;quot;, func {&lt;br /&gt;
     print(&amp;quot;I can only be triggered once.&amp;quot;);&lt;br /&gt;
     removelistener(L);&lt;br /&gt;
 });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Listener Examples ===&lt;br /&gt;
&lt;br /&gt;
The following example attaches an anonymous callback function to a &amp;quot;signal&amp;quot;. The function will be executed when FlightGear is closed.&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Instead of an anonymous function, a named function can be used as well:&lt;br /&gt;
&lt;br /&gt;
 var say_bye = func { print(&amp;quot;bye&amp;quot;) }&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, say_bye);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Callback functions can access up to four parameters which are handed over via regular function arguments. Usually there's only the first used, or none at all, like in the above example. The following code attaches the monitor_course() function to a gps property.&lt;br /&gt;
&lt;br /&gt;
 var monitor_course = func(course) {&lt;br /&gt;
     print(&amp;quot;Monitored course set to &amp;quot;, course.getValue());&lt;br /&gt;
 }&lt;br /&gt;
 var i = setlistener(&amp;quot;instrumentation/gps/wp/leg-course-deviation-deg&amp;quot;, monitor_course);&lt;br /&gt;
 &lt;br /&gt;
 # here the listener is active&lt;br /&gt;
 &lt;br /&gt;
 removelistener(i);                    # remove that listener again&lt;br /&gt;
&lt;br /&gt;
The function object doesn't need to be a separate, external function -- it can also be code that is made a function object directly in the &amp;lt;tt&amp;gt;setlistener()&amp;lt;/tt&amp;gt; call:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/signals/exit&amp;quot;, func { print(&amp;quot;bye&amp;quot;) });    # say &amp;quot;bye&amp;quot; on exit&lt;br /&gt;
&lt;br /&gt;
Attaching a function to a node that is specified as &amp;lt;tt&amp;gt;props.Node()&amp;lt;/tt&amp;gt; hash:&lt;br /&gt;
&lt;br /&gt;
 var node = props.globals.getNode(&amp;quot;/sim/signals/click&amp;quot;, 1);&lt;br /&gt;
 setlistener(node, func { gui.popupTip(&amp;quot;don't click here!&amp;quot;) });&lt;br /&gt;
&lt;br /&gt;
Sometimes it is desirable to call the listener function initially, so that it can pick up the node value. In the following example a listener watches the view number, and turns the HUD on in cockpit view, and off in all other views. It doesn't only do that on writing to &amp;quot;view-number&amp;quot;, but also once when the listener gets attached, thanks to the third argument &amp;quot;1&amp;quot;:&lt;br /&gt;
&lt;br /&gt;
 setlistener(&amp;quot;/sim/current-view/view-number&amp;quot;, func(n) {&lt;br /&gt;
     setprop(&amp;quot;/sim/hud/visibility[0]&amp;quot;, n.getValue() == 0);&lt;br /&gt;
 }, 1);&lt;br /&gt;
&lt;br /&gt;
There's no limit for listeners on a node. Several functions can get attached to one node, just as one function can get attached to several nodes. Listeners may write to the node they are listening to. This will not make the listener call itself causing an endless recursion.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Signals ===&lt;br /&gt;
&lt;br /&gt;
In addition to &amp;quot;normal&amp;quot; nodes, there are &amp;quot;signal&amp;quot; nodes that were created solely for the purpose of having listeners attached:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/exit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; on quitting FlightGear&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before resetting FlightGear (Shift-Esc), and to &amp;quot;false&amp;quot; afterwards&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/click&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after a mouse click at the terrain. Hint that the geo coords for the click spot were updated and can be retrieved from /sim/input/click/{longitude-deg,latitude-deg,elevation-ft,elevation-m}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/screenshot&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; right before the screenshot is taken, and set to &amp;quot;false&amp;quot; after it. Can be used to hide and reveal dialogs etc.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/nasal-dir-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; after all Nasal &amp;quot;library&amp;quot; files in $FG_ROOT/Nasal/ were loaded and executed. It is only set once and can only be used to trigger listener functions that were defined in one of the Nasal files in that directory. After that signal was set&lt;br /&gt;
Nasal starts loading and executing aircraft Nasal files, and only later are &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; functions&lt;br /&gt;
called and the next signal is set:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/fdm-initialized&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when then FDM has just finished its initialization&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/reinit-gui&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; when the GUI has just been reset (e.g. via Help menu). This&lt;br /&gt;
is used by the gui.Dialog class to reload Nasal-loaded XML dialogs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;/sim/signals/frame&amp;lt;/tt&amp;gt; ... set to &amp;quot;true&amp;quot; at the beginning of each iteration of the main loop (a.k.a. &amp;quot;frame&amp;quot;). This is meant for debugging purposes. Normally, one would just use a settimer() with interval 0 for the same effect. The difference is that the signal is guaranteed to be raised at a defined moment, while the timer call may change when subsystems are re-ordered.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== FlightGear extension functions ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;print()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Concatenates an arbitrary number of arguments to one string, appends a new-line, and prints it to the terminal. Returns the number of printed characters.&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;Just&amp;quot;, &amp;quot; a &amp;quot;, &amp;quot;test&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;getprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns the node value for a given path, or &amp;lt;tt&amp;gt;nil&amp;lt;/tt&amp;gt; if the node doesn't exist or hasn't been initialized yet. &lt;br /&gt;
&lt;br /&gt;
 getprop(&amp;lt;path&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 print(&amp;quot;The frame rate is &amp;quot;, getprop(&amp;quot;/sim/frame-rate&amp;quot;), &amp;quot; FPS&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;setprop()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Sets a property value for a given node path string. Always returns nil.&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;lt;path&amp;gt; [, &amp;lt;path&amp;gt;, [...]], &amp;lt;value&amp;gt;);&lt;br /&gt;
&lt;br /&gt;
All arguments but the last are concatenated to a path string. The last value is written to the respective node. If the node isn't writable, then an error message is printed to the console.&lt;br /&gt;
&lt;br /&gt;
Examples:&lt;br /&gt;
&lt;br /&gt;
 setprop(&amp;quot;/sim/current-view/view-number&amp;quot;, 2);&lt;br /&gt;
 setprop(&amp;quot;/controls/engines/engine[&amp;quot;, i, &amp;quot;]/reverser&amp;quot;, 1);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;settimer()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Runs a function after a given simulation (default) or real time in seconds.&lt;br /&gt;
&lt;br /&gt;
 settimer(&amp;lt;function&amp;gt;, &amp;lt;time&amp;gt; [, &amp;lt;realtime=0&amp;gt;]);&lt;br /&gt;
&lt;br /&gt;
The third argument is optional and defaults to 0, which lets the time argument be interpreted as &amp;quot;seconds simulation time&amp;quot;. In this case the timer doesn't run when FlightGear is paused. For user interaction purposes (measuring key press time, displaying popups, etc.) one usually prefers real time.&lt;br /&gt;
&lt;br /&gt;
 var copilot_annoyed = func { setprop(&amp;quot;/sim/messages/copilot&amp;quot;, &amp;quot;Stop it! Immediately!&amp;quot;) }&lt;br /&gt;
 settimer(copilot_annoyed, 10);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;systime()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns epoch time (time since 1972/01/01 00:00) in seconds as a floating point number with high resolution. This is useful for benchmarking purposes.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;carttogeod()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts cartesian coordinates x/y/z to geodetic coordinates lat/lon/alt, which are returned as a vector. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var geod = carttogeod(-2737504, -4264101, 3862172);&lt;br /&gt;
 print(&amp;quot;lat=&amp;quot;, geod[0], &amp;quot; lon=&amp;quot;, geod[1], &amp;quot; alt=&amp;quot;, geod[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 lat=37.49999782141546 lon=-122.6999914632327 alt=998.6042055172776&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodtocart()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Converts geodetic coordinates lat/lon/alt to cartesian coordinates x/y/z. Units are degree and meter.&lt;br /&gt;
&lt;br /&gt;
 var cart = geodtocart(37.5, -122.7, 1000); # lat/lon/alt(m)&lt;br /&gt;
 print(&amp;quot;x=&amp;quot;, cart[0], &amp;quot; y=&amp;quot;, cart[1], &amp;quot; z=&amp;quot;, cart[2]);&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 x=-2737504.667684828 y=-4264101.900993474 z=3862172.834656495&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;geodinfo()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
Returns information about geodetic coordinates. Takes two arguments: lat, lon (in degree) and returns a vector with two entries, or nil if no information could be obtained because the terrain tile wasn't loaded. The first entry is the elevation (in meters) for the given point, and the second is a hash with information about the assigned material, or nil if there was no material information available, because there is, for instance, an untextured building at that spot.&lt;br /&gt;
&lt;br /&gt;
 var lat = getprop(&amp;quot;/position/latitude-deg&amp;quot;);&lt;br /&gt;
 var lon = getprop(&amp;quot;/position/longitude-deg&amp;quot;);&lt;br /&gt;
 var info = geodinfo(lat, lon);&lt;br /&gt;
 &lt;br /&gt;
 if (info != nil) {&lt;br /&gt;
     print(&amp;quot;the terrain under the aircraft is at elevation &amp;quot;, info[0], &amp;quot; m&amp;quot;);&lt;br /&gt;
     if (info[1] != nil)&lt;br /&gt;
         print(&amp;quot;and it is &amp;quot;, info[1].solid ? &amp;quot;solid ground&amp;quot; : &amp;quot;covered by water&amp;quot;);&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
A full data set looks like this:&lt;br /&gt;
&lt;br /&gt;
 debug.dump(geodinfo(lat, lon));&lt;br /&gt;
 &lt;br /&gt;
 # outputs&lt;br /&gt;
 [ 106.9892101062052, { light_coverage : 0, bumpiness : 0.5999999999999999, load_resistance : 1e+30,&lt;br /&gt;
 solid : 0,  names : [ &amp;quot;Lake&amp;quot;, &amp;quot;Pond&amp;quot;, &amp;quot;Reservoir&amp;quot;, &amp;quot;Stream&amp;quot;, &amp;quot;Canal&amp;quot; ], friction_factor : 1, &lt;br /&gt;
 rolling_friction : 1.5 } ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;tt&amp;gt;parsexml()&amp;lt;/tt&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
This function is an interface to the built-in expat XML parser. It takes up to five arguments. The first is a mandatory absolute path to an XMl file, the remaining four are optional callback functions, each of which can be nil (which is also the default value).&lt;br /&gt;
&lt;br /&gt;
 var ret = parsexml(&amp;lt;path&amp;gt; [, &amp;lt;start-elem&amp;gt; [, &amp;lt;end-elem&amp;gt; [, &amp;lt;data&amp;gt; [, &amp;lt;pi&amp;gt; ]]]]);&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;start-elem&amp;gt;  ... called for every starting tag with two arguments: the tag name, and an attribute hash&lt;br /&gt;
 &amp;lt;end-elem&amp;gt;    ... called for every ending tag with one argument: the tag name&lt;br /&gt;
 &amp;lt;data&amp;gt;        ... called for every piece of data with one argument: the data string&lt;br /&gt;
 &amp;lt;pi&amp;gt;          ... called for every &amp;quot;processing information&amp;quot; with two args: target and data string&lt;br /&gt;
 &lt;br /&gt;
 &amp;lt;ret&amp;gt;         ... the return value is nil on error, and the &amp;lt;path&amp;gt; otherwise&lt;br /&gt;
&lt;br /&gt;
Example:&lt;br /&gt;
&lt;br /&gt;
 var start = func(name, attr) {&lt;br /&gt;
     print(&amp;quot;starting tag &amp;quot;, name);&lt;br /&gt;
     foreach (var a; keys(attr))&lt;br /&gt;
         print(&amp;quot;\twith attribute &amp;quot;, a, &amp;quot;=&amp;quot;, attr[a]);&lt;br /&gt;
 }&lt;br /&gt;
 var end = func(name) { print(&amp;quot;ending tag &amp;quot;, name) }&lt;br /&gt;
 var data = func(data) { print(&amp;quot;data=&amp;quot;, data) }&lt;br /&gt;
 var pi = func(target, data) { print(&amp;quot;processing instruction: target=&amp;quot;, target, &amp;quot; data=&amp;quot;, data) }&lt;br /&gt;
 parsexml(&amp;quot;/tmp/foo.xml&amp;quot;, start, end, data, pi);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Tips ==&lt;br /&gt;
How to play sounds using Nasal script?&lt;br /&gt;
&lt;br /&gt;
The same way one would do animations using Nasal;&lt;br /&gt;
&lt;br /&gt;
Adjust properties in Nasal (they may be &amp;quot;private&amp;quot; properties in your own&lt;br /&gt;
subtree of the property list, say /tmp/&amp;lt;aircraft&amp;gt;) and let the sound&lt;br /&gt;
configuration file act on those properties.&lt;br /&gt;
(from flightgear-devel)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Related content==&lt;br /&gt;
* [[:Category:Nasal|Category:Nasal]]&lt;br /&gt;
&lt;br /&gt;
=== External links ===&lt;br /&gt;
* http://www.plausible.org/nasal&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8543</id>
		<title>Livery over MP</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8543"/>
		<updated>2008-10-12T14:19:25Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Livery_selection_dialog.jpg|thumb|270px|The livery selection dialog of the [[Sikorsky S76C]].]]&lt;br /&gt;
&lt;br /&gt;
On this page we describe how you make use of a script to get a '''livery selection dialog''' for a [[Aircraft|plane]] in [[FlightGear]]. To get new liveries into [[FlightGear CVS]], you need to have them availabe with this script.&lt;br /&gt;
&lt;br /&gt;
The examples are based on the [[Robin DR400]].&lt;br /&gt;
&lt;br /&gt;
==Files==&lt;br /&gt;
There are a few files we need to make (or edit), namely:&lt;br /&gt;
* &amp;lt;tt&amp;gt;dr400-set.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Models/dr400.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Nasal/liveries.nas&amp;lt;/tt&amp;gt;&lt;br /&gt;
We also have to make a new directory to store our liveries in. Let's make it &amp;lt;tt&amp;gt;Aircraft/DR400/Models/Liveries&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Models/Liveries===&lt;br /&gt;
For every livery we need to make a file. Let's say we got a Rescue livery, we than need to make a file called Rescue.xml into our &amp;lt;tt&amp;gt;Models/Liveries directory&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;sim&amp;gt;&lt;br /&gt;
   &amp;lt;model&amp;gt;&lt;br /&gt;
    &amp;lt;livery&amp;gt;&lt;br /&gt;
     &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Default&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
    &amp;lt;/livery&amp;gt;&lt;br /&gt;
   &amp;lt;/model&amp;gt;&lt;br /&gt;
  &amp;lt;/sim&amp;gt;&lt;br /&gt;
 &amp;lt;/PropertyList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===dr400.xml===&lt;br /&gt;
The first part is related to the nasal script. &amp;lt;tt&amp;gt;(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&amp;lt;/tt&amp;gt; points FlightGear to the directory where we store our liveries. This is a different directory for every plane, but there should be only one folder for one plane, containing all the liveries for that plane.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nasal&amp;gt;&lt;br /&gt;
  &amp;lt;load&amp;gt;&lt;br /&gt;
   var livery_update = aircraft.livery_update.new(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
  &amp;lt;/load&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  &amp;lt;unload&amp;gt;&lt;br /&gt;
   livery_update.stop();&lt;br /&gt;
  &amp;lt;/unload&amp;gt;&lt;br /&gt;
 &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second part is very important and probably the hardest of all. We need to set which parts of the model should change when you select a new livery. To find the object-names, you could make use of software like [[Blender]] or [[AC3D]]. The &amp;lt;tt&amp;gt;&amp;lt;texture&amp;gt;S76livery.rgb&amp;lt;/texture&amp;gt;&amp;lt;/tt&amp;gt; part points FlightGear to the livery that should be shown on startup.&lt;br /&gt;
&lt;br /&gt;
'''Warning: be sure you don't have a slash (/) in front of sim/model/livery in the &amp;lt;property-base&amp;gt; tag! Otherwise, all planes will get the same livery!'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;animation&amp;gt;&lt;br /&gt;
  &amp;lt;type&amp;gt;material&amp;lt;/type&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;S76C&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Rr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Lr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;property-base&amp;gt;sim/model/livery&amp;lt;/property-base&amp;gt;&lt;br /&gt;
   &amp;lt;texture-prop&amp;gt;texture&amp;lt;/texture-prop&amp;gt;&lt;br /&gt;
   &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
 &amp;lt;/animation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===liveries.nas===&lt;br /&gt;
The only thing you might change in the nasal file is the directory of the liveries.&lt;br /&gt;
&lt;br /&gt;
 aircraft.livery.init(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===s76c-set.xml===&lt;br /&gt;
 &amp;lt;model&amp;gt;&lt;br /&gt;
  &amp;lt;path&amp;gt;Aircraft/DR400/models/dr400.xml&amp;lt;/path&amp;gt;&lt;br /&gt;
  &amp;lt;livery&amp;gt;&lt;br /&gt;
   &amp;lt;file type=&amp;quot;string&amp;quot;&amp;gt;default&amp;lt;/file&amp;gt;&lt;br /&gt;
  &amp;lt;/livery&amp;gt;&lt;br /&gt;
 &amp;lt;/model&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make a nice button in the [[menubar]] we need to add the following code, just above the &amp;lt;tt&amp;gt;&amp;lt;/sim&amp;gt;&amp;lt;/tt&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;menubar&amp;gt;&lt;br /&gt;
  &amp;lt;default&amp;gt;&lt;br /&gt;
   &amp;lt;menu n=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;Robin DR 400&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;enabled type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;
    &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Select Livery&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;aircraft.livery.dialog.toggle()&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;/item&amp;gt;&lt;br /&gt;
   &amp;lt;/menu&amp;gt;&lt;br /&gt;
  &amp;lt;/default&amp;gt;&lt;br /&gt;
 &amp;lt;/menubar&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Testing===&lt;br /&gt;
To ensure that your livery setup works correctly over MP, start two instances of FlightGear locally, one with&lt;br /&gt;
&lt;br /&gt;
 fgfs --multiplay=out,10,localhost,5702 --multiplay=in,10,localhost,5701&lt;br /&gt;
&lt;br /&gt;
and one with&lt;br /&gt;
&lt;br /&gt;
 fgfs --multiplay=out,10,localhost,5701 --multiplay=in,10,localhost,5702&lt;br /&gt;
&lt;br /&gt;
[[Category:Aircraft enhancement]]&lt;br /&gt;
[[Category:Modeling]]&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
	<entry>
		<id>https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8542</id>
		<title>Livery over MP</title>
		<link rel="alternate" type="text/html" href="https://wiki.flightgear.org/w/index.php?title=Livery_over_MP&amp;diff=8542"/>
		<updated>2008-10-12T12:48:30Z</updated>

		<summary type="html">&lt;p&gt;Melchior FRANZ: remove seldom needed optional livery_update interval argument; set menu index to 100, as 10 is rather unsafe and could overwrite a system enty&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Image:Livery_selection_dialog.jpg|thumb|270px|The livery selection dialog of the [[Sikorsky S76C]].]]&lt;br /&gt;
&lt;br /&gt;
On this page we describe how you make use of a script to get a '''livery selection dialog''' for a [[Aircraft|plane]] in [[FlightGear]]. To get new liveries into [[FlightGear CVS]], you need to have them availabe with this script.&lt;br /&gt;
&lt;br /&gt;
The examples are based on the [[Robin DR400]].&lt;br /&gt;
&lt;br /&gt;
==Files==&lt;br /&gt;
There are a few files we need to make (or edit), namely:&lt;br /&gt;
* &amp;lt;tt&amp;gt;dr400-set.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Models/dr400.xml&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;Nasal/liveries.nas&amp;lt;/tt&amp;gt;&lt;br /&gt;
We also have to make a new directory to store our liveries in. Let's make it &amp;lt;tt&amp;gt;Aircraft/DR400/Models/Liveries&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Models/Liveries===&lt;br /&gt;
For every livery we need to make a file. Let's say we got a Rescue livery, we than need to make a file called Rescue.xml into our &amp;lt;tt&amp;gt;Models/Liveries directory&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot;?&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
 &amp;lt;PropertyList&amp;gt;&lt;br /&gt;
  &amp;lt;sim&amp;gt;&lt;br /&gt;
   &amp;lt;model&amp;gt;&lt;br /&gt;
    &amp;lt;livery&amp;gt;&lt;br /&gt;
     &amp;lt;name type=&amp;quot;string&amp;quot;&amp;gt;Default&amp;lt;/name&amp;gt;&lt;br /&gt;
     &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
    &amp;lt;/livery&amp;gt;&lt;br /&gt;
   &amp;lt;/model&amp;gt;&lt;br /&gt;
  &amp;lt;/sim&amp;gt;&lt;br /&gt;
 &amp;lt;/PropertyList&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===dr400.xml===&lt;br /&gt;
The first part is related to the nasal script. &amp;lt;tt&amp;gt;(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&amp;lt;/tt&amp;gt; points FlightGear to the directory where we store our liveries. This is a different directory for every plane, but there should be only one folder for one plane, containing all the liveries for that plane.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nasal&amp;gt;&lt;br /&gt;
  &amp;lt;load&amp;gt;&lt;br /&gt;
   var livery_update = aircraft.livery_update.new(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
  &amp;lt;/load&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
  &amp;lt;unload&amp;gt;&lt;br /&gt;
   livery_update.stop();&lt;br /&gt;
  &amp;lt;/unload&amp;gt;&lt;br /&gt;
 &amp;lt;/nasal&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The second part is very important and probably the hardest of all. We need to set which parts of the model should change when you select a new livery. To find the object-names, you could make use of software like [[Blender]] or [[AC3D]]. The &amp;lt;tt&amp;gt;&amp;lt;texture&amp;gt;S76livery.rgb&amp;lt;/texture&amp;gt;&amp;lt;/tt&amp;gt; part points FlightGear to the livery that should be shown on startup.&lt;br /&gt;
&lt;br /&gt;
'''Warning: be sure you don't have a slash (/) in front of sim/model/livery in the &amp;lt;property-base&amp;gt; tag! Otherwise, all planes will get the same livery!'''&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;animation&amp;gt;&lt;br /&gt;
  &amp;lt;type&amp;gt;material&amp;lt;/type&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;S76C&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LF.door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Rr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;Lr.Door&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHbaggage&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;RHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;object-name&amp;gt;LHfrtgeardoor&amp;lt;/object-name&amp;gt;&lt;br /&gt;
   &amp;lt;property-base&amp;gt;sim/model/livery&amp;lt;/property-base&amp;gt;&lt;br /&gt;
   &amp;lt;texture-prop&amp;gt;texture&amp;lt;/texture-prop&amp;gt;&lt;br /&gt;
   &amp;lt;texture&amp;gt;texture.rgb&amp;lt;/texture&amp;gt;&lt;br /&gt;
 &amp;lt;/animation&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===liveries.nas===&lt;br /&gt;
The only thing you might change in the nasal file is the directory of the liveries.&lt;br /&gt;
&lt;br /&gt;
 aircraft.livery.init(&amp;quot;Aircraft/DR400/Models/Liveries&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
===s76c-set.xml===&lt;br /&gt;
 &amp;lt;model&amp;gt;&lt;br /&gt;
  &amp;lt;path&amp;gt;Aircraft/DR400/models/dr400.xml&amp;lt;/path&amp;gt;&lt;br /&gt;
  &amp;lt;livery&amp;gt;&lt;br /&gt;
   &amp;lt;file type=&amp;quot;string&amp;quot;&amp;gt;default&amp;lt;/file&amp;gt;&lt;br /&gt;
  &amp;lt;/livery&amp;gt;&lt;br /&gt;
 &amp;lt;/model&amp;gt;&lt;br /&gt;
&lt;br /&gt;
To make a nice button in the [[menubar]] we need to add the following code, just above the &amp;lt;tt&amp;gt;&amp;lt;/sim&amp;gt;&amp;lt;/tt&amp;gt; tag.&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;menubar&amp;gt;&lt;br /&gt;
  &amp;lt;default&amp;gt;&lt;br /&gt;
   &amp;lt;menu n=&amp;quot;100&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;label&amp;gt;Robin DR 400&amp;lt;/label&amp;gt;&lt;br /&gt;
    &amp;lt;enabled type=&amp;quot;bool&amp;quot;&amp;gt;true&amp;lt;/enabled&amp;gt;&lt;br /&gt;
    &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;label&amp;gt;Select Livery&amp;lt;/label&amp;gt;&lt;br /&gt;
     &amp;lt;binding&amp;gt;&lt;br /&gt;
      &amp;lt;command&amp;gt;nasal&amp;lt;/command&amp;gt;&lt;br /&gt;
      &amp;lt;script&amp;gt;aircraft.livery.dialog.toggle()&amp;lt;/script&amp;gt;&lt;br /&gt;
     &amp;lt;/binding&amp;gt;&lt;br /&gt;
    &amp;lt;/item&amp;gt;&lt;br /&gt;
   &amp;lt;/menu&amp;gt;&lt;br /&gt;
  &amp;lt;/default&amp;gt;&lt;br /&gt;
 &amp;lt;/menubar&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Aircraft enhancement]]&lt;br /&gt;
[[Category:Modeling]]&lt;/div&gt;</summary>
		<author><name>Melchior FRANZ</name></author>
	</entry>
</feed>